From 4d6e914f9613c1a9cc8d8c33f541ac76ff9e0c07 Mon Sep 17 00:00:00 2001 From: jazz127 Date: Sun, 27 Sep 2026 20:10:40 +1000 Subject: [PATCH 1/2] docs: move PR evidence boundary into ship skill --- .agents/skills/ship-landing/SKILL.md | 32 ++++++++++++++++++++++++++++ AGENTS.md | 23 +------------------- docs/documentation-audiences.json | 4 ++++ 3 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 .agents/skills/ship-landing/SKILL.md diff --git a/.agents/skills/ship-landing/SKILL.md b/.agents/skills/ship-landing/SKILL.md new file mode 100644 index 00000000000..7a1a44d3e03 --- /dev/null +++ b/.agents/skills/ship-landing/SKILL.md @@ -0,0 +1,32 @@ +--- +name: ship-landing +description: Load when a ship reports a PR or ready branch, when deciding or monitoring landing, and before task cleanup. +user-invocable: false +metadata: + internal: true +--- + +# Ship landing + +For PR-based ship tasks, the ready signal depends on mode: `no-mistakes` reports `done [at=]: PR checks green` after CI is green, while `direct-PR` reports `done [at=]: PR ` after opening the PR, each only for a non-draft PR; a lane that deliberately holds a draft declares a wait instead, and `bin/fm-pr-check.sh` refuses to arm merge monitoring on a draft. +Run `bin/fm-pr-check.sh ` with the URL copied from that ready signal or the resolved checks-green `fm-crew-state.sh` line - it records `pr=` and the forge's `pr_head=` when available in the task's meta and arms the watcher's merge poll. +`bin/fm-dod-lib.sh` owns the named-head gate on that ready signal: a ship `done:` whose named head exists only in the worker's disposable copy is not ready (`bin/fm-crew-state.sh` reports blocked, `bin/fm-pr-check.sh` refuses to register, and a secondmate does not publish that done upstream). +That blocked reading is the gate working, not a stuck worker, so steer the worker on the commit the refusal names rather than waiting. +A direct-PR worker pushes that commit to its PR branch, and a local-only worker commits it on its ship branch. +A no-mistakes worker re-validates it with /no-mistakes so the pipeline stays the one publisher; it never pushes from its copy. +In no-mistakes mode the earlier `done [at=]: {summary}` is the pipeline handoff and is not gated. +Before reporting any pull request to the captain, its published body is read back from the forge at the PR reporting boundary; task-owned PR registration and inactive reconciliation perform this check automatically, including for reports without an owning task record. +Preserve the reported PR outcome but append `evidence-validation=failed` when its body cannot be read or parsed, or when an evidence claim lacks the artifact, command, and capture time required by `bin/fm-dod-lib.sh`. +This check validates published text at the reporting boundary; it does not police what a generator writes before publication. +Tell the captain the PR's full `https://...` URL copied from the worker's ready line, the resolved checks-green crew-state line, or the task's `pr=` metadata, a concise outcome summary, and the no-mistakes risk level when applicable. +A captain instruction to merge is explicit authority; `yolo` is the only standing routine merge authority. +For any custom `state/.check.sh` you write yourself, keep it an ordinary single-link mode-`0700` file, print one line only when firstmate should wake, print nothing otherwise, finish before `FM_CHECK_TIMEOUT`, then bind its current bytes with `bin/fm-check-register.sh ` before the watcher may execute it. +Retire a custom check only through `bin/fm-check-unregister.sh ` (or `bin/fm-teardown.sh` for a spawned task); never hand-compose an `rm` with `$STATE`/`$ID`. + +Tear down a ship task only after landing is confirmed. +A teardown refusal for uncommitted or unlanded work is a stop-and-investigate result, never an obstacle to bypass. +Never force teardown without explicit discard authority. +After successful teardown, record completion, retain only the configured recent Done history, and re-evaluate queued work whose blockers and time gates have cleared. + +A secondmate is persistent and an empty queue is healthy. +Retire one only on an explicit captain or main-firstmate decision, after loading `secondmate-provisioning`; its home must contain no work under way, and forced discard still requires explicit captain authority. diff --git a/AGENTS.md b/AGENTS.md index f2a50abf339..6de7f33df3d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -396,28 +396,7 @@ The worker reports the PR when CI first becomes green rather than waiting for me ### PR ready, landing, and teardown -For PR-based ship tasks, the ready signal depends on mode: `no-mistakes` reports `done [at=]: PR checks green` after CI is green, while `direct-PR` reports `done [at=]: PR ` after opening the PR, each only for a non-draft PR; a lane that deliberately holds a draft declares a wait instead, and `bin/fm-pr-check.sh` refuses to arm merge monitoring on a draft. -Run `bin/fm-pr-check.sh ` with the URL copied from that ready signal or the resolved checks-green `fm-crew-state.sh` line - it records `pr=` and the forge's `pr_head=` when available in the task's meta and arms the watcher's merge poll. -`bin/fm-dod-lib.sh` owns the named-head gate on that ready signal: a ship `done:` whose named head exists only in the worker's disposable copy is not ready (`bin/fm-crew-state.sh` reports blocked, `bin/fm-pr-check.sh` refuses to register, and a secondmate does not publish that done upstream). -That blocked reading is the gate working, not a stuck worker, so steer the worker on the commit the refusal names rather than waiting. -A direct-PR worker pushes that commit to its PR branch, and a local-only worker commits it on its `fm/` branch. -A no-mistakes worker re-validates it with /no-mistakes so the pipeline stays the one publisher; it never pushes from its copy. -In no-mistakes mode the earlier `done [at=]: {summary}` is the pipeline handoff and is not gated. -Before reporting any pull request to the captain, its published body is read back from the forge at the PR reporting boundary; task-owned PR registration and inactive reconciliation perform this check automatically, including for reports without an owning task record. -Preserve the reported PR outcome but append `evidence-validation=failed` when its body cannot be read or parsed, or when an evidence claim lacks the artifact, command, and capture time required by `bin/fm-dod-lib.sh`. -This check validates published text at the reporting boundary; it does not police what a generator writes before publication. -Tell the captain the PR's full `https://...` URL copied from the worker's ready line, the resolved checks-green crew-state line, or the task's `pr=` metadata, a concise outcome summary, and the no-mistakes risk level when applicable. -A captain instruction to merge is explicit authority; `yolo` is the only standing routine merge authority. -For any custom `state/.check.sh` you write yourself, keep it an ordinary single-link mode-`0700` file, print one line only when firstmate should wake, print nothing otherwise, finish before `FM_CHECK_TIMEOUT`, then bind its current bytes with `bin/fm-check-register.sh ` before the watcher may execute it. -Retire a custom check only through `bin/fm-check-unregister.sh ` (or `bin/fm-teardown.sh` for a spawned task); never hand-compose an `rm` with `$STATE`/`$ID`. - -Tear down a ship task only after landing is confirmed. -A teardown refusal for uncommitted or unlanded work is a stop-and-investigate result, never an obstacle to bypass. -Never force teardown without explicit discard authority. -After successful teardown, record completion, retain only the configured recent Done history, and re-evaluate queued work whose blockers and time gates have cleared. - -A secondmate is persistent and an empty queue is healthy. -Retire one only on an explicit captain or main-firstmate decision, after loading `secondmate-provisioning`; its home must contain no work under way, and forced discard still requires explicit captain authority. +Load `ship-landing` when a ship reports a PR or ready branch, when deciding or monitoring landing, and before task cleanup. ### Scout outcome and promotion diff --git a/docs/documentation-audiences.json b/docs/documentation-audiences.json index e3564ff07e0..d5af1a4e0fe 100644 --- a/docs/documentation-audiences.json +++ b/docs/documentation-audiences.json @@ -248,6 +248,10 @@ "path": ".agents/skills/secondmate-provisioning/SKILL.md", "audience": "agent-runtime" }, + { + "path": ".agents/skills/ship-landing/SKILL.md", + "audience": "agent-runtime" + }, { "path": ".agents/skills/stow/SKILL.md", "audience": "agent-runtime" From 7cef8346bc0d0447a2ef53cd439ed9ade6715b93 Mon Sep 17 00:00:00 2001 From: jazz127 Date: Sun, 27 Sep 2026 20:13:02 +1000 Subject: [PATCH 2/2] no-mistakes(review): Point reporting-boundary doc links at ship-landing skill --- docs/secondmate-parent-channel.md | 2 +- docs/verification/secondmate-parent-channel.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/secondmate-parent-channel.md b/docs/secondmate-parent-channel.md index da1ebbee2ac..c01f34d5f6e 100644 --- a/docs/secondmate-parent-channel.md +++ b/docs/secondmate-parent-channel.md @@ -34,7 +34,7 @@ Every captain-facing outcome that leaves durable evidence in the mate home is pu | An outcome that exists only in the mate's reasoning | none | the charter and the `AGENTS.md` carve-outs only | The ledger delivery reads files, plus a local git reachability check on a ship `done:` with no delivery record yet (`bin/fm-dod-lib.sh`), and a bounded forge read when the report carries a pull request URL so the published body can be validated before it reaches the parent channel. -Failure handling follows the reporting-boundary contract in [`AGENTS.md`](../AGENTS.md). +Failure handling follows the reporting-boundary contract in [`.agents/skills/ship-landing/SKILL.md`](../.agents/skills/ship-landing/SKILL.md). Each delivery is keyed with the first eight hexadecimal characters of its receipt fingerprint and uses the shared append contract above, and the ledger path reuses the inactive scan's per-fingerprint receipts, so a replayed poll or restart cannot deliver an event twice while a genuinely new terminal event is delivered again. A duplicate line is harmless and a missed one is not, so the mate may still append its own judgement about a delivered outcome, and the parent reads the script's line as the fact and the mate's line as commentary. For marked replies, the report helper accepts no caller-selected destination and uses the channel resolver for both local and remote homes; its script header owns the exact invocation contract. diff --git a/docs/verification/secondmate-parent-channel.md b/docs/verification/secondmate-parent-channel.md index 3ca577acbe1..40cee063c58 100644 --- a/docs/verification/secondmate-parent-channel.md +++ b/docs/verification/secondmate-parent-channel.md @@ -18,7 +18,7 @@ No agent harness and no model runs anywhere in the fixture. The child's only action is the ordinary crewmate status append, typed into its own pane with `tmux send-keys`. The mate's only actions are the scripts a firstmate runs when it registers a PR and when it holds a task for the captain and records the answer. This fixture predates the reporting-boundary published-body validation, so its PR line verifies delivery only and is not evidence that the referenced body passed validation. -Current reporting follows the reporting-boundary contract in [`AGENTS.md`](../../AGENTS.md). +Current reporting follows the reporting-boundary contract in [`.agents/skills/ship-landing/SKILL.md`](../../.agents/skills/ship-landing/SKILL.md). ## Transcript