Skip to content
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ After an autonomous merge, give the captain a one-line full-URL or local-main ou

### Validate

For a no-mistakes ship, trigger validation on the same worker after its implementation commit, using the harness invocation owned by `harness-adapters`.
For a no-mistakes ship, the task's own worker starts validation itself after its implementation commit, using the harness invocation owned by `harness-adapters`.
Sending that worker this task's no-mistakes skill invocation, in the harness-specific form `harness-adapters` owns, is firstmate's fallback nudge for a worker that has not started its run; never send it as a second start to a worker already driving its run.
The task worker that starts a no-mistakes run drives the pipeline and owns every `no-mistakes axi run` and `no-mistakes axi respond` call through the next gate or outcome.
Firstmate never invokes `no-mistakes axi respond` for a crew-owned run.
When the captain adds or changes an ask mid-task, append the captain's words to that brief's `## Captain's intent` and steer the worker; Firstmate build constraints stay in `## Firstmate spec` or the steer.
Expand Down Expand Up @@ -535,7 +536,7 @@ Preserve durable structured identifiers, dependencies, and completion artifact l

## 11. Crewmate briefs

`bin/fm-brief.sh` and its help own scaffold syntax, generated variants, status protocol, artifact placement, delivery-mode definitions of done, and exact safety mechanics.
`bin/fm-brief.sh` and its help own scaffold syntax, generated variants, status protocol, artifact placement, and exact safety mechanics, while `bin/fm-dod-lib.sh` is the single owner of the delivery-mode definitions of done.
Use its scaffold as the contract, then fill `## Captain's intent` (`{TASK}`) with the captain's own ask plus the context needed to read it, including the substance of any report, decision, or PR the ask refers to, and fill `## Firstmate spec` (`{FIRSTMATE_SPEC}`) with Firstmate's build instructions.
`bin/fm-dod-lib.sh` owns what a no-mistakes worker may pass as `--intent` and its rule that the string must be self-sufficient.
Keep additions task-specific rather than repeating lifecycle instructions, and alter generated sections only when the task genuinely differs from the standard shape.
Expand Down
23 changes: 17 additions & 6 deletions bin/fm-dod-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
# mode is refused rather than silently rendered as the pipeline contract.
# The block opens with the fixed machine-readable "Delivery contract: mode=<mode>"
# line that bin/fm-spawn.sh checks a ship brief against.
# The no-mistakes branch owns the mode's completion signal: that block opens by
# naming the pipeline's PR as the completion and saying outright that a commit is
# not one, because workers were reading a commit as "done" and stopping there.
# This file is the one owner of the no-mistakes `--intent` contract: only the
# brief's `## Captain's intent` subsection plus later captain words, never
# `## Firstmate spec` and never the worker's own tradeoffs.
Expand Down Expand Up @@ -220,7 +223,7 @@ Delivery contract: mode=direct-PR
This task ships **direct-PR**: you raise the PR yourself, without the no-mistakes pipeline.
The task is complete only when committed on your branch.
When it is implemented and committed, push your branch and open a PR with \`gh-axi\`, then append \`done: PR {url}\` to the status file and stop.
Do NOT run /no-mistakes. The configured merge authority decides whether to merge the PR; firstmate relays the outcome.
Do NOT start the no-mistakes pipeline. The configured merge authority decides whether to merge the PR; firstmate relays the outcome.
EOF
;;
local-only)
Expand All @@ -238,12 +241,20 @@ EOF
cat <<EOF
# Definition of done
Delivery contract: mode=no-mistakes
The task is complete only when committed on your branch.
When you believe it is complete, append \`done: {summary}\` to the status file and stop.
Firstmate will then instruct you to run /no-mistakes to validate and ship a PR.
**Completion for mode=no-mistakes is a PR the no-mistakes pipeline pushed and opened, never a commit.**
A commit, a clean branch, or "ready for the run" is NOT completion; stopping there leaves the task unfinished and firstmate has to chase it.
The one completion claim is \`done: PR {url} checks green\`, written with the PR's full \`https://\` URL once the run reports CI green.
Running the pipeline belongs to this task, not to a later instruction: once your implementation is committed, start this task's no-mistakes pipeline yourself in your own harness's skill-invocation form, and keep driving its gates until that green result or a terminal failure.
The exact skill-invocation form is harness-specific and owned by \`harness-adapters\`; when you are unsure of it, state the action in natural language and proceed.
Never start a second validation run while one is already active on this branch.
Treat a firstmate delivery of this task's no-mistakes skill that arrives mid-run as a nudge to reattach and poll, not as a second start.
If a start is refused because a run is already active on this branch, follow the pipeline's own status and help lines instead of reporting the task blocked.
First run in a repo the pipeline has never seen: run \`no-mistakes doctor\`, then \`no-mistakes init\` if it reports the repo is not initialized here, before the first run.
Write the completion line as the pinned claim first, then the validated head commit and the CI result on that same line, leaving the claim itself intact.
The completion line is the LAST line in the status log: put any supplementary explanation before it, or in \`data/<task-id>/\`, never after it.

You drive no-mistakes by responding to its gates, not by implementing fixes.
Follow the guidance no-mistakes itself provides for the mechanics: it loads when you invoke /no-mistakes, and \`no-mistakes axi run --help\` plus the \`help\` lines in each \`axi\` response are authoritative and version-matched to the installed binary.
Follow the guidance no-mistakes itself provides for the mechanics: it loads when you start the skill, and \`no-mistakes axi run --help\` plus the \`help\` lines in each \`axi\` response are authoritative and version-matched to the installed binary.
When starting no-mistakes, pass \`--intent\` as only this brief's \`## Captain's intent\` subsection plus any later words the captain actually said.
For a legacy brief with no such subsection, include only words explicitly labeled \`Captain:\`, \`Captain's words:\`, \`Captain's ask:\`, or \`Captain's intent:\`; never copy its mixed \`# Task\` wholesale. If it has no provenance-marked captain words, stop and ask firstmate instead of starting no-mistakes.
Do not include \`## Firstmate spec\`, later Firstmate build constraints, or your own decisions and tradeoffs.
Expand All @@ -265,7 +276,7 @@ Two firstmate-specific rules layer on top of that guidance:
- NEVER pass \`--yes\` (or \`-y\`) to \`no-mistakes axi run\` or \`no-mistakes axi respond\`. It is banned fleet-wide.
It auto-resolves every gate including ask-user findings with no escalation, and answering your own ask-user finding is a hard rule violation.

After /no-mistakes reports CI green (the CI-ready return point - do not wait for it to keep monitoring in the background until merge), append \`done: PR {url} checks green\` and stop. You are finished.
After the pipeline reports CI green (the CI-ready return point - do not wait for it to keep monitoring in the background until merge), append \`done: PR {url} checks green\` and stop. You are finished.
EOF
;;
*)
Expand Down
81 changes: 79 additions & 2 deletions tests/fm-brief.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ test_ship_mode_is_explicit_not_registry() {
brief="$home/data/brief-explicit-a5/brief.md"
grep -qx "Delivery contract: mode=no-mistakes" "$brief" \
|| fail "registered direct-PR posture overrode the explicit --mode"
assert_grep "Firstmate will then instruct you to run /no-mistakes" "$brief" \
"explicit no-mistakes brief did not render the pipeline definition of done"
assert_grep "Completion for mode=no-mistakes is a PR the no-mistakes pipeline pushed and opened, never a commit." "$brief" \
"explicit no-mistakes brief did not render the pipeline completion signal"

# An unregistered project is not a blocker either, because nothing is looked up.
FM_HOME="$home" "$ROOT/bin/fm-brief.sh" brief-explicit-a6 never-registered --mode local-only >/dev/null 2>&1 \
Expand Down Expand Up @@ -372,6 +372,82 @@ test_no_mistakes_dod_wording() {
pass "fm-brief.sh: no-mistakes DOD keeps its apostrophe prose and bans --yes outright"
}

# Regression pin for the delivered-then-abandoned failure: three no-mistakes
# workers committed, read a commit as completion, and stopped without ever
# running the pipeline. The generated no-mistakes brief must name the PR as the
# completion signal, say a commit is not one, and keep the other modes' signals
# distinct from it. It must also hand the worker its own start in a harness-agnostic
# form, without letting a firstmate nudge collide with one already active.
test_no_mistakes_completion_is_a_pr_not_a_commit() {
local home id brief
home="$TMP_ROOT/completion-signal-home"
write_registry "$home"

id="brief-completion-c1"
FM_HOME="$home" "$ROOT/bin/fm-brief.sh" "$id" some-proj --mode no-mistakes >/dev/null 2>&1
brief="$home/data/$id/brief.md"
assert_present "$brief" "no-mistakes brief was not scaffolded"
assert_grep "Completion for mode=no-mistakes is a PR the no-mistakes pipeline pushed and opened, never a commit." "$brief" \
"no-mistakes brief must say the pipeline PR, not a commit, is the completion signal"
assert_grep 'A commit, a clean branch, or "ready for the run" is NOT completion' "$brief" \
"no-mistakes brief must say plainly that committed work is not completion"
# shellcheck disable=SC2016 # single quotes are deliberate: the backticks must stay literal
assert_grep 'The one completion claim is `done: PR {url} checks green`' "$brief" \
"no-mistakes brief must pin the one completion claim"
assert_no_grep 'state the honest real result instead of "checks green"' "$brief" \
"no-mistakes brief must keep the single pinned completion claim instead of accepting a second spelling"
assert_grep "Running the pipeline belongs to this task, not to a later instruction" "$brief" \
"no-mistakes brief must make running the pipeline the worker's own step"
assert_grep "start this task's no-mistakes pipeline yourself in your own harness's skill-invocation form" "$brief" \
"no-mistakes brief must hand the worker its own start in a harness-agnostic form"
assert_grep "when you are unsure of it, state the action in natural language and proceed" "$brief" \
"no-mistakes brief must let a worker unsure of the invocation form proceed in natural language"
assert_no_grep "/no-mistakes" "$brief" \
"no-mistakes brief handed the worker a harness-specific slash invocation"
assert_grep "Never start a second validation run while one is already active on this branch." "$brief" \
"no-mistakes brief must forbid a duplicate validation run on the branch"
assert_grep "Treat a firstmate delivery of this task's no-mistakes skill that arrives mid-run as a nudge to reattach and poll, not as a second start." "$brief" \
"no-mistakes brief must treat a mid-run firstmate delivery as a nudge, not a second start"
assert_grep "If a start is refused because a run is already active on this branch, follow the pipeline's own status and help lines instead of reporting the task blocked." "$brief" \
"no-mistakes brief must route an already-active-run refusal to the pipeline's own status rather than a blocked report"
# The brief must not assert a refusal surface or an ownership check the repo cannot verify.
assert_no_grep "pipeline ownership" "$brief" \
"no-mistakes brief must not assert a pipeline-ownership refusal the repo cannot verify"
assert_no_grep "check whether the active run is this task's own run" "$brief" \
"no-mistakes brief must not tell the worker to certify run ownership it cannot check"
assert_grep "First run in a repo the pipeline has never seen: run \`no-mistakes doctor\`, then \`no-mistakes init\`" "$brief" \
"no-mistakes Definition of done must carry its own first-run initialization step"
assert_grep "Write the completion line as the pinned claim first, then the validated head commit and the CI result on that same line, leaving the claim itself intact." "$brief" \
"no-mistakes brief must keep the pinned claim intact and append head and CI after it on the same line"
assert_no_grep "report all three" "$brief" \
"no-mistakes brief still asks for a second shape of the completion claim"
assert_grep "The completion line is the LAST line in the status log" "$brief" \
"no-mistakes brief must keep the completion claim as the last status line"
assert_no_grep "The task is complete only when committed on your branch." "$brief" \
"no-mistakes brief still declares a commit as the completion bar"

# Mode separation: direct-PR and local-only complete on different artifacts,
# so the no-mistakes pipeline claim must not leak into either of them.
local mode
for mode in direct-PR local-only; do
id="brief-completion-c2-$mode"
FM_HOME="$home" "$ROOT/bin/fm-brief.sh" "$id" some-proj --mode "$mode" >/dev/null 2>&1
brief="$home/data/$id/brief.md"
assert_no_grep "Completion for mode=no-mistakes" "$brief" \
"$mode brief received the no-mistakes completion signal"
assert_no_grep 'done: PR {url} checks green' "$brief" \
"$mode brief received the no-mistakes CI-green completion claim"
done
brief="$home/data/brief-completion-c2-direct-PR/brief.md"
# shellcheck disable=SC2016 # single quotes are deliberate: the backticks must stay literal
assert_grep 'then append `done: PR {url}` to the status file and stop.' "$brief" \
"direct-PR brief lost its own opening-a-PR completion signal"
brief="$home/data/brief-completion-c2-local-only/brief.md"
assert_grep 'When it is implemented and committed, append `done: ready in branch fm/' "$brief" \
"local-only brief lost its ready-branch completion signal"
pass "fm-brief.sh: no-mistakes completion is the pipeline PR, and the other modes stay distinct"
}

test_ask_user_escalation_format() {
local home id brief mode other_id other_brief
home="$TMP_ROOT/ask-user-home"
Expand Down Expand Up @@ -1050,6 +1126,7 @@ test_ship_mode_is_explicit_not_registry
test_delivery_flags_are_refused_where_they_do_not_apply
test_faster_paths_use_configured_authority_without_stacked_review
test_no_mistakes_dod_wording
test_no_mistakes_completion_is_a_pr_not_a_commit
test_ask_user_escalation_format
test_ship_project_memory_wording
test_herdr_lab_contract_is_explicit_and_complete
Expand Down
2 changes: 1 addition & 1 deletion tests/fm-task-delivery.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ STUB
"promoted worker lost the scout protocols and safety rules that still apply"

# The faster paths keep their own contracts rather than inheriting the pipeline's.
assert_grep "Do NOT run /no-mistakes" "$payload" \
assert_grep "Do NOT start the no-mistakes pipeline" "$payload" \
"promoted direct-PR worker lost its no-pipeline contract"
assert_grep "Do NOT push, do NOT open a PR, do NOT merge" "$TMP_ROOT/promote-dod/payload-promote-dod-local-only" \
"promoted local-only worker lost its no-remote contract"
Expand Down
Loading