Commit Graph
144 Commits
Author SHA1 Message Date
Garry Tanandcapy-ai[bot] cc6cc83573 Make the autoplan docs say what lean and full runs actually load (GST-1985) (#4186)
* Make the autoplan docs say what lean and full runs actually load (GST-1985)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep the autoplan description at its size pin and say when the eng checklist is sent

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>
2026-11-09 03:51:34 +00:00
Garry Tanandcapy-ai[bot] 914e7b6fb3 Write PR titles, commit messages and branch names in plain English (GST-1825) (#4146)
* Add a check that keeps tracker codes and internal jargon out of PR titles and branch names

gstack-plain-title checks the readable front of a title, branch name, PR opening or changelog entry against the repository's .gstack/plain-titles.json; one trailing issue code stays allowed. A Plain title workflow runs it on every new pull request, and /ship's push refuses a never-pushed branch whose name fails it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Move the PR body's machine-read lines into a closing Agent notes section

The ship receipt, its runs block and the Plan line now live in one collapsed section at the end of the body, and every reader looks there first while still accepting the old receipt-at-top layout. gstack-post refuses to post a title the plain-title check refuses, and land uses the checked PR title as main's commit title.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Teach /ship to write plain titles, PR openings, commit messages and changelog entries

The README now lists what gstack is for, so a PR opening can name the goal it serves.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep tests, size budgets and generated files in step with plain titles and Agent notes

Copy lists that install result-code modules now include the plain-title codes, the ship goldens and size ledger are refreshed, the new workflow is classified, and the pinned prose tests read the new title and body layout.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Record the test-profile list change as non-behavioral for the shared test harness

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep text people add below the PR notes, and fix three smaller review findings

The notes section now ends at its own closing tag, so a collapsible added after it survives the next post. The opening check splits the body the same way the notes reader does. Wave PR titles no longer name the area, which the plain-title check could refuse. The Capy line in the PR-body steps now puts Approvals in the notes.

Review-Finding: p1/specialist-batched#1 reader=testing
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/red-team#2 reader=red-team
Review-Finding: p1/red-team#3 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Mask credentials in refused-title lines and keep older PRs' plan lines readable

A refused title's printed match is masked by the secret scanner first. The Plan line reader falls back to the whole body when the Agent notes section has none, so a body written before this change keeps its plan when its first receipt lands. The notes section also ends at its own closing tag when its opener is split or marked open, or when a collapsible inside it is left unclosed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Print a fixed placeholder when a credential in a refused title cannot be masked

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep a plain-title policy edit from scheduling every paid eval

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Record the paid-eval list change as non-behavioral for the shared test harness

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Recheck the PR title on every edit so a base change cannot turn a refused title green

Review-Finding: s11/targeted#1 reader=targeted
Review-Finding: s11/adversarial-native#1 reader=adversarial-native
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>
2026-11-08 00:59:38 +00:00
Garry Tanandcapy-ai[bot] 7cb151bff7 Count an outside review as clean only when it ends with a VERDICT line (#4140)
* Add failing tests: outside reviews read clean only from a last-line verdict

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Count an outside review as clean only from its last VERDICT line

Every outside-review prompt now asks the reviewer to end with exactly
VERDICT: CLEAN or VERDICT: FINDINGS, and the parser reads a pass only from
that line. Prose no-findings sentences are no longer evidence for clean.
Codex's structured review and /codex review run through codex exec, since
codex review --base takes no prompt and could never give the line.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Repin the outside reviewer briefs and fix the tests the verdict line broke (GST-1821)

The outside brief, both adversarial sections and the review-army prompt-file line now carry the last-line VERDICT request; their pins move under the preregistered no-loss replay GST-1821. Test fakes that wrote a clean reply now end it with VERDICT: CLEAN, the review carve marker follows the codex exec sentence, size pins drop where skills shrank, and the plan-review prompt-file line is shortened so /plan-eng-review stays at its pin.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Give the plan-review invocation test's fake reviewer the verdict line it now needs

CI's free-suite shard 5 failed at 1de52b0 with 18 cases in test/model-role-invocation.test.ts: the fake Codex reply had no VERDICT line, so it read unverified (exit 4), and the review-mode template now has one codex exec dispatch block instead of two. The fake reply now ends with VERDICT: FINDINGS and the block count expects one.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Stop the changelog correction from claiming the verdict line closes every false-clean case

Review-Finding: p1/red-team#2 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Split the changelog correction's last sentence for readability

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Close the review fail-opens the fix-check found (GST-1821)

A /codex review whose git diff fails now stops before Codex runs instead of sending an empty diff. The verdict is read from the raw last line, so inline code after VERDICT: CLEAN no longer reads clean, and VERDICT: CLEAN beside numbered items with no severity reads unverified. Codex structured review gets the base-branch diff appended to its prompt, the way the Claude path does, so the scope no longer depends on the prompt the host writes.

Fix round granted by the Captain (a-aec3882c9d48). Review-section pins move under replay GST-1821: the free 681-input replay and the 54 scored probe replies are unchanged through the fixed parser.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Say in the changelog which numbered-list replies now read unverified, and that /codex review stops without its diff

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Say in the skills guide that /codex review now sends the diff through codex exec

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Check that the structured outside review appends the base-branch diff to its prompt

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>
2026-11-07 22:12:57 +00:00
Garry Tanandcapy-ai[bot] fd0e3390e9 autoplan: count template UI files and list-style terms; label lean phases that were not merged (GST-1750) (#4121)
* autoplan: count template UI files and list-style terms; label lean phases that were not merged (GST-1750)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: autoplan DRIVER names tagged template files as rendered UI (GST-1750)

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>
2026-11-07 08:39:20 +00:00
Garry Tanandcapy-ai[bot] 3742ee9527 feat: cut standalone /plan-eng-review; /autoplan keeps its eng phase (GST-1698) (#4108)
* feat: cut standalone /plan-eng-review; /autoplan keeps its eng phase (GST-1698)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: lower shrunk SKILL.md size pins; keep the retired methodology's pins measured beside /autoplan

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: carry /autoplan's plan-eng-review.md into Kiro installs

Kiro's per-skill loop copied only SKILL.md and sections, so ~/.kiro/skills/gstack-autoplan lacked the Phase 3 methodology file its SKILL.md reads. Generated sibling *.md files now travel with SKILL.md under the same ownership guards.

Review-Finding: p1/specialist-batched#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: file /plan-eng-review retirement follow-ups; scope the changelog claim to ./setup

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: route architecture-review requests to /autoplan by its description (journey-plan-eng)

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>
2026-11-07 04:17:35 +00:00
Garry Tanandcapy-ai[bot] e5366a52b7 fix(autoplan): export --public drops owner replies and redacts quoted owner words (GST-1243) (#3967)
* fix(autoplan): export --public drops owner replies and redacts quoted owner words, refusing what it can't redact (GST-1243)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): owner words in every deferral rendering, superseded replies, glued punctuation, short replies, echoed plan text (GST-1243 review)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): normalize markup, entities, escapes and format characters before matching owner words; each new run in an echoing reply is its own needle (GST-1243 review)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

Review-Finding: p1/outside-voice#1 reader=outside-voice
Review-Finding: p1/outside-voice#2 reader=outside-voice
Review-Finding: p1/outside-voice#3 reader=outside-voice
Review-Finding: p1/outside-voice#4 reader=outside-voice
Review-Finding: p1/outside-voice#5 reader=outside-voice
Review-Finding: p1/outside-voice#6 reader=outside-voice
Review-Finding: p1/adversarial-native#1 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

Review-Finding: p2/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: GST-1243 fragment names the 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>
2026-11-04 03:42:16 +00:00
Garry Tanandcapy-ai[bot] c07eddb5af feat(ship,autoplan): five routine stops record a no_stop and keep going (GSTA-258 L5, K1) (#3976)
* feat(ship,autoplan): five routine stops record a no_stop and keep going (GSTA-258 L5, K1)

gstack-no-stop record checks scoped-fix-check, test-timeout-fix,
pregate-flake-rerun and stamp-only-carry against lib/no-stop.ts and
appends {class, reason, evidence} to the branch ledger the receipt
write passes as --no-stop. A scoped fix-check records the standing
grant for gstack-review-plan --grant. gstack-autoplan carries a plan
edit after the owner answered when its changed words name no spend,
cap, arm or verdict, and writes <run>/no-stop.json. Anything that does
not qualify, and every other stop, still stops.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(no-stop): review pass 1: drift stays refused, timeout values only, range-base bound to the last pass, word-by-word re-gate, hunk-aware diff parse

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

Review pass 2 (below floor): import takes only autoplan-regate records with autoplan:<run>@gate_rev=N evidence; record diffs with --no-renames so a rename is a delete plus an add; a scoped-fix-check also checks the approval record for the branch's K1 grant, so a fresh checkout with an empty ledger still stops; a trailing }, N) counts as a timeout only where it closes a test callback; the re-gate words add paid, eval and model names; Step 19 sets NS on its own line so a path with spaces survives. Also launches gstack-review-read through runScriptSync (free-tests #3197 tripwire, run 41746166882).

Review-Finding: specialist-batched#1 reader=specialist-batched
Review-Finding: specialist-batched#3 reader=specialist-batched
Review-Finding: specialist-batched#4 reader=specialist-batched
Review-Finding: red-team#1 reader=red-team
Review-Finding: red-team#2 reader=red-team
Review-Finding: red-team#3 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: autoplan-regate carries only ELI5 additions; timeout and ref checks fail closed

Step 11 voices (round 2): the autoplan-regate word filter failed open on markup, spelled-out counts and reworded verdicts. A plan-file edit now carries only when it adds lines inside ## ELI5 that hold no number and no spend, cap, arm, model or verdict word; any removed or reworded line goes to the owner, and the carry still exports the reviewed plan. A trailing }, N) counts as a timeout only on a line that opens the test call. --range-base and --base resolve to commits with --end-of-options before git sees them.

Review-Finding: targeted#1 reader=targeted
Review-Finding: outside-voice#1 reader=outside-voice
Review-Finding: outside-voice#2 reader=outside-voice
Review-Finding: outside-voice#3 reader=outside-voice
Review-Finding: adversarial-native#1 reader=adversarial-native
Review-Finding: adversarial-native#6 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: test-timeout-fix counts a trailing timeout only on the line that opens the test call

Step 14.5 docs audit l5-docs-1.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): keep ship/DRIVER.md under its 12 KB cap after the main merge

Main brought the driver to exactly 12288 bytes, so the K1 'except gstack-no-stop' clause put it 20 bytes over (quick-bun-default run on ca43af4). Trim two phrases; the pinned fallback sentence is unchanged.

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>
2026-11-04 03:03:39 +00:00
Garry Tanandcapy-ai[bot] 1cf7835e62 v1.95.4.0 fix(autoplan): lean draft capture finds the committed draft on a PR-branch checkout (GST-1241) (#3969)
* fix(autoplan): lean draft capture resolves its base like gstack-diff-scope (GST-1241)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): the lean draft base default is gstack-diff-scope's base (GST-1241)

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>
2026-11-04 00:31:14 +00:00
Garry Tanandcapy-ai[bot] ade35bc813 v1.94.29.0 R56: everything in gstack earns its place (principle, evidence gates, inventory) (#3837)
* eval-plan: a no-gstack arm needs masking, install and audit lines

prereg --check now refuses a loaded comparison whose ## No-gstack arm
section lacks masking:, install: or audit:, or says none for one of them
(PREREG_NO_GSTACK_ARM). On Capy, run agents inherit the instruction to load
the user-drive gstack skill, so the arm hides both Capy drives, checks that
no gstack is installed, and audits drive reads; an arm that read a gstack
skill file is contaminated and gets zero credit (TESTING_INTERNALS.md
#no-gstack-arm). The prereg template, /eval-plan, troubleshooting and the
two passing prereg fixtures carry the new lines. eval-plan's paragraph was
dieted to hold its context-budget ceiling.

Evidence: safety: keeps the no-gstack control uncontaminated (Captain order, FOUN-32 via GGST-6)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: the R56 evidence ledger, gstack-inventory and skill-bill EVIDENCE

docs/inventory/evidence.json holds one row per inventory key: the skill
folders discoverTemplates() finds (root skill as gstack, symlinked folders
excluded) plus seven shared parts, 71 keys. lib/inventory.ts validates each
row by its status's own fields, with named codes (LEDGER_*), and joins the
ledger with lib/context-bill.ts buildBill. bin/gstack-inventory writes
docs/inventory.md, --check validates (exit 1 with codes), --json prints.
Paid dispatches per run for /ship and /autoplan are quoted from their own
docs and found by line, so a moved citation fails --check
(INVENTORY_SOURCE_MISSING). Every current row is grandfathered and seeded
from GEVA-2's table (org-gstack-gbrain/research/gstack-part-evidence.json):
in-flight fair tests and proposed registry rows as plans, earlier unfair
results under prior with why (stub, unmasked, ceiling, ...), five safety
rows. gstack-skill-bill prints the skill's EVIDENCE line.

Evidence: plan none (owner ruling R56, GST-914); the ledger itself is the measurement record
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ETHOS 9, Earn Its Place: factory, /write-skill and /autoplan carry it

Garry, 2026-11-02: "Also work this principle of only include it if it is
beneficial and good into gstack". ETHOS.md principle 9 states the rule, the
fair test (claude_code preset, frontier models per R54, masked no-gstack
arm), the R48 Why-null cycle, the safety exception, and measure biggest
first, linking docs/inventory.md. factory.md item 8 cites it, trimmed
elsewhere to 3,298 of 3,300 bytes with no rule dropped. /write-skill's edit
ladder step 2 is the evidence rule and section 4 adds the Evidence: commit
line. /autoplan's CEO phase lists each part a plan adds to gstack with its
evidence or owned, dated plan; two redundant lines went to keep autoplan
under its size pins (pins lowered by 17). CONTRIBUTING.md "Adding a new
skill" and docs/skills.md point at the ledger.

Skill-Size: 3273→3666 bytes (write-skill/SKILL.md.tmpl)
Skill-Size: 12738→12721 bytes (autoplan/sections/ceo-phase.md)
Evidence: plan none (owner ruling R56, GST-914); write-skill and autoplan rows stay grandfathered untested
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fixup! inventory: the R56 evidence ledger, gstack-inventory and skill-bill EVIDENCE

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: list the evidence table's other names and its unmapped rows

Ledger rows carry aliases (the name GEVA-2's table uses where it differs from the key, such as upgrade for gstack-upgrade), and docs/inventory.md lists them beside the installed-name rule. Unmapped rows are labeled as evidence-table rows, and the ranking notes that a skill's on-demand files can also be a shared row's.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the first inventory snapshot and the R56 changelog fragment

docs/inventory.md is generated by bin/gstack-inventory at the previous commit: 71 parts ranked by load per run, 0 helps, 0 no-effect, 0 hurts, 16 untested with a plan (4 fair tests under way, 12 proposed), 50 untested with plan none, 5 safety.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: investigate's step procedure is a fair-test CUT-CANDIDATE (GST-814)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the inventory snapshot after investigate's no-effect row

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: only the seeded backlog may be grandfathered, so a new part's row is checked (review fix)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: devex-review and retro name their GEVA-2 registry rows (R56-11, R56-12)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the inventory snapshot after the review fixes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: a concrete plan is a path, gstack-inventory never writes into a gstack install, and the ledger checks aliases, r48 and prior.why (review fixes)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* inventory: investigate's no-effect row notes that only Opus 5.5 was measured

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the inventory snapshot after the review fixes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: R56 counts after investigate's row; grandfathering and the install guard

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: register inventory-grandfathered.json as a free fixture

free-suite (1) at e56d3312c failed FREE_FIXTURES inventory: the pinned grandfather fixture from d0b3028b5 had no paid touchfile and no FREE_FIXTURES entry. Its only reader is test/inventory.test.ts.

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>
2026-11-03 17:08:30 +00:00
Garry Tanandcapy-ai[bot] 5192908de4 v1.93.36.0 autoplan: R65 defaults: no review for bug fixes, one lean reviewer with the draft code for features (#3897)
* autoplan: R65 lean defaults (--kind fix|feature, --full, draft-code binding E12)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan: R65 review fixes (draft capture errors, large drafts inlined, fence, secret-named files, run --kind, fix --json)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: autoplan lean secret fixture without a key header (CI credential scan)

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>
2026-11-03 02:08:50 +00:00
Garry Tanandcapy-ai[bot] 5209e9262d v1.93.6.0 feat: /plan-tune learns from ad-hoc question ids that carry a signal hint (#3442) (#3868)
* feat(plan-tune): signal hints let unregistered question ids move a dimension (#3442)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(plan-tune): document signal hints and hinted_events in the design reference (#3442)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: changelog and TODOS

gstack: ok 1.92.79.0 for=ship
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: record the boundaries.ts qid-hint widening as non-behavioral (HARNESS_VERSION 6)

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>
2026-11-02 16:20:02 +00:00
Garry Tanandcapy-ai[bot] 9d9d4c31bb v1.93.0.0 wave(browse): #3700 #3773 #3779 #3817 #3842 (#3858)
* feat(loadouts): Opus 5.5 lite loadout with explicit model detection (GSTA-161)

modules/loadouts.json gains the lite loadout (eleven coaching preamble
pieces dropped; upgrade-check and brain-sync kept) and a models map that
sends only claude-opus-5-5 (and its dated snapshots) to it. Detection is
explicit: Capy passes --model to the installer, Claude Code opts in with
./setup --loadout lite; anything unmapped, invalid or unreadable serves full.
The checkout always stays the full render.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(loadouts): Opus 5.5 lite, detection order, Capy SKILL_ROOT, setup --loadout; troubleshooting anchors; changelog fragment (GSTA-161)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(loadouts): claude_loadout read through CONFIG_BIN; capy skill context ceiling for the --model line (GSTA-161)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (prune keeps a reused loadout folder, GSTACK_LOADOUT_SKILL_ROOT, claude_loadout guard test) (GSTA-161)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (Capy skill passes the model as GSTACK_MODEL so an older installer ignores it) (GSTA-161)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (prune only owned, unused folders; full root from the canonical Claude install; fallback reason and source) (GSTA-161)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: loadout source example, install and resolve commands, Capy launch-file note (GSTA-161)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): --ceo-only runs the CEO review alone with zero questions (GST-537)

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>

* test: classify autoplan-ceo-only in the Codex host metadata

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: select autoplan-ceo-only on the skills it runs; say it needs Claude Code

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: run autoplan-ceo-only in the marathon lane

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: changelog entry for /autoplan --ceo-only

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: count the autoplan-ceo-only paid file in the shard inventory

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat: gstack-autoplan next --ceo-only runs the CEO review alone and ends reviewed (GST-537)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: budget and close recover a budget-stopped CEO-only run; reviewed is at rest for checkpoints

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: CEO-only finish leaves owner-only cap items undecided, refuses marker phase flags and a plan at the report path, and replaces ceo-review.md atomically

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: the CEO-only report-path guard compares real paths and refuses at the finish when the report file is the plan

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CEO_ONLY_CONFLICT covers a plan linked to the report path

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(browse): failing-first device and touch tests (GSTA-227 F3, #3058)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: the report-path guard keeps the lexical check, skips safe hard links and compares bigint file ids

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* browse: per-session tabs for parallel agents; tab pins stop moving the shared active tab (#1961)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* browse: keep the server.ts tab-pin anchor comment for source guards

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(browse): per-tab phone emulation and touch input ($B device, tap, swipe, pinch, touch; #3058, GSTA-227 F3)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: copy lib/result-codes-autoplan.ts into the fixtures that copy the result-code tables, and keep it out of derived closures

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(qa, aside): touch pointer in /qa, Aside touch recipe verified on Aside 1.26, report Phones row (GSTA-227 F3, #3058)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* browse: drop the sessions paragraph from /browse to stay inside the parity cap

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: F3 phone emulation and touch entry

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* browse: hide the ps window in the session harness walk

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the decisions.jsonl status list names auto_kept

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(browse): session cap, LRU eviction, headed release and scoped auto-session rows

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* browse: sessions keep tab <id> picks, sidebar claude stays on the user's tab, pinned rebuild and state load rebind the scope

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (touch cancel with no finger held is a no-op)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: Step 11 review fixes (headed tab adoption, pinned viewport reset, CLI retry keeps --session, rebuild id remap, --json notice, evicted-session reset, device kept after annotated captures, render opts out of sessions, session: client ids reserved)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: headed viewport auto keeps the user's active tab; render's closetab opts out of sessions

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: sessions, phone emulation and touch in BROWSER.md; session: client ids reserved; TODOS #1961/#3058 shipped

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: copy lib/result-codes-browse.ts into the fixtures that copy the result-code modules

lib/result-codes.ts imports ./result-codes-browse, so fixtures with an explicit
lib list failed with 'Cannot find module'. pr-dependencies lists it with the other
reason-code modules as selection data. GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat: gstack-clean reclaims per-repo .gstack scratch and logs, dry run by default (#2627)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* browse: name the Aside touch recipe's coordinates <tap-x>/<tap-y> with a numeric grammar

The generated-bash lint (INV-3) rejected the free-text <x>/<y> placeholders. GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(clean): leave hard-linked and unreadable logs alone; cut through a no-follow descriptor checked against the evaluated inode

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(clean): tests that expect tmp removal see a quiet ps, so a codex elsewhere on the host cannot flake them

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(clean): an unlistable tmp/ skips its group; liveness asked once per group on apply; BROWSER.md says which logs reset at daemon start

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(clean): write output synchronously so --json reaches a pipe whole; test fixes for root, wrapper git and the ps stub

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(clean): every change rechecks the verified folder and the measured file; full writes; EPIPE ends output quietly

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(clean): the early-close test checks the bin's own exit status

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: list gstack-clean among the standalone CLIs

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(clean): copied-install fixtures and the dependency list carry lib/result-codes-clean.ts

The remote pregate failed 11 cases in gstack-doctor, plan-tune-cathedral and
timeline-stop-hook-slug: each copies an explicit list of lib/result-codes-*.ts
files into a temp install, and lib/result-codes.ts now imports
./result-codes-clean. Same lists GSTA-168 extended for result-codes-eval.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: regenerate gstack-doctor-components.sh for the gstack-clean result codes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* qa: fold the touch pointer into the Phases sentence to fit the parity size cap after the main merge

qa's union was 95988 bytes (ratio 1.142 > maxSizeRatio 1.142, train 75). Now 95975 (1.1419). GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.10.0 after the main merge

GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(clean): classify gstack-tasks rows files (tasks-*) as kept, after main added the producer

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.20.0 after the main merge

GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (restore the lib/result-codes-plan.ts ratchet row the base merge dropped)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(clean): the producer scan ends a name at a colon, so prose after a path names the file (train 78)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.30.0 after the main merge

GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* outside-voice-api: caller receipts, stop_reason, OpenAI max_completion_tokens

A caller can write its own egress receipt (sink, consent, payload class);
the default stays the outside-voice receipt, so existing callers send and
record the same bytes. The result carries the provider's stop reason, and
an OpenAI request gets max_completion_tokens only when the caller sets an
output limit (GST-537 PR 3).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan gate: item classes and the owner's answer provenance

Gate items carry item_class, ruleKept() names the keep-direction pick, and
answered decision rows record owner_mode, owner_named, rec_hash and
answered_role parsed from the owner's own words (GST-537 PR 3).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan: shadow-mode decider module, frozen prompt and spend accounting

The switch (off by default, fixed at init), the lease, one model call per
gate with a page retry and a truncation retry under one deadline, the
once-per-revision record with its journaled sha256, the 10% audit mark,
and shadow-labeled ledger rows that count against the cap, show as
shadow= on GATE_SPEND and stay out of the per-voice price (GST-537 PR 3).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* gstack-autoplan: shadow every published gate, the shadow export, config and docs

Every driver command that prints a gate records the shadow first and
checkpoints after it; answer waits for a live lease and records a dead
one retrospectively; gstack-autoplan shadow exports answered revisions
for taste-replay R2 (SHADOW_BEFORE_ANSWER otherwise); gstack-config
autoplan_shadow / autoplan_shadow_model; gstack-artifact validate checks
the record's hash (GST-537 PR 3).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: shadow mode for the CEO-only decider (GST-537 PR 3)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan shadow: /ship review fixes

- register test/fixtures/shadow-fake-model.ts in FREE_FIXTURES (free-fixtures inventory failed)
- withRunLock: count dead-owner reclaims apart from waitMs iterations, so a long wait can still reclaim
- buildPage: fill the decider template in one pass, so slot names inside the plan stay plan text
- revise regate: the shared publish step prints the GATE and ESCALATE lines once

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan shadow: reply files never follow a link; the retry reserves against the current cap

- a model reply is written by temp file and rename, so a link at the reply path is replaced, not written through
- each shadow reservation reads the run's current spend cap, so a budget change during the call is not undone

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* outside-voice-api: write the egress receipt under the caller's env

callModel resolved the receipt's state root from process.env even when the caller passed env, so the shadow
tests wrote to the real ~/.gstack (the free-suite home-containment guard caught it). The receipt now uses
req.env; the shadow tests give the fake model a private HOME, GSTACK_HOME and GSTACK_STATE_ROOT, and the receipt
test no longer sets process.env to pass.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): CEO-only runs leave main's open Critical/High finding items to the owner (no decision row)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): shadow pages carry main's finding items; a finding item is never ceo_eligible

After merging #3767 (main 90a170c), open Critical/High findings are gate items
(item_class finding). The shadow records one row per gate item, so its pages now
include them. A CEO-only run leaves those items to the owner, so their rows are
ceo_eligible false (rule_pick was already null). The shadow fixtures follow
main's gate (items, counts, "Do it" tokens); the two merge adapters follow
main's doNext(out, rest, price) and its per-voice reservation (--estimate-usd).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.61.0 after the main merge

GSTA-227

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(investigate): drop the five-phase step procedure (GST-938)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: GST-938 fragment wording

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(investigate): keep the web-search sanitize guard; update BROWSER.md and docs/skills.md (review pass 1)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: GST-938 wording

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(investigate): pin the web-search guard; changelog size (adversarial review)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(clean): classify restamp-staging.json, the restamp producer main gained after #3779's base (wave browse)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (wave browse): scoped newtab keeps a concurrent tab switch; shadow validate catches a deleted record; a failed shadow publish is journaled

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: a failed shadow publish journals under the run lock and never throws (wave browse review pass 2)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(unattended): shadow publish failures and the missing-record validate check (wave browse docs audit)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: wave browse integrator fixes fragment

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: shadow reader dedupes by run folder, so two runs started in the same second both count (wave browse CI free-suite 16)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: regenerate doctor result anchors in generator order (wave browse rebuild without #3818)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: name the wave fragment after the rebuilt wave

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>
2026-11-02 14:49:46 +00:00
Garry Tanandcapy-ai[bot] 924ac4d406 v1.92.58.0 feat: gstack-autoplan next --ceo-only runs the CEO review alone (GST-537 PR 2) (#3767)
* feat(autoplan): --ceo-only runs the CEO review alone with zero questions (GST-537)

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>

* test: classify autoplan-ceo-only in the Codex host metadata

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: select autoplan-ceo-only on the skills it runs; say it needs Claude Code

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: run autoplan-ceo-only in the marathon lane

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: changelog entry for /autoplan --ceo-only

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: count the autoplan-ceo-only paid file in the shard inventory

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat: gstack-autoplan next --ceo-only runs the CEO review alone and ends reviewed (GST-537)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: budget and close recover a budget-stopped CEO-only run; reviewed is at rest for checkpoints

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: CEO-only finish leaves owner-only cap items undecided, refuses marker phase flags and a plan at the report path, and replaces ceo-review.md atomically

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: the CEO-only report-path guard compares real paths and refuses at the finish when the report file is the plan

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CEO_ONLY_CONFLICT covers a plan linked to the report path

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: the report-path guard keeps the lexical check, skips safe hard links and compares bigint file ids

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: copy lib/result-codes-autoplan.ts into the fixtures that copy the result-code tables, and keep it out of derived closures

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the decisions.jsonl status list names auto_kept

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (restore the lib/result-codes-plan.ts ratchet row the base merge dropped)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): CEO-only runs leave main's open Critical/High finding items to the owner (no decision 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>
2026-11-02 05:13:19 +00:00
Garry Tanandcapy-ai[bot] 90a170c941 v1.92.50.0 wave(autoplan): #3781 #3743 #3751 #3762 (#3788)
* fix(eval-plan): per-arm pilot projection and --seat-metered arms (#3653)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): guard tolerates Claude Code's cwd-reset footer and recovers after an unreadable init (#3651)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (journal reader strips the cwd-reset footer; an init with no text block no longer locks the session)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: journal reader skips a failed or unreadable init, as invocation() does

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): --ceo-only runs the CEO review alone with zero questions (GST-537)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(eval-plan): all-seat pilot, single-attempt arm and --seat-metered CLI wiring

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(eval-plan): summed deviation adds arm deviations, matching the summed band (arms share rows)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (test pins an unpriced seat-metered arm)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (seat-metered declaration fixed per --out, price row still required, a real charge settles as spent)

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>

* test: classify autoplan-ceo-only in the Codex host metadata

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: a seat-metered arm that settles a charge is projected as a priced arm

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: select autoplan-ceo-only on the skills it runs; say it needs Claude Code

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(skills): /eval-plan --seat-metered and per-arm projection

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(eval-plan): skill prose stays under its context budget and carries no $N token

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: run autoplan-ceo-only in the marathon lane

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(skills): a seat-metered arm leaves the seat set once it settles a charge

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: changelog entry for /autoplan --ceo-only

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): init_failed covers unreadable init output and the cwd-reset line (#3651)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: count the autoplan-ceo-only paid file in the shard inventory

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(autoplan): #3651 tests pass the test-code type ratchet

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(dx): CAP finding titles carry a one-line description (GBRA-223 claim 2)

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>

* fix(autoplan): reconcile pairs same-file findings that carry no line (GBRA-223 claim 1)

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>

* fix(autoplan): open Critical and High findings reach the gate as apply items (GBRA-223 claim 3)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): a spend cap binds on every unattended host; --estimate-usd persists; DRIVER names --usage-usd (GBRA-223 claim 4)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): run binds complete api results, names a truncated response, --max-tokens; DRIVER documents run (GBRA-223 claim 6)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): carry an item-by-item answer when the later gate asks nothing new (GBRA-223 claim 7)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(dx): trim the compact error contract so plan-devex-review stays under its size pin

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (p1b applies finding fixes, api attempts reserve no host default, cross-file title pairing, paired severity counted)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: review fixes (priced api reservations, no file-only twins, two-pass pairing, partial replies keep p1-dependent defaults open, outside refusal degrades)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* P7: record whose words answered a gate (--words-by agent:<id>), never carry an agent's own words, import each row under its own answerer (GEVA-2)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: review pass 2 (p1b needs --rec-hash after recommend; api calls send the output limit they reserve for)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: fragment for the /autoplan field-report wave (GST-672)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: captain record notes --words-by agent attribution

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: follow finding apply items in approval-class and Captain flow tests; bind run-api limit to DEFAULT_MAX_TOKENS

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* wave autoplan: lower the gemini plan-devex-review pin to its exact size after #3781's DX trim

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): CAP titles on different paths never match by title in reconcile or confirm rounds (wave review)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): a truncated api call settles its cost and a retry is admitted afresh against the cap

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): an applied finding stays open until the revised plan is reviewed; a shared location alone never twins two findings

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(approval): a plan gate answered in an agent's own words is not owner approval

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(gate): a new answer replaces the earlier answer's authorship and words

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): a failed api call with no usage keeps its attempt open; reservations price the bound prompt (wave fix-check)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): a spend cap fails closed: only a call refused before sending keeps its attempt; a sent call with unknown usage settles at its reservation

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): the 16384 output default applies to both providers; changelog for the wave's integrator fixes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): how run settles a failed api call; changelog scopes it to the native voice

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): a spend cap fails closed on every exit of run; an unpriced model reserves the default once a cap is set

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): every sent call settles; an unpriced model under a cap reserves the default

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): DRIVER and help say a cap reserves in any session kind and how run settles a sent call

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>
2026-11-02 01:35:47 +00:00
Garry Tanandcapy-ai[bot] ed107918db v1.92.6.0 feat: proactive core routes only the four core skills, and they carry their trigger phrases (#3770)
* proactive core: the CLAUDE.md offer and descriptions follow core; core skills carry their trigger phrases (#3446, #2118)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (core routing line keeps in-skill handoffs)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: keep document-release's pre-merge cue and the ship catalog-mode pin after the description edits

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* changelog: plain sentence break in the fragment

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>
2026-11-01 01:25:15 +00:00
Garry Tanandcapy-ai[bot] 0cab97447c v1.91.314.0 feat(autoplan): carry the owner's answer forward, gate ELI5 field, stacked approvals import (#3583)
* refactor: share the decision-trail append rules (lib/decision-trail.ts)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): carry the owner's answer to a later gate that asks nothing new, gate.json eli5, stacked approvals import

A later gate revision with nothing new is answered with the owner's recorded words
(CARRIED); a 'do it' also covers new auto items that change no scope, cost or
direction; an unreviewed post-cap delta gets one cross-family reviewer first
(CARRY_CHECK, gstack-autoplan check). gate.json gains eli5 and the Captain brief
requires ## ELI5 on runs that carry it. gstack-approvals import --stack writes
every branch or none. The first next prints REVIEW_ESTIMATE.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: carry-forward, ELI5 section and stacked approvals import

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): carry only fully owner-answered gates; void stale delta checks

- a pending delta check is voided (reservation released) when the owner answers,
  the plan is revised, or a new gate is written; a check bound to an older delta is void
- carry refuses a gate with any approval item still pending or answered in item tokens
- "do it" never covers an option that changes the plan; isDoIt ignores Captain-relayed prefixes
- captain brief rebuilds ELI5 from the current plan and lists items taken under "do it"
- gstack-approvals import --stack locates every branch before writing any
- DRIVER.md back under its 162-line budget

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: carry-forward conditions, delta-check voiding and import --stack match the final code

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: changelog for autoplan carry-forward (unreleased; stamped at merge)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: stamp v1.91.314.0

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>
2026-10-29 09:58:34 +00:00
Garry Tanandcapy-ai[bot] 148d28ea81 feat(ship): /ship and /autoplan size their review to the diff (GSTA-131) (#3527)
* wip(GSTA-131): review depth, fix-check transitions, dispatch counters, carry pregate, autoplan round policy

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* wip(GSTA-131): reviewers stay at full effort; audits light

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(ship): Step 9 dispatches what gstack-review-plan plans; fix-check after below-floor fixes; cap two full passes plus one fix-check

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: review-dispatch-compare has a free lane; review-depth fixtures registered free; resumed max_rounds case off the old default

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(GSTA-131): ship review pass-1 repairs: fix-check binds under its own skill, Step 11.5 accepts a fix-check or a planned adversarial skip, delta carry with a pregate, carry --pregate pinned to the checkout, quiet-after-cap revise regates, skill-dir markdown and rule docs classed code, gate signals from tests class up, plan fails closed on git errors, per-class compare ratios

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(GSTA-131): ship review pass-2 repairs: Step 11 follows the last full-pass plan, Important Rules restored, ship goldens regenerated, true per-class medians, review-policy transitions and once-per-invocation voices, docs/** assets stay docs-class, CLI and fix-check binding tests

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): GSTA-131 review depth, fix-check, delta /ship and autoplan rounds

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: ship-policy cap and counters, review-policy /review cycle cap, unattended passes (docs audit)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(review): 400-word findings cap fits the /review size pins (five host pins lowered by 2); CHANGELOG max_rounds wording

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): gate integrity names the size-ledger entry and the lowered /review pins

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: the round-budget case asserts the default through ROUNDS output only (pregate literals heuristic)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: curate ship-receipt-carry-pregate out of the Windows lane like its --pregate siblings

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): end the Windows curation sentence instead of a mid-sentence colon

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): one decision each for the review-loop exits, the planned adversarial skip and Step 16's TODOS rerun (screen judge repair)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): fix-check repairs: pin the renamed Step 11 heading, keep the below-floor exit at the cap, name the plan run a repeat reuses, print the native skip on outside-only plans

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>
2026-10-28 05:45:54 +00:00
Garry Tanandcapy-ai[bot] 10b77de4f2 v1.91.284.0 feat(absorb-tstack): /modernize skill, per-skill Codex default prompts, gstack-post --attribute, the unattended grant and a CONTRIBUTING porting section (#3497)
* feat(absorb-tstack): /modernize skill, per-skill Codex default prompts, gstack-post --attribute, the unattended grant and a CONTRIBUTING porting section

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(modernize): read the PR text through gstack-issue-guard; re-measure the context ceiling

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

- gstack-post: with --attribute, report scan findings at the body file's own
  line numbers and a finding inside the callout as PART: attribute (the
  coordinates were shifted by the three callout lines)
- /modernize: route commit messages through gstack-issue-guard with the rest
  of the PR text, read isCrossRepository and maintainerCanModify, fetch a fork
  head from pull/N/head, refuse a PR whose head is the base branch, and list
  moved files NUL-safely
- docs/unattended.md: say that /ship never rebases or force-pushes and an
  unattended /modernize stops at its verdict
- CHANGELOG: seven skills carry a codex_default_prompt, not six

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: /modernize fetches a fork head with a forced refspec and stops when the PR moved

A rerun after the author force-pushed left refs/modernize/pr-N stale (the
non-forced refspec is rejected with exit 0 through the pipe), and the lease
pinned to the current remote head would then have let the rebased stale head
overwrite the author's newer commits. The fetch is forced, Steps 2 and 4 stop
when the head is not the one observed in Step 1, and the head-is-base guard
applies only to same-repository PRs (a fork's main into main is a valid head).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: /modernize stops on merge commits in the PR range and pushes a fork head to the fork

A plain git rebase drops merge commits and git range-diff compares only the
non-merge patches, so a change authored in a PR's merge commit disappeared
while the proof printed = for every patch and Step 5 force-pushed the loss.
Step 4 now counts merges in $MERGE_BASE..$OLD_HEAD and stops when there are
any, switches with -C so a rerun after a refused lease does not fail on the
existing branch, and asks for a cross-repository diff to be read as untrusted
input before the repository's test command runs it. Step 5 pushes a fork head
to the fork's URL with the same pinned lease instead of to origin, where the
lease could never match.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: cover the Codex default-prompt render, the openai.yaml ownership proof and the unattended grant

Adds the /ship coverage audit's tests: test/host-renders-openai-yaml-proof.test.ts
drives bin/gstack-host-renders.sh's weakened proof against a rendered yaml, a
hand-written one and a generic-prompt one; test/unattended-grant.test.ts pins the
docs/unattended.md grant section and the handoff pointer; test/gen-skill-docs.test.ts
adds modernize to the skills whose codex_default_prompt must reach openai.yaml.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: name the static lists a new skill still needs and the Codex metadata file

From the ship documentation audit: CONTRIBUTING's new-skill checklist said no
static list needs a row, which this PR disproved (lib/doctor-components.ts
SKILL_REQUIREMENTS and the catalog rows); the host comparison table and
docs/ADDING_A_HOST.md gain the agents/openai.yaml default_prompt source; a blank
line before the new docs/unattended.md grant heading.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

CHANGELOG [Unreleased] gate-integrity record: the catalog and context-budget
figures re-measured on top of main (1,314 -> 1,359; modernize 9466;
alwaysOnTotal 7458 -> 7880), as the merge commit's ratchets state.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: name the optional codex_default_prompt key in the new-skill checklist

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(parity): re-pin the ship union cap at 1.7405 after the main merge

GSTA-36 grant 2026-10-27. On the tree merged with f27a7605 the ship union is 326,691 / 187,706 = 1.7404 against #3487's 1.7400; the only ship bytes this PR adds are the handoff section's one-line pointer. Cap 1.7400 -> 1.7405, measurement appended to the comment.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): the [Unreleased] gate-integrity bullet names the ship cap re-pin

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

CHANGELOG [Unreleased]: end the Codex default-prompts sentence at
"generator input only." so bin/gstack-prose-lint --unreleased --gate
(main's new quality-gate step) passes, and restate the gate-integrity
bullet's figures for the tree merged with 1f246e35: ship cap
1.7524 -> 1.7528 (329,005 / 187,706), modernize 9466 -> 3772 after the
preamble hoist, alwaysOnTotal 7769 -> 7880, catalog 1,359 unchanged.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

CHANGELOG [Unreleased] gate-integrity bullet names the current ship cap pin
(1.7525 -> 1.7529, measured 329,024 / 187,706 on the 392f50d4 merge) and keeps
the 1.7528 pin in the earlier-merges clause.

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>
2026-10-27 22:23:20 +00:00
Garry Tanandcapy-ai[bot] 3e4240a76f v1.91.276.0 feat(preamble): tier 2+ skills load the shared preamble once per session (GSTA-96) (#3434)
* fix(preamble): completeness means complete coverage with minimal code (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(preamble): tier 2+ skills load the shared preamble once per session (GSTA-96)

Every tier 2+ SKILL.md inlined the same ~23 KB preamble. It now renders once
per host into sections/preamble.md beside each tier 2+ SKILL.md; the SKILL.md
keeps a pointer that asks for the Read only when the file's id is not already
in context. Only sections byte-identical to the shared render move, so every
skill keeps exactly its pre-hoist paragraphs (verified across all 41 skills).

Parity caps for ten skills raised to their measured unions (owner-approved,
Garry 2026-10-25: "do it"); 63 size pins lowered and 26 deleted.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(paid-select): a generated sections/preamble.md takes its skill template's identity in the PR planner (GSTA-96)

screen-summary failed on #3434 with 'PR profile requires full validation' for nine
skills whose only paid coverage is periodic: their new sections/preamble.md had no
dependency identity, while the SKILL.md beside it inherits its template's.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(section-manifest): the shared sections/preamble.md renders from the hoist resolver, not a section template (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (CHANGELOG says 3 characters shorter; model-overlays guards the coverage half)

The completeness section shrank by 3 characters (5 bytes), matching the 89 pins lowered by 3. The default-copy test pinned only the minimal-code half; an expectMentions check now fails if the full-coverage or never-excuses-a-gap clause is dropped.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (model-overlays binds smaller diff to equal coverage)

The default-copy check now also fails if 'on equal coverage' is dropped from the smaller-diff rule (which would tell models to prefer the smaller diff unconditionally) or if the no-impossible-state-checks clause is removed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG lists the model-overlays coverage checks

The [Unreleased] Tests bullet now says the default-copy test checks both halves of the rule (full coverage of the requirement; smaller diff only at equal coverage; no impossible-state checks; never excuses a gap), matching 88e3cc0 and 44eacaf.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: plan-ceo-review and ETHOS say completeness means coverage, not more code

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (CEO bullet bounds code by accepted scope; tests bind each completeness rule)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: cover the shared-preamble hoist (ship Step 7)

Adds test/preamble-hoist.test.ts (tier 1 unchanged; tier 2+ SKILL.md plus
sections/preamble.md reproduces the pre-hoist preamble; pointer position and id)
and two gen-skill-docs-checks cases (one shared preamble per host, beside every
pointer and named by its id; preamble artifact kind).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (ship Step 9.4)

- setup: follow a symlinked sections/ dir in the carved-pointer status check
- touchfiles: select preamble-hoist.ts alongside every preamble.ts entry
- section-manifest: exempt sections/preamble.md only for skills whose SKILL.md
  carries the shared-preamble pointer
- skill-size-budget: growth ceiling measures SKILL.md plus its shared preamble
- host-conformance: tolerate a missing sections/ dir, as setup does
- skill-validation: read bin/gstack-skill-start directly
- skill-fixture: error messages and docblocks name the actual boundary
  (harness-version non-behavioral note updated)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: describe the size-budget growth check's startup measure (ship Step 9.4, pass 2)

The growth ceiling now measures SKILL.md plus the shared preamble, the same
measure as the shrink floor; the docblock said SKILL.md only.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG says simplification.md quotes the old rule and CLAUDE.md restates the new one

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG lists the hoist tests and the growth-ceiling measure (ship Step 9.4)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: cover the symlinked sections/ status check and the ETHOS house-rule quote (ship Step 7)

host-conformance: --status still finds a broken bare sections/ pointer when a
carved Claude skill's installed sections/ is a directory symlink (fails at the
pre-repair 0e5d11fd9). gen-skill-docs: the house rule review/specialists/
simplification.md quotes from ETHOS.md still appears in ETHOS.md.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: describe the shared preamble file (ship Step 14.5 docs audit)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: the shared-preamble skip needs the skill's own Read; digest and first-run intro say complete coverage, minimal code (GSTA-96)

The pointer skipped the shared file when any text carrying its id was in context, so a
page or file with that heading could stand in for the anti-spoofing rules (security,
red team and adversarial review, ship run 2). It now requires the skill's own earlier
Read. The digest's Boil the Ocean bullet and the first-run intro still said 'AI makes
completeness cheap, so do the complete thing' (docs audit blocker); both now carry
Garry's 'complete coverage, minimal code' (2026-10-25: '1/ yes fix this').

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: pin the shared-preamble provenance skip and the new Boil the Ocean wording (ship Step 7)

preamble-hoist: on every host, tier and render option the pointer allows the
skip only when the skill's own Read is in context. agents-digest and
gstack-skill-start: the digest bullet and the lake intro say complete
coverage, minimal code, never the retired phrasing. Each fails at 9af36d010.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: describe the provenance skip where the docs still described the id-only one (ship Step 9.4)

The preamble-hoist.ts docblock and ARCHITECTURE.md still said the shared
preamble is re-read only when its id is absent; since 2acf1a44a the pointer
requires the skill's own earlier Read of the file.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG lists the provenance-pointer and Boil the Ocean wording tests (ship Step 13)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* revert(digest): keep the agents digest at main's bytes; an unstamped head cannot change a release output (GSTA-96)

CI 'Check VERSION is not stale vs queue' classified #3434 as stamped because it touched
agents-digest/gstack-AGENTS.md (a release_outputs path), while regenerating only the
generator fails the digest freshness test. The first-run intro rewording stays.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: voice judge reads the hoisted preamble; register ETHOS.md on its reader cases

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: refresh the claude ship golden the main merge took from main (ship Step 5 preflight)

The 1a4dcaf07 merge resolved test/fixtures/golden/claude-ship-SKILL.md to
main's pre-hoist bytes. The golden is a copy of ship/SKILL.md; regenerated
with bun scripts/gen-ship-goldens.ts (pregate regen: REGEN_STALE).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: pr-dependencies' unplaceable-file example uses SECURITY.md now that ETHOS.md is mapped

6183ca8ae registered ETHOS.md on its reader cases in touchfiles-data.ts, so a
PR touching only ETHOS.md plans in pr mode and no longer restores the full gate.
The fail-closed test and the real-unknown label check now use SECURITY.md, which
is tracked and unmapped; the assertions are unchanged. CHANGELOG names the
third test file. (CI free shard 7 at 7c21720ac; remote pregate shard 6.)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: host path-leak checks read the moved shared preamble too; name SHARED_PREAMBLE_FILE (ship review pass 2)

The external-host path-leak assertions in gen-skill-docs.test.ts (Codex,
Factory) and host-config.test.ts (Copilot, Antigravity) read SKILL.md
alone, so a Claude path that moved into sections/preamble.md with the
hoist went unchecked. They now read the skill's startup text through
readSkillStartup. workflow-judge-input and host-conformance use the
SHARED_PREAMBLE_FILE constant instead of a bare 'preamble.md' literal,
and preamble.ts's header describes the hoisted composition.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG token savings name the per-skill skip and the autoplan follow-up (ship review pass 2)

The pointer's skip is bound to the skill's own copy of sections/preamble.md,
so "every later one saves about 5,800" holds per skill, not per session, and
/autoplan's skip list and the inline /office-hours loader do not yet skip the
pointer section. The entry now says so instead of claiming the full /autoplan
saving. Adding the skip entry grows size-pinned skills, so it is a follow-up.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: corpus budget measures startup bytes; carve-safety counts shared preamble as uncarved (ship review pass 2)

skill-size-budget's growth ceiling and shrink floor already measured
SKILL.md plus sections/preamble.md, but the total-corpus check still summed
hoisted SKILL.md bytes against the pre-hoist baseline, hiding about 0.9 MB
of headroom. It now sums the same startup bytes (3,114,885 -> 2,590,484,
x0.832); the unreachable SKILL.md-missing fallback is gone.

auq-format-always-loaded's carve-safety guard treated any sections/ dir as
carved, so every skill with only the shared preamble ran it and its sanity
check passed on preamble.md. It now uses setup --status's rule: a section
other than the shared preamble. Those skills keep the per-skill checks.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: remaining SKILL.md-only negatives read the shared preamble too (ship review pass 3)

The parameterized external-host path-leak smoke test, the two Codex
.claude path checks and both vestigial-handshake negatives read SKILL.md
alone, so text that moved into sections/preamble.md went unchecked. They
now read readSkillStartup. preamble.ts's header no longer says tier 1
renders through generatePreamble().

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: ratchet skeleton caps and eager context ceilings down after the hoist (ship review pass 3)

The hoist moved about 22 KB out of every tier 2+ SKILL.md, which left
each hoisted maxSkeletonBytes cap and each eagerPerInvocation ceiling
roughly 22 KB / 5-6K tokens slack. The 20 hoisted skeleton caps now sit at
the post-hoist skeleton plus their pre-hoist headroom, and 42 context-budget
ceilings take the recaptured (lower) values. Nothing was raised: the four
ceilings the recapture would have raised keep their old values.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: preamble-hoist's section splitter closes a fence only on a bare delimiter (ship Step 11)

Inside an open fence, a line such as "```bash" is content in CommonMark,
but splitSections treated it as the closing fence, so a later "## " line in
the same block could split a section mid-code-block and hoist half of it.
A closing delimiter now needs nothing but whitespace after it. Every host's
render is unchanged (gen-skill-docs --dry-run FRESH on all twelve hosts).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: skill-startup.ts is a global, pinned harness file like skill-fixture.ts (ship review pass 3)

skill-fixture.ts is a global touchfile pinned in scripts/harness-version.json
because it reshapes the skill content most E2E suites read, and it now
builds that content through test/helpers/skill-startup.ts. That helper was
in neither list, so a later edit to it would change fixture inputs without
the harness-version guard and select only 27 keys. It is now global and
pinned, recorded non-behavioral (its fixtures are byte-identical to the
pre-hoist output). ARCHITECTURE.md and the CHANGELOG stop calling the
pointer id a content id: it hashes the shared text before host rewrites.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG matches the merged skip lists and the baseline diff (ship review, run 4)

The headline still called the autoplan and inline /office-hours skip
entries a follow-up, but the main merge added them; it now says the loaded
skills skip their shared Read. The #3451 sentence is dropped, because that
fix shipped in v1.91.237.0 and is recorded there. The typecheck baseline
line says the TS2769 entry was re-keyed for the 'preamble' artifact kind
with its count unchanged, not fixed and lowered.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: pin the pointer entry in the loader skip lists; drop a carve-safety tautology (ship review, run 4)

A new INVOKE_SKILL test checks that plan-ceo-review's inline /office-hours
skip list and autoplan's section skip list both name the shared-preamble
pointer heading, and that office-hours and the four plan reviews carry it.
The carve-safety "sanity" assertion repeated the predicate discoverSkills()
now uses to set sectionsDir, so it could never fail; it is removed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: gstack-doctor finds the Codex model patch in the hoisted shared preamble (ship Step 11, run 4)

The doctor's patch row grepped only the Codex review SKILL.md for the
"Model-Specific Behavioral Patch (" heading. The hoist moves that section
into sections/preamble.md, so the required row (for ship, review, the plan
reviews, office-hours, investigate and more) would fail on every correct
post-hoist Codex install and block install.sh's "gstack: ok". It now checks
the SKILL.md and then its shared preamble and names the file it found. A
new doctor test covers a hoisted render.

preamble-hoist's variantSubsections also returns null when no subsection
differs, instead of emitting a replacing heading with no subsections.
Every host's render is unchanged.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(docsync): fixtureDocs installs the generated sections/preamble.md (hunk taken from #3472)

A generated skill that loads the shared preamble names sections/preamble.md
as a required asset before skill start, and a spawned document-release child
blocks on its absence, so docsync-spawned stayed red on every #3434 screen.
fixtureDocs now copies that file when the generated skill has it.

This single hunk is taken unchanged from gstack#3472 (head 2e3f7ba1,
GSTA-107), which trains ahead of #3434, so the train merge sees identical
lines. Nothing else from #3472 is included.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG notes the docsync fixture hunk taken from #3472

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG names the post-merge context-budget ratchet (captain hoisted)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(auq): planted skill fixtures resolve the shared preamble like an install (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(plan-format): mode menu delivers its question without output-harvesting wording (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): record the v1.91.270.0 merge values (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(auq): parallel-capture contract expects the planted skill with its sections path mapped (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): record the v1.91.273.0 merge re-measurements (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): restore the released entries the previous commit truncated (GSTA-96)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): end two sentences the prose gate flags (GSTA-96)

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>
2026-10-27 13:28:18 +00:00
Garry Tanandcapy-ai[bot] 295b32e2c4 v1.91.269.0 feat(autoplan): gates print their cost, approvals mirror to the Captain's drive, Eng asks for a perf budget (GSTA-114 lane F, PR 3) (#3496)
* feat(autoplan): gates print their cost, --owner-standing rec cites a standing approval, approvals mirror to the Captain's drive

E16: GATE_SPEND and GATE_REC_COST under every GATE line (lib/autoplan-gate-cost.ts), and a
Cost so far sentence in the owner brief; host-subagent attempts stay priced unknown.
E21: gstack-autoplan answer --owner-standing rec --by agent:<id> answers rec by citing the
newest standing approval covering autoplan recommendations from any branch's record; the
id lands on every decision row, in run.json and in the approvals import; refused with
STANDING_APPROVAL_ABSENT or STANDING_APPROVAL_INAPPLICABLE (urgent finding).
E22: the approvals mirror honours the approvals/ directory a Captain created in its drive,
between GSTACK_APPROVALS_DIR and the private project-user folder; gstack-approvals path
names the rule.
E23: the Eng phase asks for a performance budget and a bench step on hot-path changes.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): review pass 1 — standing answers bind to the run's project and refuse recommend-edited gates, cost is an upper bound and reaches JSON and the Captain brief

Review pass 1 (6 specialists + red team) on the standing-approval and gate-cost change:
- the standing lookup resolves the approvals record of the repository the run's plan lives in,
  never the caller's cwd (red team: project A's row answered project B's gate)
- standingAnswer refuses a gate that `recommend` edited (rec_rev > 0 or recommended_by), a
  missing or unreadable findings.jsonl, and an outside-plan finding; the STANDING line flattens
  control characters so a crew-writable row cannot forge a protocol line
- coversAutoplanRec matches the recommendation words in the owner's words only and rejects
  negations; STANDING_APPROVAL_ABSENT's fix names every required gstack-approvals flag
- recReopens is the upper bound of the answer/revise rules (a plan change counts every phase,
  a round grant its phase plus Eng); gate_cost rides the JSON payloads, `run` prints the lines
  at its final gate, and `gstack-owner-brief render --captain` appends a ### Cost section
- locate keeps the other mirror roots as read_also so rows mirrored under an earlier rule stay
  visible; gstack-approvals path prints READ_ALSO
- the Eng phase edit is size-neutral: five nearby phrases shortened so every host's autoplan
  SKILL.md stays at its size-guard pin
- tests: isolated fixtures, the run's plan inside its own git repo, cross-project refusal,
  amend_pending vs complete, recommend-then-standing, injection, gate_cost JSON, Captain brief

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (pass 2)

Standing approvals: the newest row about autoplan recommendations decides, so a later refusal
blocks older grants; rows whose id or date is not the recorded shape are never cited; the
project is fixed at init from the plan's physical path (run.json project_root) so a symlinked
plans folder or a checkpoint restore cannot borrow another repository's record. Gate cost:
recReopens counts every phase revise can keep or add and prices answers already recorded at
the gate; run --json emits one payload; the Captain brief's ### Cost sits above the relaying
trailer.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (pass 4, rule-23 exception)

Standing grammar fails closed: the newest standing row mentioning autoplan decides and grants only
with the canonical scope and affirmative owner words; same-id copies keep the newest recorded; id and
date are type-checked before the regexes. Gate cost prices the effective choices exactly as answer
does (p1d, carried overrides, non-recommended options). The run records project_slug beside
project_root so a restored run names its record on another machine, and project_root is a recorded
root for export --public.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* refactor(autoplan): drop --owner-standing rec (E21) from this PR

Pass-4 review (red team + Codex adversarial) still found that the keyword
grammar over the owner's standing words could read a refusal as a grant
("I won't take the recommendations", "Taking the recommendations is
forbidden" granted under the canonical scope) and that gstack-approvals add
deduped a same-day scope revocation as the grant. A free-text negation
parser cannot fail closed, so the standing answer leaves this change and
returns with a structured grant in its own PR.

Kept: GATE_SPEND/GATE_REC_COST cost lines and gate_cost (E16), the
Captain-drive approvals mirror with READ_ALSO (E22), the Eng perf-budget
question (E23). Removed: standingAnswer, standingRecApproval,
coversAutoplanRec, citableRow, project_root/project_slug in run.json,
STANDING_APPROVAL_* result codes and anchors, the standing DRIVER
paragraph and docs, test/autoplan-standing.test.ts (its E16/E22 cases move
to test/autoplan-gate-cost.test.ts).

Focused: 793 pass / 0 fail across 45 files; typecheck, typecheck:test,
format: cso:check clean; renders regenerated with gen:skill-docs --host all.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* RESTAMP: 1.91.268.0 -> 1.91.269.0 (stamped; queue_mode=stamp-at-merge base=origin/main@76aa68fc9e7a policy=base origin/main@76aa68fc9e7a:.gstack/ship-policy.json)
ship, next in queue at 1.91.269.0
STAMP_VERSION: 1.91.269.0
claims: ignored (stamp-at-merge)
stage version: done (wrote 1.91.269.0)
stage release_tool: done (bun scripts/gen-agents-digest.ts)
stage changelog: done (Unreleased -> 1.91.269.0)
stage stamp_paths: skipped (no stamp_paths in policy)
stage mirror: skipped (no mirror in policy)
stage apply: done (4 file(s))
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4e28308c..566bb525c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
 # Changelog

-## [Unreleased]
+## [1.91.269.0] - 2026-10-27

 **An autoplan gate now arrives with its price, and the approvals record lands where the whole crew can read it.** Captains reported the same two frictions: review rounds and reviewer subagents had no credit figure at the gate, and the approvals mirror sat in a private project-user folder no sibling thread could read. The Eng phase also gains the performance-budget question, after a correctness pass doubled a consumer's p95 with no bench step to catch it. (The standing "take the recommendations" answer planned beside these, `answer --owner-standing rec`, was cut from this release after review: a keyword grammar over the owner's words could still read a refusal as a grant, so it returns with a structured grant in its own change.)

diff --git a/VERSION b/VERSION
index c31f84688..6437fa3e4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.91.268.0
+1.91.269.0
diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md
index 3548eb690..4bdc2879f 100644
--- a/agents-digest/gstack-AGENTS.md
+++ b/agents-digest/gstack-AGENTS.md
@@ -1,4 +1,4 @@
-# gstack digest v1.91.268.0 — regenerate/re-copy after upgrading gstack
+# gstack digest v1.91.269.0 — regenerate/re-copy after upgrading gstack

 Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
 for agent hosts without a full skill install. The full skills add workflows,
diff --git a/node_modules b/node_modules
new file mode 120000
index 000000000..1de79460f
--- /dev/null
+++ b/node_modules
@@ -0,0 +1 @@
+/workspace/gstack-ap/node_modules
\ No newline at end of file
diff --git a/package.json b/package.json
index 7a672beb5..26a9702da 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "gstack",
-  "version": "1.91.268",
+  "version": "1.91.269",
   "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
   "license": "MIT",
   "type": "module",
FILES: CHANGELOG.md VERSION agents-digest/gstack-AGENTS.md package.json
MERGE_CONDITION: sha=624f0eedec7c3aebdd0cecd70be4e4ebd10eb4af
next: NEW_VERSION=1.91.269.0; commit and push only the stamp diff above (FILES), with no edit of your own: the train's verify accepts the CHANGELOG only as the base's plus this PR's entry re-headed; merge with the expected head 624f0eedec and recompute on a stale queue.
GSTACK_RESULT: skill=restamp status=complete run=/workspace/gstack-ap/.gstack/tmp/restamp-journal.json

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>
2026-10-27 06:54:56 +00:00
Garry Tanandcapy-ai[bot] 76aa68fc9e v1.91.268.0 feat(bin): gstack-decision-trail and gstack-worktree-audit, ported from pstack (GSTA-123) (#3494)
* feat(bin): gstack-decision-trail and gstack-worktree-audit, ported from pstack (GSTA-123)

Two MIT ports from Lauren Tan's pstack (licenses/MIT-pstack.txt, NOTICE.md):
a TSV decision trail with the header-once append, the formula guard, a start
row per run and a --run admission check; and a read-only worktree audit with
size, merge state, dirty, remote, PR, last chat and a suggested bucket.
Docs: docs/unattended.md (the decision trail and its end-of-run audit),
autoplan/DRIVER.md, docs/CONTRIBUTOR_REFERENCE.md, docs/standalone-binaries.md,
docs/troubleshooting.md, one line in landing-report.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(egress): reasoned scanner exemption for gstack-worktree-audit's base fetch

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review of the pstack ports

bin/gstack-worktree-audit: a worktree path with a space is read whole (sed
on the porcelain 'worktree ' line, not awk's second field); a registered
worktree whose directory is gone prints a 'prunable' row instead of being
skipped; 'safe' now requires a clean tree and either merged into the base
or a closed/merged PR with every commit pushed, so unpushed commits or
untracked files on a merged branch read 'review' (the port's rule called
them safe); fork PRs are dropped and an open PR wins over an older closed
one on a reused branch name; GIT_TERMINAL_PROMPT=0 on the base fetch.

bin/gstack-decision-trail: only a leading -h/--help is help, so a '-h'
cell is appended as data; a trail without a final newline, with CRLF rows
or with a repeated header line is appended to correctly; a run id is
limited to [A-Za-z0-9._:@/-] (exit 2) so a tab or quote cannot break the
start-row idempotence check.

Tests cover each case; the 'without gh' test resolves git from
'git --exec-path' instead of a PATH rebuilt from a tool list. Docs,
CHANGELOG and --help text describe the stricter buckets.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes, pass 2

bin/gstack-worktree-audit: a worktree whose own .git link is gone (git
marks it prunable, or its toplevel is another repository) prints a 'broken'
row in 'review' instead of describing the containing repository as clean
and safe; a locked entry whose directory is gone reads 'review', not
'prunable', since prune would not touch it; a clean tree names its
gitignored entries as 'clean,ignored:<n>' without changing the bucket; the
branch name is read from refs/heads/ by hand so a tag of the same name
cannot hide the PR; porcelain blocks are read with IFS=tab so paths with
leading or trailing spaces survive; a failed git status reads 'unknown',
never 'clean'; the base fetch also sets GIT_ASKPASS=true and ssh BatchMode.

bin/gstack-decision-trail: a file whose first line is not the header (a
blank file, rows written by hand) gets the header appended, and a UTF-8
BOM before the header no longer turns it into a data row.

Tests: the fake gh records its argv and runs the audit's own --jq over
canned JSON with a fork PR when jq is installed; row counts are asserted
before the every() checks; each test starts from the same gh and closed
worktree; the snapshot includes the worktree registry; new fixtures for
locked, broken, tag-shadowed and ignored-only worktrees, a blank trail and
a BOM. Docs and CHANGELOG describe the new DIRTY values and buckets.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes, pass 3

bin/gstack-decision-trail: hasHeader looks for a header line anywhere in
the file, so a blank or hand-written trail gets exactly one header rather
than one per append. bin/gstack-worktree-audit: the broken-worktree check
uses rev-parse --show-cdup and the presence of /.git instead of
comparing two spellings of the same path, which differ on Git for Windows.
Test: the blank-trail case appends twice and asserts a single header.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: adversarial review, pass 5 (rule-23 grant, one finding)

bin/gstack-worktree-audit: git status runs with --untracked-files=normal
--ignore-submodules=none, so a user's status.showUntrackedFiles=no config
cannot hide untracked files and let a worktree holding them read clean and
safe. Test: the fresh worktree under that config via GIT_CONFIG_* still
reads scratch:1 / review (red before the fix).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: documentation audit corrections for the pstack ports

docs/standalone-binaries.md, docs/CONTRIBUTOR_REFERENCE.md,
docs/troubleshooting.md: the audit's safe condition is stated in full
(clean and merged, or PR closed/merged with every commit pushed), the
DIRTY list names missing, broken and unknown, start is a reserved phase
name, and 'read-only' names the base fetch as the one write --no-fetch
skips. CHANGELOG.md says the same (the audit's one decision item).
Audit id gsta123-docs-20261026T221657Z, status updated, no blockers.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Stamp 1.91.268.0 for #3494 (train slot 1, base d9b0d600)

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>
2026-10-27 06:36:56 +00:00
Garry Tanandcapy-ai[bot] 4d48d39e51 v1.91.253.0 feat(captain): /captain skill (also /crew), crew templates and docs/captain.md for running a crew from one controller (#3473)
* feat(captain): /captain skill (also /crew), crew templates and docs/captain.md for running a crew from one controller

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore(captain): regenerate SKILL.md at main's version

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(captain): AGENTS.md and NOTES.md templates, roles, ship lane sequence, owner device and lessons loop in docs/captain.md; owner-brief closes with the do-it reply

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(captain): review pass 1: 'do it' parses as rec, READY template matches the tool's lines, slot-2 and freeze wording, mergeChangelogs named, parameter lists and doc numbers aligned

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(captain): align the slot-call BASE merge, freeze repair and severe-race wording across skill, CREW.md and docs; router routes on phrases; receipt head width as printed

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(captain): CREW.md template becomes pointers plus parameters; every crew rule gets a canonical home in gstack (lane discipline, outside contributions, stale READYs, standing spend, the lane side of flaky reruns in docs/captain.md; the rule-to-home map)

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>
2026-10-26 18:04:22 +00:00
Garry Tanandcapy-ai[bot] b9222a57b7 v1.91.247.0 fix(plan-eng-review): define the three references its judged text left dangling (GSTA-91) (#3421)
* fix(plan-eng-review): define the three references its judged text left dangling (GSTA-91)

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: pre-landing review fixes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: ship coverage test, unattended doc and CHANGELOG for review fixes

test/plan-reality.test.ts asserts each phase's gstack-plan-reality check line names PLAN_REALITY (Step 7 gap). docs/unattended.md names the unattended-session block the skill prose now cites (Step 14.5 audit). CHANGELOG [Unreleased] covers the hook pointer fix and the new tests.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): drop the hook directive claim (GSTA-91)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: keep destructive options pending in the unattended AUQ fallback (GSTA-91)

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: trim the unattended pointers so every size pin goes down (GSTA-91)

The failure fallback's unattended branch now says a consent, destructive or irreversible option, unrecommended question or approval gate stays pending, keeping the carve-out. Item 1 drops its dangling '(per its printed unattended-session block)' pointer. CQ3 now asserts no section or block pointer remains in item 1; CQ4 is retitled to the block and hook; the plan-reality pointer loop drops devex, which renders no reality rows. Every host and the /ship goldens are regenerated and all 89 pins go down versus 4814b3d8a (78 by 62, 11 by 38).

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>

* docs(unattended): drop the claim that skill prose cites the block id (GSTA-91)

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: pre-landing review fixes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: item 1 names destructive or irreversible options as pending in unattended runs (GSTA-91)

Dropping item 1's block pointer also dropped its only route to the printed block's destructive/irreversible carve-out. Item 1 now lists them in its unattended pending set, matching the failure-fallback branch, the hook and the printed block; the shared Exception is unchanged. CQ3 requires destructive and irreversible. Regenerated every host and the /ship goldens; every pin still goes down versus 4814b3d8a (78 by 32, 11 by 8). Includes the /ship Step 7 test that docs/unattended.md names the printed block header and END.

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>
2026-10-26 13:36:43 +00:00
Garry Tanandcapy-ai[bot] 8018ba52fe v1.91.243.0 fix(capy): source the launch environment from a 0600 file; no skill fence may print the environment (GSTA-104) (#3449)
* fix(capy): the launch environment is sourced from a 0600 file and no skill fence may print the environment (GSTA-104)

During GSTA-96's unattended /ship on #3425, the Step 14.5 docs-audit child
re-typed the GSTACK_LAUNCH assignments as `export $(...)`; the substitution
came back empty, the bare `export` printed the whole environment, and three
API key values landed in its tool output.

- bin/gstack-capy-install writes the assignments to <verdict>.env (mode 0600,
  idempotent PATH prepend) and prints GSTACK_LAUNCH_FILE: <path>.
- ship Step 14.5 prompt, document-release's spawned note, autoplan/DRIVER.md
  and gstack-skill-start's capy-asks block say: source the file; never
  export $(...), env, printenv or bare set in a tool fence.
- test/launch-env-echo-ratchet.test.ts greps every generated SKILL.md,
  sections, DRIVER.md, the Capy skill and bin/ shell helpers, with negative
  controls under test/fixtures/launch-env-echo/.
- lib/redact-engine.ts: env.value (HIGH) finds the value of any *_KEY,
  *_TOKEN, *_SECRET, *_PASSWORD variable in the writer's environment, so a
  leaked value cannot reach a PR body, receipt, report or Drive file.
- scripts/lib/shard-engine.ts scrubs the Capy launch markers from shard
  environments (GSTA-99's finding).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ci): DRIVER.md back to 159 lines; shard-engine recorded non-behavioral at HARNESS_VERSION 6; verdict-count test lists .json only

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: register test/fixtures/launch-env-echo as a free fixture

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(redact): env-value fixtures stay out of pregate's env.kv net

A credential-named assignment with an entropic literal on one line is what
the repo's own pregate secrets scan refuses in added lines, so the fixture
values move into plainly named constants and the scanned text is built from
them. The scan under test still sees the same values through processEnv.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(windows): the late-completion remote-caller case gives its second attempt a 2s budget (run 40263984171)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact): env.value trims the value, keeps a prefix value's longer match, hides the preview and skips PUBLIC names

/ship Step 9.4 review fixes for the GSTA-104 env-value scan:

- a value whose environment copy ends in a newline (a key read from a file)
  is searched for trimmed, so its leaked form still matches (the length
  check already trimmed; the search used the raw value);
- when one credential value is a prefix of another, the dedup key carries the
  span length, so the longer value is redacted whole in either order instead
  of leaving its tail in the text and dropping its finding;
- the env.value preview is a fixed mask instead of the first characters of a
  live credential;
- framework-public names (NEXT_PUBLIC_*_KEY, *_PUBLIC_KEY) are not scanned,
  since those values are committed on purpose;
- the header and the processEnv docstring state the name rule (KEY, TOKEN,
  SECRET, PASSWORD, PASSWD, any case) and that process.env is the engine's
  one ambient input.

Step 7 coverage extensions and a regression test for each fix in
test/redact-env-value.test.ts; docs/capy-install.md names the full rule.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* refactor(capy-install): write_launch_file quotes through shq; header names the launch file

Review finding: _sq duplicated shq() from the same file. The launch file's
assignments now go through shq, and the header comment describes the
GSTACK_LAUNCH_PATH and GSTACK_LAUNCH_FILE lines beside GSTACK_LAUNCH.

Step 7 coverage: the verdict test sources the launch file and runs --check;
the single-quote path test sources the file too; a new case makes the
launch-file directory unwritable and checks the run says so, prints no
GSTACK_LAUNCH_FILE line, leaves no temp file and keeps its exit code and
trailer (linux, non-root).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(preload): strip the Capy launch markers so a direct bun test matches the shard sandbox

Red Team finding: the launch-marker scrub lived only in createShardSandbox,
so a direct `bun test <file>` run under an unattended Capy session inherited
GSTACK_SESSION_KIND, GSTACK_CAPY, GSTACK_EPHEMERAL and GSTACK_INSTALL_VERDICT
(GSTA-99's symptom). The preload now deletes the same four names, and
test/shard-engine.test.ts imports CAPY_LAUNCH_MARKERS instead of re-typing them.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(ratchet): the launch-env echo scan catches backtick and $VAR exports, typeset -p, env flags and a set in any segment

Review findings 11 and 12: export-subst also trips on `export \`...\`` and
an unquoted `export $VAR` (both splat a NAME=value file; `export "$name"` is
one word and stays allowed); the export rule adds `typeset -p`; env trips
with only flags (`env -0`) and as `/usr/bin/env`; set is judged per segment
and with redirections, allowed only when piped straight into an anchored
grep filter. Quoted strings are blanked offset-preserving so a `#` inside
quotes no longer hides the rest of the line. The negative control covers
each new form on both sides.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(ship): Step 14.5 names where the launch-file placeholder comes from

The /document-release prompt line read `. <file>` with no word on what fills
it. It now says the placeholder is the GSTACK_LAUNCH_FILE: path the parent's
own install check printed. Worded to stay under the ship skill's pinned
parity size (313,279 of 313,281 union bytes).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact): env.value admits *_PASS, *_PAT, *_APIKEY and *_PWD, and skips path values and gstack's lock token

/ship Step 11 adversarial findings. The name rule also covers DB_PASS,
GITHUB_PAT, *_APIKEY and *_PWD (the shell's own PWD and OLDPWD stay out). A
credential-named variable whose value is a filesystem path (SSL_KEY=/etc/ssl/
private/x.key) names where the credential lives, so the path is no finding,
and GSTACK_BRAIN_LOCK_TOKEN (pid-random-epoch, written to the lock owner file)
is not a secret. Without these, an ordinary mention of that path or token in a
PR body, receipt or CSO report was a HIGH fail-closed blocker.

The adversarial pass also recommended an entropy floor so dev defaults such as
DB_PASSWORD=postgres stop matching prose; declined here on purpose, because the
scan's promise is to catch a leaked value whatever its shape, and a weak real
password is still a credential. Recorded as an open decision in the ship report.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy-install): a failed launch-file write removes only its own temp file

The failure path ran rm -f "$LAUNCH_FILE".tmp.*, which also deleted the temp
file a concurrent installer run (two threads on one machine, same verdict
path) was about to mv, so that run lost its launch file too. write_launch_file
now cleans up its own $tmp and returns 1; the caller only reports. The file's
comment no longer embeds the state-root path (a newline in GSTACK_STATE_ROOT
could have ended the comment).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: the launch markers come from one list, and the echo ratchet scans setup and scripts/*.sh

The preload imports CAPY_LAUNCH_MARKERS instead of re-typing the four names,
and the ratchet asserts the installer exports every name on that list, so a
fifth marker cannot be added to one place only. The shell scan also covers
./setup and the scripts/*.sh install scripts callers run first.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(changelog): the Unreleased entry states the review-fixed env.value rules, the ratchet forms and the one test-budget change

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact): the env.value path exemption asks whether the file exists instead of matching a shape

Second review cycle: a path-shaped rule also matched a base64 secret that
starts with "/" and holds another "/" (about 1 in 150 AWS-shaped keys), which
then went unscanned. The exemption now fires only when the value names a file
that exists on the scanning machine (SSL_KEY=/etc/ssl/private/x.key). The
module header names that stat as the engine's one filesystem read.
NON_SECRET_ENV_NAMES is exported so the test can prove bin/gstack-brain-lock.sh
still exports every name in it; the PWD/OLDPWD fixtures hold plain words so only
the name rule keeps them out.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: the installer's own-temp-file cleanup is exercised, and the ratchet coverage test names setup and scripts

An mv shim first on PATH refuses only the launch-file target, so the temp
file exists when the move fails: the run removes that file alone (a sibling
from a concurrent run survives), says so, prints no GSTACK_LAUNCH_FILE line
and keeps the earlier file, exit code and trailer. The ratchet coverage test
asserts setup, scripts/build.sh and scripts/sandbox-doctor.sh are scanned.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact): env.value has no path exemption and matches the value in normalized form

Second adversarial pass: the existence check let the scanned agent exempt
any "/"- or "~/"-prefixed secret by creating a path of that name, a silent
bypass of the one guard this branch adds, so the exemption is gone; a
path-valued SSL_KEY that must appear in a text goes through the allowlist.
The engine is back to no I/O. The value is now normalized the way the text
is before indexOf, so a credential NFKC rewrites (fullwidth digits) still
finds its leaked ASCII form.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy-install): the launch file is written only on a passing run; the ratchet checks the marker list both ways

A gstack: fail run no longer writes or announces a sourceable file whose PATH
prepend points at an unverified Bun. The ratchet also asserts every variable
the launch file exports is a CAPY_LAUNCH_MARKERS entry or GSTACK_STATE_ROOT,
so a sixth export cannot reach fixture children unstripped. The Capy skill's
prose no longer offers re-typing the assignments as an alternative to sourcing.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy-install): the launch file is part of the ok verdict

Third adversarial pass: a passing run whose launch file could not be
written still said gstack: ok with exit 0 and printed only the GSTACK_LAUNCH
line, leaving a shell-evaluating caller with the re-typing path the branch
exists to remove. The file is now written before the verdict is recorded;
a write failure on a passing run turns the run into
"gstack: fail launch-file — could not write the launch file <path>; fix: …
(LAUNCH_FILE_UNWRITABLE)" with exit 1 and an ok:false verdict, and every
failing run removes the launch file an earlier passing run left beside the
verdict. The two failure tests assert the new contract, the doctor-FAIL
tests assert no launch file is announced or left, and the docs, Capy skill
and CHANGELOG say the same.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact): the env.value allowlist and placeholder rules see the normalized value too

An allowlisted value in NFC did not suppress a match on its NFKC-composed
form, and a value that is a placeholder only after normalization was still
searched for. Fixture nits from the third review cycle: fixed directory
string instead of process.cwd(), the fullwidth assertion guards its own
vacuity, a zero-width-padded value under the floor is pinned, and the
ratchet comment names the one kept export and the PATH case line.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy-install): LAUNCH_FILE_UNWRITABLE is a registered result code; a kept profile verdict keeps its launch file

Fourth review cycle. The new trailer code now has its row in
lib/result-codes-capy.ts (the owner module is at its size cap) and its
docs/troubleshooting.md anchor, so the install-side code scan resolves it.
A failing profile check (--for review-voice) that keeps a fuller ok verdict
for this HEAD no longer deletes that verdict's launch file: the fail branch
removes the file only when the run rewrites the verdict, and setup_failed
removes it too. The docs say "a failing run that rewrites the verdict",
and that an unwritable directory keeps both the old file and the old
verdict. A new test runs a passing install, then a failing profile check,
and asserts the file and the ok verdict both survive.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(redact): the normalized allowlist and placeholder rules each have an assertion that fails without them

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(capy-install): a setup failure after a passing install removes the earlier launch file

Fifth review cycle: setup_failed's cleanup had no assertion. The setup
failure test now installs once (launch file present), commits a new HEAD so
setup runs again, fails that setup, and asserts the launch file is gone and
the verdict says ok:false before the next run sets up again and ends ok.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: state-root, contributor reference and capy-install follow the launch-file contract (Step 14.5 audit)

The /document-release audit (docs-3449-1792992068) corrected three authored
docs: docs/state-root.md shows the GSTACK_LAUNCH_FILE line and says to apply
it with ". <that file>" instead of prefixing or exporting the assignments;
docs/CONTRIBUTOR_REFERENCE.md names scan()'s one ambient input instead of
calling it pure; docs/capy-install.md's bun-shim bullet and exit table name
the launch file and the fail launch-file trailer.

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>
2026-10-26 12:00:20 +00:00
Garry Tanandcapy-ai[bot] 021d817c36 v1.91.240.0 feat(proactive): default to the four core skills (core | all | off), with docs, prompt and tests (GSTA-99) (#3432)
* feat(proactive): default to the four core skills (core | all | off); docs, prompt and tests (GSTA-99)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(proactive): gstack-skill-start falls back to core, not true, when gstack-config is missing

The PROACTIVE status line's fallback literal still said true (= all) after the default moved to core. Found by /ship's coverage audit; the regression test fails at the previous head and passes at main.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(proactive): STATUS line carries the stored value; every surface names the same core four and three values

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(proactive): off gates the office-hours handoff; the preamble and router scope the setting to unasked suggestions

The office-hours next-review handoff gated on the legacy false only, so an off user was still asked to launch /plan-eng-review. The per-skill preamble now says the setting governs unasked suggestions and this skill's own steps still run (a handoff, a review gate, a dispatched /document-release is not a suggestion), at exactly the previous length, so the 89 size pins return to main's values; the router says the same in full. Found by /ship's specialist and red-team review.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(skill-start): unknown proactive values read as core; first-run tips name core skills and stay quiet under off

A hand-edited config can hold any value and only set validates, so STATUS normalizes anything but core|all|off|true|false to core. The first-run and first-loop tips named /spec, /investigate and /plan-eng-review whatever the setting; they now name the core four and are skipped under off. The fallback regression test folds into test/proactive-skill-start.test.ts, the duplicate header assertion leaves proactive-config, and the frozen-length preamble test is retired (the size guard enforces it).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(proactive): scope note, the unknown-value rule, and the CLAUDE.md routing follow-up; CHANGELOG

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(skill-start): no CLAUDE.md routing offer under proactive off

The one-time offer to append ## Skill routing to the project's CLAUDE.md fired whatever the proactive value, and its rules are the auto-invocation an off user turned off. The offer is skipped under off and the legacy false; a section already in CLAUDE.md is left alone. Under core the offered section still routes every skill, which docs/proactive.md records as the follow-up. Found by /ship's red team.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(proactive): STATUS says only core | all | off, and the preamble carves out only named skills

gstack-skill-start reads the legacy true/false as all/off and tolerates a quoted, upper-case or commented hand edit (proactive: OFF # mine read as core before), so every surface sees one of three values and the off gating lives in one flag. The per-skill preamble drops the legacy spellings and replaces 'This skill's steps still run', which licensed any in-skill offer under off, with 'Skills the user or this skill's steps name run', at the same length, so the 89 size pins stay at main's. Tests run the script for the tips and the routing offer under core and off instead of grepping the source. Found by /ship's fix-range repeat (red team, testing, maintainability).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(config): set proactive is case-insensitive; follow-up #3446 cited; test hygiene

set proactive OFF warned and stored core, the opposite of the opt-out typed; the value is lowercased first, as gstack-skill-start does for a hand edit. The fixture git init carries the tripwire timeout, the source-shape assertion on the private _PROACTIVE_OFF line goes (the routing-offer test proves the behavior), and the CHANGELOG Tests bullets collapse to one per file with the known gap pointing at #3446. Found by /ship's full repeat pass and its tests lane.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(proactive): a stored off answers the one-time prompt; the router names /browse and /investigate under core instead of invoking them

Red team, full repeat pass: with proactive: off stored before the prompt, skill-start still emitted the opt-in prompt; it now writes the marker and asks nothing. The router's Route-first browser step and the Failures branches invoked non-core skills under core while the core block said to answer directly; one sentence in the core block resolves it, pinned by the core-set tests. CHANGELOG and docs/proactive.md say both.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(proactive): the full-catalog skill descriptions are the second surface that still routes every skill under core (#3446)

From /ship's document-release audit: a --catalog-mode=full build and the non-Claude hosts keep the "Proactively suggest when ..." description sentences, which do not follow the setting; the default Claude build trims them.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(proactive): the tips test runs skill-start as an interactive session

GitHub CI sets CI/GITHUB_ACTIONS, which gstack-session-kind reads as headless, and a headless start skips first-task detection, so the first-run tip never fires there (Free Tests shard 16 red at 0d7dbe6; green locally and on the Ubicloud pregate, which have no CI marker). The fixture now sets CLAUDE_CODE_ENTRYPOINT=cli, the positive interactive signal; reproduced locally with CI=1 and fixed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(proactive): an opt-out never fails open; the preamble carves out invocations, not offers

The YAML yes/no family (yes/on/1, no/none/0/disabled/never) reads as all/off in both gstack-skill-start and gstack-config set, so a typed or hand-edited opt-out cannot land on core. The per-skill preamble says "Skills the user names or this one invokes run" (same 168-char length, pins unchanged): a skill dispatching another is not a suggestion, an in-skill offer to run one still is under off. The stored-off prompt marker is written before STATUS prints PROACTIVE_PROMPTED, so the line is true. docs/proactive.md's table row carves out in-skill handoffs.

Fourth /ship fix cycle, past the skill's three-cycle cap by GStack Minder's decision (2026-10-26) under Garry's "do it" on the proactive core set; items from the Step 11 adversarial pass.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.240.0 stamp

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>
2026-10-26 10:05:57 +00:00
Garry Tanandcapy-ai[bot] 9dc1dfb729 v1.91.227.0 fix(windows): shell bins pass NUL as Bun's empty config when MSYS path conversion is off (#3415) (#3431)
* fix(windows): shell bins pass NUL as Bun's empty config when MSYS path conversion is off (#3415)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(windows): detect Git Bash/MSYS2/Cygwin from OSTYPE, as gstack-doctor does, so uname stubs in setup fixtures stay untouched

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (#3415)

- Choose NUL only when cygpath is also on PATH, so an OSTYPE=msys inherited
  by a POSIX bash keeps /dev/null instead of a cwd-relative NUL file.
- gstack-developer-profile --log-session reports a Bun failure instead of
  skipping it as invalid input, like gstack-timeline-log.
- learnings-injection tests check that their anchored bun -e block exists.
- CHANGELOG names the callers this fix does not cover; curation reason fixed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes, cycle 2 (#3415)

- timeline-log and developer-profile validators print their verdict; any
  non-zero Bun exit is a reported failure (a Bun crash on Windows exits 3).
- timeline-log keeps the original event when ts stamping fails.
- The definition ratchet scopes a local GSTACK_BUN_CONFIG to its function.
- The shell-bins fixture clears its preload marker per test.
- CHANGELOG states the callers that discard the report and the Bun 1.3.x case.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG notes Bun 1.3.10 evidence and remaining literal /dev/null callers (#3415)

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>
2026-10-26 04:32:27 +00:00
Garry Tanandcapy-ai[bot] c279ce045d fix(autoplan): linked worktrees resolve from a project directory below the repo root (#3296) (#3383)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-25 12:27:01 +00:00
Garry Tanandcapy-ai[bot] e7a1df9e18 v1.91.172.0 feat(capy): approvals per thread, Captain plan briefs and before/after PR images (#3328)
* feat(capy): approvals per thread, Captain plan briefs and before/after PR images (GSTA-61)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy): mark whole rewrites in PR images, point the ship guide at the skill folder, refresh ship goldens (GSTA-61)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(context-budget): raise the Capy skill ceiling for "Working under a Captain" (GSTA-61)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* revert(capy): keep wrapper 2; owners copy the skill folder by hand (GSTA-61)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.172.0 stamp (#3328)

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>
2026-10-20 23:55:41 +00:00
Garry Tanandcapy-ai[bot] 5de607f26c v1.91.170.0 fix(autoplan): guard waits for an unflushed journal; plan floor harness reads cropped menus; office-hours reviewer recovers with Write (GSTA-57) (#3326)
* fix(autoplan,evals): guard waits for an unflushed journal; floor harness reads cropped menus; office-hours reviewer recovers with Write (GSTA-57)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.170.0 stamp

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>
2026-10-20 19:02:57 +00:00
Garry Tanandcapy-ai[bot] 4c6fa89cdc v1.91.159.0 security: gstack's Bun entry points ignore the audited repo's .env and bunfig.toml (S1) (#3312)
* security: isolate every gstack Bun entry point from the audited checkout's .env and bunfig.toml

Bun auto-loads .env, .env.local and .env.<NODE_ENV> from its cwd and runs a
cwd bunfig.toml preload before the program starts. gstack runs inside the repo
it audits, so a committed .env could steer state roots, the claude binary or
spend caps, and a bunfig preload ran arbitrary code in every bin and hook.

Every bun shebang, shell and skill caller, TypeScript spawn and compiled build
now disables both (--no-env-file --config=/dev/null, bunIsolationArgs(),
--no-compile-autoload-dotenv/bunfig), with a ratchet and hostile-fixture
regressions.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: name the directly executed scripts in the isolation ratchet

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: follow the isolation flags in touchfiles, copy lists, recipe assertions and the harness pin

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: keep browse/src/bun-child-config.ts unchanged so the native cookie qualification still binds

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(windows): the empty bunfig outlives its process so the timeline hook's detached repair child can read it

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.159.0 security: gstack's Bun entry points ignore the audited repo's .env and bunfig.toml (S1)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: plan-mode render pattern accepts the isolation flags

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>
2026-10-20 00:24:28 +00:00
6237994016 v1.91.157.0 perf(gen-skill-docs): drop the "When to invoke" body section from Claude SKILL.md files (port of #3129) (#3305)
* perf(gen-skill-docs): stop emitting the "When to invoke" body section

The Claude catalog trim moved each skill's routing prose ("Use when...",
"Proactively invoke...", voice triggers) out of the frontmatter description
into a "## When to invoke this skill" section at the top of the body. Claude
Code reads only name + description to choose a skill and loads the body after
the skill is invoked, so that text cannot route anything and costs tokens on
every invocation. Keep the one-line trimmed description; drop the section.

The routing prose stays in each template's description, which
--catalog-mode=full and the other hosts still render. Tests that pinned the
section now assert its absence, or check the template instead.

(cherry picked from commit 707ccd6f38)

* feat(gen-skill-docs): keep voice triggers in the root routing block

The Claude catalog trim drops each skill's "Voice triggers (speech-to-text
aliases)" line from its description, and the body section that used to hold
it is gone. {{VOICE_TRIGGER_ROUTING}} renders them in the root router's
routing block instead: one "Voice trigger ... → invoke /<skill>" line per
skill, read from the templates' voice-triggers lists, so disabled-skill
filtering applies to them like any other routing line. Other hosts keep the
line in each description and render nothing here.

extractVoiceTriggers moves to the new resolver so the generator and the
resolver share one parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 645e75b1e8)

* chore: regenerate SKILL.md files without the "When to invoke" section

Output of `bun run gen:skill-docs --host all` after the previous commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit ff4c813337)

* test: refresh context-budget ceilings for the smaller skill bodies

`bun test/helpers/capture-context-budget.ts`. Against a recapture of the base
commit, 55 skills that lost the section get a lower ceiling and the root
gstack router rises by 532 tokens for the voice-trigger routing lines (5,369
tokens lower in total). devex-review and eval-plan differ from the committed
fixture only because it already lagged main. alwaysOnTotal is unchanged: the
catalog descriptions did not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit d886fcecc1)

* test: refresh the claude ship golden without the "When to invoke" section

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit f1789dca5c)

* test: lower the claude design-review size pin

The size guard (#3199) asks for it: claude/design-review shrank by 437 chars
without its "When to invoke" section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 3a446fcc62)

* test: skip alias symlinks in the voice-routing check, keep unrelated budget ceilings, add #3129 CHANGELOG entry

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: rebuild the historical cookie approval with the dropped section, record the skill-fixture change as non-behavioral

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.157.0 perf(gen-skill-docs): drop the "When to invoke" body section from Claude SKILL.md files (port of #3129)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: thanhnguyentung95 <17350411+thanhnguyentung95@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-19 22:55:42 +00:00
Garry Tanandcapy-ai[bot] fd13cf25e8 v1.91.133.0 docs(coordinator-contract): Before done treats requires-remote as unfinished (#3261)
* docs(coordinator-contract): Before done treats requires-remote as unfinished and names the --remote clear

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore(release): v1.91.133.0

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>
2026-10-18 02:51:19 +00:00
Garry Tanandcapy-ai[bot] c71d764ba4 v1.91.115.0 feat: field list 2 wave A: autoplan round cap and public export, eval-plan diagnostics and model rules, --for review-voice (#3234)
* fix(capy): the install trailer says behind=<n> and its fix, so a stale install shows in every relayed trailer (field list 2 item 13, #2378)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy): a lease records its holder's start identity, so a pid reused after a wake is reclaimed; a skipped session-start upgrade ends fail behind, never ok (GBRA-105, GBRA-106)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(lease): stale needs proof (unreadable or malformed identities keep the lease), ps identity is timezone-independent, and reclaim never deletes a concurrent renewal

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): enforced round cap and spend budget, deferred close, public export without machine paths, opt-in durable checkpoints (field list 2 W5-W7)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(lease): one directory lock for publish, prune and reclaim; reclaim rereads the record judged stale, so a renewal is never deleted or hidden

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(lease): the directory lock names its holder; broken only when the holder is dead or its pid reused, unlock removes only its own lock, touch exits 3 under a live holder

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(lease): breakers serialize on .lock.break and reread the lock before removing it; gstack-skill-start reports a lease the held lock kept out

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(lease): name the double-crash limit of breaking a dead lock

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(capy): --for review-voice install profile, no-Drive bootstrap command, reviewer prompt trailer (field list 2 W11)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 89bf556c11)

* test: pin review-voice row, helpers row and the no-Drive fallback in existing install tests

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 7f6c70459a)

* test: the DRIVER template names the reviewer trailer relay (pregate lane)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 2545d9a6d2)

* test(context-budget): capy skill eager ceiling for the review-voice subagent paragraph (W11; ratchet protocol, capture value)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(eval-plan): prereg diagnostics dry run (W8) and .gstack/eval-models.json lint (W9), WIP

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit b509096218)

* feat(eval-plan): W8/W9 tests, docs/eval-models.md, troubleshooting anchors, /eval-plan steps

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 9335e45de2)

* test(eval-plan): eval-plan/SKILL.md names only defined codes and accepted flags

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit a7a974d268)

* test(review-voice): the launch line points at the verdict's bun-only directory (#3233's launch contract)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(third-party-actions): the Aside drive-offer detector matches the product name, not the English idiom (paid run 38988927989 tpa-absent-linux false positive)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): export refuses artifact paths outside the run before writing; a deferred close keeps earlier undecided findings; reopening CEO grants Eng its rerun (review of #3234)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(autoplan-budget): bind the reservation expectation to lib/autoplan-budget's default estimate (test-of-test ratchet)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(evals): the docs observer accepts the spawned-prefixed gstack-skill-start --help read

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(windows): curate capy-review-voice out of the Windows subset (POSIX launcher contract)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: changelog entry for field list 2 wave A

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: stamp v1.91.115.0

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>
2026-10-17 02:40:45 +00:00
Garry Tanandcapy-ai[bot] bc2ed0cee7 v1.91.114.0 feat(dx): score every error for an AI agent reader (agent-ready error contract + gstack-error-capture) (#3226)
* feat(dx): agent-ready error contract for the DevEx review skills

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(dx): gstack-error-capture runs a CLI with no terminal and prints a redacted record

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(dx): CI-clean fences, runtime-root-safe contract location, path-agnostic launch-check test

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(dx): preregistered behavior case for the agent-ready error contract; README skill rows

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(dx): grader items come from the contract; paid-file count includes the new case

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(dx): outside DX voice uses the agent-ready contract; DX_CAPTURE_* codes join RESULT_CODES with troubleshooting anchors

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(dx): review fixes for gstack-error-capture and the paid grader

- every helper diagnostic passes the record's redaction, fail-closed
- forwarded values are masked before and after sanitizing, plus JSON-escaped forms
- the final secret check reads the record's string fields with byte-based scan limits
- mise/asdf config, trust and env-loading variables need --pass-env; only data locations pass by default
- launch reports whether the target started; --launch-check's probe result is exit_code
- Step 3 captures --help first; help states the containment lifetime limit
- the paid grader validates the bound result with parseReviewResult

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(dx): mask forwarded values before argument validation; protocol strings never match literals; Step 3 captures stay read-only

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.114.0 feat(dx): score every error for an AI agent reader (agent-ready error contract + gstack-error-capture)

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>
2026-10-17 02:10:12 +00:00
Garry Tanandcapy-ai[bot] 0bf9d50808 v1.91.107.0 fix: the GBRA-40 field list (one Bun for install and check, rec gate approval, pregate never silent) (#3190)
* fix(autoplan): empty findings fences, repo-relative rows, PLAN_REALITY flags, pending/--all/provider (Lane B: B3 B6 B7 B8 B9 B10 B11)

B3  parseFences: the body group is optional (lazy), so an LF/CRLF empty fence is zero
    findings in both the canonical and record grammars; opener without closer still
    RESULT_FINDINGS_MISSING.
B6  plan-reality/3: item/section references are not quantities; backtick phrases are
    exempt only from the plan-scope rule-phrase check (B-f); a measured number inside
    backticks stays flagged in review scope. vaguePlanTerms() feeds an advisory
    `flagged: PLAN_REALITY ...` line under the p1 approval item (never blocking).
B7  canonical rows: absolute repo paths become repo-relative; snapshot/active-plan
    citations become the plan file name with the source line mapped (or dropped).
B8  `status` prints `PENDING: <id> phase=<p> voice=<v> result=<file>` per open attempt.
B9  `gstack-gate render --all`; paged output says to relay every page.
B10 `gstack-plan-reality check --plan <snapshot>`: a number in a "quoted" span copied
    verbatim from the reviewed plan needs no receipt (reviewer scope only).
B11 submit defaults the provider to host-subagent when --runner is omitted.

Lane B files: lib/autoplan-reconcile.ts lib/plan-reality.ts lib/autoplan-gate.ts
lib/gate-list.ts lib/autoplan-plan-text.ts lib/autoplan-run.ts bin/gstack-gate
bin/gstack-plan-reality scripts/resolvers/plan-reality.ts autoplan/sections/ceo-phase.md
autoplan/sections/eng-phase.md test/plan-reality.test.ts test/autoplan-gate-artifacts.test.ts

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ubicloud): ubi-runner up/run -S accepts only Ubicloud's storage sizes, before any API call (A11)

Files: scripts/ubicloud/ubi-runner.sh, test/ubicloud-runner.test.ts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(issue-links): promotion candidates, Related PRs, validated flake issues, body/receipt consistency (Lane D: D1-D3)

D1: the GBRA-40 fix wave's gbrain #6279 body had no `## Issues` section and no
receipt (it was not composed by /ship, so gstack-issue-links never ran), and
#6252 appeared only as a subject parenthetical `(#6252)`, which the closure
rule correctly treats as Refs. The rule is kept. Same-repo references are now
printed as promotion candidates (`(promote: fix #N)`, `candidates` in --json),
and `gstack-ship-receipt write --issues ... --body` refuses a body that lacks a
line its issues object records (ISSUE_LINKS_MISSING), so a /ship body can no
longer drop its closing lines.

D2: open PRs by other authors whose closing set overlaps this PR's Fixes are
`Related: #N (@author)` (paged GraphQL closedByPullRequestsReferences; viewer
and this branch excluded; cross-repo PRs keep owner/repo#N). `Supersedes` and
`Contributed by` only with --supersedes/--credit; --no-auto-links skips the
lookup; the stderr preview names each added line's source. A failed lookup is
ISSUE_LOOKUP_FAILED (installer form with docs anchor) and keeps the other lines.

D3: a --ci-run match becomes a Flake line only for a bot-opened issue of this
repository that names that run (flake:json first_seen.run_id or this repo's
actions/runs URL) and a test; duplicates of one test keep the lowest number;
every refused match prints its reason.

Files: bin/gstack-issue-links, bin/gstack-ship-receipt, lib/issue-links.ts,
lib/ship-receipt.ts, lib/headless-artifacts.ts (ship-receipt issues.related),
lib/result-codes.ts (ISSUE_LOOKUP_FAILED, ISSUE_LINKS_MISSING,
resultLineWithDocs), bin/gstack-doctor-components.sh (regenerated),
docs/pregate.md, docs/troubleshooting.md, test/ship-issue-intent.test.ts,
test/helpers/pregate-fixture.ts (gh shim: repo view, api graphql, full issue rows).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship): link issues by intent at publish and handoff; Fixes: trailer at commit (Lane D: D1, D2, D-a)

- Step 15: a commit fixing a user-named issue carries a `Fixes: #<n>` trailer
  (offset by tightening Step 15 so the skeleton stays at 80,998 <= 81,000).
- pr-body: an explicit "Issue links" step runs gstack-issue-links before the
  body is composed (previously only a placeholder inside the body template);
  interactive runs ask once about `(promote: fix #N)` references and add
  `--supersedes`/`--credit` only on the owner's confirmation; unattended runs
  keep Refs and list unpromoted candidates, Related lines and lookup failures
  in the completion message; `ISSUE_LINKS_MISSING` from the receipt write.
- handoff (no-PR lanes): runs gstack-issue-links and passes --issues to the
  receipt; the completion message gains an `issues:` line.
- Regenerated ship/SKILL.md and sections; refreshed the four ship goldens.
- Parity: union 309,431 / 187,706 = 1.6485 (> 1.6450 by 655 bytes); maxSizeRatio
  raised to the measured 1.6485 with its justification, as previous waves did.

Files: ship/SKILL.md.tmpl, ship/SKILL.md, ship/sections/pr-body.md.tmpl,
ship/sections/pr-body.md, ship/sections/handoff.md.tmpl, ship/sections/handoff.md,
test/fixtures/golden/{claude,codex,factory,agy}-ship-SKILL.md,
test/helpers/carve-guards.ts (ship maxSizeRatio).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(install): one Bun resolution contract, versioned runtime store, verdict per (checkout, project), drift and wrapper rows (A1-A3, A5, A6, A8, A-c, A-d, A-f, A-h, A-i)

- bin/gstack-bun-version.sh: GSTACK_BUN_DEFAULT=1.4.3 beside the 1.4.2 floor,
  gstack_bun_install_version (GSTACK_BUN_INSTALL_VERSION override),
  gstack_bun_store, portable gstack_realpath, and gstack_bun_resolve (pin and
  default in the store, $BUN_INSTALL/bin, ~/.bun/bin, PATH; first candidate
  satisfying every pin; shim-marked files never returned). gstack_bun_launch_dir
  is replaced by it.
- lib/pregate/runtime.ts: resolveBun, the TypeScript twin; launchRuntime runs
  the Bun the install verdict recorded under the admission condition and
  explains the skip otherwise.
- bin/gstack-capy-install: install and --check resolve through the contract;
  verified archives publish atomically to <state root>/runtimes/bun/<v>/bun
  under ~/.gstack-runtime.lock and ~/.bun/bin is never written; the "no Bun
  satisfies" line names the candidates judged; --check reports
  BUN_RESOLUTION_DRIFT with one converging fix.
- bin/gstack-install-verdict.sh, lib/install-verdict.ts: schema 2 verdicts
  keyed by (checkout, project) with pin, bun_path, bun_version, bun_rule;
  schema 1 path still read; admission binds test-running workflows to the
  project and refuses a running Bun the verdict did not record.
- bin/gstack-doctor-check.sh, lib/doctor-components.ts: wrapper core row
  (CAPY_WRAPPER_STALE by active provenance, WARN for stale Drive copies),
  runtime drift row, shim note, install-version note.
- lib/result-codes.ts: BUN_RESOLUTION_DRIFT, BUN_INSTALL_VERSION_INVALID;
  CAPY_WRAPPER_STALE fix names the workaround and the owner action.

Files: bin/gstack-bun-version.sh, bin/gstack-capy-install,
bin/gstack-doctor-check.sh, bin/gstack-doctor-components.sh (generated),
bin/gstack-install-verdict.sh, lib/doctor-components.ts,
lib/install-verdict.ts, lib/pregate/runtime.ts, lib/result-codes.ts,
test/bun-resolve.test.ts, test/gstack-capy-install.test.ts,
test/gstack-doctor.test.ts, test/install-verdict.test.ts,
test/pregate-guards.test.ts

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(issue-links): --author for the Related lookup when gh runs as an app (Lane D: D2)

On a Capy machine the gh viewer is `capy-ai[bot]`, not the owner (checked live
against garrytan/gbrain #6252), so "other authors" needs the PR author named:
`--author <login>` overrides the viewer; the pr-body Issue links step says to
pass it when gh runs as an app.

Files: bin/gstack-issue-links, docs/pregate.md, ship/sections/pr-body.md.tmpl,
ship/sections/pr-body.md, test/ship-issue-intent.test.ts,
test/helpers/carve-guards.ts (ship maxSizeRatio re-measured: 309,483 / 187,706 = 1.6488).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(troubleshooting): BUN_RESOLUTION_DRIFT and BUN_INSTALL_VERSION_INVALID anchors; CAPY_WRAPPER_STALE covers the wrapper row (A5, A8, A-f, G1)

Files: docs/troubleshooting.md, bin/gstack-capy-install, bin/gstack-doctor-check.sh, test/gstack-capy-install.test.ts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(install): marked per-directory bun and bunx shims for fresh Capy shells (A4, A-e)

gstack-capy-install (install mode, Capy machines only, GSTACK_BUN_SHIM=0 opts
out) writes ~/.local/bin/bun and bunx under ~/.gstack-runtime.lock. The shim
bakes the store, verdict directory, checkout and install default, walks up to
.git without spawning git, runs the Bun the (checkout, project) verdict
recorded, else a store Bun matching the .bun-version/package.json subset
(stderr names the --check to run when none matches), else the install
default, else the next unmarked bun on PATH. A foreign file or dangling link
is never touched. GSTACK_BUN_SHIM_EXPLAIN=1 prints project, record, choice and
rule; the doctor's runtime row shows the shim and its target.

Files: bin/gstack-capy-install, test/gstack-capy-install.test.ts, test/gstack-doctor.test.ts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): test stage never hangs silently; small machines record the remote gate (Lane C, GBRA-95)

C1 diagnosis (gbrain 92f0ea87, a core edit selecting 3,683 local files, 358
serial; Bun 1.4.2 and 1.4.3 identical): --timeout was applied per runner
spawn (unit group plus one per serial file), so the check was unbounded, and
spawnSync buffered all output until it returned: 360 s with 0 bytes on stdout
and stderr. A backgrounded child holding stdout made spawnSync wait the full
timeout and then report exit 0 (a silent wait, then green). Not the Bun 1.4.2
spawnSync hang.

C2/C-b: test-tier commands (lanes runner, guards, the --remote gate) run via
lib/pregate/supervise.ts: own process group (setsid), stdout/stderr appended
to a log file (no pipes), async supervision; CheckDef.run may return a
promise and runPregate/withFingerprint await it (a rejection is incomplete).
Leftover group members are killed after exit; SIGINT/SIGTERM to pregate
SIGKILLs running groups, writes no pregate.json, exits 130/143. Windows:
taskkill /T /F (reparented or detached descendants can survive; documented).

C3/C-a: --timeout bounds the whole check; groups past the deadline are not
started. --stall-timeout <s> (default stall_timeout_s, else 300; 0 disables)
kills a group whose log stops growing and records PREGATE_STALLED naming the
last file started. Live stderr: PREGATE_TEST per file (bun test adapter; any
runner for one-file runs), PREGATE_HEARTBEAT after 60 s without progress,
PREGATE: tests <verdict>. --json stdout unchanged.

C4/C-c: under 8 cores, a base-branch remote_gate or a non-local test_backend
records the local tier as a requires-remote obligation with its command
(pregate.json/remote_gate or test_backend/<backend>). --remote runs the
declared remote_gate now (needs --allow-repo-commands, never --policy-from
head) under --spend-cap/GSTACK_SPEND_CAP_USD; it clears only on
PREGATE_REMOTE: tree=<tested tree> tests>0 failed=0 with exit 0, and reports
spent/reserved/unknown.

G1: new code PREGATE_STALLED has its result-codes row, troubleshooting anchor
and the installer-form error line (CODE; url#anchor).

Files (G2): lib/pregate/supervise.ts (new), lib/pregate/types.ts,
lib/pregate/context.ts, lib/pregate/index.ts, lib/pregate/checks/lanes.ts,
lib/pregate/checks/guards.ts, lib/pregate/config.ts, lib/headless-artifacts.ts,
lib/result-codes.ts, bin/gstack-pregate, bin/gstack-doctor-components.sh
(generated), docs/pregate.md, docs/troubleshooting.md,
test/pregate-supervise.test.ts (new), test/pregate-remote.test.ts (new).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(ship): Step 5 pre-gate text for stalls and the small-machine remote gate (Lane C-c)

The pre-gate paragraph now says `incomplete` blocks (a stall is incomplete)
and that `requires-remote` covers the remote gate under 8 cores, cleared by
`gstack-pregate clear` or `--remote --spend-cap <usd>` only under a cap the
user gave. Kept within the ship parity size cap (union 308,771 of 308,776
bytes; base 308,767), so the `--explain` hint moved to docs/pregate.md. The
handoff's escalation line already names any `requires-remote` lane; unchanged.

Files (G2): ship/sections/tests.md.tmpl, ship/sections/tests.md (generated).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(install): one ok-trailer grammar with requested, pins-skipped and latest notes; bootstrapper revision 2 exports origin's VERSION (A9, A-a)

Notes ride only on the ok trailer in fixed order; the failure head is
unchanged, pinned by a test that runs the Capy skill's dispatch examples
against real doctor output. The latest note comes only from
GSTACK_CAPY_REMOTE_VERSION, which the bootstrapper sets from a fetch in this
run and unsets otherwise (a stale FETCH_HEAD never reaches the installer).

Files: bin/gstack-capy-install, bin/gstack-capy-session,
capy/skill/gstack/scripts/install.sh, capy/skill/gstack/SKILL.md,
test/gstack-capy-install.test.ts, test/capy-skill-wrapper.test.ts,
test/gstack-doctor.test.ts

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(upgrade): every success path certifies the caller's project; a pins failure keeps the move, ends on gstack: fail pins, exit 1, no pending marker (A7, A-b)

gstack-upgrade captures the caller's directory and git toplevel before any
cd. Already-current, fast-forwarded and resumed-pending paths run
bin/gstack-capy-install --project <it> on Capy (installing a verified pinned
Bun) or gstack-doctor --check --require runtime,pins elsewhere. The
reinstall's own trailer is held back when a project certification follows,
so no ok precedes a pins failure; a RUNTIME_PIN_CONFLICT stop becomes
gstack: fail pins — <conflict>. --check and --ff-only-no-reinstall certify
nothing.

Files: bin/gstack-upgrade, test/gstack-upgrade-bin.test.ts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(install): fresh-install log lines name the clone and every host installed (A10)

gstack-capy-install prints `cloned <repo> at <sha> (<version>)` for a checkout
it cloned, or one the bootstrapper (revision 2, GSTACK_CAPY_CLONED) cloned in
this run, instead of `reusing`. setup's final line is
`gstack ready (<hosts>)` from the same rows as its summary table, including
the --refresh-registered upgrade summary.

Files: bin/gstack-capy-install, bin/gstack-capy-session,
capy/skill/gstack/scripts/install.sh, setup, test/gstack-capy-install.test.ts,
test/host-conformance.test.ts

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): --remote runs the gate only when local tests are selected (Lane C4)

With only platform lanes selected, --remote no longer launches the remote
gate with an empty file list; the existing no-local-lane path applies.

Files (G2): lib/pregate/checks/lanes.ts.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): one-word rec, verified pairing, sealed attempt results, deferred reopen (Lane B: B1 B2 B4 B5)

B1/B-b/B-c  `rec` (aliases: all, approve all, accept all, take all recommendations)
    takes every recommendation, plan changes included; `as-is` keeps every
    direction. The render offers `rec` first and prints what it resolves to
    with gate_rev and rec_hash. `gstack-autoplan recommend` changes one
    recommendation before relay (provenance recorded, p1 and decisions follow)
    and bumps rec_rev, so a `rec` without the new --rec-hash is refused
    (GATE_REC_STALE). An agent answer needs the owner's words verbatim
    (--owner-reply <text>|-, --owner-reply-file; OWNER_REPLY_REQUIRED); a
    parseable owner reply that resolves differently from the relay is refused
    (GATE_OWNER_REPLY_MISMATCH). Supersedes field-wave R1 per the owner's
    gate_rev 1 decision.
B2/B-a  reconcile associates by title first; a file:line-only match is
    `unverified` (associated, never confirmed). `b` is recommended only for a
    confirmed pair with the same `changes` and one shared proposal (override)
    or the same normalized remedy; the basis says which. Negative control and
    positives copied from run-20261014225954 (test/fixtures/autoplan-pairing).
B4/B-e  each attempt writes <phase>-<voice>.<attempt>.md; submit refuses another
    attempt's file (ATTEMPT_MISMATCH) and binds a sealed 0444
    <phase>-<voice>.<attempt>.bound.md copy, so a late write changes nothing
    bound; reopen keeps sealed copies in place.
B5/B-d  answer records accepted changes as amendments (status amend_pending) and
    reopens nothing; revise reopens what changed. `revise --settle <id|d4>`
    discharges a packaging/ordering change on an unchanged plan
    (AMENDMENT_NOT_SETTLEABLE otherwise). APPLY/NEXT/status lines say which.

DRIVER.md and the reply table move to the rec grammar.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): durable checkpoint and resume --from; Capy checklist (Lane B: B12)

With GSTACK_AUTOPLAN_CHECKPOINT_DIR set, every command that leaves a run at
rest (gate_pending, amend_pending, complete, incomplete) publishes
<dir>/<run>/: checkpoint.json listing every file's sha256, the run under run/,
the owner's plan file under plan-input/ when it lives outside the run, and
restore.md as the human index. Publication swaps in a fully written sibling.
Checkpointing at every rest state, not only gate_pending, keeps accepted
decisions from rolling back on restore.

`gstack-autoplan resume --out <new dir> --from <checkpoint>` checks
containment (no absolute or .. paths, regular files only) and every hash
before publishing the run with one rename. It restores a missing plan file
into the run, journals `restored` with both hosts, and takes the lock.
CHECKPOINT_INVALID and CHECKPOINT_TARGET_EXISTS each get a result-codes row
and a troubleshooting anchor. Journal and revise staging paths are now
run-relative, so a moved run recovers.

DRIVER.md and the Capy skill's autoplan section get a short Capy checklist:
always drive gstack-autoplan, never present a hand review as an autoplan run,
relay every gate page with rec as the default, pass --owner-reply, and point
the checkpoint at the private project-user Drive folder.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* A-g: run the quick free tier on GSTACK_BUN_DEFAULT in CI; drift test pins it

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): unattended contract and reply-unparsed fix move to rec, sealed results, settle and checkpoints (Lane B)

docs/unattended.md: rec/as-is/rec except grammar, --owner-reply and recommend/--rec-hash, unverified pairing and the shared-proposal rule for b, amend_pending and revise --settle, attempt-owned result paths with the sealed .bound.md copy, render --all, and the checkpoint/resume --from paragraph. GATE_REPLY_UNPARSED's fix names rec/as-is (DRIVER.md regenerated).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs/capy-install: resolver, versioned store, bun shim, trailer notes; wrapper minimum 2

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): --timeout bounds each runner process again, not the whole lanes check

Lane C made --timeout a deadline for the whole lanes check, so a repo whose
unit group and serial files each fit in 600 s but exceed it together ended
incomplete and blocked /ship. --timeout is per runner process again (unit
group, each serial file); the stall timeout still catches hung or silent
processes. A timed-out process is incomplete naming its last file, and the
next serial file still runs. Regression: three 1.5 s serial files under
--timeout 3 pass; one 5 s file is incomplete.

Files (G2): lib/pregate/checks/lanes.ts, bin/gstack-pregate (help),
docs/pregate.md, test/pregate-supervise.test.ts.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pins): CI exact pins for this platform are alternatives; the installer prefers a non-CI exact pin, else the install default among CI alternatives, else the highest verified (integration item 1)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): clear validates the remote gate receipt; test_backend run URLs are attested

`gstack-pregate clear` accepted any --run-url for a small machine's
obligation. A pregate.json/remote_gate obligation now clears only with
--receipt <file> holding the gate's PREGATE_REMOTE: line, validated as
--remote validates it (tree equals the tested tree, tests > 0, failed = 0;
shared parseRemoteReport/remoteReportProblem); a run URL is usage (exit 2)
and a bad receipt is PREGATE_RECEIPT_INVALID (exit 1, obligation unchanged).
A test_backend/<backend> obligation has no machine-checkable receipt: its
--run-url is recorded as attested:<url> and the output says attested, not
validated. Platform lanes are unchanged. Hints name the right clear form.

New code PREGATE_RECEIPT_INVALID: result-codes row, troubleshooting anchor,
installer-form error line, regenerated doctor components.

Files (G2): lib/pregate/index.ts, lib/pregate/checks/lanes.ts,
bin/gstack-pregate, lib/result-codes.ts, bin/gstack-doctor-components.sh
(generated), docs/pregate.md, docs/troubleshooting.md,
test/pregate-remote.test.ts.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(issue-links): derive this PR's author when gh runs as an app, so handoff and pr-body exclude the owner's own PRs (Lane D fix 1)

The handoff ran gstack-issue-links without --author, and the pr-body step only
asked the agent to pass one, so under Capy's app identity (viewer
`capy-ai[bot]`) the owner's own open PRs were listed as `Related:`. The bin now
derives the author itself: --author, else the gh viewer, else (for a `…[bot]`
viewer) the HEAD commit's GitHub user, else the owner of a user-owned
repository; with none it keeps every PR and reports ISSUE_LOOKUP_FAILED.
`--json` gains `author: {login, source}`; the stderr preview names it. Both ship
steps work unchanged, so the pr-body `--author` clause is dropped (union
309,487 -> 309,435 bytes, under the unchanged 1.6488 cap; skeleton 80,998).

Files: bin/gstack-issue-links, lib/result-codes.ts (ISSUE_LOOKUP_FAILED row),
docs/troubleshooting.md (#issue-lookup-failed), docs/pregate.md,
ship/sections/pr-body.md.tmpl, ship/sections/pr-body.md,
test/helpers/pregate-fixture.ts (gh stub: PR-author query),
test/ship-issue-intent.test.ts.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(wrapper): GSTACK_CAPY_MIN_WRAPPER back to 1; an active wrapper below the minimum is a WARN; gstack-upgrade never leaves a pending marker for the wrapper row and maps every installer stop to a trailer (integration items 2, 9)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(shim): validate and contain store pins, read the 'none' record outside projects and in the checkout, fall back in the resolver's order, stay quiet without a pin; quote baked paths; publish bunx and replace store entries without a window (integration items 3, 4, 6, 9)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(install): --check fails BUN_RESOLUTION_DRIFT only when the recorded Bun is gone, changed or no longer satisfies the pins; a newer candidate is a note and the recorded Bun stays the launch Bun (integration item 5)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(install): one final 'gstack ready (claude, codex)' after both host setups (integration item 7)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): lanes and guards validate the install verdict like admission and return incomplete (INSTALL_UNVERIFIED, BUN_RESOLUTION_DRIFT) before launching; the checkout binds the 'none' verdict (integration item 8)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CI pin alternatives, shim order and containment, drift note, wrapper WARN, final ready line

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): settle after or with a revise, title pairs need the same remedy, legacy gates refuse rec (integration items 1, 7, 8)

1. A gate with a scope change (uc1) and a packaging change (uc2) answered
   `rec` deadlocked: after `revise --plan v2 --incorporates uc1` reopened the
   phases, `revise --settle uc2` compared against the first phase snapshot
   (now undefined) and was refused forever. Settle evidence is now the plan
   hash recorded when the owner accepted the change (Amendment.plan_sha256)
   or a later plan_revised hash, plus "the plan file has no unrevised edits".
   `--settle` may ride the same revise as `--plan/--incorporates` and binds
   to the revision's hash. Settling the last amendment after a reopen leaves
   the run `running` (the reopened phases rerun) instead of approving it.
   NEXT and PLAN_AMEND_PENDING list the settle step before the edit step.
7. A title association alone no longer confirms: the same remedy confirms,
   opposite remedies (one keeps, drops or negates what the other changes)
   disagree, different or missing remedies stay `unverified`. The pairing
   fixture gains same-title negative controls (opposite and different
   remedies) and a same-remedy positive, for ordinary findings and user
   challenges.
8. A gate.json without rec_rev (written by 1.91.101.0, whose render said
   `all` leaves b items pending) refuses rec/all/approve all/`all except`
   with GATE_REC_STALE until a re-render binds --rec-hash; explicit tokens
   still answer. New gates carry rec_rev: 0.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): checkpoints never touch the live run; generations, newest-valid restore, validated staging (integration items 2-6)

2. checkpointRun canonicalizes the collection and the run directory (symlinks
   resolved through the deepest existing ancestor) and refuses, before
   touching anything, when they are the same or one contains the other
   (CHECKPOINT_OVERLAP); restore applies the same check to source, target and
   staging. Before, <root>/<run> equal to the live run replaced it.
3. Publication writes an immutable generation (generations/g<revision>-…),
   renames it into place complete, then switches current.json with one
   rename; the previous generation is kept, so an interruption at the publish
   boundary (fault hook checkpoint-before-pointer) leaves the last checkpoint
   current. A generation never replaces a newer one (higher run revision):
   "CHECKPOINT: skipped … newer". Publication and restore hold the
   collection's .lock; restore also holds <out>.lock.
4. Restore checks every listed file's real path stays inside the generation
   (an ancestor symlink no longer copies outside files), parses run.json and
   runs validateRun on the staged run before publishing; a refusal leaves
   --out absent. readState reroots plan_input and plan_source for moved runs,
   and a restore with the owner's plan file gone points both at the restored
   copy, so a second restore cycle and a later revise work.
5. A checkpoint failure after a committed command prints
   "CHECKPOINT: failed for <run>: … ; the command's result stands" on stderr
   and keeps the command's exit code.
6. `gstack-autoplan checkpoints --from <dir>` lists generations newest first
   (run, gate_rev, status, revision, time, hash ok|bad, current).
   `resume --from <collection or root>` restores the newest generation that
   verifies, printing each corrupt newer one it skipped; a root holding
   several runs must name one.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: budget the Capy skill's autoplan checklist and trim its install notes

Files: capy/skill/gstack/SKILL.md, test/fixtures/context-budget.json (capy/skill/gstack ceiling only: 2364 tok x 1.10)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: release 1.91.102.0 (tentative stamp) — GBRA-40 field list

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: supply _setup_ready_line to setup-tail harnesses, register the pairing fixture, make the admission test runner-Bun independent; announce shim writes

Files: test/setup-hook-syntax-gate.test.ts, test/redact-prepush-hook.test.ts, test/setup-playwright-best-effort.test.ts, test/helpers/free-fixtures-data.ts, test/pregate-guards.test.ts, bin/gstack-capy-install
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ci: run quick-bun-default on the ubicloud-standard-8 class the free suite uses

The ubuntu-24.04 runner timed out two Swift typecheck tests at 30 s (render @Observable marker, ios-qa-regen); both pass on Bun 1.4.3 on Ubicloud.

Files: .github/workflows/free-tests.yml
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): read bun test's GitHub Actions group headers; exclude pregate-remote from the Windows subset; give quick-bun-default the free suite's flake policy

Files: lib/pregate/supervise.ts, test/pregate-supervise.test.ts, scripts/lib/windows-curation.ts, .github/workflows/free-tests.yml
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: run the Capy wrapper and shim doctor-row tests on POSIX only (Git Bash prints MSYS paths)

Files: test/gstack-doctor.test.ts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: restamp 1.91.107.0 (1.91.106.0 is claimed by #3209)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pregate): spawn the supervised shell through lib/script-invocation (#3197 tripwire)

The supervisor now resolves bash via bashCommandInvocation, so Windows uses
Git Bash instead of a PATH bash, and an unresolvable bash reports spawn-failed.
guards.ts and lanes.ts no longer spawn bash (they run through supervise.ts),
so their KNOWN_SITES entries are removed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(qa-functional): disable auto gc and maintenance in the fixture repo

On eval-slices (9), qa-functional-webhook-fix failed mid-run with 100+
'directory watch lost: .git/objects/..' entries and forbidden writes to
.git/info/refs and .git/objects/pack. That is git's detached auto
maintenance repacking the fixture under the write observer. This applies the
same gc.auto=0 / maintenance.auto=false config qa-callers-fixture uses.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(autoplan-guard-pty): say Phase 2 starts without waiting for user input

On eval-slices (1), haiku published Phase 1 and then ended its turn with
'Waiting for next invocation to continue with step 8'. Step 5 tells it to end
its turn while the reviewer runs, so step 8's 'In a later message' read as a
later user turn. Phase 2 never started, the guard logged 2 of the 4 expected
allows, and the run hit its deadline. Step 8 now says to continue in the next
assistant message, still separate from the step 7 publication message.

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>
2026-10-16 23:09:23 +00:00
Garry Tan 47d639abff v1.91.101.0 fix: close the field wave's residual gaps (#3173)
The field wave's residual gaps are closed. v1.91.96.0 through v1.91.100.0 
shipped the install-honesty and unattended-`/autoplan` wave 
(`docs/designs/GSTACK_FIELD_WAVE_2026_10_12.md`); running that release on a 
Capy machine left six gaps, each reproduced here with a test that failed 
first.
2026-10-14 17:36:39 +00:00
Garry Tanandcapy-ai[bot] 7edaf4f50a v1.91.98.0 fix: plan obligations meet repo gates; priced paid gates; machine-proved restamps (field wave C, items 14-17) (#3166)
* docs(designs): gstack field wave plan (2026-10-12) and the shared simulated Capy host fixture

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(pregate): price_command config key for the non-executing call plan a paid gate is priced from

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(pregate): repo guards a lane must pass, verified launch Bun and per-file serial runs in lanes, unknown flags exit 2

The guards check runs each .gstack/pregate.json guard whose globs match a
touched file in its own process with its own timeout (PREGATE_GUARD_FAILED,
never downgradable, incomplete without --allow-repo-commands). The lanes
runner and guards get the first Bun in $BUN_INSTALL/bin or ~/.bun/bin that
satisfies gstack's and the project's engines.bun; serial_patterns files run
one process each. price_file replaces the unreleased price_command key: a
paid gate is priced from a call-plan data file, never by running a command.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pricing): Sonnet 5.5, Gemini 3.x and gbrain embedding rows from fetched pages; Opus 4.7 at its current list price

Each new row carries its source URL and fetch date (2026-10-12). Embedding
models bill input only, so they live in EMBEDDING_PRICING beside PRICING
(eval arms never resolve to them); pricingRow also accepts gbrain's
provider:model ids (voyage:voyage-4). claude-opus-4-7 moves from 15/75 to the
5/25 the Anthropic pricing page lists; benchmark-runner's expected costs follow.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(eval-plan): price-gate prices a paid gate from a call-plan data file, never executing it

gstack-eval-plan price-gate --gate "<exact command>" reads a GSTACK_EVAL_CALLS
v1 file (--plan-file, else the base policy's price_file at HEAD), checks its
binding (gate command string equality, head with only the plan file changed
since, every input's sha256 at HEAD), prices each call purpose (aggregate
totals) and each one-call reservation, and writes a receipt binding the price
to the gate, head, inputs and plan bytes. Unpriced models print unknown, never
zero (EVAL_PRICE_MISSING); a missing plan or no call lines is
EVAL_GATE_UNPRICED unless --allow-unpriced records an owner override; over
--cap-usd / --smoke-cap-usd is EVAL_GATE_OVER_CAP; malformed or partial files
refuse EVAL_DRY_RUN_FAILED and stale ones EVAL_PLAN_STALE. dry-run --cap adds
the same reservation-fits-cap check. Wire format, receipt and the reference
emitter (formatEvalCalls): docs/eval-calls.md.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(eval-plan): the approval step prices every paid gate with price-gate

Step 4 runs gstack-eval-plan price-gate for each paid gate the plan names and
puts its GATE_PRICE line in the ask; the dry-run checklist documents
reservation-fits-cap under --cap.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(sealed): sealed-output guard over every published commit, in the pre-push hook and gstack-pregate sealed

A repo with a sealed key in .gstack/pregate.json (base branch union the
pushed commit, so a push can tighten but never relax) refuses publishing
sealed paths, transcripts, quoted answers, seeds or local home paths to a
public or unknown destination (SEALED_OUTPUT_REFUSED); private warns.
Path rules see every added, renamed or copied path in each published
commit (git rev-list <local> --not --remotes=<remote>), text rules each
commit's added lines; waivers only from the base branch allow file; a
malformed policy fails closed; visibility caches public 24 h, private 1 h.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(eval-plan): only an undeclared plan is unpriced; a missing price_file is stale, a bad base policy refuses

price-gate's EVAL_GATE_UNPRICED (and --allow-unpriced) now covers only no
plan declared at all or a plan with zero call lines. A declared price_file
missing from the HEAD commit is EVAL_PLAN_STALE (exit 1, not overridable); an
unresolvable origin/<base> is POLICY_SOURCE_UNAVAILABLE and an invalid
.gstack/pregate.json is PREGATE_CONFIG_INVALID (both exit 3).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(restamp): the repo's stamp rule (stamp_files, literal stamp_patterns) and restamp_command in the staging worktree

stamp_files is an allowlist applied before every stamp rule; stamp_patterns
are bounded literal {version} templates shared by the restamp writer and the
tree receipt. restamp_command runs first in the staging worktree with the
target version (argument and GSTACK_RESTAMP_VERSION), needs a clean caller
tree, skips gstack's version writer and keeps output confinement; a failure
or a wrong version writes nothing. migrations { dir, id } is the policy key
gstack-pregate regate reads.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(pregate): gstack-pregate regate --against <gated-head> with per-lane reuse and migration collisions

Reuse comes only from a tree receipt evaluated now, with a bundle produced
on the gated tree, the current execution identity and an unmoved, known
predecessor head. Each lane prints reusable/rerun/not-reusable; REGATE:
not-needed needs stamp-only, every bundle and --require lane reusable (a
stamp-sensitive lane reruns) and a finished migration lookup. Migration
numbers the branch adds are checked against the base tree and every other
open PR (gh pr list --limit 1000; 100-file lists refetched with gh api
--paginate); any lookup that cannot finish is unknown and blocks
not-needed (MIGRATION_COLLISION). Bare --against routes to the verb.
docs/pregate.md gains the regate section and the gbrain worked configs.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(contract): lanes run gstack-pregate (and the sealed guard where configured) before done; handoff carries the gstack trailer and PREGATE: line

The coordinator contract gains a 'Before done' paragraph and the handoff
order GSTACK_RESULT, gstack: ok|fail <rev>, PREGATE:, gate summary; the
spec section is regenerated and docs/unattended.md states the same rule.
A new test pins the terms and their order; the byte-identity pins stay.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.98.0: pregate guards, priced paid gates, regate and the sealed-output guard

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: drop the helper-only Capy host fixture test (test-of-test ratchet); lane tests exercise the helper

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: price-gate --gate-file keeps free text out of the /eval-plan fence; shortest dependency traces; bounded test spawns

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ci(windows): curate out the new pregate/restamp tests that spawn bin/ shebang scripts through runBin

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>
2026-10-13 15:38:41 +00:00
Garry Tanandcapy-ai[bot] 945ac301a9 v1.91.97.0 fix: closable unattended /autoplan runs on Capy (field wave B, items 6-13) (#3165)
* docs(designs): gstack field wave plan (2026-10-12) and the shared simulated Capy host fixture

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): scope keys on rendered surfaces, per-axis provenance, --no-dx and a read-only plan marker

UI scope reads the Implementation plan only and needs a rendered file path or a UI
term next to a visual noun; bare UI words stay weak evidence (sections load, no
Design phase). Scope records sources {ui,dx} (flag|marker|detected), --no-dx turns
DX off, a first-line <!-- gstack-autoplan-scope: ... --> marker is read and never
written, and the first next prints SCOPE: evidence plus a SCOPE_PIN hint. The
snapshot tool's scope output carries uiRequired from the same detector and
autoplan Step 2 uses it instead of a prose grep (field wave item 11).

Intentional pin change: test/review-checklists.test.ts Scope literal and the
source= line shape (source=ui:detected,dx:detected).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(plan-reality): a receipt per measured number, the rule text for a rule claim, dot-path receipts

Each clause stating a measured quantity (a unit, or a number after measured/costs/
takes/took) needs its own receipt; misses print unreceipted_numbers=<n> and one
NUMBER_UNRECEIPTED: <clause> line each. A line claiming a decision rule must quote
it or link its file:line (unquoted=<n>). Either miss maps to the existing verdict
(incomplete unattended, repair otherwise). RECEIPT_RE accepts dot paths and needs
a hex letter or a commit/backtick context for a sha. New pure checkPlanReality(planText)
runs the same checks over plan prose for gstack-autoplan submit (field wave item 12).
The unreceipted= text token is now pinned as well as the JSON.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(autoplan): generated DRIVER.md, the compact entry for a parent driving gstack-autoplan

autoplan/DRIVER.md (from autoplan/DRIVER.md.tmpl) is what a parent agent on any host
reads instead of autoplan/SKILL.md: phase order and scope flags, the next/submit/
answer/revise/export loop with the plan-specified submit --record/--attest/
--unavailable, revise --incorporates/--withdraw and next --scaffold, the reviewer
RESULT FORMAT, the gate grammar including all as-is, the run files, the result codes
and the coordinator contract, every list rendered from code (117 lines). gen:skill-docs
emits it as a Claude asset, so normal, out-dir and dry-run inventories and the
freshness check cover it. gstack-autoplan --help and the first next print
DRIVER: <root>/autoplan/DRIVER.md, resolved through an install root's recorded
.source-path (new lib/source-root.ts) (field wave item 13).

Intentional pin change: test/gen-skill-docs-checks.test.ts asset inventory gains
autoplan/DRIVER.md.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(doctor): --min-revision, a launch Bun found off PATH, planning-only pins SKIP

gstack-doctor --check gains --min-revision <v>|unknown: below it the revision
row FAILs with REVISION_BELOW_MINIMUM naming the Capy wrapper or
bin/gstack-upgrade; unknown says so and never claims the minimum. The runtime
and pins rows name a supported Bun found in $BUN_INSTALL/bin (not on PATH)
with the export/GSTACK_LAUNCH fix (gstack_bun_launch_dir, one helper in
bin/gstack-bun-version.sh). --for a planning-only workflow (autoplan, the plan
reviews, office-hours) reports a repo test-pin mismatch as SKIP pins
(planning-only; ...). New result codes UPGRADE_REFUSED, UPGRADE_FETCH_FAILED,
REVISION_BELOW_MINIMUM, CAPY_WRAPPER_STALE, INSTALL_UNVERIFIED with
troubleshooting anchors; REVISION_UNMET's fix names bin/gstack-upgrade.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(install): install verdict and install admission at skill start

bin/gstack-install-verdict.sh (Bash) and lib/install-verdict.ts (TypeScript)
are the one reader of the install verdict gstack-capy-install writes to
<state root>/install-verdicts/<sha256(checkout realpath)>.json (checkout,
HEAD, workflow and required components, planning-only pins, trailer). The
source checkout and capy/support.env resolve through gstack_source_root /
sourceRoot, which follow an installed root's .source-path.

gstack-skill-start, after SESSION_KIND: an unattended session (any host)
refuses on a PATH Bun below the supported minimum; with GSTACK_CAPY=1 an
unattended or explicit spawned session also refuses without a passing
verdict for this checkout, HEAD and workflow (INSTALL_UNVERIFIED). A refusal
prints the INSTALL: row, an install-refused instruction block bound to its
SESSION_ID, GSTACK_RESULT ... status=refused run=- and exits 3. Ambient
spawned sessions warn; GSTACK_ALLOW_UNSUPPORTED_RUNTIME=1 admits and says so.
capy/support.env declares GSTACK_MIN_REVISION and GSTACK_CAPY_MIN_WRAPPER.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(capy-install): launch PATH, Bun reuse and CI pins, setup skip on HEAD, verdict, --check

The GSTACK_LAUNCH line carries PATH=<dir>:$PATH when the certified Bun is not
first on PATH, plus GSTACK_CAPY=1 and GSTACK_INSTALL_VERDICT, and
GSTACK_LAUNCH_PATH: <dir>; the doctor runs with that PATH. A supported Bun in
$BUN_INSTALL/bin is reused instead of downloaded again. Project pins are read
with bin/gstack-runtime-pins.ts (CI lanes included): when every exact pin is
gstack's verified version the archive is installed alongside a different PATH
Bun; any other exact pin is RUNTIME_PIN_CONFLICT. Both ./setup runs are
skipped when this HEAD was set up with the same hosts, model and browser flag
and the check passes (never after a fast-forward); a failed setup ends with
gstack: fail setup and is retried next run. --check certifies only;
GSTACK_CAPY_LOCK_HELD=1 accepts the bootstrapper's held lock; result anchors
come from the generated components table; REV_NOTE names bin/gstack-upgrade.

Intentional pin change: test/gstack-capy-install.test.ts --revision trailer
now names <root>/bin/gstack-upgrade (the old text named a command that never
existed).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* result codes: PLAN_SECTIONS_INVALID, PLAN_AMEND_PENDING, GSTACK_VERSION_CHANGED, INSTALL_VERDICT_FAILED, ARTIFACT_GATE_UNSETTLED

Troubleshooting anchors for each and the regenerated doctor components table (field wave lane B-core).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* artifact contract: changes, recommended_basis, carried decisions, attested count, settled-gate check

Findings and decisions carry the user challenge's `changes` value; decisions record recommended_basis, origin,
carried_from and chosen_text; validate refuses a complete run with an unsettled gate (ARTIFACT_GATE_UNSETTLED) and
prints attested=<n>. The gate reply grammar gains `all as-is` and resolves partial replies against prior answers
(field wave B2a/B2b).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan: run-state fields, plan-text hashing, version migration and admission modules

RunState gains gstack_version, plan_input/heading, scope_flags, plan_revision, amendments and plan_reality; voices
record receipt kind and reviewed hash. New pure modules: Implementation-plan review hash, scaffold and drift lines
(B1c); gstack_version stamp and legacy decision-id migration (B1a); install-verdict and Bun-minimum admission
with a local verdict shim until lane A's lib/install-verdict.ts lands.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

bin/gstack-autoplan-snapshot.ts exports its section scanner and review projection, and initializes only a plan with
no section headings by wrapping it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* autoplan: closable runs - submit --record/--attest/--unavailable, revise, amendment interlock, agreeing-UC defaults, admission

B1a: an older run directory prints GSTACK_VERSION_CHANGED once and migrates legacy decision ids; a newer one refuses.
B1b: submit binds hand-run records (fence, table, severity list, No findings.), attested binds need --attempt,
--attempt is optional with one open attempt, --unavailable/--failed close an outside voice native_only, and submit
caches the plan-reality report by Implementation-plan hash.
B1c: revise reviews a revised plan in the same run as one recoverable transaction (reopen on hash drift plus Eng,
add newly in-scope phases, .r<rev>/.v<k> archives, gate_rev+1 at the gate); PLAN_SECTIONS_INVALID and next --scaffold;
PLAN_CHANGED / PLAN_SOURCE_CHANGED drift hints.
B2a/B2b: user challenges carry changes; agreeing voices with the same changes on a confirmed finding recommend b with
both remedies shown (or the reconcile proposal); accepted changes print APPLY and become pending amendments that next
and export refuse past until revise --incorporates names them or --withdraw drops one; all as-is; partial replies,
DECIDED block, carry-forward and rerun demotion.
Mutating verbs pass admission (GSTACK_CAPY install verdict; unattended Bun minimum; override recorded as a deviation).
Intentional pin rewrite: test/autoplan-answer-invalidation.test.ts reopen tests now revise --incorporates before rerun.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(upgrade): bin/gstack-upgrade, the unattended fast-forward every fix line names

--check fetches and prints current|behind <installed> -> <remote> (<n>
commits); the default fast-forwards to the remote default branch tip and
reinstalls (bin/gstack-capy-install on a Capy install, else ./setup
--refresh-registered), completing a pending reinstall on the next run. It
refuses (UPGRADE_REFUSED, exit 3, nothing changed) a dirty tracked byte, a
diverged commit, a pinned checkout, the incoming Bun floor and a held
.setup-lock; never stashes or resets; an unreachable remote is
UPGRADE_FETCH_FAILED. Fetches are receipted (fail-open). The unattended
skill-end UPGRADE_AVAILABLE line is followed by UPGRADE_COMMAND naming it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(capy): vendored Capy skill, frozen bootstrapper and full wrapper bin/gstack-capy-session

capy/skill/gstack/ is the Drive skill's source of truth. scripts/install.sh
is a frozen bootstrapper: it prints gstack-capy-skill: wrapper <n> (<path>),
clones or fetches under .gstack-capy-install.lock, reads the remote
capy/support.env (FETCH_HEAD), fast-forwards a clean unpinned checkout below
GSTACK_MIN_REVISION (refusing dirty, diverged or pinned checkouts with the
exact commands; GSTACK_CAPY_AUTO_UPGRADE=0 disables), and execs the
checkout's own bin/gstack-capy-session with GSTACK_CAPY_LOCK_HELD=1 so the
held lock is never taken twice. Offline it says the remote minimum is
unknown. A Drive copy older than GSTACK_CAPY_MIN_WRAPPER prints an owner
action (CAPY_WRAPPER_STALE). SKILL.md: check at session start, install
lazily before the first workflow, the GSTACK_LAUNCH line, the trailer rule,
the subagent first-report line, gstack-pregate sealed before any push, and
the autoplan/DRIVER.md pointer. The context-budget fixture gains the skill's
entry.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: Capy install layers, lazy install, snapshot bake, forward-only recovery, raising the minimum

docs/capy-install.md describes the three layers (Drive bootstrapper, full
wrapper, installer), the lazy install, the GSTACK_LAUNCH line, install
admission, baking gstack into a Capy snapshot, and that recovery after an
interrupted fast-forward completes or refuses the pending install stages
(checking out an older commit is not a rollback). docs/CHANGELOG_STYLE.md
(the release doc; there is no docs/RELEASING.md) says when
GSTACK_MIN_REVISION may be raised.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* refactor(capy): the stale-copy owner action moves from the frozen bootstrapper to bin/gstack-capy-session

The checkout-owned full wrapper reads GSTACK_CAPY_MIN_WRAPPER through
gstack_support_env_get(gstack_source_root) and compares it with the
bootstrapper revision it was handed, so the rule can change without
recopying the Drive skill. The bootstrapper keeps only what a stale checkout
cannot do: clone, fetch, read the remote minimum, fast-forward, exec.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.96.0: honest install and self-upgrade on Capy; supported minimum 1.91.96.0

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.97.0: closable unattended autoplan runs on Capy

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: drop the helper-only Capy host fixture test (test-of-test ratchet); lane tests exercise the helper

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): revise naming a non-pending decision refuses with AMENDMENT_UNKNOWN, not PLAN_AMEND_PENDING

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: bound the new sync spawns in the install-verdict and wrapper tests (spawnSync tripwire)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(autoplan): pin CLI refusals to the result-code registry's fix text

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(gen-skill-docs): emit autoplan/DRIVER.md only when the autoplan template is in the tree (setup fixtures with a skill subset)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): run.lock is linked into place with its owner written; a fresh unreadable lock is held, not stolen

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ci(paid-pr-profile): the vendored Capy skill is free-only; free-only files are not prompts needing paid coverage

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore(harness): non-behavioral HARNESS_VERSION decision for the PR-profile free-only rule

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(doctor): lane A runtime and pins cases are platform-neutral (bash paths; a lane-free .bun-version pin)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(designs): field wave plan with amendments and the gate rev 2-3 review record (ARTIFACT_VALID, 3 gate revisions)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy-install): follow a project's exact Bun pin above the minimum when gstack has its verified archive (adds Bun 1.4.3)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: the installer follows a verified exact project Bun pin (capy-install, troubleshooting, changelog)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(capy-install): the install reason names the project's pin and gstack's real minimum

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ci: run the main-targeted checks after retargeting #3165 to main

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(autoplan-admission): the PATH-Bun refusal case needs the POSIX Capy host stub; skip it on Windows

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>
2026-10-13 15:17:39 +00:00
3b7254a54d v1.91.92.0 feat(outside-voice): enforce codex_reviews consent in the send binaries, codex_effort setting, privacy disclosures (Wave 9 Lane C) (#3144)
Outside-review consent (codex_reviews) is enforced in gstack-codex-probe
run-with-timeout, gstack-claude-code, gstack-outside-voice run and the
autoplan runner (not_run / consent_missing, exit 3; #3102). Codex reasoning
effort resolves GSTACK_CODEX_EFFORT, then codex_effort, then each gate's
default inside run-with-timeout --effort (D1-A; #3098, closes #2934). README
and telemetry privacy disclosures corrected (#1081, #1080, #1150).

Co-authored-by: Lockyer <135391289+Lockyer228@users.noreply.github.com>
Co-authored-by: Lubos Buracinsky <159481718+lubosxyz@users.noreply.github.com>
2026-10-11 19:09:12 +00:00
Garry Tanandcapy-ai[bot] 2865cfcb3f v1.91.82.0 fix(plan-reality): name the review input and the PLAN_REALITY line in the reality-rows prose (#3126)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-11 05:52:27 +00:00
Garry Tanandcapy-ai[bot] 5d647455f2 v1.91.79.0 feat(eval-plan): /eval-plan tier 1, lane-check, evidence verify, coordinator contract, owner brief, contributor-PR mode, banned terms (multi-agent wave PR E) (#3123)
* v1.91.79.0 feat(eval-plan): /eval-plan tier 1, lane-check, evidence verify, coordinator contract, owner brief, contributor-PR mode, banned terms (multi-agent wave PR E)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(spec,review): fail closed when the coordinator contract cannot be read; restore the omitted-Army sentence

The spec --execute spawn captures `gstack-autoplan contract` before piping
the archive, so a lane never starts without the contract; the C9 fixture
installs its gstack-like checkout (bin, lib, a contract stub) at every
host's global root. Review Step 5.8 keeps the pinned
'without claiming specialist coverage' wording.

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>
2026-10-11 03:10:06 +00:00
Garry Tanandcapy-ai[bot] ab79e55119 v1.91.78.0 feat(review): plan reality rows, sideways review and cso sweep, investigate recipes (multi-agent wave PR D) (#3119)
* v1.91.70.0 feat(unattended): artifact contract, unattended session kind, findings-derived review log, gate list

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.72.0 feat(autoplan): unattended runner next|submit, pluggable outside voice, review checklists, spec-loop cap

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(b-runner): atomic lock creation in spend-ledger, judge bundle skips runner-only sections, fixture env spelling

- lib/spend-ledger.ts: create the lock by linking a complete temp file so a
  contender never reads an empty lock and breaks a live owner (CI admitted 20
  of a cap of 8 under contention); unreadable locks break only by mtime age.
- test/helpers/workflow-judge-input.ts: exclude manifest runner_only sections
  (the B4 checklists) from the judge bundle; the judge rates the interactive
  workflow. test/workflow-judge-input.test.ts expects the same set.
- test/helpers/autoplan-run-fixture.ts: spell the runner's session kind
  without the literal the free-suite environment scan rejects.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.74.0 feat(review): plan reality rows, sideways review and cso sweep, investigate recipes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: register the investigate carve case and map Reality rows to real headings in the review checklists

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: pin the corrected Reality rows obligation rows

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(investigate): use allowlisted placeholders in the flake and polluter fences; select the investigate carve case on PTY changes

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>
2026-10-11 02:14:23 +00:00
Garry Tanandcapy-ai[bot] 140003be95 v1.91.72.0 feat(autoplan): unattended runner gstack-autoplan next|submit, pluggable outside voice, review checklists, spec-loop cap (multi-agent wave B-runner) (#3117)
* v1.91.70.0 feat(unattended): artifact contract, unattended session kind, findings-derived review log, gate list

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.72.0 feat(autoplan): unattended runner next|submit, pluggable outside voice, review checklists, spec-loop cap

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(b-runner): atomic lock creation in spend-ledger, judge bundle skips runner-only sections, fixture env spelling

- lib/spend-ledger.ts: create the lock by linking a complete temp file so a
  contender never reads an empty lock and breaks a live owner (CI admitted 20
  of a cap of 8 under contention); unreadable locks break only by mtime age.
- test/helpers/workflow-judge-input.ts: exclude manifest runner_only sections
  (the B4 checklists) from the judge bundle; the judge rates the interactive
  workflow. test/workflow-judge-input.test.ts expects the same set.
- test/helpers/autoplan-run-fixture.ts: spell the runner's session kind
  without the literal the free-suite environment scan rejects.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(spend-ledger): accept Windows' status-only report of the killed child

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>
2026-10-11 00:32:15 +00:00
Garry Tanandcapy-ai[bot] 45a678323b v1.91.70.0 feat(unattended): artifact contract + validator, unattended session kind, findings-derived review log, gate list (multi-agent wave B-core) (#3115)
* v1.91.70.0 feat(unattended): artifact contract, unattended session kind, findings-derived review log, gate list

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: register test/fixtures/multi-agent-wave as a free fixture (consumer: headless-artifacts.test.ts)

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>
2026-10-10 23:26:08 +00:00
Garry Tanandcapy-ai[bot] 5b9b8372c4 feat: honest work and gate integrity — gate-edit detector, review/ship gate pass, zero-run green, claims-need-evidence kernel (#3114)
* docs(designs): honest work and gate integrity plan (autoplan-reviewed)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(e2e): review-gate-integrity rule case registered in touchfiles and the PR profile

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(honesty): claims-need-evidence kernel, no_claim card field, CEO value test, implementer dispatch rules, ACCEPTANCE_EDITED, Honest Work ethos

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(gate-diff): gate-edit detector lib + CLI, patch fixtures, calibration script, tests_ran in gstack-evidence

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(gate-diff): RH-15? only on CI/config floors after calibration

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(review,ship): Gate Integrity category, GATE_SCAN_BLOCK, one-way gate disposition, actor stamping, ZERO-RUN lanes, draft-while-open

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: re-measure parity and context budgets on the integrated tree

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(touchfiles): gate-diff fixtures and helpers select review-gate-integrity

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: archaeology lint wording, paid-file census, harness-version non-behavioral record

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pin review Step 3.5 rename, plan-path placeholder, mktemp template, per-stream evidence tail

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: ACCEPTANCE_EDITED fence substitutes the <plan-path> placeholder

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(gate-diff): shallow boundary commits report no_base instead of a whole-tree inventory; recalibrate

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>
2026-10-10 22:33:01 +00:00
+22 8bb6d65270 v1.91.66.0 fix: /autoplan without permission prompts after background reviewers, 34 contributor PRs from the backlog triage (#3087)
* docs: fix CONTRIBUTING.md test-tiers link in TESTING_INTERNALS

The link resolved relative to docs/, pointing at a nonexistent
docs/CONTRIBUTING.md. Adopts #3070.

Co-authored-by: thearbajonart <334330110+thearbajonart@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ci: refresh GitHub Actions SHA pins (setup-buildx 4.4.1, build-push 7.4.0, attest 4.2.2, setup-node 7.0.0)

Rewrite of dependabot #2988. Every bumped `uses:` stays pinned to the full
commit SHA (verified against the upstream tags) and now carries its exact
version comment, including the lines that had none. setup-node 6.5.0 -> 7.0.0
is a major bump; its notes list an ESM migration, cache outputs and removal of
a dummy NODE_AUTH_TOKEN export, none of which affect our node-version-only use.
actionlint 1.7.11 (CI image) and 1.7.12 are clean.

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(openclaw): stop advising a per-spawn env for spawned sessions

OpenClaw's sessions_spawn has no env argument (openclaw/openclaw#51654
was closed without adding one), so the documented
env: { OPENCLAW_SESSION: "1" } silently did nothing. Point users at the
ACP harness or Gateway environment instead and guard the old advice.
Adopts #2749.

Co-authored-by: DanCanadian <211164803+DanCanadian@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(benchmark): scope /benchmark routing to web page performance

/benchmark claimed the bare words "benchmark" and "performance", so model
and eval benchmark requests could route to the web performance skill
instead of /benchmark-models. Narrow the description, Use-when list and
triggers to web-specific phrases, point model/skill benchmarks at
/benchmark-models, and split the root router line the same way. The
catalog lead stays within the discovery budget ("Web performance ...").

Adopts #2302 and closes duplicate #2083 (rewritten on current main).

Co-authored-by: Nader Helmy <31414549+creatornader@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(llms.txt): link skills by generated path, drop host-skipped skills

gen-llms-txt built every skill link as <name>/SKILL.md, so the router
pointed at a nonexistent gstack/SKILL.md (it is the root SKILL.md) and
/claude-code pointed at a SKILL.md the Claude host never generates.
Links now use the template's generated output path, and skills the
Claude host skips are left out of the index. Adopts #2279.

Co-authored-by: Nader Helmy <creator.nader@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ci): install Bun from the SHA-256-verified release archive in GitLab CI and Ubicloud setup

Rewrite of #1713. .gitlab-ci.yml's .setup-bun anchor and
scripts/ubicloud/setup-free-suite.sh still piped https://bun.sh/install into
bash. Both now download the bun-v$BUN_VERSION linux-x64 release zip, check it
against the same SHA-256 Dockerfile.ci uses (#1706) before unzipping, install
it to ~/.bun/bin and assert `bun --version`. test/ci-image-cli-pin.test.ts runs
curlPipedToShell over both files and binds their hash and BUN_VERSION to
Dockerfile.ci's amd64 arm and package.json's engines floor, so a Bun bump has
to move all of them together. Verified by running the GitLab anchor in
debian:stable-slim (bash and sh) and the Ubicloud block in a temp HOME.

Co-authored-by: Zee Zheng <228040220+spacegeologist@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(browse): viewport auto unpins a pinned viewport without a restart

`viewport WxH` pinned the page with no way back short of `browse restart`,
which also drops a headed /connect-chrome session. `viewport auto` (aliases
`reset`, `unpin`) now undoes the pin:

- headed: the context already launches with `viewport: null`, but Playwright
  cannot drop a page's emulated size (and re-applies it on new frame
  sessions), so the active tab gets a fresh page in the same context at the
  same URL or load-html content. Cookies and storage persist, the tab id and
  ownership stay, refs reset as on navigation, and the page follows the real
  window again.
- headless: back to the 1280x720 launch default, tracked viewport included.

`auto` with --scale is rejected. Fixes #1059. Adopts #2782 and #1881.

Co-authored-by: Jack Thomas <17882510+loulanyue@users.noreply.github.com>
Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(browse): screenshot accepts --clip=x,y,w,h and --selector=<css>

Agent-generated commands often use the GNU `--flag=value` form, which threw
"Unknown screenshot flag". Both value flags now accept it, through the same
validation and conflict checks as the space-separated form. Adopts #1563.

Co-authored-by: techcenter68 <75930234+techcenter68@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(benchmark): price Codex cached input at the cache rate, stop calling Gemini OAuth ready

Codex reports cached_input_tokens as a subset of input_tokens, but the
adapter billed all of input_tokens at the full input rate. Split them
into disjoint uncached and cached counts (what estimateCostUsd expects)
and show new+cached input in the table and Markdown reports. A stored
Gemini OAuth file alone is now reported as not ready, with a reason
naming GEMINI_API_KEY; key-based auth stays ready. Adopts the focused
subset of #2283; the capacity error code and stdin change are left out
(no captured failure or reproduced hang).

Co-authored-by: Mattias Petersson <mattias.petersson@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(review): catch loosened-input consumers and stale user-facing strings

The Enum & Value Completeness check fired only on newly added values, so a
diff that widens what a validator, parser or guard accepts, and breaks an
unchanged downstream consumer outside the diff, was a blind spot. Widen the
check's trigger (heading unchanged) and add a consumer-grep bullet. Teach
the maintainability specialist to flag user-facing strings whose guarding
condition changed while the text did not.

Adopts #2141 (rewritten on current main; the section heading is kept).

Co-authored-by: Arno V <38716+aversini@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(global-discover): bucket Codex sessions by originator

Every Codex rollout counted as one undifferentiated codex bucket, so
/retro global could not tell interactive Codex Desktop work from
codex_exec runs or Claude Code-driven calls. Normalize
session_meta.payload.originator into desktop, exec, claude_code or
other (missing, unknown and non-string values), report the split per
repo as codex_originators and globally as tools.codex.originators, and
print it in the summary. Existing totals are unchanged. Adopts #1488.
Refs #1315.

Co-authored-by: 0xDevNinja <manmit0x@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(hook-check): cover skill frontmatter hooks, sourced helpers, conflict markers and the caller's tsconfig

Rewrite of #3066. bin/gstack-hook-check only listed setup's hooks plus
/autoplan's by name, so the /careful and /freeze PreToolUse checks (also run
by /guard and /investigate), /plan-ceo-review's hand-off hook and the helpers
they source were never parse-checked before Claude Code ran them.

- The hook list is setup's _hook_command_path arguments plus every gstack path
  on a `command:` line in a generated */SKILL.md frontmatter (9 hooks, up from
  6). The generated files are read rather than the .tmpl sources because the
  /autoplan and /plan-ceo-review commands come from resolvers.
- Each shell hook's gstack-tree helpers (`.`/`source` lines, assignments and
  shellcheck source= directives, followed transitively) are parsed too:
  careful/bin/hook-extract.sh and bin/gstack-state-root.sh for /careful and
  /freeze.
- The shim, its helpers, each TypeScript entry and every local module the
  bundle used (bun build --metafile; entry only when bun lacks it) are scanned
  for conflict-marker lines, which still parse inside heredocs, strings and
  template literals.
- bun build runs from the gstack root, so the caller's broken tsconfig.json or
  bunfig.toml no longer fails every TypeScript hook. Lists are newline
  separated, so a root with spaces works.

Tests in test/setup-hook-syntax-gate.test.ts cover each case; the gstack-doctor
fixture now copies autoplan/SKILL.md, whose frontmatter registers the hook its
hooks-row test breaks. docs/troubleshooting.md describes the wider check.

Co-authored-by: Benjamin D. Smith <7134745+BenjaminDSmithy@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(review): extend defensive-security framing to the security specialist and Red Team

The "authorized defensive-security review" framing and fixture summary mode
lived only in the adversarial subagent prompt. The security specialist and
the Red Team also reason adversarially over the full diff, so repos whose
test corpus is attack payloads could still get those passes refused.

Move both paragraphs into scripts/resolvers/defensive-review.ts (the
adversarial render stays byte-identical), state them once in the specialist
dispatch for the security specialist and the Red Team, and have the Red
Team prompt start from them. Testing and the other specialists keep full
fixture reads; the codex host still strips Review Army. Parity caps for
ship and review rise by the measured 1,380 bytes each (carve-guards notes).

Adopts #1921 (rewritten on current main).

Co-authored-by: Brian Majewski <1693720+bmajewski@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(team-init): make the required-mode hook shell-neutral (node CommonJS, no shell variables)

Rewrite of #2217. Required team mode wrote a bash check-gstack.sh and
registered it as "$CLAUDE_PROJECT_DIR/.claude/hooks/check-gstack.sh", which
only works when the hook runner is a POSIX shell. Under cmd.exe or PowerShell
(Windows, Copilot CLI) the variable is not expanded and the .sh cannot run, so
an intended allow or deny became a hook error.

- The hook is now .claude/hooks/check-gstack.cjs: the same root search
  (GSTACK_ROOT, every host's global root, the migrated repo), with the home
  directory from HOME, then USERPROFILE, then os.homedir(). It prints {} when
  gstack resolves and the PreToolUse deny JSON with exit 2 when not.
- The registered command is `node -e "require(require('path').resolve(
  process.env.CLAUDE_PROJECT_DIR || '.', '.claude', 'hooks',
  'check-gstack.cjs'))"`: no `$` or `%`, so sh, cmd.exe and PowerShell all
  pass it through unchanged.
- An existing check-gstack registration (matcher Skill or Skill|skill) is
  replaced in place; duplicates are dropped and unrelated hooks in the same
  entry kept. The legacy .sh is deleted only after the settings write
  succeeds (a tracked one joins the suggested git add), and is kept when bun
  is missing or the write fails, which now reports instead of claiming success.

Tests: team-mode and the hook-schema test run the command as registered;
test/team-init-hook-shell-neutral.test.ts runs it through the platform's
default shell (cmd.exe on the Windows lane, which curates it in) and through
PowerShell when installed (verified here in the pwsh 7 container). The
routing-probe check for the bash `_GSTACK_ROOT` gate now pins the same
contract in the .cjs: every host root probed, block only when none resolves.

Co-authored-by: neallee2012 <1499497+neallee2012@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(setup-gbrain): register the gbrain MCP through bun.exe on Windows so no console window opens

Rewrite of #2007, folding #1963's MCP notes. On Windows the local stdio
registration stored the bun `gbrain` binstub; gbrain.exe starts bun in a new
console, so every Claude Code session opened a visible terminal for the MCP
(the contributor's process trees show it; bun.exe launched directly attaches
to Claude Code's headless ConPTY).

Under MINGW/MSYS/Cygwin the skill now resolves BUN_ROOT from BUN_INSTALL or
~/.bun and registers `$BUN_ROOT/bin/bun.exe <global node_modules
gbrain/src/cli.ts> serve`. That path also covers a `bun link`ed clone, whose
global node_modules entry links to it; gstack-gbrain-install records no other
clone location. When bun.exe or the entry is missing it registers
`$BUN_ROOT/bin/gbrain.exe` by its full name, because Claude Code does not
apply PATHEXT to a stored path (#1963). POSIX keeps the binstub line. The
skill also notes that `claude mcp list` can show "Failed to connect" while a
live session holds a local PGLite brain's single-writer lock (#1963).

test/setup-gbrain-windows-mcp.test.ts runs the generated fence under bash with
stub uname/claude and a temp HOME for MINGW64, MSYS with BUN_INSTALL, a
missing entry, and Linux. It is listed as Windows-incompatible (POSIX stubs);
the console behavior needs a manual Windows check.

Co-authored-by: Max Hogan <max@maxhogan.dev>
Co-authored-by: maxpetrusenkoagent <280464918+maxpetrusenkoagent@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(hosts): rewrite every "Agent tool" phrasing for agent-runtime hosts

The Agent-tool rewrite for hermes, gbrain, openclaw and factory keyed only
on "use the Agent tool", but templates mostly say "via the Agent tool",
"with the Agent tool", "multiple Agent tool calls" or "Use the Agent tool",
so the Claude tool name leaked into those hosts' skills and sections. Add
ordered rules after the existing key (possessive, "the Agent tool", then
bare "Agent tool") mapping to sessions_spawn (gbrain/openclaw),
delegate_task (hermes) and delegation (factory). No goldens change.

Adopts #1935 (rewritten on current main, without the new goldens).

Co-authored-by: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(setup-deploy): Vercel auto-deploys only when connected to the Git repo

/setup-deploy stated that Vercel always deploys on push, which is false for
CLI-only projects with no Git integration, and its nothing-detected path did
not say why such a project is invisible to detection. Qualify the Vercel
trigger (ask for and record the CLI deploy command otherwise) and note that
`vercel link` creates .vercel/ so a re-run detects the project.

Adopts the Vercel accuracy part of #2992 (rewritten on current main); the
third-party bring-up tool pointer is not adopted.

Co-authored-by: mikehasa <91774998+mikehasa@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(retro): persist recommendations so the next retro detects follow-through

/retro produced "3 Things to Improve" but never saved them in its JSON
snapshot, so the next retro could not tell whether last week's
recommendations were acted on. Step 13 now drafts the items before saving
and always writes a `recommendations` array ({category, text}, [] when
empty); Step 12 scores each prior recommendation addressed/partial/open
against this window's commits, files and metrics and renders a
follow-through line, skipping silently for snapshots without the key. The
report format ties the items to the saved array. Global mode is unchanged.

Adopts #1853 (rewritten on current main). Refs #1834.

Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(global-discover): count the interactive Codex CLI (codex_cli_rs) in its own cli bucket

* feat(developer-profile): --reconcile backfills office-hours tenure from timeline.jsonl

sessions[] is written only at office-hours Phase 4.5, so runs that ended
earlier never counted toward tenure and the tier undercounted. Add a manual
`--reconcile` that scans projects/*/timeline.jsonl for office-hours
`completed` events and appends a count-only row ({date, mode, project_slug,
signal_count: 0, signals: [], backfilled: true}) for each run with no
sessions[] entry for the same project within 60 minutes, extended back by a
duration_s under 8h. It is idempotent, skips malformed lines, and leaves the
file untouched on a no-op. `--read` counts backfilled rows for SESSION_COUNT
and TIER but takes LAST_*, DESIGN_*, CROSS_PROJECT and the nudge from logged
sessions only. Not wired into the preamble yet; the office-hours greeting
guard for backfill-only profiles is left to the office-hours owner.

Adopts #2668 (rewritten on current main). Closes part (b) of #2657.

Co-authored-by: Briac <137724549+briacSck@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): the publication hook approves /autoplan's own Reads after the skill turn

Claude Code applies a skill's allowed-tools only to the turn that invoked it.
On 2.1.292 the default fork-subagent mode runs reviewers in the background, and
the completion notice starts a new turn, so later Reads outside the working
directory (the next phase's section file, the close packet) raised permission
cards. Skill hooks stay registered for the session, and a PreToolUse "allow"
skips the card (reproduced in a PTY on 2.1.292).

autoplan/bin/owned-read.ts approves a parent Read only when the guard itself
returned no output, and only for this installation's autoplan/sections/*.md
(canonical path or the gbrain :user render) or an immutable phase artifact in
<repo>/.gstack/tmp/autoplan/autoplan-<phase>-*/ whose repo is the session's
project directory or contains it. Denials, unverified allows, child calls and
every other path are unchanged. renderSectionBase and userRenderRoot move
there with it.

Tests that asserted a verified driver Read as {} now expect the approval;
autoplan-owned-read covers the shipped shim, the close packet without a
journal, verified artifacts through the guard, look-alikes (foreign install,
writable copy, symlink alias, other repository, other names) and a guard
denial staying a denial.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): restore point and phase artifacts live in the project's .gstack/tmp/autoplan/

Skill hooks do not run inside subagents, so a reviewer launched after a
background completion notice raised a card for its own input (native-prompt.md
under the state root). Step 1 now puts RESTORE_PATH in the repository's
git-excluded .gstack/tmp/autoplan/ (added to .git/info/exclude, mode 700), and
the snapshot tool writes every phase artifact beside it, so /autoplan and its
reviewers read them from the working directory without a card. The guard's
bindings are unchanged: they anchor on the restore point's directory. Step 1
still prints the slug, which the old RESTORE_PATH carried.

A free test runs the generated Step 1 block twice from a repository
subdirectory: the restore point lands in <repo>/.gstack/tmp/autoplan/, the
exclude line is written once and git status stays clean. The autoplan parity
cap rises by the measured bytes (115,270 / 101,979 = 1.1303).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(evals): autoplan-guard-pty fails on any permission card after the reviewer's notice turn

The scripted boundary now mirrors Step 1's layout (restore point and artifacts
in the project's .gstack/tmp/autoplan/) and continues past the Phase 2 entry to
dispatch the Phase 2 reviewer after the CEO reviewer's completion notice. The
case asserts four verified guard allows, that the close packet Read, the Phase 2
section Read and the Phase 2 dispatch came after a task-notification turn, that
the Phase 2 reviewer read its input, and that no permission card appeared at
all. Still one trial on haiku, about 75-85 seconds.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(autoplan): permission cards after a background reviewer, and where /autoplan keeps its files

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(outside-review): read a trailing '— Medium.' or '(High)' severity on a finding line, the shape Codex now writes

* feat(design): honor OPENAI_BASE_URL for every design API call

One resolver, openaiUrl() in design/src/auth.ts, now builds every OpenAI
URL the design binary, its prototype and its live model check use. Setting
OPENAI_BASE_URL sends image generation and screenshot analysis to an
OpenAI-compatible gateway; unset or blank keeps api.openai.com. The
prototype script now goes through receiptedFetch, so its egress is
receipted like the rest, and receipts already record the gateway host.

A source scan keeps any design file outside auth.ts from hardcoding an
OpenAI API URL again, and a request-shape test proves the gateway reaches
both the vision and image endpoints.

Co-authored-by: JackJin <1037461232@qq.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* review: testing specialist treats negative assertions as decisions

A new assertion that something is absent records a behavior removal and
needs cited intent. A rename or removal in the diff can empty a standing
negative assertion so it passes forever; the specialist now greps the suite
for negative assertions naming the old value.

Adopted from the testing-specialist part of a community PR; the scope-check
hunk targeted text that no longer exists.

Co-authored-by: EmilianoU26 <314541067+EmilianoU26@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* review: security specialist checks authorization a route-guard read misses

Four access-control classes where the guard is correct and the object still
leaks: error pages composed outside the guard, ownership surviving a role
downgrade, list/detail/download paths checked as one, and a session mutated
before the identity-switch callback is validated.

Adopted to review/specialists/security.md only; the /cso hunk targeted a
bullet list that is now an OWASP/ASVS table.

Co-authored-by: EmilianoU26 <314541067+EmilianoU26@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* review: zero findings is valid; suppress six common false positives

The checklist now says a clean diff may come back clean, and suppresses
framework-owned error handling, long exhaustive switches, null derefs a
type guard already narrows, N+1 on fixed-cardinality loops, hardcoded test
fixture values and non-cryptographic Math.random().

The contributor's "missing input validation on an internal function" and
"missing await on fire-and-forget" suppressions are left out: both can hide
real bugs.

Co-authored-by: frosimanuel <frosimanuel@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(todos): parked contributor ideas by theme; /autoplan permission follow-ups

* design-review: capture code tokens before universal principles

/design-review read only DESIGN.md and otherwise fell back to universal
principles, so a project whose system lives in CSS custom properties,
tailwind.config or a theme file got audited and mocked up against an
invented aesthetic. The skill now reads code tokens before falling back,
and the target-mockup brief reuses the captured colors, fonts, radii and
spacing, changing layout only.

The contributor's optional microcopy checks (domain vocabulary, human
register) are not adopted here.

Co-authored-by: Tom Lam <tomlam0811@berkeley.edu>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(sidebar): add a terminal text-size picker to the toolbar

The sidebar terminal toolbar gets an XS-XL text-size picker beside
Restart. SM (13px) stays the default, so nothing changes until a user
picks a size; the choice persists in chrome.storage.local and applies
to the live terminal, re-fitting xterm and re-sending the PTY size two
frames later so the new character cell is measured first.

A VM test runs the real sidepanel-terminal.js through one auto-connect
and checks the creation size, the stored-size fallback, persistence and
the live resize.

Co-authored-by: Yotam <yotsurfing@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(design-shotgun): generate with Codex's built-in $imagegen on Codex

On the Codex host, /design-shotgun now generates and edits mockups with
Codex's documented $imagegen skill in its default built-in mode (the
image_gen tool), so users signed in with ChatGPT need no OPENAI_API_KEY.
The design binary stays for the local comparison board only, images are
published with gstack-design-claim as before, and screenshot evolution
loads the captured page with view_image before an $imagegen edit.

Step 3c-3d moved into a DESIGN_SHOTGUN_GENERATION resolver that returns
the existing design-binary text unchanged for every other host; the
Claude output differs only in two host-neutral rewordings of the
evolve-from-screenshot pointers. DESIGN_SETUP and the regenerate step of
the board loop gain matching Codex-only text for design-shotgun.

Co-authored-by: Jinzhe <hwang.phy@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* voice: ban the "load-bearing" stock phrase

Models overuse "load-bearing"; it joins the AI-vocabulary ban line in both
voice tiers. The tier-2 voice directive is also tightened (the meta
"compressed for runtime" tag and the bounded closer's restated exemption
clause) so the shared preamble shrinks by 163 bytes per tier-2+ skill,
which also pays for the reply-language rule that follows. The ship goldens
are refreshed for the new render.

Co-authored-by: Nader Helmy <creator.nader@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* voice: reply in the language of the user's latest message

Every skill's voice directive now tells the agent to reply in the language
of the user's latest message unless asked otherwise, so long English skill
text no longer drags a Chinese (or any non-English) session into English.
Mixed-language sessions follow the latest message. Code, commands, paths,
identifiers and quoted output stay verbatim, and at tier 2+ so do the
machine-read question markers (D<N>, option letters, (recommended)).

The rule costs 205 bytes per tier-2+ skill and 144 per tier-1 skill. A
further 25-byte cut to the bounded closer's exemption list leaves the net
for this wave at +17 bytes per tier-2+ skill and +158 per tier-1 skill.
review, qa and browse caps rise with measured notes; the ship goldens are
refreshed.

Co-authored-by: Xianying Tan <shrektan@126.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(redact-prepush): committed exact-span allowlist at .gstack-redact-allowlist

The pre-push hook never fed the engine's allowlist option, so a reviewed,
known-benign value (a public dev-compose URL, a documented sample key) warned
or blocked every push, and the only ways out were a bypass or reshaping code
until the detector stopped matching.

The hook now reads the repo-root .gstack-redact-allowlist from each pushed
commit (never the working tree), one exact matched span per line with #
comments. Only a finding whose matched text equals an entry is suppressed: a password alone, a
substring, or a different key still reports and still blocks, and engine.*
unscanned findings are untouched. Every push that carries entries prints the
entry count and each suppressed finding's rule and file line. Oversized files
(over 64 KiB) are ignored. gstack.redact.allowEmail keeps working as before.

Co-authored-by: Boyard Engels <boyard.engels@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(brain-sync): opt-in removal publishing with a bulk-removal valve

gstack-brain-sync never published a removal: a deleted synced file, or the
old directory after a project slug migration, stayed on the remote forever
and gbrain indexed both copies.

New setting artifacts_sync_removals (off by default). When on, each drain
commits and pushes, receipted like every push, the removal of tracked files
that are gone from disk and match the sync allowlist. Transcript pages are
never removed here, and a decision log goes only together with its active
snapshot. One valve: a drain that would remove more than 20 files at once
publishes none and says so. `gstack-brain-sync --publish-removals` lists the
pending removals and `--publish-removals --yes` publishes them on demand,
whatever the setting.

Co-authored-by: Jey2311 <5177215+Jey2311@users.noreply.github.com>

* feat(windows): setup.ps1 checks prerequisites and runs ./setup in Git Bash

A PowerShell entry point for Windows users. It checks that Git for Windows,
Bun and Node.js are on PATH (printing the winget command for each missing one
and changing nothing), finds Git Bash from git.exe rather than a PATH bash
that may be WSL's, and runs ./setup from the checkout with every argument
passed as its own argv entry to a constant bash script. No argument is
interpolated into shell source. ./setup itself is unchanged.

Co-authored-by: Jim McKeeth <jim@mckeeth.org>

* v1.91.63.0: CHANGELOG, version

* fix(ci): link bunx after the SHA-verified Bun install in GitLab CI and the Ubicloud setup

* fix(redact-prepush): strip every parent column from combined-diff lines, so a merged release bump is exempt like any other

* fix(hook-check): treat a Windows drive path as absolute (cygpath when present), so --list finds the skill hooks from a native caller

* fix(windows): owned-read requires the read-only attribute on Windows; setup.ps1 passes arguments NUL-separated through a private file; Windows-only tests expect the owned-read approval

* perf(hook-check): bundle every hook's TypeScript entries in one bun process instead of two bun starts per entry (seconds each on Windows)

* perf(hook-check): read all skill frontmatter in one awk and scan conflict markers with one grep per hook (half the process starts)

---------

Co-authored-by: thearbajonart <334330110+thearbajonart@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: DanCanadian <211164803+DanCanadian@users.noreply.github.com>
Co-authored-by: Nader Helmy <31414549+creatornader@users.noreply.github.com>
Co-authored-by: Nader Helmy <creator.nader@gmail.com>
Co-authored-by: Zee Zheng <228040220+spacegeologist@users.noreply.github.com>
Co-authored-by: Jack Thomas <17882510+loulanyue@users.noreply.github.com>
Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com>
Co-authored-by: techcenter68 <75930234+techcenter68@users.noreply.github.com>
Co-authored-by: Mattias Petersson <mattias.petersson@gmail.com>
Co-authored-by: Arno V <38716+aversini@users.noreply.github.com>
Co-authored-by: 0xDevNinja <manmit0x@gmail.com>
Co-authored-by: Benjamin D. Smith <7134745+BenjaminDSmithy@users.noreply.github.com>
Co-authored-by: Brian Majewski <1693720+bmajewski@users.noreply.github.com>
Co-authored-by: neallee2012 <1499497+neallee2012@users.noreply.github.com>
Co-authored-by: Max Hogan <max@maxhogan.dev>
Co-authored-by: maxpetrusenkoagent <280464918+maxpetrusenkoagent@users.noreply.github.com>
Co-authored-by: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com>
Co-authored-by: mikehasa <91774998+mikehasa@users.noreply.github.com>
Co-authored-by: Briac <137724549+briacSck@users.noreply.github.com>
Co-authored-by: JackJin <1037461232@qq.com>
Co-authored-by: EmilianoU26 <314541067+EmilianoU26@users.noreply.github.com>
Co-authored-by: frosimanuel <frosimanuel@gmail.com>
Co-authored-by: Tom Lam <tomlam0811@berkeley.edu>
Co-authored-by: Yotam <yotsurfing@gmail.com>
Co-authored-by: Jinzhe <hwang.phy@gmail.com>
Co-authored-by: Xianying Tan <shrektan@126.com>
Co-authored-by: Boyard Engels <boyard.engels@gmail.com>
Co-authored-by: Jey2311 <5177215+Jey2311@users.noreply.github.com>
Co-authored-by: Jim McKeeth <jim@mckeeth.org>
2026-10-08 17:40:06 +00:00
4e5ffbb857 v1.91.59.0 fix(autoplan): bind init through symlinked plan directories and superseded failed inits (#3083)
* fix(autoplan): bind init through symlinked plan directories and superseded failed inits

The publication guard compared snapshot init's JSON against the literal argv
spelling, but init reports canonical destinations, so a plan under macOS /tmp
or /var (realpath /private/...) always denied init_mismatch. The guard also
hard-failed on the first errored init, so a corrected re-run never bound.

- bin/gstack-autoplan-snapshot.ts: export canonicalDestination (the inner
  destination() path math); initializePlan output is unchanged.
- autoplan/bin/phase-publication-hook.ts: compare activePlan/restorePath
  against the canonicalized argv; a mistyped tool path is unbindable, not a
  crash; skip errored inits and deny init_failed only when the most recent
  init errored; Write/Edit to the active plan match by canonical path.
- autoplan/bin/guard-reasons.ts: init_mismatch never says re-run; init_failed
  does.
- tests: PAX-3638 Fix A/A2/B/C cases (bun test -t "Fix B" runs one fix); the
  three autoplan-init assertions that failed on macOS now compare canonical
  paths. 9 of the 11 new guard cases fail against the previous hook.
- docs: init_mismatch, init_failed, Symlinked plan directories.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(autoplan): canonicalRequested comment matches realpath behavior

realpathSync resolves a leaf link as well as directory links; only a
missing target or dangling link keeps the literal spelling. Note why
resolving a leaf link cannot bind an aliased active plan, and drop Read
from the callers list (only Write/Edit use it).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.59.0 fix(autoplan): bind init through symlinked plan directories and superseded failed inits

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: Wyatt Barrett <wyatt@Wyatts-MacBook-Pro.local>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-08 15:26:56 +00:00
Garry Tanandcapy-ai[bot] 9a1dc81a2b v1.91.54.0 fix: office-hours first sessions get the first-session closing, design doc shown before approval, strict timeline --limit (#3075)
* fix(timeline): reject a missing or malformed --limit with exit 2 (#1723)

gstack-timeline-read parsed --limit with parseInt and fell back to 20, so
'--limit 1abc' became 1, 'nope', 0 and -5 silently became the default, and a
bare --limit crashed on an unbound $2. Validate the argument as a positive
integer before the no-timeline early exit and exit 2 with an example. No flag
still means 20.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(skill-start): echo SESSIONS, the live session-marker count (#1651)

The sessions directory is touched and expired at skill start, but the count
was never printed, so CLAUDE.md rules that read the preamble's session count
had nothing to read. Echo SESSIONS: N (markers fresher than 120 minutes,
this session included). Idea from @0xDevNinja's PR #1747, redone in the
consolidated skill-start script.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(office-hours): pick the closing tier from the profile read before this session is logged (#2801)

Phase 4.5 appended this session to the builder profile and Phase 6 then read
the profile to choose its closing, so every run saw itself as history: a
first-time user got welcome_back and was asked how the assignment issued
minutes earlier went. Phase 4.5 now reads the profile before --log-session and
records the prior tier, count and last-session fields in the transcript;
Phase 6 uses those values (this session is prior + 1) and re-reads only the
running totals. A failed read proceeds as a first session and says so. Tier
headers now name the session numbers each tier actually covers.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(office-hours): print the full design doc inline before asking for approval (#879)

Tool output collapses in Claude Code, so users were asked to approve a doc
they could not see. Port of @RyanAlberts's PR #1116 into the carved
design-and-handoff section.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(office-hours): report success only when this run wrote its design doc (#1049)

Before telemetry, check the design doc this run wrote, by its exact path under
the state root, never the newest file in the folder. Success needs a
non-empty doc there; otherwise the outcome is abort or error with failed step
design_doc. Rewrite of @walton-chris's PR #1049, which matched the newest
global session marker and hardcoded ~/.gstack.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(plan reviews): skip the /office-hours prerequisite offer in spawned and headless sessions (#1958)

The BENEFITS_FROM offer had no recommended option, so a spawned run had
nothing defined to auto-pick and a headless run could only block. Skip it
there and continue with the standard review.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore: regenerate SKILL.md files

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: office-hours tier order, failed-read fallback, inline doc, design-doc check and offer skip

Rendered-block tests run the Phase 4.5 read and log on a temp state root
(first session reads introduction, failed read is marked) and the
pre-telemetry check against this run's doc, an empty doc, another session's
doc and a path outside the state root. Parity caps take the measured growth.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore(release): v1.91.37.0 changelog and TODOS

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(browse): run watchdog test servers under a private HOME

The headed-mode case starts a real server with BROWSE_HEADED=1, and its
headed launch writes ~/.gstack/.auth.json for the extension. With the
caller's HOME, a slow kill let that write reach the real home and failed the
free runner's home-containment check (free-suite shard 5 on #3075). Give each
spawned server a private HOME and GSTACK_HOME, keeping Playwright's browser
cache path.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(evals): name the office-hours-auto-mode case so the PR lane can select it

The PR lane runs each short probe with a Bun name pattern ending in its case
id. The office-hours AskUserQuestion-blocked smoke had a descriptive test
name and no CASE_TEST_NAMES label, so whenever office-hours changed its shard
matched 0 tests and failed in 0 s (E2E Evals slice 6 on #3075). Name the
test after its id, keep the description on the describe, and check that
every literal-named PR probe has a test the pattern selects.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(office-hours): skip a last-session greeting clause whose value is empty

A profile backfilled from the timeline can carry a welcome_back or regular
tier with empty LAST_ASSIGNMENT and LAST_PROJECT. The welcome_back and
regular greetings now drop the "last time" clause and its question when the
value it names is empty, and say only "Welcome back."

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>
2026-10-08 10:36:00 +00:00
Garry Tan 92cfd07a79 v1.91.45.0 feat: configurable model tiers and advisory freshness (#3073)
* feat: add configurable model tiers and advisory freshness

* fix: disclose role selections before Claude review execution

* fix: reject malformed model policies and keep model pins portable

* fix: separate readiness diagnostics and bound version checks

* fix: preserve actionable model failures and validate review inputs before probes

* fix: retry released probe locks and retain late-rejection repair context

* feat: finalize configurable model tiers and verified release repairs

* fix: preserve strict model policy reads on Windows

* fix: keep fixture probes read-only and clarify pending CEO decisions

* fix: verify native terminal closure before bounded descriptor settlement
2026-10-08 08:00:08 +00:00
f67c478f05 v1.91.34.0 fix: /autoplan on current Claude Code and long sessions, quieter pre-push and sync guards, gstack-post, gstack-doctor (#3069)
* docs: Oct 7 follow-up wave plan (pre-review)

* docs: Oct 7 follow-up wave plan, reviewed through /autoplan

* docs: Oct 7 wave plan, record final gate decisions (UC1 accepted, UC2 rejected)

* docs: credit #1822 to @Mike-E-Log and #1743 to @habassa5 (v1.64.0.0)

The v1.64.0.0 CHANGELOG entry credited the extension token fix (#1822)
and the polyfill exited promise (#1743) to the wrong handle, and the
extension-sender-auth test header repeated the first slip. Commit history
is not rewritten.

Fixes #3054.

Co-authored-by: Mike Ilog <48659643+Mike-E-Log@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(context-restore): offer newer checkpoints from nested repos and task worktrees

/context-restore could present an older checkpoint as the latest with no
error in two layouts:

1. A session started in a non-git parent saved from a nested repo, so the
   checkpoint went to the nested repo's bucket. Restore in the parent now
   lists checkpoints of other buckets whose project_root lies below the cwd
   (BELOW_CWD; the 200 newest are read, and from $HOME only each project's
   newest). /context-save also leaves a JSON pointer (checkpoint path, bucket,
   project_root) in the starting directory's bucket when $CLAUDE_PROJECT_DIR
   is set and files elsewhere; restore lists those as POINTER, in or out of git.
2. A plan checkpoint on the main tree's branch shadowed a newer checkpoint
   saved in a ticket worktree. When another branch holds a newer checkpoint
   for the same task (a worktree below the main tree, read from the new
   worktree: stamp; equal normalized titles; or a shared #123 / ABC-123
   token in titles or branch names), restore prints NEWER_TASK and the skill
   shows both and proposes the newer one. Generic titles (wip, checkpoint,
   save, notes, todo) never match on title alone, and the worktree rule
   applies only when restoring from the main tree, so sibling worktrees
   still never shadow each other.

The branch-first ordering itself is unchanged.

Refs #3065.

Co-authored-by: Thomas Gernhardt <t.gernhardt@softwareprojekt.net>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact-prepush): list each MEDIUM finding with rule, file line and fix

The pre-push hook printed only a MEDIUM count, which nobody could review
without re-running the engine by hand. It now prints one line per finding:
rule id, file and file line, and a fix, never the matched value.

Line numbers come from the hunk headers (combined --cc headers included), so
a finding in a later hunk or past a scan-chunk boundary points at the real
file line. Findings from the per-commit catch-up path name the commit whose
file line it is, so content removed before the pushed tip is still locatable.

Plan items: CEO-7 (summary half), DX-9 (fix lines), ENG-8 (line mapping).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(redact-prepush): stop flagging your own email and already-public authors (#3060)

The hook never passed the engine's selfEmail / repoPublicEmails, so every
push that added the pusher's address, or a commit author's, raised a MEDIUM
pii.email warning for an address the destination already shows.

The hook now reads `git config user.email` and one bounded `git log` of
author and committer addresses, raw and mailmapped (%ae %aE %ce %cE): the
history of every pushed tip (those commits become public with the push),
each remote tip being replaced, and, for a new branch or an unknown remote
tip pushed to a configured remote, that remote's own tracking refs. A URL or
unknown destination never borrows tracking refs, and another remote's
history never counts.

The read stops at 50,000 commits (the newest authors are used) and 5 seconds.
An error or the timeout passes no history and, when an email finding is
listed, prints one line saying suppression was limited for this push. The two
inputs fail independently. HIGH findings and every other rule are untouched.

Controls: a stranger's address, an address only another remote knows, a URL
push next to a matching remote, and a first push of a repo with no history
all still report.

Plan items: A3, CEO-7, CEO-23 (A3 half), DX-9 (partial history), ENG-8
(history scope, mailmap).

Co-authored-by: akmandhania <143462686+akmandhania@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(redact-prepush): per-address allowlist for pii.email (gstack.redact.allowEmail)

`git config --add gstack.redact.allowEmail <address>` allows that address for
MEDIUM pii.email findings only, so a team alias or support address that has
to be in the repo stops warning without reaching for --no-verify. It never
affects HIGH findings or any other rule, and the pii.email fix line names it.

Controls: a different address still reports, and a HIGH secret next to an
allowed address still blocks.

Plan item: DX-17.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(troubleshooting): pre-push pii.email findings, exemptions and allowlist

Plan item: DX-12 (pre-push touchpoint).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(redact-prepush): assemble fixture addresses at runtime

The email fixtures were literals, so this branch's own push listed 47
pii.email findings in its test file. Build them from a helper instead, the
way the neighbouring tests build credential and IP fixtures.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(browse): offer the user's signed-in tab, name silent aside repl failures

Rules (rendered into every browsing skill, kept short):
- Rule 1: before the first openTab, offer the user's tabs on the target
  origin (title and origin only; the rest of listBrowserTabs() stays
  private) and attach only after the user confirms one.
- Rule 4: a second sign-in wall after a confirmed sign-in means the session
  is bound to the tab or URL; offer that tab instead of another sign-in.
- Rule 6 no longer suggests an early return; rule 7 says a fast [ok without
  GSTACK_STEP_OK is an abort.

Cookbook (browse, devex-review): a "Silent failures" list (evaluate returns
only serializable values, no top-level return, locator(sel).press(key), an
empty DOM read is about the selector until the screenshot and the request's
response say otherwise, read toggle state before clicking) and a signed-in
tab recipe that prints only target-origin tabs and never closes the user's tab.

Parity caps for design-consultation, land-and-deploy, qa and the browse
skeleton are raised to the measured sizes, with notes.

Refs #3063, #3064.

Co-authored-by: Thomas Gernhardt <t.gernhardt@softwareprojekt.net>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(codex): run gstack-codex-probe as a command, one subcommand per probe

Generated skills now execute bin/gstack-codex-probe (select-model, check-auth,
show-sandbox, check-sandbox, probe-model, check-version, show-first-use-notice,
run-with-timeout, log-event, log-hang, help) and capture its KEY: value lines,
so no helper state crosses into the calling shell and the preflight works from
bash, zsh or sh. select-model keeps --model > GSTACK_CODEX_MODEL > config.toml
precedence; run-with-timeout supervises with the existing gtimeout/timeout/
watchdog chain and returns 124 on a deadline; an unknown subcommand exits 64.

Sourcing keeps working for skills rendered before the upgrade and prints one
deprecation line naming /gstack-upgrade; it and the zsh self-locate block are
removed in a release on or after 2026-10-21 (DX-18). Parity caps raised with
measured notes for the longer capture lines.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(gstack-post): one argv-only, redaction-scanned write path for PR and issue text

bin/gstack-post posts a PR/MR or issue comment, a review-comment reply, a
PR title or body, a new PR/MR or a new issue from agent-written files. Every
value reaches gh/glab as its own argv element in --flag=<value> form or on
stdin, never through a shell string, and a target is a number or a URL of
this repository on the same host.

The helper owns the redaction scan: it reads each file once, scans those
exact bytes (visibility from config, then gh/glab; the pusher's own email
suppressed) and sends the same bytes. HIGH is refused with exit 1 and no
confirmation can post it. MEDIUM exits 2 with RULE:/LINE:/PART: lines and a
TOKEN: digest of the bytes, destination, operation and findings; only
--confirm <token> for those exact bytes posts, so any edit needs a new
confirmation. gh/glab failures exit 3, usage errors 64. It also carries the
projectCards REST fallback and the title read-back that /ship did by hand.

The logic lives in lib/gstack-post.ts behind an injectable runner, so its
tests run in the Windows free lane; the stub-gh executable test is POSIX.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): guard verifies dispatches on Claude Code 2.1.29x (schema strip, unflushed call, named causes)

Cause A: Claude Code journals the model's raw Agent input but hands
PreToolUse the schema-parsed input; with the fork-subagent gate on (the
interactive default in 2.1.292) run_in_background is dropped, so the journal
record never deep-equaled the payload. nativeToolInput now drops only that
documented strip for Agent. Agent input is bound on both paths: keys limited
to prompt, description, subagent_type (general-purpose) and
run_in_background; a model override or any other key is denied.

Cause B: when a ready journal lacks the current call, the guard evaluates
the payload placed after the last journaled record instead of polling for a
record that may arrive only with the tool result. A phase transition counts
a report only when a later journaled record follows it (and, on the journal
path, it is not in the current call's message). One batch rule covers both
paths; a background reviewer keeps the invocation armed until its
completion notice.

Every outcome now has a stable reason code, disposition and anchor
(autoplan/bin/guard-reasons.ts). UC1: Claude-Code-caused states
(unrecognized shape, journal lag, rewritten journal, oversized record,
unchecked-version schema strip) allow with a visible warning; integrity
failures stay denials. No denial advises a bare retry. Every guarded
decision appends one content-free line to analytics/autoplan-guard.jsonl,
trimmed to 1,000 lines past 256 KiB.

Co-authored-by: Jared <182125291+yolo-jared@users.noreply.github.com>
Co-authored-by: crblabs <293123359+crblabs@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): publish each phase report with a no-op call; foreground requests are conditional

Phase-close step 6 sends the report in a message whose only tool call is
the Bash no-op ': autoplan-published <phase>', and step 7 makes the next
guarded call in a later message, so the guard sees the report flushed
before the next phase entry regardless of Claude Code's journal timing.

Every site that asked for run_in_background: false now asks for it only
when the Agent schema offers it and says how to recover when a dispatch
runs in the background anyway (wait for its completion notice). Parity
caps rise by the measured bytes.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(ship,spec,review): PR and issue text goes out only through gstack-post

/ship: Step 18 writes the title into an agent-written file. An existing PR's
title is piped from gh/glab through gstack-pr-title-rewrite.sh --stdin (new),
so neither the agent nor a shell string carries it; a new title is written
with the file tool and its version prefix checked in the file. Step 19
composes the body as before and publishes with gstack-post pr-create, or
pr-body then pr-title, which scan the exact bytes they send. The separate
title and body scans, the hand-rolled REST fallback and the title self-check
are gone (the helper does all three). Title preparation moved into the
pr-body section, so the skeleton shrinks.

/spec files its issue with gstack-post issue-create and drops the pre-issue
re-scan; Greptile replies use gstack-post reply and pr-comment.
scripts/resolvers/redact-doc.ts loses its PR and issue sinks, and a test
keeps any template from rendering one again.

Tests that pinned the old scan-then-gh wiring now pin the gstack-post wiring;
the publication tests run the real compose and publish blocks against a stub
gh with the real helper (HIGH in title or body refused, MEDIUM token flow).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* ci: pin Claude Code 2.1.292 in the CI image

2.1.292 is the npm latest users run. Its interactive default turns on the
fork-subagent gate, which strips run_in_background from the Agent schema
and backgrounds reviewers; CI on 2.1.284 never saw the /autoplan guard
break. The image tag is a content hash, so every eval workflow picks up
the new image without a workflow edit.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(brain-sync): one drain lock for every writer to the artifacts repo

gstack-artifacts-init, gstack-brain-restore, gstack-gbrain-source-wireup
and the skill-start merge ran git in $GSTACK_HOME without the drain's lock,
so the drain could never tell an abandoned .git/index.lock from a live one.
They now take the same mkdir lock (bin/gstack-brain-lock.sh): the drain and
the skill-start merge skip when it is held, user-run writers wait for it
(GSTACK_BRAIN_LOCK_WAIT, default 120 s), and a child of the holder (the
drain's daily worktree advance, restore's wireup) inherits it by token.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(brain-sync): hold back only the flagged file, keep coupled artifacts whole

One file with secret-shaped text used to block every push, silently. The
drain now attributes scanner hits to files in one pass over the staged diff
(split on its diff --git headers), holds back each flagged file with the
rest of its coupled group, unstages it, and requires the remaining staged
diff to re-scan clean; anything short of that falls back to a full unstage
and status blocked. Held files stay queued and are re-scanned every drain.

- Status file gains held_count, drainable, last_drain_at, last_push_at and
  held[] (path, scanner rule, dependents, both fixes); new status held.
- Coupled groups come from an explicit map (decisions.jsonl and
  decisions.active.json): a queued member stages the whole group, a group
  stages only when its snapshot matches its log in the index, a skipped
  member stops the whole group.
- --unskip-file undoes --skip-file and queues the path again.
- An index lock older than 10 minutes is removed under the drain lock; a
  younger one, a failed git add, a failed commit (hooks included) keep the
  queue and report status error. A verified empty staged diff is the only
  "nothing to commit". git add runs once, batched.
- The scanner reads bytes, so undecodable content no longer crashes it into
  a false clean; matched text never reaches the status file.
- An empty-queue run with unpushed sync commits stays push_failed.
- Privacy-held duplicate records collapse to one per path; --status counts
  a spool too deep for a shell glob.
- --attention prints skill start's fixed attention lines from the sync
  status table in the usage header.

Co-authored-by: v639dragoon <matthewsbrickley@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(skill-start): ARTIFACTS_SYNC attention lines for a stuck sync

Skill start now prints one fixed attention line per sync-status-table row
that applies (held, blocked, push_failed, error, unknown, stale-push,
stale-drain), each naming gstack-brain-sync by absolute path. Values from
the status file are clamped (status code to the table, counts to digits,
timestamps to their shape), so the status message, file paths and scanner
output never reach the line. The preamble tells the model to surface the
line in one sentence and continue. Skill-start tests are generated from the
table in bin/gstack-brain-sync, and docs/gbrain-sync-errors.md carries the
same table.

Co-authored-by: v639dragoon <matthewsbrickley@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(outside-review): severity words in label position count as findings

The Oct 7 /autoplan run's Codex CEO and DX reviews labeled seven and eight
findings High/Medium without [Pn] tags, and the classifier printed
VERDICT: clean / FINDINGS: none for both. lib/outside-review-result.ts now
reads severity words in label position (Severity: High, a leading High: /
High — / [High], **High**, a table cell): critical/high block like P0/P1,
medium/low are advisory. Words in prose (high-level, low-risk, no critical
findings) never count. A review or structured response with neither tags,
labels nor an explicit no-findings statement is unverified, never clean
(DX-11, ENG-10). Design-direction proposals move to a new proposal gate so
they keep needing only their Recommendation line, and review prompts ask
for a severity per finding. Fixtures reproduce the CEO/DX label shapes, the
eng [P1] output, a table and prose negative controls; the stored Codex panel
keeps its verdicts. docs/troubleshooting.md explains how the verdict is read.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat: gstack-doctor readiness report and setup --status Codex row (B5)

bin/gstack-doctor prints one row per check without starting a skill:
install root (the registry rows behind ./setup --status), state root, Bun
against the floor, hook parse check, Codex mode and self-locate via
gstack-codex-probe subcommands, the cached model probe with its age
(--live runs the paid probe-model), artifacts-sync health from the status
file with the status code clamped, the browse bundle, Claude Code version,
the largest session journal and the last five schema-1 guard reason codes.
Rows are ok, warn, not configured or fail; only fail exits non-zero; fix
lines name helpers by absolute install-root path.

./setup --status gains a read-only Codex row (bin/gstack-codex-status.sh,
shared with the doctor) and ends with the doctor's absolute path.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: bug-report template asks for doctor output; README troubleshooting entry; doctor test in the Windows lane

The template gives the Claude Code doctor path and a lookup for other
hosts and names no bare gstack- command (asserted in
test/gstack-doctor.test.ts). The doctor test runs every script through
explicit bash argv, so it joins the curated Windows free subset.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(troubleshooting): readiness check section points at gstack-doctor

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(question-tuning,plan-tune,gbrain): free text reaches helpers only through agent-written files

Question tuning no longer pipes the question summary through printf: a
registered id needs no summary, and for an unregistered id the agent writes
the summary to .gstack/tmp/qt.txt and passes --summary-file (new). The
helper resolves a relative path against the git top level, removes scratch
files under .gstack/tmp, and asks normally when the file is missing.

/plan-tune tune events carry the user's own words again: they go into a
file the agent writes and reach gstack-question-preference --write through
--free-text-file (new), still behind the injection filter and the
user-origin gate.

docs/gbrain-write-surfaces.md drops its heredoc templates for the
agent-written page file on stdin, matching the per-skill save block, and the
generic save block stops showing a quoted --content argument.

The tuning prose was tightened so every preamble stays within its size cap.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(evals): daily autoplan-schema-canary on the latest Claude Code

A periodic rule case installs the latest published Claude Code with
install scripts off, verifies registry signatures, and runs one headless
session with the fork-subagent gate on whose PreToolUse hook records an
Agent and a Read payload. Each payload must match its journal record under
the guard's own comparison, keep the journal's key set apart from the
documented run_in_background strip, and stay inside the Agent allowlist;
a background Agent's completion notice must keep the shape the guard reads.
evals-periodic.yml runs it daily on its own schedule and concurrency group
(read-only token); the weekly census also includes it. A free test proves
the comparison fails on an injected strip.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(doctor): read the artifacts sync held count from held_count, the field the drain writes

* fix(artifacts sync): the init and restore pre-commit hooks catch Bearer/Basic/Token-prefixed JSON auth headers like the drain does

* feat(greptile-early): detect Greptile, ask once on public repos, open the early draft, wait for the review

bin/gstack-greptile-early backs /ship's early Greptile PR:
- detect: a root .greptile/ folder (which takes precedence), greptile.json,
  or a Greptile comment on the repo in the last 90 days; triggerOnDrafts from
  the effective root config; repo visibility; public-repo consent. It prints
  the signal, that /ship will push and open a draft now, the 10-minute wait
  cap and the absolute gstack-config command that turns it off.
- consent yes|no: the public-repo answer, remembered per repo in the
  project's state.
- open: opens the draft through gstack-post with a body saying /ship opened
  it early, and posts one @greptileai comment through gstack-post when the
  config does not set triggerOnDrafts: true. An open PR is left alone.
- wait: polls every 30 s for a completed Greptile check run, a Greptile
  review of the head commit or a summary naming it; each call returns within
  about 90 s and reports timeout 10 minutes after the PR opened.

gstack-config gains ship_greptile_early (default true, invalid values
rejected): on automatically whenever the repo uses Greptile, off per user.
The logic is in lib/greptile-early.ts behind an injectable runner, so its
fixture-repo tests run in the Windows lane; an end-to-end test drives the
real helper and gstack-post against a stub gh.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(ship): early Greptile PR at Step 6.5, bounded wait at Step 10 (#3020)

When the repo uses Greptile, /ship pushes and opens a draft PR right after
its free tests pass (new lazy section greptile-early, Step 6.5), so Greptile
reviews while Steps 7-9 run. A public repo asks once, remembered per repo;
declining keeps today's order. Step 10 waits for that review with
gstack-greptile-early wait and takes the existing unavailable route on a
timeout, never a claim of zero comments. Step 18 replaces the provisional
title, Step 19 marks the draft ready unless a draft was requested, and a
/ship that stops after Step 6.5 leaves the draft open with one comment
saying why.

ship's union cap rises to 1.5275 with the measured note (B4 +836 bytes,
B2 +4,732 bytes); the step-numbering guard allows 6.5; ship goldens are
refreshed for B4 and B2.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): the publication no-op is 'true autoplan-published <phase>'

Measured on Claude Code 2.1.292 in a default-settings interactive session:
a bare ':' Bash command asks for approval ('This command requires
approval'), and after a background reviewer's completion notice starts a
new turn the skill's allowed tools no longer cover it, so the phase-close
no-op prompted the user. 'true' with arguments runs without approval and
prints nothing. The guard only needs a later journaled record, so the
command changes everywhere it is named.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(evals): live autoplan-guard-pty case on the pinned Claude Code

A gate-tier rule case (one trial, haiku) drives an interactive PTY
session with default settings through a project skill that carries
/autoplan's own hook block: init, Phase 1 entry, a CEO reviewer dispatch
that sends run_in_background, a prepared close packet, the report
published with the no-op, and the Phase 2 entry in a later message. It
reads outcomes from the guard decision log (three verified allows) and
fails if the no-op raises a permission card; other cards are approved and
printed.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(autoplan): bounded, append-tolerant owned-journal read (A2)

The publication guard no longer reads the whole parent journal or refuses
it at 32 MiB. lib/claude-owned-journal.ts streams the bytes present at open
to the last complete line (pass one), keeps a content-free index per record
and decides ownership, ancestry and causal order on it with the same checks
and reason codes as before. Pass two reloads in full only what the
evaluation reads (autoplan/bin/guard-journal.ts): every literal init and its
result, the current call, and inside the invocation window (from the latest
human turn at or before the bound chain's first init) guarded and
close-packet Read results, structured Bash results, error results, assistant
text after the first close Read and active-plan mutations, plus the earlier
Read a dedup reply cites even before the window (ENG-4).

- lib/claude-journal-records.ts: per-record event extraction, record
  metadata and the causal-order checks, shared by readPlanCountTranscript
  and the bounded reader. The batch reader keeps its whole-file read and cap.
- Appends after open never fail a read; same device and inode and no
  shrink are required (identity). A second read in one hook invocation must
  hash bytes [0, first size) the same, or it is `rewritten` (UC1 unverified);
  the unrecognized-shape double read uses that prefix hash. `changing` is
  removed (REMOVED_CODES; its anchor stays).
- OWNED_RECORD_MAX_BYTES (32 MiB): only one record over it is too_large.
  OWNED_RETAINED_MAX_BYTES (32 MiB): over it is the new oversized_invocation
  fallback denial. GSTACK_TRANSCRIPT_TEST_MAX_BYTES and
  GSTACK_TRANSCRIPT_TEST_RETAINED_BYTES can only lower them.
- ENG-5: evaluation groups uses and results by tool id once (no per-tool
  rescans).

CEO-25 / ENG-5 spike (120 MiB synthetic, 31,242 records, 4 vCPU Linux,
Bun 1.4.2): a full streaming rescan (parse every line, small index, sha256)
took 254-326 ms at 147-161 MiB peak RSS; a pass-one index cache under the
state root (load cached index, verify a 64 KiB tail hash, parse the tail)
took 26-29 ms at 47 MiB. The rescan meets the 1 s budget, so the cache is
not adopted: it would add trusted persistent state and invalidation for no
budget need. A backward tail read cannot prove competing_root or cycle, so
it was not a candidate.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(autoplan): journal-read benchmark and its dispatch-only workflow (CEO-2, CEO-6)

scripts/measure-journal-read.ts builds two synthetic 120 MiB parent journals
around a real /autoplan invocation (mixed: ~28k records, most bytes inside
the invocation; large-invocation: ~89k records with a current invocation of
many small records), keeps appending while the guard reads, and measures one
hook call in a fresh process (wall ms, peak RSS). The workflow runs it on
ubuntu-latest and macos-latest on workflow_dispatch only.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(evals): autoplan-long-session, a resumed >100 MiB session enters Phase 1

CEO-15 with ENG-6's observer: a real session is compacted, its journal
padded past 100 MiB with owned records before the compact boundary, and
the resumed interactive session runs the scripted phase boundary; the
guard decision log must show a verified Phase 1 allow. A free test proves
that observer on a padded journal through the lower-only bound seams
(the PTY counting reader refuses the same journal), with a sidechain
control that must deny.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.34.0: CHANGELOG, TODOS, version; harness decision for test-pr-profile; ship title-step test reads its new section

* docs(changelog): use an example.com address in the allowEmail example

* test: assemble GitHub-token fixtures at runtime in the new brain-sync and skill-start tests (CI credential scan)

* fix: integration repairs across the wave (Step 6.5 fence, printed helper paths on Windows, probe usage without a heredoc) and tests pinned to the moved title and gstack-post contracts

* test(doctor): the healthy fixture builds browse.exe on Windows, the name setup uses there

* test(shared-libs): recognize Claude Code 2.1.292's internal git probe prefix (format.pretty and per-hook disables), with its CI receipt

* fix(ship-measure): report lists v1 measurements as an older format instead of crashing

---------

Co-authored-by: Mike Ilog <48659643+Mike-E-Log@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: Thomas Gernhardt <t.gernhardt@softwareprojekt.net>
Co-authored-by: akmandhania <143462686+akmandhania@users.noreply.github.com>
Co-authored-by: Jared <182125291+yolo-jared@users.noreply.github.com>
Co-authored-by: crblabs <293123359+crblabs@users.noreply.github.com>
Co-authored-by: v639dragoon <matthewsbrickley@gmail.com>
2026-10-07 23:29:05 +00:00