* test(install): a --project repo slug is a usage error, not a project-less verdict (GST-743, failing first)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(install): --project refuses a value that is not a directory (GST-743)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (GST-743: key --project by its git toplevel, refuse a non-directory before cloning, ignore CDPATH)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (GST-743: --project resolves to its git toplevel for pins and the key; an unenterable directory is refused)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: GST-743 fragment names the subpackage-pin and admission-key behavior
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: capy-install names how --project resolves (GST-743)
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): base merges, adjacent base edits, test-only and audit-requested fixes no longer force a second review loop (GST-407, GST-384, GST-391)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship driver: trim two phrases for headroom with #3662
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship driver: keep the Next steps heading phrase the handoff check reads; trim elsewhere
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: regenerate ship goldens
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
comparePath returns same only when every hunk sits where the base change puts it (patch-ids ignore positions) and treats a file-mode change as changed; the scoped-review packet says when a fence is truncated; --docs-result must be the posted audit's result; the --context-reviewed record goes beside the packet, outside the worktree. Negative controls for each.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pass-2 review fixes
A test edit routes as tests= only when it adds lines with no gate tag; a removed or changed line or an unreadable test diff goes through the full loop. Diffs skip textconv. A hunkless patch (binary, empty, mode-only) is same when its patch-id matches. Without --reviewed-base test files route as before. finish's packet path and attempt's state directory have fallbacks.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: Step 11 review fixes; a version-only stamp_files edit after review is release metadata (GBRA-251)
gateEditedPaths reads removed lines only inside hunks; carry refuses when a path listing fails; docs freshness stops on a failed listing; attempt counts an unreadable state file. releasePaths includes stamp_files paths whose edit is a version swap under stamp_patterns.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: no test edit skips review; guard packet writes; exclusive attempt state
A test-only edit with no gate tag gets the scoped fix-check of its test hunks instead of a lanes-only rerun. Packet write failures print a STOP or RECEIPT_CARRY_REFUSED. attempt's allowance uses an exclusive create.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: attempt prints gstack's install command; carry checks the product diff outside context paths
The attempt STOP no longer echoes the audit child's fix text. A scoped-review carry now requires the product patch-id without the context paths to match at both heads.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: oversized packets take the full loop; exact --docs-requested match; name-only test globs only in test dirs
A scoped-review packet section over 200 lines sends that path to the full loop instead of a truncated packet. The docs-result path match is exact. test_*.py, *Test.java and similar count as test code only under a test directory.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(unattended): carry's scoped-review refusal and what it keeps
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: carry's scoped-review route in ship-policy, review-policy and troubleshooting (docs-a-1)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(windows): curate ship-rereview-triggers out of the Windows lane like ship-release (run 41193336209)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: restore bin/gstack-ship-receipt after the main merge
The merge commit b10e2db wrote a truncated copy of the file. This is the
three-way merge of both sides with the refused() union: main's codes plus
RECEIPT_CARRY_SCOPED_REVIEW.
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>
* G1: gstack-plan-reality check opens every file:line receipt (#973)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G1: office-hours spec reviewer checks paths and flags through a bin-enforced probe (#973)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G2: plan-review reruns reconcile the last task list (gstack-tasks prior/supersede) (#1791)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G2: plan reviews write task lists through gstack-tasks start/add/close
The emit block shrinks to three calls: prior (now defaulting --dir and
--branch, and printing how to reconcile), start (creates the empty
branch-named list) and add (one validated row per task). close records a
done or dropped prior task. The plan-review result codes move to
lib/result-codes-plan.ts so lib/result-codes.ts stays under the module-size
ratchet; generated plan-review sections shrink, so their size pins go down.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* F2: office-hours saves the sketch beside the design doc; /plan-design-review reads it
Step 5 copies sketch.png/html to <PROJECT_DIR>/{user}-{branch}-sketch-{datetime}.*
and writes a Wireframe: line (state-root relative) or Wireframe: none (<reason>).
The design review section finds the design doc before Pass 1 and opens the
wireframe, text-only when the file is missing. G4's signals line rides along
in the same generated office-hours files; tests in planning-wave-prose.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G3: plan reviews tie storage to queries, not file count (#1048)
One bullet in each of plan-eng-review and plan-ceo-review: fields queried,
constrained or updated on their own get explicit columns or tables; JSON suits
a document read and written whole. Written fresh; the reporter's patch is not
ported.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* evals: GSTA-228 planning-wave cases with branch, main and no-gstack arms
planted facts (G1, behavior), data model (G3, behavior), task-list rerun (G2,
rule) and closing signals (G4, behavior). GSTACK_WAVE_ARM picks the arm; only
the branch arm asserts the preregistered bar, every arm writes a score row.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: GSTA-228 planning wave fragment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G1: the probe takes subcommand words for fixed-subcommand CLIs
The planted-facts eval's one branch miss: the reviewer asked to probe
"git log", the probe refused it, and git's top-level help cannot show a log
flag, so the fabricated --since-commit stayed "unverified".
probe --help <command> [<subcommand> [<subcommand>]] now runs
<cli> <sub> --help for git, gh, docker, cargo, go, npm and uv (never node,
bun, python3, make, yarn, pnpm or a gstack bin, where the word could name a
script), in an empty temporary directory with pagers set to cat, falling back
to -h when --help has no usage line (a minimized system's missing man page).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G2: task text goes through a rows file, never a command line
The free suite's generated-bash lint (INV-3) refused the add command's
<title>/<finding> placeholders: free text reaches a command only as a file the
agent writes with its file-write tool. start now also creates an empty rows
file in the repository's git-excluded .gstack/tmp and records the run; the
agent writes task and disposition rows there; add validates every row,
stamps phase, run, branch and commit, appends tasks to the list and
dispositions to task-dispositions-<phase>-<branch>.jsonl, then supersedes the
branch's earlier lists. close is gone (dispositions are rows).
The new planning-wave cases get measured periodic walls in
scripts/paid-test-durations.json so the periodic census still packs into 40
slices, the schema case declares the preamble sources its eng-template owners
need, and the paid file count is 114.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G2: fold start into add so each plan review emits one bash fence
The rows file lives at .gstack/tmp/tasks-<phase>-rows.jsonl; add writes this
run's list (empty when there are no rows), appends dispositions, deletes the
rows file and supersedes the branch's earlier lists. Lowers 27 size pins.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G2 tests: give gstack-tasks a private HOME and state root
CI shard 13 home containment caught gstack-slug writing ~/.gstack/slug-cache
entries from the tasks-prior fixtures.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: gstack-tasks has no start command
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G1/G2: tighten the probe and the rows file after ship review
The probe now accepts only each CLI's listed built-in subcommands (no uv run,
docker run, go test, npm exec or gh extensions), refuses gstack bins that do not
handle --help and never retries them with -h, and runs with a throwaway HOME and
an environment without keys. gstack-tasks resolves the slug through
runScriptSync (Windows) and prior deletes a rows file an unfinished run left.
Adds tests for the dropped disposition and the stale rows file.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G2: add refuses while an earlier task is neither carried nor closed
Ship review (state matrix): a rerun that skipped RECONCILE silently retired
open tasks. add now names each undecided <run_id>/<id> and writes nothing.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* G1/G2: fixes from the ship fix-check and Step 11 voices
Probe: find the repository root without running git, drop relative and
in-repository PATH entries for lookup and for the child, keep HOME and
toolchain locations (rustup, mise, asdf) but no keys, drop cargo fmt/clippy
(external cargo-* programs), restore planted env in the test.
gstack-tasks: resolve the exclude path against the cwd (subdirectories),
resolve --dir, stamp an empty branch on a detached HEAD like the aggregator,
name the file from --branch, and refuse a same-second second list instead of
appending. Receipts: line 0, reversed ranges, dangling links and paths
through files are unresolved instead of crashing.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: probe limits and the reconcile refusal
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: probe subcommand counts per CLI (ship 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>
* feat: a .gstack-project marker makes a nested repo or umbrella folder its own project (#2649, #1923)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: marker tests ignore an ambient GSTACK_STATE_ROOT
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (per-repo records ignore every marker, worktree binding in remote-slug and under a git HOME)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(slug): a linked worktree finds its main checkout's marker on its first run
The worktree binding was written only when the main checkout resolved, so a
worktree outside an umbrella resolved first kept its old bucket and later
switched. Walk up from the main checkout on a miss instead (under its own
$HOME rule) and drop the binding file.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs/test: pregate user policy names REPO_SLUG; pin greptile consent to REPO_SLUG
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(slug): no-clobber checkpoint recovery, unambiguous marker cache keys, ignore unusable folder names; remote-slug resolves once
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(slug): remote-slug reads a quoted marker path; repo mode stays per repository
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(slug): the review log and /ship spend-cap pointer stay with the repository under a marker; recovered checkpoints keep their repository; a linked worktree's own marker stands for its main checkout
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(captain): approvals live under the repository's own slug
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-queue: wave PRs — group 3-6 same-area READY PRs into one train slot (GST-574)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship-queue wave: review fixes — stamped wave re-READY, constituent double-land, drop dry-run, settle names hand-resolved merges, one settled row per PR, ready refuses an unreadable PR
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship-queue wave: release a wave (drop under --min, or --release), and accept stacked train stamps after the last constituent
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship-queue wave: Step 11 fixes — settle binds to a merge on the base, drop fetches pins first, close re-reads the head, drop and release wait for the wave PR to close, stacked constituents refused, conflict worktree derived from the nonce
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: wave PRs — drop/release wait for a closed wave PR, settle's base checks, more QUEUE_WAVE_* cases
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship-queue wave: DROP line and QUEUE_WAVE_MOVED text match the closed-PR rule
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: wave PRs fragment covers release, stacked-PR refusal and settle checks
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* captain: keep the skill generic and under its context budget (wave paragraph trimmed)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(wave): settle a wave PR the train merged directly onto a moved main
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(wave): settle accepts a wave PR the train merged directly
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>
* design: make images and read screenshots with Gemini when there is no OpenAI key (#990)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design: test the live Gemini check; set fixture env keys without secret-shaped assignments
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (setup keeps piped keys and names the provider export; Gemini iterate fallback tests)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design: setup doc comment matches --key-stdin behavior
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: Gemini saves the final image of a thinking answer; iterate uploads only absolute-path PNGs under 15 MB; sessions store absolute output paths
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: fragment holds the entry text only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* todos: Gemini design provider follow-ups
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the egress fail-open list names design Gemini calls
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: 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(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(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>
* 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>
* 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>
* 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>
* test(ship): failing-first Step 12 keep-current refusal and unattended early bump write (GST-380)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): Step 12 keeps VERSION on --keep-current, adds bump never, and waits for the owner's answer before an unattended bump (GST-380)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: regenerate ship SKILL goldens (GST-380)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (answer gate covers ALREADY_BUMPED --version writes; typed session rows; never drift and --answer rejection cases)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (the answer gate names every flag that decides the write; Version Gate and validate understand bump never)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: under bump never a release PR that moves VERSION takes the Version Gate's ordinary rules
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): fragment for GST-380 Step 12 keep-current and bump never
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(benchmark): particle-1 and DeepSeek V4.1 Flash awareness, gateway provider, preregistered model panel (GSTA-173)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(evals): particle-1 model panel results, run 2026-10-30-0105 (GSTA-173)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(model-panel): name the task field id (credential scanner false positive on key)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: gateway reports a missing OpenRouter key first; register the model panel in the paid count and test-of-test baseline
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: run the fake claude through bun so the gateway provider test passes on Windows
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: gateway benchmark runs load no Claude Code settings
A settings.json env block's ANTHROPIC_API_KEY was sent to the OpenRouter base URL as x-api-key; --setting-sources '' loads no settings source.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: name particle-1 and DeepSeek V4.1 Flash in the /benchmark-models row
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: changelog fragment and TODOS for the particle-1 model panel
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: name particle-1 and DeepSeek V4.1 Flash in the AGENTS.md /benchmark-models row
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(skill-evals): close four Lane A check-command holes (GST-377)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: register skill-eval-checks in the test-of-test baseline; docs: describe the tightened checks (GST-377)
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(review): variant G part 4: data files no code names are docs in classifyDiff, untested state-matrix cells map below the floor per cell (GSTA-167 PR-a)
Part 4a: lib/review-depth.ts owns DATA_PATH (JSON, JSONL, NDJSON, CSV, TSV, raster
images; YAML, TOML and SVG stay code) and applies the data rule only in classifyDiff,
to candidates lib/review-collect.ts finds no non-docs consumer for (git grep of
basenames at head, merge base and, live, the working tree; data-to-data chains four
deep; over 2,000 candidates keeps all code; a grep failure fails closed). classifyPath
and every path-only caller are unchanged; the receipt gate scan decides through
gateScanNeeded (path-only), so it cannot be skipped. gstack-ship-preflight computes
RUNTIME_LINES with classifyDiff over gstack-review-plan --json (now with consumed).
Part 4b: lib/review-scope.ts mapStateMatrixOutput maps an "untested cell" finding to
INFORMATIONAL when its cell has test null in the same output's matrix and it is the
only finding on that cell; gstack-state-matrix findings prints it for Step 9.2 before
the merge. state-machines.md is byte-identical; check still reads the raw output.
Reviewer-brief pins repinned under no-loss replay PR-a (Arm 4: plan identity at the 14
cohort heads; free exact re-score of saved C, D and A' findings).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(review): variant G parts 1 and 3: blocking floor in both prose voices, specialists at medium (GSTA-167)
Part 1: the native adversarial and outside-voice prompts end with the blocking
floor ("would fail a test, break production, or lose data or secrets") and ask
each finding for Severity and Blocks: yes|no. Additive rule: a finding is
CRITICAL when its label rule says so or it says Blocks: yes; Blocks: no never
lowers one (proseVoiceSeverity, BLOCKING_FLOOR in lib/review-scope.ts).
Part 3: ROLE_EFFORT puts specialists at medium; Red Team, native adversarial
and fix-check stay full; light's batched specialist (carries the Red Team
prompt) stays full; --no-tiers sends specialists to host.
Repinned reviewer briefs with no-loss replay G1 (live Arm G1, not yet run):
ship/sections/review-army.md, ship/sections/adversarial.md,
review/sections/adversarial.md, lib/review-depth.ts. Merge only on G1's pass.
Review-skill parity ratio 1.3136 -> 1.3180 and the gstack-review size pins
+537 for the approved +0.3k tokens per voice.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(review): variant G part 2: lean ensemble, one batched specialist at every depth (GSTA-167)
planReview dispatches one 'specialist batched' at standard and full depth (and
light, which adds the Red Team checklist): Testing and Security always on code
and gate class, plus State-machines, Data-migration, API-contract and Design
when scope asks; a forced checklist always joins. Maintainability, Performance
and Simplification are read only when forced (SKIP names them). LIGHT_FIXED is
[testing, security]; BATCH_SCOPED joins DEPTH_RULES so old receipts re-plan.
The Red Team rule and prompt are unchanged; it reads the batched reader's
merged findings. specialistsFor stays as the legacy selection the dispatch
compare script models.
Repinned reviewer briefs with no-loss replay L (live Arm L, scored L∘G1 vs G1;
not yet run): ship/sections/review-army.md, lib/review-depth.ts. Merge only on
L's pass.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(review): variant G on #3648's dispatch: Blocks: yes collects as CRITICAL, batched checklists by name (GSTA-167)
Integrates parts 1 and 2 with gstack-review-dispatch (#3648):
- lib/review-ledger.ts parseFindings: a prose voice's "Blocks: yes" makes its
own line, or the finding on the line just before it, CRITICAL in
merged.jsonl (normalizer v2, certified by round 5's G1), so judge refuses a
lead that keeps it below the floor; with no finding before it the Blocks
line is its own CRITICAL finding. "Blocks: no" never lowers a label.
- lib/review-brief.ts: the outside-voice brief no longer appends "Give each
finding a severity"; the section's prompt now asks for Severity and Blocks,
so the brief is the certified section prompt plus the branch diff.
- bin/gstack-review-dispatch render --checklists takes the plan's
checklists= names (review/specialists/<name>.md) as well as paths and
refuses an unknown one, since the batched reader is now every depth's
specialist dispatch.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore(changelog): GSTA-167 variant G reviewer stack fragment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): consumer scan survives grep.lineNumber/grep.column; collect reads separate-line Severity/Blocks
/ship pass 1 (PR #3660): the Red Team CRITICAL at lib/review-collect.ts:120 and the
informational findings in the same batch. proseVoiceSeverity had no caller and is
removed; the normalizer v2 table now runs through parseFindings, the path collect uses.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): collect keeps every prose blocker and one id per finding
/ship pass 2 (PR #3660): an unlabeled line carrying an inline Blocks: yes collects as
CRITICAL again; Severity/Blocks continuation needs a colon, stops at a list item, heading,
bold paragraph opener or a repeated field, and never swallows a top-level bullet or its
section label; the native voice's FIXABLE collects as CRITICAL under its role with or
without a dispatch name; the consumer scan adds --no-color.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): a later finding's fields never land on the one before it; explicit Severity wins its line
/ship pass 2 Red Team (PR #3660): prose after a finding's Severity/Blocks field, a
post-blank paragraph or a line in an indented block starts the next finding, and a
line's explicit Severity: label decides it over other label words on the line.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): FIXABLE outranks a Severity label on its line; a blocker keeps its own id and subject
/ship fix-check (PR #3660): labels are named before the strongest is taken, so a one-line
native FIXABLE ... Severity: Medium collects as CRITICAL; a later finding starts at a
file:line after the open finding's fields, field bullets stay on their finding, a field
line may omit the colon, and continuation prose never replaces a list item's subject.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): GSTA-167 fragment adds round 6 and the collect and consumer-scan 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>