Repository navigation
v1.91.270.0 feat(ship): version-less repos, docs-audit record and caps, the frozen-scope paid case, and the review-loop follow-ups - #3487
Merged
Conversation
capy-ai
Bot
changed the base branch from
harness-lane-e/ship-review-convergence
to
main
October 26, 2026 20:48
|
😎 This pull request was merged. |
…n-scope paid case, and the review-loop follow-ups Follow-up to the review-loop convergence PR: Step 12 and the CHANGELOG step skip cleanly in a repository with no version source (receipt version "none"); the receipt records the docs audit outcome and the owner exception (DOCS_AUDIT_BLOCKED without one) and a policy may declare doc caps (gstack-ship-receipt docs-caps); docs/unattended.md names the READY evidence and the cross-family outside voice; the ship-frozen-scope-convergence behaviour case runs the generated Step 9.4 under review_scope frozen through the real binaries; carry probes git >= 2.39 (RECEIPT_GIT_TOO_OLD); defer passes the repository to gh repo view positionally and names its search limit; late defers count without being passes; reviewers diff from RANGE_BASE on pass 2+; the cap check runs before edits; --review-fanout batches specialists by free slots; read --check-prose compares quoted counters with the receipt (RECEIPT_PROSE_MISMATCH); checklist rule ids prereg-with-results and test-keyboard-count-loop; gstack-coauthor-trailers. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
garrytan
force-pushed
the
capy/version-less-repos-docs
branch
from
October 26, 2026 20:50
66efb94 to
2d73fad
Compare
Seven test files, no product change. The pull_request run at 2d73fad failed 5 Linux shards and 4 Windows shards: - test/ship-frozen-scope-actor.test.ts imported only test code, so the test-of-test ratchet refused it; the first case now recomputes the loop summary with summarizeReviewLoop/reviewLoopLine from lib/review-scope and asserts the exact REVIEW_LOOP line. Its three cases replay the bash workflow through bash -c and the shebang bins, so they are POSIX-only. - test/codex-host.test.ts: the new gate case is Claude-specific (33 -> 34). - test/paid-retry-supervision.test.ts: the gate census fixture now carries a trial record for the one planned behavior-kind gate case, the way test/ci-paid-coordination.test.ts already does. - test/review-fix-range.test.ts asserted the pre-#3487 DIFF_BASE sentence; it now asserts the ${RANGE_BASE:-merge-base} clause that carries the same contract (every reviewer reads the range from pass 2 on). - test/gstack-coauthor-trailers.test.ts: the fixture sets its own git identity; a CI runner has none to auto-detect ("Committer identity unknown"). - test/review-scope-followups.test.ts and test/gstack-ship-receipt-docs.test.ts: the gh and old-git stand-ins are sh scripts on a colon-joined PATH, which CreateProcess cannot run, so those three cases skip on win32. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Twelve informational findings from the /ship pass-1 review, all below the blocking floor, fixed in place: - docs-caps reads docs.caps from origin/<base>'s policy (--base <ref>), never the branch's copy; an unavailable base policy refuses with POLICY_SOURCE_UNAVAILABLE instead of substituting DEFAULT_POLICY - receiptVersion returns "none" only when the stamp file is absent; other errors surface as undefined - checkReceiptProse groups counters by leaf key and uses word boundaries that cover hyphenated names, so shared leaf keys and hyphenated words no longer report RECEIPT_PROSE_MISMATCH - gstack-coauthor-trailers refuses a --range/--base starting with "-", prefixes origin/ when origin/<ref> resolves (slash-named branches), and passes --end-of-options to git log - REVIEW_SCOPE_KEY_VERSION and DOCS_CAPS_KEY_VERSION name the releases that first read their keys - the Step 11 late-defer row logs under skill review-late-defer so a tokenless review row never reads UNVERIFIED; summarizeReviewLoop counts both - the "already filed" literal is one constant shared by bin and renderer - receiptDocs (dead) removed - Step 14.5 clears .gstack/tmp/docs-audit.json on first entry - dispatched review prompts carry a literal diff-base sha (<diff-base>) instead of a shell variable the reviewer process never sees - the coauthor-trailers tests launch the bin through runScriptSync so the Windows lane can run them Tests extended for each change; SKILL.md, sections and goldens regenerated. 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>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
gstack-coauthor-trailers --message appended the new Co-authored-by lines as a separate paragraph after existing trailers, so git interpret-trailers (and GitHub attribution) read only the last paragraph and the existing co-author lost credit. The new lines now join the existing trailer block; the test checks the result with git interpret-trailers --parse. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
gstack-coauthor-trailers --message now runs git interpret-trailers --in-place, so the appended lines join the existing trailer block whatever its shape (CRLF, comment lines, folded continuations) and the existing co-author keeps attribution; the interpret-trailers check in the test carries a timeout for the spawnSync tripwire. DOCS_CAPS_KEY_VERSION names the release after the newest CHANGELOG heading on main (1.91.258.0), and a test ties every unreleased policy key to that next release so a stamp elsewhere fails loudly. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…trailer placement The CHANGELOG-heading test asked for the exact next release after the newest heading, which a depth-1 CI clone (no origin/main) computes from the branch alone, so it went red there. It now requires an unreleased key's version to be newer than every heading the checkout can see, which holds at depth 1, on the stamped train tree and on main; the ship-policy comment says who moves the constant when the stamp lands under another number. gstack-coauthor-trailers pins git interpret-trailers' placement on the command line (--no-divider so a --- body line is not a divider, --where end, --if-exists addIfDifferentNeighbor, trailer.separators=:, -- before the path) so a user's trailer.* config cannot replace or drop the existing co-author. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
CHANGELOG [Unreleased]: docs-caps --base <base> reading origin/<base>'s policy, the review-late-defer row, the literal <diff-base> prompt rule, the coauthor-trailers placement and refusals, the policy key versions (review_scope 1.91.256.0 re-pin, docs.caps at the stamping release), the version-less conditions split between Step 12 and the receipt, and the carry refusal wording. docs/ship-policy.md, docs/review-policy.md and docs/unattended.md follow the code: docs-caps --base, the literal diff-base sha, the trailer block, the gstack-outside-voice run binding and the Step 11 row fields. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ame where the outside-voice cause lives Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This was referenced Oct 26, 2026
…xclude .gstack/tmp at the Entry The ship-docsync-completion and ship-docsync-current paid cases failed twice at 775d980: Step 14.5's continue path now runs gstack-ship-receipt docs-caps and writes .gstack/tmp/docs-audit.json, and the docsync fixture's closed interface declared neither, while its repository had no origin/main for docs-caps to read. The actor stopped correctly (blocked, no exception) and never reached the publication stand-in. - test/helpers/docsync-interface.ts: the three housekeeping commands (the shared exclude line, rm -f of the record, docs-caps --base main) and the record write are declared, byte for byte with the generated section; DOCS_AUDIT_RECORD_PATHS names what the kernel observer may see. - test/helpers/docsync-observer.ts: accepts exactly those commands and the record write; every neighbour (another base, --json, write --docs, another .gstack file) stays outside the interface. - test/helpers/docsync-fixture.ts: every scenario pushes main to the fixture remote, as Steps 0-14 would have. - ship/sections/documentation.md.tmpl: the Entry runs the shared .gstack/tmp exclude line before rm -f, so the record never surfaces as an untracked file when no earlier step added it; the caps paragraph tightened to hold the ship parity ratio at 1.7400. - test/docsync-command-grammar.test.ts: pins the literals against the generated section and the refusals around them. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… and the fault cases too Pass 9's outside voice found two gaps in the fixture change (2524ec4): a read-only audit (ship-docsync-current) must still write .gstack/tmp/docs-audit.json, but docsToolFailures flagged every product write under readOnly before the record allowance; and the unseeded fault cases (missing-asset, legacy-completion) run the Entry too, so their kernel-write check saw .git/info/exclude as a forbidden write because only the lifecycle test named the housekeeping paths. - docsToolFailures: the record write is permitted under readOnly; the document and every other product file stay refused. - docsWriteFailures: DOCS_AUDIT_RECORD_PATHS are permitted for every caller, so the fault evaluator needs no per-scenario list; anything else under .git or .gstack stays forbidden. - test/docsync-command-grammar.test.ts pins both: the record under readOnly, the document refused there, the observed housekeeping paths accepted with an empty allowance and two neighbours refused. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… section prints (pass 9 Red Team note) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…tainability note) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… cap gate can load (2524ec4 rerun: module error, not a verdict) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…rd (0230fc2 rerun: both lifecycle cases red on it) The paid rerun at 0230fc2 cleared every earlier refusal and both cases then failed on one path: forbidden docs write: .gstack/tmp/docs-audit.json.tmp.<pid>.<12 hex>. Claude Code's Write and Edit tools land every file, new ones included, through that sibling plus fsync and rename, and the fixture's kernel observer proved such a landing for the document only (atomicTargets: [DOC_PATH]). The observer now treats the record's sibling as a transient file too, and docsWriteFailures admits it only as the cookie-paired MOVED_FROM source of a MOVED_TO on the record whose other events are create/modify/attrib/close_write and which is left in neither snapshot nor in changed. A lingering sibling, an unpaired move, a move onto another path or a sibling of the document moved onto the record stay forbidden (grammar test). A live check on this machine saw the second landing's create/modify/close_write/moved_from events admitted and a stray sibling refused. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…docs CHANGELOG.md through mergeChangelogs (the [Unreleased] entry kept above main's headings); bin/gstack-doctor-components.sh regenerated from scripts/gen-doctor-components.ts; docs/troubleshooting.md and lib/result-codes-release.ts additive (gstack-pr-wait's two codes beside this branch's three). DOCS_CAPS_KEY_VERSION unchanged; the stamp moves it. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
garrytan
force-pushed
the
capy/version-less-repos-docs
branch
from
October 27, 2026 07:13
c2a11ce to
e78f9be
Compare
FILES: CHANGELOG.md VERSION agents-digest/gstack-AGENTS.md package.json MERGE_CONDITION: sha=e78f9beb5b4be0ac80be18f656f754d4a6af0e64 NEW_VERSION=1.91.270.0 base=295b32e2c47a3c30a2b797739fd0300012533f55 expect-order=3487 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
6 tasks done
garrytan
added a commit
that referenced
this pull request
Oct 27, 2026
GSTA-36 grant 2026-10-27. On the tree merged with f27a760 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>
6 tasks done
This was referenced Oct 27, 2026
capy-ai Bot
added a commit
that referenced
this pull request
Oct 27, 2026
…y versions move through stamp_paths at the slot stamp (#3511) * fix(ship-policy): DOCS_CAPS_KEY_VERSION is 1.91.270.0; key versions move through stamp_paths at the slot stamp #3487 was written naming 1.91.258.0 for docs.caps and main stamped that number for another PR first; the slot call cannot edit anything beyond the four stamp files, so the constant shipped stale. lib/ship-policy.ts now sits in .gstack/ship-policy.json stamp_paths with the _KEY_VERSION = '{version}' template, so a new key written as a tentative future version is moved by gstack-restamp's stamp_paths stage at the slot (read from the base policy, so live from the next PR on). test/gstack-ship-policy.test.ts gains the check the incident lacked: a released key's version must be a heading whose entry names the key. Dry-run proof: a tentative 1.91.272.0 on a branch line moved to the allocated 1.91.271.0 with --policy-from head. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship-policy): tentative key versions are clear of main's pace; the receipt accepts the move only at the base version until #3512 Pass-1 review notes: the next patch above the fork point is the number main takes first, so the convention names the next minor; and the tree receipt's stamp-only check (lib/tree-receipt.ts stampOnlyHunks, with stampOnlyText and stampFreeTree) rewrites only base VERSION -> new VERSION, so a tentative move passes the train only when the tentative value equals the base version at the slot. Filed as #3512 (outside this diff, deferred under the frozen scope). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(ship-policy): read origin/main's CHANGELOG with a 64 MiB maxBuffer; say plainly that a new-key PR cannot clear the train until #3512 Pass-2 Red Team: CHANGELOG.md is past spawnSync's default 1 MiB maxBuffer, so both CHANGELOG-reading tests dropped origin/main's file silently and the incident shape passed at the pin. With the buffer the released-key test sees main's headings on a full clone. The comment and CHANGELOG now state the practical consequence of the receipt limit. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship-policy): gstack's own policy excerpt names lib/ship-policy.ts under stamp_paths 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>
5 tasks done
capy-ai Bot
added a commit
that referenced
this pull request
Oct 27, 2026
…fault 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 f27a760 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 1f246e3: 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 392f50d 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second PR of the /ship and /review convergence lane; #3481 (v1.91.256.0) landed, so this one targets main. Everything here is generic: no crew names, configurable repository names. main d9b0d60 (v1.91.267.0) is merged in under the owner's rule-19 grant: CHANGELOG.md through
mergeChangelogs(the [Unreleased] entry above main's headings),bin/gstack-doctor-components.shregenerated from its generator,docs/troubleshooting.mdandlib/result-codes-release.tsadditive (gstack-pr-wait's two codes beside this branch's three); the branch's diff over main is byte-identical to its diff over the old base except one dropped blank line in troubleshooting.md.DOCS_CAPS_KEY_VERSIONstays 1.91.258.0 for the pin; the stamp moves it.Summary
Repositories without a version source
/ship Step 12 and the CHANGELOG step no longer assume
VERSION,package.json#versionorCHANGELOG.md. When the head has none of them and the policy names no stamp file, the steps printVersion bump: skipped (no version source: <path, reason>)andCHANGELOG: skipped (none at <path>), the PR title is unprefixed, the run log records"version": null, and the receipt records"version": "none"(gstack-ship-receipt writederives it only after VERSION, package.json#version, the stamp files and the CHANGELOG are all absent;read,resultand the queue accept it).Docs audit record and doc caps
gstack-ship-receipt write --docs <json|@file>recordsdocs: { status: updated|current|blocked, scope, exception?: { accepted_by, date, via, reason } }(newlib/ship-receipt-docs.ts). A blocked audit with no owner exception isDOCS_AUDIT_BLOCKEDand no receipt is written; with--body, the body must carry the exception line verbatim. A repository may declaredocs.caps: [{ path, max_bytes }]in.gstack/ship-policy.json(needsmin_gstack_versionat or aboveDOCS_CAPS_KEY_VERSION);gstack-ship-receipt docs-caps [--base <ref>] [--policy <file>]reads the base branch's policy (POLICY_SOURCE_UNAVAILABLEwhen it cannot), prints oneDOCS_CAP: <path> <bytes>/<max> ok|overline per cap and exits 1 on any over or absent file; Step 14.5 runs it before the verification gate and clears a stale.gstack/tmp/docs-audit.jsonon first entry.Unattended evidence
docs/unattended.md#ship-evidencenamesgstack-ship-receipt result(itsGSTACK_RESULTline and run directory) as the machine-readable READY evidence, thereview_loopcounters, theCARRY:lines, and the accepted outside voice on a host without the Codex CLI: a subagent on a different model family, logged as anadversarial-reviewrow with its source and outside status, the unavailable cause on thegstack-outside-voice run:stderr line.Paid case:
ship-frozen-scope-convergenceA behaviour case (gate tier) reusing the ship e2e harness: a fixture with one CRITICAL in the diff and one in untouched code; the actor runs the generated Step 9.4 and repeat decision under
review_scope: frozenthrough the realgstack-review-scopeandgstack-review-logbinaries. The verdict requires the in-diff fix committed, the untouched file byte-identical and deferred, pass 2 on the range only, exit via decision 4, andREVIEW_LOOP: passes=2 blocking_found=2 deferred=1 fixed=1 scope=frozen. Registered inE2E_TOUCHFILES/E2E_TIERS/E2E_KINDS(+BEHAVIOR_WHY) and the SDK host list; a free scripted actor test with negative controls (test/ship-frozen-scope-actor.test.ts). The fixture actor's message handling was repaired after the first focused panel (see Eval Results).Docsync fixture: Step 14.5's own-tree commands (test-only)
The focused paid run of the 51 /ship and /review own cases at the pooled pin left
ship-docsync-completionandship-docsync-currentred twice: the actor stopped at the Step 14.5 cap gate because the docsync fixture's closed interface did not declare the section's three own-tree commands (the shared.gstack/tmpexclude line,rm -f .gstack/tmp/docs-audit.json,gstack-ship-receipt docs-caps --base <base>) or the record write, and its repositories had noorigin/mainfor the gate to read. The repair is confined to the fixture (test/helpers/docsync-{interface,observer,fixture}.ts,test/docsync-command-grammar.test.ts,test/skill-e2e-ship-docsync.test.ts): the interface declares exactly those commands (derived from the samefreeTextFileBashthe section renders, so byte-identical; the~/.claude/skills/gstackform the section prints is accepted when the fixture's skills dir is under its HOME), every scenario pushesmainto a bare remote, the fixture installslib/besidebin/so the gate can load (pinned by a live spawn printingDOCS_CAP: none declared), the record write is housekeeping for read-only audits too, the shared record paths are permitted for everydocsWriteFailurescaller, and the Write tool's atomic landing of the record (<record>.tmp.<pid>.<12 hex>+ rename) is admitted only as the cookie-paired source of a move onto the record that leaves nothing behind. One prose line moved inship/sections/documentation.md.tmpl: the Entry runs the exclude line before itsrm -f, and the caps paragraph was tightened to hold the ship parity union at 1.7400.Follow-ups from #3481's review notes
gstack-ship-receipt carry: probes git ≥ 2.39 beforepatch-id --verbatimand refuses older gits withRECEIPT_GIT_TOO_OLDnaming the installed version; a failing patch-id isRECEIPT_CARRY_REFUSEDwith git's stderr, never a carry; the per-path walk covers branch-touched paths only and names at mostCARRY_NAMED_PATHS(20);stampOnlyTextdigit-bounds the version replacement.gstack-review-scope defer:gh repo viewreceives the repository positionally, so the visibility read works under--repo;DEFERRED_SEARCH_LIMIT = 200is named and an exactly-full page is reported as truncated.review-late-defer(LATE_DEFER_SKILL): their deferred findings count inreview_loop, but they are not passes.scripts/resolvers/review-army.tsrenders for /ship carry their diff base as a literal sha (DIFF_BASE=<diff-base>: the merge base on pass 1,RANGE_BASEfrom pass 2 on), never a shell variable; Step 9.4 runs the cap check before any edit (0. Scope→1. Cap, then classify→2. Auto-fix) and names its scratch files under.gstack/tmp/.--review-fanout auto|serial|parallel, /ship only): underauto, fewer free subagent slots than specialists means batches of the free-slot count;docs/review-policy.md#reviewer-fan-out.Also in this PR
gstack-ship-receipt read --check-prose: every counter the body quotes (passes=2,1 deferred,passed: 41) is compared with the receipt'sreview_loop,gateandciintegers; a difference isRECEIPT_PROSE_MISMATCH(lib/ship-receipt-prose.ts; shared-leaf and pass-through counts are not compared). No ship step invokes it yet (Deferred items from the /ship review of #3487 (docs-caps fail-open and symlinks, docs not in the receipt schema, --check-prose unwired, REVIEW_SCOPE_KEY_VERSION move) #3504).review/checklist.mdrule ids:prereg-with-results(Gate Integrity, ASK: a preregistration and its results in one diff) andtest-keyboard-count-loop(Pass 2: Playwright tests that drive UI with counted key presses in loops).bin/gstack-coauthor-trailers: prints theCo-authored-bytrailers a ported range owes (distinct authors other than the committer, first appearance order), refuses a leading--path, resolvesorigin/bases, and with--message <file>letsgit interpret-trailers --in-place --no-divider --where end --if-exists addIfDifferentNeighborplace them in one trailer block (docs/review-policy.md#porting-a-contributors-work).REVIEW_SCOPE_KEY_VERSIONis 1.91.256.0 (the release that shipped v1.91.256.0 feat(ship): review loop converges (frozen scope, 3-pass cap, NO FINDINGS) and receipts carry across conflict-only merges #3481);DOCS_CAPS_KEY_VERSIONnames the release that stamps this entry (1.91.258.0 at authoring; main stamped 1.91.258.0 for v1.91.258.0 feat(capy-install): project floor, --for none, WARN for behind and Node-only pins, in-place review-voice upgrade, /cso env hygiene (GSTA-114 lane F, PR 1) #3475 while this PR was in review, so the slot moves the constant to the stamp version);test/gstack-ship-policy.test.tsrequires an unreleased key version to be newer than every CHANGELOG heading the checkout can see.DOCS_AUDIT_BLOCKED,RECEIPT_GIT_TOO_OLD,RECEIPT_PROSE_MISMATCHinlib/result-codes-release.ts, each with adocs/troubleshooting.mdanchor.Gate integrity
No threshold, timeout, trial count or case kind changed. The ship parity
maxSizeRatiointest/helpers/carve-guards.tsmoves 1.7150 → 1.7400 (measured 326,437 / 187,706 = 1.7391, held after the pass-1 fixes by tightening prose rather than re-pinning);test/fixtures/module-size-ratchet.jsonrecords the two new modules. Registry-count tests (eng-finding-retry-budget110 → 111 discovered files,paid-run-manifestderiving trial counts,ship-skip-selection,exercised-map) follow the new case;test/review-fix-range.test.tsfollows the literal-diff-base sentences.Test Coverage
Coverage: 70% value-weighted (83% including 5 weakly covered paths) over 30 new code paths at the Step 7 audit (pass 1 of 2; the 60 ≤ 70 < 80 gate was answered under the unattended rule: generation restricted to true gaps).
Test value: 1 test written (the carry patch-id refusal,
test/gstack-ship-receipt-docs.test.ts), 0 rejected by the authoring gate, 0 existing tests extended, 5 paths weakly covered (weak = ★, gate-failing or unrated); 4 of the 5 gaps were then covered by the pass-1 fix tests (--baseresolution, shared-leaf and hyphen prose, package.json / stamp_files / changelog fallbacks, docs-caps base policy).Proposed strengthening, not written: the prompt-token tests for the review-army and documentation templates assert that sentences exist (
DIFF_BASE=<diff-base>,rm -f .gstack/tmp/docs-audit.json,docs-caps --base <base>) and do not exercise an agent following them; the paidship-frozen-scope-convergencecase covers the review-army half.Tests ran: local pregate (unit + e2e tiers) at 6f4bbff9: 7 checks; remote gate (Ubicloud) 21,817 tests, 0 failed; Free Tests dispatch run 40420998019 29 jobs green; Windows Free Tests dispatch run 40421001513 (see Test plan).
Pre-Landing Review
Eight passes under the frozen finding scope. Pass 1 (whole diff, 8 specialists + Red Team + QA): 12 INFORMATIONAL findings, none at the blocking floor, all fixed in d39ea5d. Pass 2 (range): 9 noted, clean. Pass 3 (the Step 11 queue): one blocking defect, the co-author trailers appended as a separate paragraph so
git interpret-trailers --parsesaw only the last one, fixed in 12d0463. Pass 4: two blocking (aspawnSyncwithout timeout in the new trailer test;DOCS_CAPS_KEY_VERSIONnaming a release main had stamped for another PR) fixed in 48ab55a. Pass 5: one blocking (the new heading test readorigin/main, absent in depth-1 CI clones; reproduced) left at the fix-cycle cap and granted by the owner as one bounded pass; pass 6 fixed it in 47e693b (strictly newer than every visible heading; depth-1 clone 15 pass) and read clean. Passes 7 and 8 (docs-only ranges after Steps 13 and 14.5): two wording overclaims corrected in 775d980; pass 8 clean, two notes. Passes 9–11 covered the owner-granted docsync fixture repair after the focused paid run: pass 9 (range 775d980..2524ec4; testing, maintainability, Red Team, Step 11 native and outside) found six floor-level fixture gaps (the record write refused under read-only, the shared housekeeping paths not admitted for the fault and store callers, the fixture install withoutlib/, the~form of the cap gate, the Write tool's temp sibling of the record), fixed in 8aa3578, 2549a32, 0230fc2 and 57ac5b0; pass 10 (range 2524ec4..0230fc2) reproduced the temp-sibling gap with the pinned Claude Code binary against the real observer, the same red the 0230fc2 paid rerun hit, fixed in 57ac5b0; pass 11 (range 0230fc2..57ac5b0) read clean: every watch-installation point of the landing enumerated against the live kernel, every abuse probe refused, five notes. Pass 12 (delta pass on the base merge e78f9be; testing, Red Team, Step 11 native and outside) read clean: the four resolutions reproducemergeChangelogsandrenderDoctorComponentsShbyte for byte and carry every line from both sides,git merge-treeconflicts in exactly those four files, the branch's diff over main equals its diff over the old base; three notes.REVIEW_LOOP: passes=12 blocking_found=10 deferred=0 noted=43 fixed=30 scope=frozen
Gate edits: none detected (34 listed, 18 read; the 18 untagged hunks are tests and regenerated goldens that follow product changes; the ship parity re-pin 1.7150 → 1.7400 is the declared cap raise above). Later passes added tests only (the carry refusal test, the heading test, the tripwire-compliant trailer test).
Outside review: Codex CLI absent on the host; the outside voice was a subagent on a different model family (openai/gpt-6.1-sol), logged as
adversarial-reviewrows with sourceoutside-subagent: at 9ea5bfd 2 P2 (the trailer-block defect, verified and fixed; the prose checker accepting swapped lane counts, noted), Verdict pass; at 47e693b 1 P2 (noted), Verdict pass; at 775d980 twice NO_FINDINGS, Verdict pass; at 2524ec4 2 P0 (both confirmed by helper replays and fixed in 8aa3578), Verdict fail; at 0230fc2 the reviewer ran on the author's model family, so that row is native coverage; at 57ac5b0 NO_FINDINGS, Verdict pass; at e78f9be NO_FINDINGS, Verdict pass. Native adversarial re-reads at 9ea5bfd (10 informational), 47e693b (6), 5ceaa5e (2 wording, corrected), 775d980 (2 informational, noted), 2524ec4 (4 floor-level, fixed), 0230fc2 (1 floor-level, fixed in 57ac5b0) 57ac5b0 (2 informational, Recommendation ship) and e78f9be (2 informational, Recommendation ship with notes); Step 11.5 bound the pass-12 review, native and outside rows on reviewed tree 740dcf0ca5ab48ce87c0ffacf5fde86c14a75a1d at e78f9be (pass 11 bound on 0e47daf4 at 57ac5b0; passes 9 and 10 boundchanged, their fix commits landing under the reviewers).Review notes
Below the blocking floor (advisory, informational, test-gap or wording items); recorded here and not fixed in this PR.
bin/gstack-ship-receipt:554docs-caps --base fails open: loadPolicyFromBase merges defaults when the base policy has any validation error, cmdDocsCaps surfaces only docs.* errors, so an unrelated invalid key zeroes the declared caps and prints DOCS_CAP: none declared exit 0 (red-team probe confirmed)bin/gstack-ship-receipt:126receiptVersion decides absent-vs-refusal by regex on versionAtRef's error prose, and a declared .gstack/version-path whose file is missing reads as absent and records version nonescripts/resolvers/outside-voice-steps.ts:134the Step 11 native adversarial prompt still says DIFF_BASE=$RANGE_BASE applies from pass 2 on; the subagent never has RANGE_BASElib/ship-policy.ts:166DOCS_CAPS_KEY_VERSION hard-codes 1.91.257.0 but the train assigns the version at merge; nothing ties the constants to the stamped CHANGELOGbin/gstack-coauthor-trailers:51the range half of the dash guard is unreachable: a positional starting with - is an unknown flag before the guard runs (QA probe)test/gstack-ship-receipt-docs.test.ts:93untested cell updated × no exception after receiptDocs was removedlib/ship-receipt-prose.ts:54leaf-only matching accepts swapped, explicitly lane-qualified counts (gate.unit.pass=7; gate.e2e.pass=41 against unit 41 / e2e 7)bin/gstack-ship-receipt:561docs-caps measures the working tree with fs.statSync, which follows symlinks: a symlink to a tiny file, or an uncommitted trim, passes a cap the pushed head violates; the receipt records no DOCS_CAP resultlib/ship-receipt-prose.ts:2read --check-prose has no caller in ship/SKILL.md or ship/sections/*, though the header, docs/review-policy.md:177 and docs/ship-policy.md say Step 19 / Data PRs run it; RECEIPT_PROSE_MISMATCH exists only when typed by handlib/ship-receipt-prose.ts:50once wired, every lane contributes pass/fail/skip leaves, so ordinary prose like '3 fail before the fix' or quoted CI text trips the check; read --check-prose --json also changes read --json's shapelib/headless-artifacts.ts:207docs is not in the receipt schema, so read/result/queue accept any docs shape; a hand-edited body with docs.status blocked and no exception reads as a valid receiptbin/gstack-ship-receipt:548docs-caps --policy with non-object JSON exits 0 'none declared': the root validation error (path '') is dropped by the docs-prefix filter; the POLICY_INVALID line names .gstack/ship-policy.json instead of the given filebin/gstack-coauthor-trailers:80--message writes trailers after everything, so on agit commit -vCOMMIT_EDITMSG they land below the scissors line and are discarded while COAUTHORS: n appended is printed; --message --json consumes --json as the file namelib/ship-policy.ts:165REVIEW_SCOPE_KEY_VERSION 1.91.249.0 → 1.91.256.0 rejects policies written under released 1.91.256.0 with a minimum in 1.91.249.0–1.91.255.0; CHANGELOG:37 still says since 1.91.249.0ship/sections/documentation.md.tmpl:105docs-audit.json is an unsigned self-report half-protected against staleness: a step range re-entering at 17–21 reuses whatever is on disk, and a run ending Step 14.5 blocked writes nothing so write --docs @… fails with a bare ENOENT exit 2bin/gstack-ship-receipt:460asId maps a per-path or test patch-id git failure to '' (no diff), so a one-sided failure can omit the changed path from the refusal's names or flip the tests-changed evidence; the top-level product check is guardedship/sections/adversarial.md.tmpl:97the Step 11 prompt says DIFF_BASE=$RANGE_BASE applies from Step 9's pass 2 on, but Step 11 first runs after Step 9 converges and has read nothing yet, so a literal reading reviews only the last range and skips the branch; this run read the whole branch against the merge basebin/gstack-coauthor-trailers:86token-specific trailer.co-authored-by.key/.cmd/.command config still rewrites the new lines (key=Reviewed-by turns co-authors into Reviewed-by while --json reports Co-authored-by); only the user's own git config reaches itbin/gstack-coauthor-trailers:87when --in-place cannot create its temp file git exits 128 with empty stderr, so the error line ends in 'cannot append to : ' with no detailbin/gstack-coauthor-trailers:85a missing message file now gets a leading blank line (commit cleanup strips it); a symlinked message path is replaced by a regular file (--in-place renames over it)bin/gstack-coauthor-trailers:16--no-divider needs git >= 2.20; older git exits 1 'unknown option' where the hand-rolled append worked, and the exit legend says exit 1 is only an unresolved rangetest/gstack-coauthor-trailers.test.ts:77the two direct git interpret-trailers --parse assertions omit env: ENV, so a developer's global trailer.* or core.commentChar reaches them while the bin under test runs isolatedlib/ship-policy.ts:168the heading guard is one-shot: once any heading >= the constant exists the key is skipped forever, so DOCS_CAPS_KEY_VERSION is right only if this PR stamps as 1.91.258.0 (the slot call carries the move); archiving old CHANGELOG headings would make released keys fail the testbin/gstack-coauthor-trailers:86the pinned interpret-trailers placement (--no-divider, --where end, --if-exists addIfDifferentNeighbor, trailer.separators=:) has no dedicated test; QA pass 6 probed a --- body line and a hostile trailer.* config by handtest/gstack-ship-policy.test.ts:83git show origin/main:CHANGELOG.md (1.9 MB) exceeds spawnSync's default 1 MiB maxBuffer (ENOBUFS), so the base-branch headings never load and the heading check reads the working tree only; maxBuffer: 64 MiB fixes itdocs/unattended.md:194the ".meta.json" half of the unavailable-cause sentence holds only when a runner was selected and then failed; the no-runner refusal (OUTSIDE_RUNNER_UNAVAILABLE, bin/gstack-outside-voice:103-106) writes the stderr line alone and no meta.json (pass 8, Red Team and native re-read)test/helpers/docsync-observer.ts:233the Step 14.5 housekeeping commands are exact-match only: a decorated form (2>&1,; echo $?, a$HOMEspelling, an&&join,--base origin/main) is refused as outside the interface, which the interface text states; actor behaviour under test, not a helper defecttest/helpers/docsync-observer.ts:253gstack-ship-receipt --helpis refused while the interface grants--helpfor the other three binaries; the next most likely actor refusaltest/helpers/docsync-observer.ts:160admitting the record paths for every caller removes the kernel-level catch of a record written on a blocked fault outcome or in store; nothing in the fixture consumes the record and production is defended bygstack-ship-receipt write --docsrefusing a blocked record without an exception; fix would assert the record absent in the blocked fault scenariostest/helpers/docsync-observer.ts:31within one 10 ms poll window a symlink renamed onto the record and unlinked before a legitimate landing is admitted; the same sequence works with no sibling at all (pre-existing class), and the actor cannot create symlinks through Write/Edit or the gated Bash grammar; requiring modify+close_write would refuse the MOVED_FROM-only shape the kernel delivers when the watch lands between close and renametest/helpers/qa-functional-observer.ts:213events inside a directory created during the run are seen only when a drain tick lands before the activity ends, so a first write into a fresh directory is judged by chance; pre-existing, benign for the record once its sibling is admittedtest/docsync-command-grammar.test.ts:551the two partial landing shapes the kernel delivers (close_write+moved_from only; moved_from alone) are not pinned;landing.slice(1)keeps modifytest/docsync-command-grammar.test.ts:530expect(gate.stderr).toBe('')is strict: a future Bun or lib warning reddens the free test rather than the paid casetest/helpers/docsync-interface.ts:12docsCapsCommandpins one literal path form; actor spelling drift is a flake risk, not a defecttest/gstack-ship-policy.test.ts:90after the base merge, main's 1.91.258.0 heading makes the newer-than-every-heading guard skip thedocskey, so a staleDOCS_CAPS_KEY_VERSIONis caught by no test; neither restamp nor release-cut references the constant, so the stamp's move (the recorded slot note) is a hand steptest/helpers/carve-guards.ts:171ship parity measures 326,604 / 187,706 = 1.73998 against the 1.7400 cap (4 bytes of headroom) and the comment's measured line is stale; pre-existing on the branch, owned by the slot re-measuredocs/troubleshooting.md:4684the additive merge resolution dropped the blank line between the DOCS_AUDIT_BLOCKED Fix paragraph and main's<a id="gstack-pr-wait">anchor; the id still lands and the heading still breaks the paragraph (two identical pre-existing spots on main)ship/sections/review-army.md:379pre-existing: the item-4 (FIXTURE_SUMMARY_MODE) replacement text for the Security specialist uses git diff "$DIFF_BASE" without the DIFF_BASE= assignment, so a literal substitution hands that one specialist an unset variable (pass 8 native re-read; outside this PR's range)Exploratory QA
CLI surfaces only (
gstack-ship-receiptwrite --docs / docs-caps / read --check-prose / version none / carry,gstack-coauthor-trailers,gstack-review-scopedefer / summary): pass 1 14 charters, one probe not run (late-defer summary, rerun at pass 2: 14 of 14 pass); passes 4, 5 and 6 probed the trailer placement by hand (---body lines, hostiletrailer.*config, scissors, leading blank) withgit interpret-trailers --parseon each result: NO FINDINGS. Passes 3, 7 and 8 reused the unchanged candidate or were prose-only. No browser or API surface.Design Review
No frontend files changed — design review skipped.
Eval Results
Paid
ship-frozen-scope-convergence(behavior, gate tier, panel of 3): at f9e8f7b PASS 2/3 (✗✓✓; trial 1 a fixture-message assertion intest/helpers/ship-frozen-scope-actor.ts, repaired in d39ea5d), $0.70; PASS 3/3 at 775d980, $0.65. The 51 /ship and /review own cases focused at 775d980 in the CI image on Ubicloud: 49/51, $22.35;ship-docsync-completionandship-docsync-currentred in round 1 and on their one rule-16 rerun, both on the same fixture-interface gap (the actor stoppedDocumentation: blockedat the undeclared Step 14.5 cap gate), which is a fixture defect rather than a product one and was repaired under the owner's bounded grant (see "Docsync fixture" above). The two cases were then rerun alone: at 2524ec4 red twice (Cannot find module '../lib/headless-artifacts'from the fixture install; the~cap-gate form outside the interface), $3.94; at 0230fc2 red twice onforbidden docs write: .gstack/tmp/docs-audit.json.tmp.<pid>.<12 hex>(the Write tool's atomic landing of the record), $1.81; at 57ac5b0 PASS 2/2 in round 1, $2.09. No threshold, budget or case kind changed; every attempt is recorded above.Plan Completion
Plan completion audit: not run (no plan is bound to this branch and no docs/designs/ file matches). Fix: add "Plan: " to the PR body, or run /autoplan.
Issues
Refs #3504
Verification Results
No Step 8.1 obligations (no bound plan). Docs caps:
gstack-ship-receipt docs-caps --base main→DOCS_CAP: none declared, exit 0. TODO scan clean.TODOS
No TODO items completed in this PR.
Documentation
Status: current — read-only audit (ship3487-20261026T232704Z-r3); no edits, no blockers. Scope: the
capy/version-less-repos-docscandidate against base 576839c (10 commits, head 775d980, clean tree; every candidate hash matches the working tree and the post snapshot reports head_changed=false, content_changed=[], newly_dirty=[]): docs/ship-policy.md, docs/review-policy.md, docs/unattended.md, docs/troubleshooting.md, CHANGELOG.md [Unreleased], review/checklist.md, ship/SKILL.md.tmpl and ship/sections/{changelog,documentation,pr-body,review-army}.md.tmpl with their generated output, cross-checked against bin/gstack-ship-receipt, bin/gstack-coauthor-trailers, bin/gstack-outside-voice, lib/ship-receipt{,-docs,-prose}.ts, lib/ship-policy.ts, lib/review-scope.ts, lib/outside-voice-runner.ts, scripts/resolvers/review-army.ts and ship/sections/adversarial.md. Attempt 2's two blockers and the two reviewer wording items are corrected in commits 5ceaa5e and 775d980 and verified against the code: (1) docs/unattended.md:184-203 no longer names"none"orunavailable_reason, sayscodexfor completed CLI output andsource: "in-host"for the native row (ship/sections/adversarial.md:273), and locates the unavailable cause on thegstack-outside-voice run:stderr line and in<out>.meta.json(bin/gstack-outside-voice:115,122; the no-runner path writes its cause as theOUTSIDE_RUNNER_UNAVAILABLEline at :104); (2) CHANGELOG.md:16 now reads "the paths the branch itself touched and names at mostCARRY_NAMED_PATHS(20)" (lib/ship-receipt.ts:149, bin/gstack-ship-receipt:463-470); (3) CHANGELOG.md:19 and docs/review-policy.md:174 scope the literalDIFF_BASE=<diff-base>claim to the specialist and Red Team prompts scripts/resolvers/review-army.ts renders for /ship (review-army.ts:98,142,321; ship/sections/review-army.md:19,385,556), leaving adversarial.md:97's$RANGE_BASEoutside the claim. The other claims new since attempt 2 also hold:docs-caps [--base <ref>] [--policy <file>]reading origin/'s policy withPOLICY_SOURCE_UNAVAILABLEon an unreadable base (bin/gstack-ship-receipt:553-555), documentation.md.tmpl:11rm -f .gstack/tmp/docs-audit.jsonon first entry and :87docs-caps --base <base>, coauthor-trailers' leading--usage refusal (:52),origin/resolution (:59-60) andgit interpret-trailers --where end(:86),LATE_DEFER_SKILL = 'review-late-defer'(lib/review-scope.ts:261),REVIEW_SCOPE_KEY_VERSION1.91.256.0 /DOCS_CAPS_KEY_VERSION1.91.258.0 with the unreleased-key heading test (test/gstack-ship-policy.test.ts:78-91),receiptVersionreturning"none"only past VERSION, package.json#version, stamp files and CHANGELOG (bin/gstack-ship-receipt:123-134) and the shared-leaf /3 pass-throughprose rule (lib/ship-receipt-prose.ts:30-56). Checks:bun run gen:skill-docs --dry-run138 FRESH, nothing stale;gstack-banned-terms check --diff-base 576839cb: none; focused tests 325/325 (ship-workflow-clarity, gstack-ship-receipt-docs, gstack-ship-policy, review-scope-followups, gstack-coauthor-trailers, ship-receipt-prose, troubleshooting-anchors); git status clean before and after; no repository writes.Documentation health:
README.md Current (no claim touched by the diff)
ARCHITECTURE.md Current (no entity from the diff; no diagram drift)
CONTRIBUTING.md Current
CLAUDE.md / AGENTS.md Current (/ship row stays generic)
CHANGELOG.md Current ([Unreleased] entry matches the code; wording items from attempts 1-2 corrected)
TODOS.md Current
docs/ship-policy.md Current (
docsrow, #ship-receipt, #receipt-carry match lib/ship-policy.ts, receiptVersion, lib/ship-receipt-prose.ts, CARRY_NAMED_PATHS 20, git 2.39 probe)docs/review-policy.md Current (fan-out, checklist ids, #porting-a-contributors-work, late-defer row, literal diff base scoped to review-army.ts prompts)
docs/unattended.md Current (#ship-evidence row fields match ship/sections/adversarial.md:255-273 and bin/gstack-outside-voice)
docs/troubleshooting.md Current (3 new anchors match lib/result-codes-release.ts; #outside-runner-unavailable at :2879)
review/checklist.md Current
ship/*.tmpl Current (generated SKILL.md and sections fresh)
Decisions (not doc edits): docs/unattended.md:187 "the outside provider that reviewed" names no value for the host-subagent row;
gstack-outside-voice runreportsprovider=host-subagentand adversarial.md:271 only says SOURCE is "the actual outside provider or native in-host source", so the prose is consistent but leaves the literal to the host. ship/sections/adversarial.md:97 (generated, unchanged by this branch) still showsDIFF_BASE=$RANGE_BASEfor the Step 11 prompt; the docs now scope the literal-sha claim to review-army.ts prompts, so no contradiction remains, noted for the section owner.DOCS_CAPS_KEY_VERSIONis 1.91.258.0 (lib/ship-policy.ts:168) and CHANGELOG.md:7 and :23 say "the release that stamps this entry": true only if this entry stamps as 1.91.258.0 (branch VERSION 1.91.256.0, main at 1.91.257.0). CHANGELOG.md:10 "First panel 3/3 at $0.66" is a run result outside the tree, unverified here. lib/ship-receipt-prose.ts:2 still says the prose check runs at "/ship Step 19" while no ship section invokes--check-prose(code comment, unchanged from attempts 1-2).Documentation coverage:
version-less repo (Step 12 skip, receipt "none") reference ✅ ship-policy#ship-receipt how-to ✅ ship/sections/changelog.md tutorial ❌ explanation ✅
write --docs / receipt docs record ✅ ship-policy ✅ documentation.md, pr-body.md ❌ ✅ troubleshooting#docs-audit-blocked
docs-caps --base, policy docs.caps ✅ ship-policy table ✅ documentation.md ❌ ✅
read --check-prose ✅ ship-policy ❌ (no step runs it; "Data PRs run it before READY" only) ❌ ✅ troubleshooting
DOCS_AUDIT_BLOCKED / RECEIPT_GIT_TOO_OLD / RECEIPT_PROSE_MISMATCH ✅ troubleshooting anchors n/a n/a ✅
bin/gstack-coauthor-trailers ✅ review-policy ✅ synopsis ❌ ✅
--review-fanout ✅ review-policy#reviewer-fan-out ✅ ship/sections/review-army.md ❌ ✅
carry git >= 2.39, CARRY_NAMED_PATHS walk ✅ ship-policy#receipt-carry ✅ unattended#ship-evidence ❌ ✅
review-late-defer row, literal DIFF_BASE, cap before edit, .gstack/tmp scratch ✅ review-policy, ship-policy ✅ review-army.md ❌ ✅
defer 200-issue truncation (DEFERRED_SEARCH) CHANGELOG only ❌ ❌ ❌
REVIEW_SCOPE_KEY_VERSION 1.91.256.0 / DOCS_CAPS_KEY_VERSION ✅ CHANGELOG n/a n/a ✅ CHANGELOG
paid case ship-frozen-scope-convergence CHANGELOG only ❌ ❌ ❌
cross-family outside voice (unattended#ship-evidence) ✅ ✅ ❌ ✅
Common gaps:
read --check-proseandDEFERRED_SEARCH: truncatedhave reference-only coverage;ship-frozen-scope-convergenceis CHANGELOG-only. Coverage gaps are reported, not filled.Diagram drift: none (ARCHITECTURE.md carries no entity from this diff).
Test plan
bun run typecheckclean;bun run typecheck:test819 known diagnostics, none new (at 12d0463, 775d980, 57ac5b0 and e78f9be)gstack-pregate --allow-repo-commandsat e78f9be (tree 740dcf0c): regen fresh (skill-docs, ship-goldens, doctor-components), 7 checks, requires-remote onlygstack-pregate --stage tests --remote(Ubicloud): tree 740dcf0c, 21,964 tests, 0 failed, $0.06;pregate.json/remote_gateclearedgstack-pregate verifyok; mergeStateStatus CLEANmaxSizeRatioline oftest/helpers/carve-guards.tsagainst v1.91.276.0 feat(preamble): tier 2+ skills load the shared preamble once per session (GSTA-96) #3434, v1.91.277.0 feat(preamble): office-hours stops copying the shared AskUserQuestion subsections (GSTA-96) #3453 and v1.91.273.0 feat(ship): PR bodies open with the problem and a Blast radius line, and gstack-prose-lint catches autopilot phrasing before /ship publishes a CHANGELOG entry or PR body #3501 (see the PR description)ship-frozen-scope-convergenceat 775d980 in the CI image on Ubicloud: PASS 3/3 (✓✓✓), $0.65ship-docsync-completionandship-docsync-currentat 57ac5b0 in the CI image on Ubicloud: PASS 2/2 in round 1 (150 s / 161 s, $2.09) after red twice at 775d980, 2524ec4 and 0230fc2 on successive fixture-interface gaps (see Eval Results); the base merge touches none of the fixture, the ship sections or the receipt binary, so the result stands for e78f9be🤖 Generated with Claude Code