Files
gstack/captain/templates/READY.md
T
Garry Tanandcapy-ai[bot] 901f246d74 feat: crew PRs carry their brief's Plan line; ship-queue ready and land check it (GST-1751) (#4118)
* feat: crew PRs carry their brief's Plan line; ship-queue ready and land check it (GST-1751)

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

* feat: /ship finish and train ready/land check the Plan line (GST-1751)

finish --plan resolves the brief's Plan line before stage 1; train ready,
base-red ready, train land and stamp land read and write the READY note's
plan record like direct ready and land. Review fixes: grant and exception
rows never pass as plan approvals, render --plan stays short when redacted,
no explicit changelog-only exemption, off mode still records a resolved line.

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

* fix: pre-landing review fixes

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

* test: cover the plan check at ready, train ready, land-direct, finish and the policy key (GST-1751)

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

* fix: the Plan line stands for the gate's real state, and a broken store never throws (GST-1751)

A row id from an autoplan run resolves to that run's newest gate revision; a
run id needs the plan approval answered and no decision left unanswered.
readStore skips malformed rows and unreadable files; with the key off the
check never throws or prints. Train land rechecks the Plan line before its
merge on every path. /ship's Step 19-C renders Approvals with --plan;
DRIVER.md back under its size limit.

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

* test: train land refuses a slot with no plan record under require (GST-1751)

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

* fix: pre-landing review fixes

Step 8 plan discovery (lib/ship-audit.ts and the plan-completion sections) skips the Plan record line, so a later Plan: <path> binding is still found; render --plan refuses a line it cannot parse. The review skill's pins drop by 4 bytes.

Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: scripts/resolvers/plan-gates.ts:206:functional-contract reader=qa
Review-Finding: p1/red-team#3 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: changelog fragment passes the prose lint (GST-1751)

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

* docs: captain.md describes the READY PLAN: line (GST-1751)

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

* fix: plan discovery splits the Plan line on whitespace and skips record kinds in any case (GST-1751)

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

* test: lower the gstack-review size pins after the Step 8 binding shrank 4 bytes (GST-1751)

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 09:53:38 +00:00

3.3 KiB

READY block

Sent by the lane: first the block exactly as gstack-ship-queue ready --pr <n> --no-screen|--screen prints it, then the lane's own lines. The controller validates every field before the pin enters train build. A missing or wrong field goes back to the lane, never into a train.

The tool's lines (shapes as printed; screen: is inserted as the second line under a train policy):

READY #<n> <sha40> STAMP_VERSION=unstamped
screen: <screen|no-screen> policy=<selection> nonce=<nonce> run=<run id or ->
pr: <PR url>
head: <sha40>
version: unstamped
base: origin/<BASE>@<base sha40>
ci: green at <sha12> (passed=<k> failed=0 pending=0 skipped=<s>)
PREGATE: pass tree=<tree12> head=<sha12> checks=<c>
gate: command=<"…"|none> full_e2e=<yes|no> gate-ahead=<…>
SHIP_RECEIPT: pr=<n> head=<sha12> version=- base=<BASE> tree=<tree> session_kind=unattended …
PLAN: approved <run id> row=<a-…> (…) | exempt <reason> | warn … (<CODE>)
READY_RECEIPT: <path the tool wrote> (<local and notes-ref detail>)

A wave PR (docs/ship-policy.md#wave-prs) adds two lines after READY, and the controller checks that every constituent named is one the wave was planned for:

WAVE: <nonce> area=<area> branch=wave/<nonce> constituents=<k> integrator_commits=<i>
CONSTITUENTS: #<n>@<sha12>,#<n>@<sha12>,... (heads frozen; fixes go on the wave branch)

Under changelog_fragments (docs/ship-policy.md#changelog-fragments) the PR's entry is a fragment, changelog.d/<slug>.md, never an [Unreleased] section or a version, and the controller merges with train land or land, so no slot call follows this block.

The lane's own lines, after the block:

pin: <sha40>                      # the full head SHA, restated
screen choice: <--no-screen: cases <ids> ran focused and passed | --screen: <reason>>
flaky: <none | case, both run ids, logged in the ledger on <date>>
review passes: <n> (deferred: <items filed as issues, or none>)
Unverified: <none | each claim the lane did not check itself, and why>
Head frozen from now on; a push drops this PR from any train and I will READY again.

Unverified: is required. It lists every claim in the READY that the lane did not check itself: a local test that timed out, a paid run skipped, a number a model reported, a claim inherited from another thread, and a review finding set aside on an assumption nobody tested. none means the lane looked for each of these and found none. A missing line is asked for as a follow-up message: it never holds a PR out of a train, does not stale READYs sent before the line existed, and needs no new ready or /ship run.

Optional lines a crew's rules file may require:

gate_run: <run id> tree=<tree12>        # when lanes gate on their own machines
closes: #<issue>
image: <URL of the key before/after image>

Refuse (send back) when: the SHA is short or a fork head; SHIP_RECEIPT reads none or invalid, or its head is not the pin; ci: is not green at the pin; PREGATE: is not pass for the pin's tree; PLAN: is missing, says warn, or names another plan than the brief's Plan: line; --no-screen names no cases; a flaky case is not in the ledger; the PR page is "green" but no block was sent; the evidence offered is a cheap tier.

After the slot call the lane answers with the stamped head:

READY #<n> <stamped sha40> STAMP_VERSION=<X>