* fix: review-dispatch pass accepts the scoped plan; the fix-check runs on its own (GST-619)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: a scoped pass stages its readers on the fix range base (GST-619)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: keep the pinned /ship reviewer prose; the scoped fix-check already runs inside the pass (GST-619)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: a scoped pass gives the fix range to the Red Team; pending Step 11 voices keep the merge base (GST-619)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the scoped pass's adversarial reader reads the whole branch until Step 11 runs (GST-619)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(freeze): resolve the full path before the boundary check, fail closed when it can't (#3623)
check-freeze.sh canonicalized only an existing parent directory and compared
the raw string otherwise, so any path through a directory that did not exist
yet kept its literal in-boundary prefix: '<b>/../outside/new/x',
'<b>/link-out/new/x', '<b>/..', '~/.zshrc' with cwd inside, and
'C:\proj\src\..\..\other\new\x' were all allowed.
_resolve_path now walks the path one component at a time, follows symlinks at
any depth, and requires both the OS reading and a lexical normalizer's reading
of '..' to land inside. Paths it cannot place deny with a reason: symlink
loops and chains over 40 links, line breaks, Windows drive- and root-relative
paths, names Windows trims, odd UNC roots. Windows rules keep '..' at the drive
or share root. The shared extractor keeps trailing newlines and maps lone
surrogates on path fields only; /careful's command values are unchanged.
Co-authored-by: Quinn O'Donnell <90010678+Quinnod345@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(freeze): deny paths over PATH_MAX before the quadratic walk (#3623)
A PreToolUse hook that outlives the host's timeout does not block the edit,
and the component walk is quadratic in path length. Deny a file_path over
4096 characters, and links that grow the walk past 8192, before walking.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(freeze): bound the total length of followed link targets (#3623)
The PATH_MAX cap bounded only the file_path text; each link hop could add
up to 8192 characters again, and a padded 40-link chain kept the quadratic
walk busy for 104s. Count every target against one 8192-character budget.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(freeze): cheap link-chain budget test; name the path in the budget reason (#3623)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): /freeze boundary escape fix (#3623)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(freeze): describe full-path resolution and fail-closed cases (#3623)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* freeze: deny Windows link targets relative to a drive or its root (#3623)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* freeze: read a leading // as / on POSIX hosts, never as a UNC prefix (#3623)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* freeze: compare Git Bash paths by cygpath's drive spelling (#3623)
Git Bash mounts %TEMP% at /tmp and converts HOME through its mounts, so
'~/x' and 'D:\...\x' named one file in two spellings and the hook denied
a legit edit (windows-free-shard 2 on #3758).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* freeze: name the edited path as given in the deny, with where it lands (#3623)
cygpath's drive spelling made a Windows deny print /c/Program Files/Git/etc/hosts
for /etc/hosts (windows-free-shard 2 on #3758, 'Edit denials name the tool and
file_path too').
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: Quinn O'Donnell <90010678+Quinnod345@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): env.kv reads Python and Dart type names and variable reads as code (#3630)
Extends the #3048 source-syntax exemption to .dart/.py/.pyi and JSX braces
joined by ?? || &&, with a Dart/Python-only triple-quote guard. pregate scans
changed Python/Dart files whole and keeps added-line findings, and the
allowlist names a pattern entry that missed its finding.
Co-authored-by: Adam Balazs <4034736+adam-balazs@users.noreply.github.com>
Co-authored-by: Hamish Barney <1049017+hbarney@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): triple-quote spans skip comments and one-line strings; prepush and large-file fallback scan Python/Dart without the exemption (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): untracked Python/Dart files keep the source exemption; allowlist rows name file lines for whole-file scans (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): a whole-file Python/Dart scan falls back to added lines when the working copy differs from the diff; count added lines, not file lines (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): one string-span pass for Python/Dart (block comments, raw strings, continuations); a literal fallback after a name still reports (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): a name whose expression continues on the next line still reports; allowlist miss rows only for patterns written from the name; clear the span cache after each scan (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): a trailing comment is not part of a name's expression (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(pregate): Python keyword form still reports; the pre-push hook scans Python/Dart without the exemption (#3630)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: Adam Balazs <4034736+adam-balazs@users.noreply.github.com>
Co-authored-by: Hamish Barney <1049017+hbarney@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): gstack-review-plan and review-dispatch let stdout drain before exit, so a large plan JSON reaches pass whole (GST-507)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (gstack-review-dispatch: a BriefError no longer falls through to the rethrow, GST-507)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(upgrade): refuse an install whose enclosing project tracks its files (#1022)
A project that commits gstack's files as plain blobs puts the old ones back on
every checkout of its own, so VERSION froze behind HEAD while gstack-upgrade
reported the install current. bin/gstack-ff-update, the one move the
auto-updater and /gstack-upgrade share, now refuses with exit 6 (nothing
changed) when the enclosing repository tracks non-gitlink paths under the
install, or when VERSION differs from HEAD (eol-normalized). gstack-upgrade
runs the same checks through --preflight before any fetch; the auto-updater
holds the update with a banner and a troubleshooting anchor.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Leave an unmerged VERSION to the rescue, keep the enclosing project's
fsmonitor hook from running during the preflight, and word the
version-reverted refusal for a hand edit as well as a project checkout.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(troubleshooting): name the hand-edited VERSION case
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: review pass fixes for the #1022 preflight
The printed repair untracks the install with --literal-pathspecs and escapes
glob characters in the ignore rule; the message is no longer capped short.
version-reverted compares VERSION's first line with HEAD's, yields to the
rescue when any file is unmerged, and runs inside the install lock on a full
update.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: the literal-repair decoy matches the install's glob
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: fragment for the #1022 preflight
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: finish an interrupted move instead of holding it as version-reverted
The in-lock VERSION check accepts a VERSION already at the target's. Adds a
session-update case for the version-reverted hold, and backdates mtimes in
the new ff-update fixtures so the barrier's recapture is not racy.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: name the preflight's best-effort exit (gate-tail lint)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: say already-reverted installs need the one-time repair
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(eval-plan): results --check refuses a results table without its no-gstack rows
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(model-panel): a <model>#no-gstack arm per model, identity-keyed cells, one campaign, results.md (GST-468)
Each panel model also runs as <model>#no-gstack: the same fixture, ticket,
tools, limits, route and reservation, with no skill folder and no routing
line. The arm identity keys the ledger attempt, test name, row and summary;
candidate folders are named after the fixture project and the seed commit
has a neutral author. summarize reads one campaign (run id and PREREG.md
sha256) and refuses a duplicate cell; suggestionLine reads the skill arms
only, so the preregistered particle-1 line is unchanged. renderResults writes
results.md, which passes gstack-eval-plan results --check against the new
test/fixtures/model-panel/PREREG.md (supersedes GSTA-173 for later runs).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(arm-benchmark): no-gstack arm on a pinned model, 3 paired trials, both-order paired judge, spend ledger (GST-469)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(evals): no-gstack arm for the safety-rule and router evals (GST-470)
GSTACK_SAFETY_ARM and GSTACK_ROUTER_ARM take a third value, none: the same
fixture, tools and user request with no skill excerpt, rule text, step file
or installed skill. Under none every behavioral check is recorded as an
observation (none-arm-observations.jsonl) and never fails the case or writes
contract-violations.jsonl; harness preconditions still assert.
The four safety prompt builders (ship-evidence, codex-boundary,
codex-consult, design-risk) and the router fixtures move into helpers; the
rule, removed, current and before prompts stay byte-identical, proven
against reference copies of main's code. pair-agent and ios-demo refuse
none with the reason (NO_NONE_ARM). GSTACK_ROUTER_ARM now throws on an
unknown value instead of silently running current.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: changelog fragment for the no-gstack arms in existing evals
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(arm-benchmark): arm-pair paired-judge calibration run (bar met 6/6, $7.22)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(paid-shards): keep loop-named panel and arm-benchmark cases selectable by --case
The lanes moved each cell's testName into helpers, so the static detector no
longer saw a computed registration and B4 failed for all eight cases. Same
runtime test names; the paid runs are unaffected.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(tests): keep FREE_FIXTURES and the placeholder allowlist current for the no-gstack arms
scripts/judge-calibration.ts is now an arm-benchmark paid touchfile, so it can no
longer be a free consumer of test/fixtures/judge-calibration/** (CI free-suite 8).
The eval-plan Step 5 fence names <prereg-path> and <results-path>; allowlist both
as PATH placeholders (CI free-suite 19).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(eval-plan): cover a complete table after a partial one, --json output and the results usage error
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(eval-plan): keep the Step 7 coverage test as reviewed
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: name the changelog fragment after the branch slug
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: arm-benchmark project folder names and the arm-pair calibration corpus
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: keep the judge-calibration fixture README as reviewed
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(skills): describe eval-plan results --check
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Plan reviews name files, rarely lines, and reconcile associated by location
only when both findings had a line, so findings both voices raised on one
file were filed new and native-only. A same-file pair with a missing line is
now associated as unverified (basis file), never confirmed; a CAP code no
longer counts in title comparison. DRIVER.md names submit --reconcile.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The DX error contract told both autoplan DX voices to title capped findings
exactly CAP4:<path>:<item>, so gates, tasks and reconcile saw a bare code.
The title is now CAP4:<path>:<item> <what fails>; the grader already parses
that shape.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: clear the remote gate with verified Actions runs on the same tree (clear --run)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: REUSE accepted/refused lines, run-url regression test, receipt bind end to end
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: review fixes for clear --run (re-run veto, profiled lanes fail closed, no pull_request runs, user-policy keys)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: adversarial fixes for clear --run (unknown profiles fail closed, lane coverage, run re-read, base binding, paging, artifact bound, full assignment)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: pass-2 review fixes for clear --run (docstrings, tests_uncovered reason, unreadable-base and user-policy tests)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(troubleshooting): clear --run refusals, run-profile keys in the user policy, verify's foreign-tree run receipt
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: CHANGELOG for clear --run (unreleased; stamped at merge)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: receipt clear --run's gh reads and head fetch in the egress ledger (sink run-evidence)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: run the remote gate inventory through runBashSync (script-invocation tripwire)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): clear --run reads origin before url.insteadOf, so Capy's git.capy.ai proxy still names the GitHub repository
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): clear --run re-reads every run before recording, ties veto, inventory runs under pipefail, freshness reads job completion, and a pregate.json rewritten mid-clear refuses
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(pregate): the veto counts runs started at or after the candidate; quote clear's real refusal line
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(pregate): user policy refuses the run-profile keys; the remote gate clears one of three ways
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(ubicloud): reattach to a live verify VM and checkpoint tiers (GSTA-158 P3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ubicloud): replay on reattach, tear down TTL-less VMs on HUP, trim skill prose (GSTA-158 P3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(eval-plan): require a no-gstack arm in every head-to-head preregistration
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(eval-plan): lint loadout arms by their model; refuse arms sharing a ledger attempt
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(flaky): gstack-flaky run reruns a failed JUnit test once and ledgers the flake (GSTA-158)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(flaky): stream output, keep unreported runner failures red, fail-closed duplicates and nonzero reruns
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
gstack-flaky never greens an incomplete run: a targeted rerun needs the
runner's summary proving the first run complete, otherwise (and always for
generic runners) the rerun repeats the whole command. A rerun clears a test
only when it exits 0 and the test passes once on its first attempt. Killed
runners exit 3 (FLAKY_COMMAND_KILLED) and signals are forwarded. The first
report is restored at --junit with reruns kept beside it; ids are redacted at
every output; the ledger gets its own GSTACK_FLAKE_LEDGER_JUNIT; fixtures are
registered in FREE_FIXTURES.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: latch cancellation and check whole-command rerun reports
A cancel forwarded to a runner that traps the signal now counts as killed for
every later attempt, so a cancelled job is never rerun or greened. A
whole-command rerun clears nothing when its report has a failed test, misses a
first-run test, or its runner counted failures outside the report.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: whole-command rerun when coverage or runner-flaky tests can fail the run
A coverage threshold or a fail-on-flaky policy fails a run for a reason a
narrowed rerun cannot reproduce, so either forces a whole-command rerun.
--junit refuses an existing file that is not a JUnit report instead of
deleting it.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(flaky): rerun the whole command by default; targeted rerun is opt-in
A rerun counts only on the runner's own full green verdict: exit 0, no failed
or missing test, nothing counted outside the report. That covers every way a
run can fail, which a narrowed rerun cannot (a coverage threshold with an lcov
reporter, a fail-on-flaky policy, a test never reached). --rerun-scope test
reruns the failed test alone, with its preconditions documented and the
complete-run checks kept as a safety net. An unreadable existing --junit file
is a usage error, not a crash.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: gstack-flaky CHANGELOG entry and standalone-binaries row (GSTA-158)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ci(evals): a pr-summary run skips the readiness wait it never used
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: CHANGELOG [Unreleased] entry for the pr-summary readiness skip
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: move the CHANGELOG entry to changelog.d/capy-gsta149-pr-summary-wait.md (fragments policy since #3654)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ci(free-tests): one runner and shard constant for every event, dispatch overrides for sizing, per-shard memory and disk peak
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(free-tests): type the refused dispatch overrides
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ci(free-tests): run the free suite on ubicloud-standard-2 at 20 shards
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(testing): the free-suite runner constant, sizing overrides and RESOURCES line
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: CHANGELOG [Unreleased] entry for the standard-2 free suite
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: move the CHANGELOG entry to changelog.d/capy-gsta149-free-runner.md (fragments policy since #3654)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* gstack-wtree: exclude .bun only when it exists and is not gitignored (GST-449)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* gstack-wtree: ask the ignore rules alone (--no-index) so a tracked file under an ignored .bun/ still fingerprints (GST-449)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: GST-449 fragment covers the tracked-file case
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: --remote gate is bounded by its timeout, not the stall timer; heartbeat names its last line (GST-431)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: remote heartbeat sanitizes and tolerates a removed log; timeout detail names its source (review fixes)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): collect counts a reply with no finding and no clean marker as a non-review, never clean (GSTA-167)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a label word used as a word is no finding, and a paragraph finding keeps its detail bullets (GST-435)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a negation counts only when it applies to the label; compact table rows keep their label; register the review-ledger fixtures (pre-landing review)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): negation stops at a conjunction, a summary line with a blocker stays, detail bullets need no gap and no locus; a re-sent review voids a refusal and the outside voice can be collected unavailable (pre-landing review)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): bold and code marks keep a negated label a word, a subject phrase with and/or stays negated, table negation counts, --unavailable refuses an output with findings, VOIDED needs a re-send (fix-check)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a quoted label counts at the end of its line and in table cells, which ends a negated subject, and a negated subject never cancels a label on a file:line line (fix-check)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a line naming a file:line or a table row always keeps a finding; "of which" stays inside a negated subject (fix-check)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(ship): the review-pass fake outside voice ends with its Recommendation: line, the marker its brief prescribes (#3665 integration)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* revert(ship): parseFindings labels and negation back to main; GST-435 moves to its own PR (seed branch gsta-435-seed). Keeps the non-review rule and the detail-bullet merge (split)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* gstack-post: a partial pr-body post keeps the PR's intro; only a full post owns the preamble
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* gstack-post: only a receipt above the first heading makes a full post (review fixes)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: a partial pr-body post's own lead text still replaces the PR's (docs audit)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(outside-review): an unclosed code fence no longer hides a later [P1] or not-ready verdict (GST-436)
withoutCode() blanked every line after a fence that never closed, so a reply with a
no-findings line, an unclosed fence and then a [P1] or 'Verdict: not ready' classified
clean. A fence that never closes is now not code. Test fails first on main 89f20330.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(outside-review): an unclosed code fence no longer hides a later [P1] or not-ready verdict (GST-436)
withoutCode() blanked every line after a fence that never closed, so a reply with a
no-findings line, an unclosed fence and then a [P1] or 'Verdict: not ready' classified
clean. A fence that never closes is now not code. Test fails first on main 89f20330.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(outside-review): text in an unclosed fence blocks but never makes a reply clean; one-pass fence matching (GST-436 review)
Review pass 1 found the first commit read an unclosed fence's remainder for every
signal: a quoted Verdict: ready, [P3] or No issues found. there turned a not-ready or
unverified reply clean, and each unmatched fence rescanned the rest of the reply
(3,000 fences: 5.9 s, 4.7 GB). Blocking signals now read the remainder; the evidence
for clean keeps it blanked; fence matching is one linear pass.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: outside-review verdict rules name the unclosed-fence behavior (GST-436)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: unclosed-fence wording matches the classifier: unparsed label is unverified, only P0/P1 block (GST-436)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship: poll readers in-program, never wait on wakes; 32 KB returns; gated fix program; unattended push defers the guard offer; calls meter (GSTA-167 calls PR 1)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (inventory lib/ship-release.ts as a GSTACK_SESSION_KIND reader)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(ship-budget): document calls and dotted --step notes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship: one call per review pass on Capy; staged dispatch manifest, chunked briefs, intent before create (GSTA-167 calls PR 2)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (pass program reruns a failed review-log start and stops on a failed reader every run)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: Step 11 review fixes (PASS: none read from the last line only, queued readers reconciled and timed out, a budget stop ends the pass)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship: judge treats a missing severity as invalid; Capy passes rendered briefs via cat (replay C1-34 breaks)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the batched reviewer reads its checklists by path, as the render CLI is given them (PR #3665 review)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: keep the Capy skill under its context budget after the main merge
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: drop PR 1's changelog fragment, which main's v1.91.355.0 stamp already consumed
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): the pass program takes extras as JSON and a cwd, and waits a minute for a done reader's summary (replay C2-34)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(capy): reviewer installs leave the lane's launch environment alone; gstack-upgrade counts capy-server leases (GST-395/396/401/402)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(capy-install): restore the header comment prefixes; borrow the lane's launch file only when it reaches a Bun (GST-401)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(capy-install): gate the store-download borrow test to Linux like its siblings
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(eval-selector): changelog.d fragments have no eval dependents (GST-400)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(pr-profile): derive the fragment-naming case from touchfile selection, not a hardcoded input
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* harness-version: record scripts/test-pr-profile.ts as non-behavioral (selection only, GST-400)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (fragment exemption only for .md directly in the folder; rename lists keep the old path)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(paid-free-boundary): re-audit test-selection.ts after --no-renames; computed import unchanged, repin its hash
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* review: targeted read-only pass on money, gate, auth and secret diffs (GST-257 part 1, report-only)
lib/review-targeted.ts classifies a diff's added and deleted lines into
money, gate, auth and secret (token-bounded, docs and tests excluded,
fails closed to all four). gstack-review-plan prints TARGETED and
dispatches one read-only targeted reader at full effort when a class
hits; review/specialists/targeted.md is its brief. The receipt records
review_targeted bound to product_patch_id, a carry keeps it, and
gstack-ship-queue ready / train build print a report-only
REVIEW_TARGETED line that refuses nothing.
No-loss evidence: the dispatch-superset test in
test/review-targeted.test.ts runs gstack-review-plan on 18 fixture diffs
and requires every reviewer main dispatched at 8be7f21, unchanged, plus
only the targeted reader. Brief identity: gstack-review-dispatch render
on this tree and origin/main 2356792 gives 13 of 13 existing reviewer
briefs byte-identical (handoffs/GSTA-160/gst257-briefcmp/SUMMARY.txt).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (targeted patch id covers tests, record binds the diff it read, role list pin)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: targeted reader reads the merge base on every pass; dirty-tree record test
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: targeted render takes --base and any spelling of the merge base; Step 11 says the merge base; docs gate-path list
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: type the fail-closed class list (typecheck:test ratchet)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): literals skips a version-history row when the branch extended its table (GST-344)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): literals reads the merge base through renames, treats an unreadable base as not extended, and recognizes quoted digit-leading history keys
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): literals exempts only a history row's first field, finds tables in one pass, and matches rows within one line
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): literals checks only the text after a history row's closing bracket; restore digest fixtures
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Also: the Captain digest drops an archived thread from In progress in the same turn (GST-371).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>