Repository navigation
Conversation
a85e73f to
5078ad1
Compare
0597eb7 to
5f670cf
Compare
5078ad1 to
04d25ce
Compare
5f670cf to
45917e2
Compare
04d25ce to
8ecdf45
Compare
45917e2 to
85b51f2
Compare
8ecdf45 to
b12d406
Compare
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…publishes S_i exactly; backstop covers exact trees (PR B) 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>
…r stamped trains 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>
…; regenerate the doctor anchors 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>
…ndows-safe subset (same gh shim as the train tests) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
- train land checks commit-tree and stamps with a fixed identity and date, journals before the push, and adopts its own stamp head on a rerun; a failed commit-tree never pushes a branch deletion - a symlinked release file in the merged tree refuses before the train stamp writes - mergeStep merges a conflicted manifest three-way with the predecessor's version (mergeManifest, shared with land) - train land refuses a PR retargeted off the base and a failed base refresh - Version Gate skips a released fragment carried in by a stacked pin instead of counting its bump - bisect of a stamped train tests T0 and S_1..S_k Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…amp step after a journaled, unpushed stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
85b51f2 to
739a374
Compare
…stamping; a merge main does not show yet pends Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…order slot refuses without freezing; stamps never sign Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…e PR never reads as a move; reruns of landed slots confirm; T0 in the out-of-order refusal Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ing; require changelog_fragments.required_checks green on the stamp commit Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ume and required checks; stamped bisect; three-way manifest merges Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
E2E Evals: ✅ PASS125 executed, 0 reused rule/judge records | 0 manual accepted (unscored; no score-cache credit) | $33.18 rule/judge cost | reconcile exit: 0 Profile: pr / mode Full gate restored by:
Derived dependents (scripts/pr-dependencies.ts):
Rule and judge shards
Fail-closed reconciliationSliced lane: planner → duration-packed executors → fail-closed report. Behavior cases run a pre-registered 3-trial panel (PASS at 2/3 with no contract violation); a PASS 2/3 is shown with its failed trial, never as a clean pass. Reused results retain their original provenance and expiry. Dispatched narrow screen (gstack-ship-queue ready --screen) of merge commit |
GSTA-154 PR B, stacked on #3594 (draft). /ship runs after PR A; the body is replaced by the /ship receipt and PR summary.
What changed
gstack-ship-queue traingainsland: underchangelog_fragmentsa train builds stamped prefixes S_i andtrain landpublishes each slot's S_i exactly, so no lane stamps a slot by hand.Before/after as text: train help
Why
Stacked on #3594. With fragments, a PR no longer carries a version, so a train has to assign versions itself. Today the controller makes a slot call and the lane stamps, verifies and waits per slot (a median 14.5 minutes from stamp commit to merge over 30 slots, Oct 27-29). Here
train buildcomputes every slot's stamped tree S_i = stamp(merge(S_(i-1), pin_i)) up front and gates S_k, so the gate covers exactly the trees that land, andtrain landpublishes them without a lane.Blast radius
Everything new is reachable only from a train built under
changelog_fragments, which gstack's own policy leaves off; plain trains, slot calls andverify --trainbehave as before. Shared with #3594 and other lanes: docs/ship-policy.md, docs/captain.md, docs/troubleshooting.md, docs/recommended-harness.md, captain/templates (READY.md, slot-call.md), lib/ship-queue*.ts, lib/restamp.ts, lib/ship-policy.ts, lib/changelog-fragments.ts, lib/version-gate-train.ts, lib/result-codes-release.ts, scripts/train-gate.ts, scripts/train-backstop.ts, scripts/lib/windows-curation.ts, bin/gstack-doctor-components.sh and CHANGELOG.md.With fragments off.
train buildmakes stamped prefixes only underchangelog_fragments(lib/ship-queue-train.ts:428) andtrain landrefuses a record without them (test "a plain train refuses train land").train landdoes not read the policy key itself, so a hand-edited or forged train note could still reach its merge-confirm path with fragments off. #3603 tracks the record-trust follow-ups; until it lands, keeptrain landout of production trains.Approvals
changelog_fragments.required_checksSummary
train build(lib/ship-queue-train-stamp.ts) builds S_1..S_k on top of the plain prefixes, checks each S_i equals the plain prefix outside release paths and keeps every earlier release entry byte for byte (QUEUE_TRAIN_STAMP_MISMATCH), refuses a symlinked release file before stamping, and gates S_k.train land --train <nonce> --pr <n>(lib/ship-queue-train-land.ts) first verifies the whole record against git: T0 and S_1..S_k must be the gated head's first-parent chain, with each S_i's second parent equal to slot i's pin. Every later step uses only that verified chain. It makes a deterministic stamp commit of S_i on [pin, main] with a fixed identity and no signing, journals it, pushes under the pin's lease withevals-no-debounce, waits for checks, refuses unless every name in the newchangelog_fragments.required_checksis present and green on that commit, squashes with--match-head-commitand confirms main's tree is S_i. A rerun adopts its own journaled stamp, a retargeted PR refuses, an earlier slot out of order refuses without freezing, and any other main freezes the queue as before. Train merges now resolve apackage.jsonor lockfile conflict three-way; the main backstop covers a stamped prefix only by exact tree;train bisectof a stamped train tests T0 and S_1..S_k; Version Gate skips a stacked parent's already-released fragment.Test Coverage
New tests: test/ship-queue-train-stamp.test.ts (S_i order and bumps, stacked child fold, four-part package.json, manifest edit survival, symlinked CHANGELOG, tampered earlier version), test/ship-queue-train-land.test.ts (exact publish with the label, foreign push never overwritten, merge outside the train freezes, failed stamp commit pushes nothing, rerun after push or journal resumes, retargeted PR, stamped bisect, plain train refused, forged chain entries, a required check that never reported), test/train-backstop.test.ts, test/version-gate-fragments.test.ts. Review fixes landed with failing-first tests (7/7 for the Codex batch; the required-check test fails on b1c6e9f).
Tests ran: remote free tier 23641 tests, 0 failed (tree 04e1d1cc); macOS and Windows lanes cleared by dispatched runs 40854173484 and 40854180721
Pre-Landing Review
Pass 1 (six specialists and the red team) found 7 blocking defects; the Codex outside voice and the native adversarial pass found more. Fixed: commit-tree failure pushing a branch deletion, push before journal freezing the queue, symlinked release files, manifest conflicts dropping pin edits, retargeted PRs, stacked-child double counting, failed base refresh, stamped bisect. Fix checks 2 to 4 each found a record field the per-slot guards left unverified; after the fourth cycle (GStack Minder's exception) the record checks were redesigned into one verified-chain pass. The redesign's fix-check raised two CRITICALs outside the verified-chain logic (slot↔PR binding and trust in
t.merged), filed as #3603 under GStack Minder's ruling. The final pair on fa62ea3 bound clean.REVIEW_LOOP: passes=1 blocking_found=7 deferred=4 noted=12 fixed=10 scope=frozen fix_checks=6 dispatches=7
Deferred: #3599 (train land skips the shared land lock; one controller merges under CREW rule 6) and #3603 (slot↔PR binding,
t.merged,t.headvalidation, journal-resume tree, intermediate S_i, required_checks name matching).Review notes
required_checks, the stamp commit can read green before every check has registered (the same class as ship-queue: assign VERSION/CHANGELOG at merge time (changelog fragments + gstack-ship-queue land) #3594's late-registering checks note). Setrequired_checkswhen turning fragments on.required_checksis read from main's policy at land time, not pinned in the train record.node_modulessymlink was shipped dangling; it was excluded locally (no tracked change) and the gate reran at the commit's own tree.Exploratory QA
No separate probes.
train land's gh-backed paths run in test/ship-queue-train-land.test.ts against a gh shim; the live pilot is one train with GStack Minder after READY.Design Review
No frontend files changed — design review skipped.
Eval Results
No prompt or skill-template change; the paid gate runs on the train.
Plan Completion
Plan items 10-16 (stamped prefixes, gate S_k, train land, backstop by exact tree, stamped bisect) are built here. Deferred with approval: S_i pretests, the controller reuse check and train-prefix refs wait for GSTA-156; peer-repo opt-ins and gstack's policy flip come after the pilot train.
Issues
Refs #3557
Refs #3567
Refs #3599
Refs #3603
Verification Results
Focused suite: 268 green, none red; docs tests: 316 green, one E18 5 s timeout under load that passes alone;
bun run gen:skill-docs && bun run buildclean.TODOS
No TODO items completed in this PR.
Documentation
Status: blocked. Factual edits to docs/ship-policy.md, docs/troubleshooting.md and docs/recommended-harness.md; the /captain skill's merge-train section is open.
Documentation exception: accepted by GStack Minder for Garry 2026-10-29 via GSTA-154: /captain SKILL.md.tmpl Merge trains still teaches only the slot-call loop; the policy-flip PR teaches train land and changelog_fragments stays off until the pilot
Scope: branch
gsta154-train-stampsagainstgsta154-changelog-fragments: docs/ship-policy.md, docs/troubleshooting.md, docs/recommended-harness.md, docs/captain.md, captain/templates/READY.md, captain/templates/slot-call.md, captain/SKILL.md.tmpl, docs/skills.md.Documentation health:
required_checks)train landper slot)Coverage debt:
train landhas no /captain skill or docs/skills.md coverage;required_checkshas no worked policy example; the TRAIN_HELP bisect line still says T0..Tk.Diagram drift: docs/recommended-harness.md's mermaid flow shows only the slot-call loop (still true for plain trains).
Test plan
bun run typecheck,bun run gen:skill-docsfreshness,bun run build🤖 Generated with Claude Code