Skip to content

fix: prefill verification criteria in Firstmate ship briefs - #206

Merged
dnth merged 4 commits into
mainfrom
fm/fm-brief-firstmate-verification-ac
Oct 5, 2026
Merged

dnth merged 4 commits into
mainfrom
fm/fm-brief-firstmate-verification-ac

Conversation

@dnth

@dnth dnth commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Intent

Make bin/fm-brief.sh pre-fill the correct verification criterion for ship briefs that target the Firstmate repository itself. Today the scaffold leaves - AC1: {ACCEPTANCE CRITERION} free-form, and two Firstmate-repo briefs on 2026-10-05 asked for "full suite green". That contradicts .no-mistakes.yaml (lines ~31-35: ci.yml owns broad regression; local runs are intent-targeted). The result was hours of serial local full-suite runs on a loaded host and a mid-run reinterpretation of AC3. Change: when the target project is this Firstmate repository (detect it the way the scaffold already distinguishes projects), add one standard criterion after the task's own criteria, worded like: "AC: changed tests green via bin/fm-test-run.sh --changed, FM_LINT_JOBS=1 bin/fm-lint.sh clean, and the PR's full GitHub CI suite green, recorded as an evidence line with the CI run URL and head before reporting PR-ready". Its id must not collide with the brief's own criteria and must stay parseable by bin/fm-receipt-check.sh. Briefs for other projects stay unchanged. Load the firstmate-coding-guidelines skill before editing shared tracked material. Run lint with FM_LINT_JOBS=1 (host memory is constrained).

Acceptance criteria:

  • AC1: a Firstmate-repo ship scaffold contains the standard verification criterion, and bin/fm-receipt-check.sh parses it as a criterion; a non-Firstmate ship scaffold does not contain it. Prove both with a regression test in tests/ that fails on the parent commit.
  • AC2: the criterion wording matches .no-mistakes.yaml test policy, with no local full-suite requirement; the docs or help that own the scaffold contract are updated.
  • AC3: changed tests green via bin/fm-test-run.sh --changed, FM_LINT_JOBS=1 bin/fm-lint.sh clean, and the PR's full GitHub CI suite green, recorded as an evidence line with the CI run URL and head.

Implementation decisions made deliberately:

  • Detection: the repo argument is treated as this Firstmate repository when it resolves to a directory whose git common dir equals the code root's git common dir (so any worktree of this repo counts); projects/<name> resolves under FM_HOME. A bare project name that is not a directory gets the plain scaffold. This is a best-effort convenience, not a safety gate, so the existing --herdr-lab explicit-flag safety contract is kept unchanged.
  • The id is a fixed reserved AC99, appended as the last criterion line, so task criteria AC1..AC98 never collide and fm-receipt-check.sh's criterion parser accepts it unchanged.
  • The wording explicitly states no local full-suite run is required because .github/workflows/ci.yml owns broad regression. For --mode local-only delivery (no PR, no CI) the CI clause is dropped and evidence binds to the branch head before reporting ready in branch.
  • The fm-brief.sh header (rendered verbatim by --help) is the single owner of this contract; CONTRIBUTING.md and the firstmate-coding-guidelines skill previously claimed firstmate-repo detection was impossible and now cross-reference the header. Firstmate still adds the coding-guidelines load line to firstmate-repo briefs by hand (only AC99 is automatic).
  • Local bin/fm-test-run.sh --changed on this loaded host showed 8 failing scripts unrelated to fm-brief (7 fail identically on parent 1350717; fm-hermes-harness failed once under load and passed on isolated rerun); PR GitHub CI is the authoritative broad regression signal.

Firstmate-Validation-Generation: 34a51385f8abca38f809168b4990c614

What Changed

  • Detect Firstmate checkouts by Git common directory and append reserved AC99 to ship briefs, leaving other repositories’ criteria unchanged.
  • Require changed tests, serial lint, and branch-head evidence; assign broad regression to PR GitHub CI without requiring a local full-suite run. Local-only briefs bind evidence to reporting ready in branch.
  • Document the scaffold contract in the help header, cross-reference it from contributor guidance, and add regression coverage for criterion parsing, delivery modes, and repository detection.

Risk Assessment

✅ Low: Captain, the change is bounded, matches the amended requirements, and introduces no substantiated correctness or scope issues.

Testing

The focused regression and live CLI checks passed, including detection boundaries, delivery wording, criterion parsing, and parent failure reproduction. CLI transcripts and generated briefs were preserved; disposable setup was removed. No lint, static analysis, or full suite ran.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Generate Firstmate no-mistakes and direct-PR briefs; both append parseable AC99 with targeted verification and CI ownership wording ✅ pass live Live scaffold and receipt-parser transcript; generated Firstmate PR brief
Generate a local-only Firstmate brief; AC99 binds evidence to branch readiness and omits CI ✅ pass live Generated local-only brief; live scaffold and receipt-parser transcript
Resolve a Firstmate checkout through FM_HOME/projects; the generated brief includes AC99 ✅ pass live Live scaffold and receipt-parser transcript: projects/firstmate alias
Target an unrelated Git repository, unresolved name, or non-Git code copy; none receives AC99 ✅ pass live Live scaffold and receipt-parser transcript; focused test_firstmate_repo_ship_brief_prefills_verification_criterion
Fill task criteria AC1 through AC98; the real receipt parser accepts all 99 unique criteria with AC99 last ✅ pass live Live scaffold and receipt-parser transcript: 98-criteria.md
Request scaffold help; it exposes the reserved criterion, detection boundary, and no-local-full-suite contract ✅ pass live Live scaffold and receipt-parser transcript: bin/fm-brief.sh --help
Evidence: Live scaffold and receipt-parser transcript
$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh live-pr ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7 --mode no-mistakes
scaffolded: ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-pr/brief.md (ship, mode=no-mistakes; replace {TASK} and every {ACCEPTANCE CRITERION}; AC99 is pre-filled with the firstmate verification criterion and must be kept)
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-pr/brief.md
AC1	Task-specific observable outcome
AC99	changed tests green via `bin/fm-test-run.sh --changed` and `FM_LINT_JOBS=1 bin/fm-lint.sh` clean, recorded as an evidence line with the branch head before validation planning; no local full-suite run is required; broad regression is owned by the PR GitHub CI per .no-mistakes.yaml.
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/98-criteria.md --require AC99
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/98-criteria.md
AC1	Task outcome 1
AC2	Task outcome 2
AC3	Task outcome 3
AC4	Task outcome 4
AC5	Task outcome 5
AC6	Task outcome 6
AC7	Task outcome 7
AC8	Task outcome 8
AC9	Task outcome 9
AC10	Task outcome 10
AC11	Task outcome 11
AC12	Task outcome 12
AC13	Task outcome 13
AC14	Task outcome 14
AC15	Task outcome 15
AC16	Task outcome 16
AC17	Task outcome 17
AC18	Task outcome 18
AC19	Task outcome 19
AC20	Task outcome 20
AC21	Task outcome 21
AC22	Task outcome 22
AC23	Task outcome 23
AC24	Task outcome 24
AC25	Task outcome 25
AC26	Task outcome 26
AC27	Task outcome 27
AC28	Task outcome 28
AC29	Task outcome 29
AC30	Task outcome 30
AC31	Task outcome 31
AC32	Task outcome 32
AC33	Task outcome 33
AC34	Task outcome 34
AC35	Task outcome 35
AC36	Task outcome 36
AC37	Task outcome 37
AC38	Task outcome 38
AC39	Task outcome 39
AC40	Task outcome 40
AC41	Task outcome 41
AC42	Task outcome 42
AC43	Task outcome 43
AC44	Task outcome 44
AC45	Task outcome 45
AC46	Task outcome 46
AC47	Task outcome 47
AC48	Task outcome 48
AC49	Task outcome 49
AC50	Task outcome 50
AC51	Task outcome 51
AC52	Task outcome 52
AC53	Task outcome 53
AC54	Task outcome 54
AC55	Task outcome 55
AC56	Task outcome 56
AC57	Task outcome 57
AC58	Task outcome 58
AC59	Task outcome 59
AC60	Task outcome 60
AC61	Task outcome 61
AC62	Task outcome 62
AC63	Task outcome 63
AC64	Task outcome 64
AC65	Task outcome 65
AC66	Task outcome 66
AC67	Task outcome 67
AC68	Task outcome 68
AC69	Task outcome 69
AC70	Task outcome 70
AC71	Task outcome 71
AC72	Task outcome 72
AC73	Task outcome 73
AC74	Task outcome 74
AC75	Task outcome 75
AC76	Task outcome 76
AC77	Task outcome 77
AC78	Task outcome 78
AC79	Task outcome 79
AC80	Task outcome 80
AC81	Task outcome 81
AC82	Task outcome 82
AC83	Task outcome 83
AC84	Task outcome 84
AC85	Task outcome 85
AC86	Task outcome 86
AC87	Task outcome 87
AC88	Task outcome 88
AC89	Task outcome 89
AC90	Task outcome 90
AC91	Task outcome 91
AC92	Task outcome 92
AC93	Task outcome 93
AC94	Task outcome 94
AC95	Task outcome 95
AC96	Task outcome 96
AC97	Task outcome 97
AC98	Task outcome 98
AC99	changed tests green via `bin/fm-test-run.sh --changed` and `FM_LINT_JOBS=1 bin/fm-lint.sh` clean, recorded as an evidence line with the branch head before validation planning; no local full-suite run is required; broad regression is owned by the PR GitHub CI per .no-mistakes.yaml.
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh live-direct ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7 --mode direct-PR
scaffolded: ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-direct/brief.md (ship, mode=direct-PR; replace {TASK} and every {ACCEPTANCE CRITERION}; AC99 is pre-filled with the firstmate verification criterion and must be kept)
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-direct/brief.md
AC1	Task-specific observable outcome
AC99	changed tests green via `bin/fm-test-run.sh --changed` and `FM_LINT_JOBS=1 bin/fm-lint.sh` clean, recorded as an evidence line with the branch head before validation planning; no local full-suite run is required; broad regression is owned by the PR GitHub CI per .no-mistakes.yaml.
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh live-local ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7 --mode local-only
scaffolded: ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-local/brief.md (ship, mode=local-only; replace {TASK} and every {ACCEPTANCE CRITERION}; AC99 is pre-filled with the firstmate verification criterion and must be kept)
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-local/brief.md
AC1	Task-specific observable outcome
AC99	changed tests green via `bin/fm-test-run.sh --changed` and `FM_LINT_JOBS=1 bin/fm-lint.sh` clean, recorded as an evidence line with the branch head before reporting ready in branch; no local full-suite run is required.
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh live-alias projects/firstmate --mode no-mistakes
scaffolded: ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-alias/brief.md (ship, mode=no-mistakes; replace {TASK} and every {ACCEPTANCE CRITERION}; AC99 is pre-filled with the firstmate verification criterion and must be kept)
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-alias/brief.md
AC1	Task-specific observable outcome
AC99	changed tests green via `bin/fm-test-run.sh --changed` and `FM_LINT_JOBS=1 bin/fm-lint.sh` clean, recorded as an evidence line with the branch head before validation planning; no local full-suite run is required; broad regression is owned by the PR GitHub CI per .no-mistakes.yaml.
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh live-foreign ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/foreign --mode no-mistakes
scaffolded: ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-foreign/brief.md (ship, mode=no-mistakes; replace {TASK} and every {ACCEPTANCE CRITERION})
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-foreign/brief.md
AC1	Task-specific observable outcome
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh live-bare unresolved-project --mode no-mistakes
scaffolded: ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-bare/brief.md (ship, mode=no-mistakes; replace {TASK} and every {ACCEPTANCE CRITERION})
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh --parse-criteria ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-bare/brief.md
AC1	Task-specific observable outcome
[exit 0]

$ ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-brief.sh --help
Scaffold a crewmate brief or persistent secondmate charter at
data/<task-id>/brief.md under the active firstmate home.
For ordinary tasks, the standard Setup/Rules/Definition-of-done contract is
filled in. Firstmate then replaces the {TASK} and every acceptance-criterion
placeholder with the task description, concrete outcomes, and context, and may adjust other sections
when the task genuinely deviates (e.g. working an existing external PR instead
of shipping a new one).
Usage: fm-brief.sh <task-id> <repo-name> --mode <no-mistakes|direct-PR|local-only> [--herdr-lab] [--orchestrate]
       fm-brief.sh <task-id> <repo-name> --scout [--herdr-lab]
       fm-brief.sh <task-id> --secondmate {<project>...|--no-projects}
       fm-brief.sh --render-ship-delivery <task-id> <no-mistakes|direct-PR|local-only>
  --scout writes the scout contract instead: the deliverable is a report at
  data/<task-id>/report.md (no branch, no push, no PR) and the worktree is scratch.
  --secondmate writes a persistent secondmate charter. The project list
  is cloned into the secondmate home, while the natural-language scope
  tells the main firstmate when to route work there; routine churn stays in its own home;
  captain-relevant escalations and marked from-firstmate replies append to this
  home's status file.
  --orchestrate opts an ordinary ship task into native OMP orchestration: it
  records the `orchestration: enabled` marker as front-matter at the top of the
  brief and lets bin/fm-spawn.sh carry the exact lowercase `orchestrate` keyword
  as a separate OMP launch message before the unchanged encoded brief. It is
  refused on scout and secondmate briefs, which are not ship tasks.
  --no-projects writes a project-less charter for a domain whose subject is the
  firstmate repo itself (its home is a firstmate worktree, its crews take pooled
  worktrees of the same repo). It is mutually exclusive with a project list, and
  omitting both still fails loudly so an accidental omission is never silent.
  Set FM_SECONDMATE_CHARTER='<charter>' to fill the charter text.
  Set FM_SECONDMATE_SCOPE='<scope>' to write a routing scope distinct from the charter text.
  --herdr-lab is mandatory when the task will issue Herdr lifecycle commands.
  It adds the hard isolation contract backed by bin/fm-herdr-lab.sh.
  The flag must be explicit because {TASK} is filled after scaffolding and the
  caller-supplied repo string cannot be relied on to identify this repo for a
  safety gate. Briefs made without it carry a loud declaration so an omitted
  contract cannot be silent.
For ship tasks, --mode is REQUIRED and shapes the definition of done. Firstmate
resolves it per task at intake (AGENTS.md section 7); data/projects.md holds the
captain's standing posture as context, and this script never reads it:
  no-mistakes  implement -> /no-mistakes pipeline -> PR -> configured merge authority
  direct-PR    implement -> push + open PR via gh-axi (no pipeline) -> configured merge authority
  local-only   implement on branch, stop and report "ready in branch" (no push/PR);
               the configured merge authority approves, firstmate merges to local main
no-mistakes-prod-only is a registry policy, not a task mode; resolve it to one of
the three concrete modes at intake before calling this script.
The generated ship brief records the chosen mode as a fixed machine-readable
"Delivery contract: mode=<mode>" line. bin/fm-spawn.sh reads that line and refuses
to launch a ship task whose explicit --mode disagrees, so an adjusted brief and the
recorded task metadata cannot drift apart.
Every ship scaffold also declares stable acceptance-criterion ids in an exact
"# Acceptance criteria" section and creates the append-only evidence ledger at
data/<task-id>/evidence.jsonl. bin/fm-receipt-check.sh owns the section parser,
evidence gate, conservative binary risk plan, and validation timing.
When the repo argument resolves to a checkout of the same git repository as
this code root (any worktree of it counts), the ship scaffold also appends the
reserved criterion AC99 as the section's last line, matching .no-mistakes.yaml's
test policy: evidence of targeted local tests plus lint is sufficient before
validation planning; broad regression is owned by the PR GitHub CI per
.no-mistakes.yaml (local-only wording drops the CI clause). No local
full-suite run is required. Other repos get no extra criterion; the reserved
high id keeps task criteria AC1..AC98 collision-free.
Ship briefs begin with a worktree-isolation assertion before the branch step.
--mode is refused on scout and secondmate scaffolds: a scout's deliverable is a
report rather than a merge, and a charter is not a delivery contract.
There is no --yolo flag here. The worker never owns merge decisions, so yolo is
a spawn-time and firstmate-side input only (AGENTS.md section 7).
Every scaffold's status protocol distinguishes the configured
declared-external-wait verb (FM_CLASSIFY_PAUSED_VERB, default "paused") from
"blocked:": pause for a known external wait expected to clear on its own,
blocked when firstmate must act.
Every scaffold also carries the steering-inbox receive-and-ack section:
process state/<id>.inbox/*.msg in order and acknowledge each by moving it to
handled/ (record, doorbell, and ladder owned by bin/fm-task-inbox-lib.sh).
Ship and scout scaffolds also carry the bounded read-only scouting
delegation contract: delegate file maps, call paths, evidence gathering, and
broad pattern searches to native read-only subagents (on OMP, the bundled
`scout` agent from `omp agents unpack`), while edits, verification, and
evidence receipts stay in the worker's main trajectory.
Ship tasks include a project-memory section so durable project-intrinsic
learnings can be committed to AGENTS.md through the project's delivery path;
it carries the AGENTS.md authoring bar (widely useful knowledge only, pointers
over copied detail) and has the crewmate add the fm-ensure-agents-md.sh
self-governance section when a touched project AGENTS.md lacks it.
Refuses to overwrite an existing brief.
[exit 0]
Evidence: Generated Firstmate PR brief
You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

# Task
{TASK}

# Acceptance criteria
- AC1: Task-specific observable outcome
- AC99: changed tests green via `bin/fm-test-run.sh --changed` and `FM_LINT_JOBS=1 bin/fm-lint.sh` clean, recorded as an evidence line with the branch head before validation planning; no local full-suite run is required; broad regression is owned by the PR GitHub CI per .no-mistakes.yaml.

# Herdr lifecycle declaration - NOT ENABLED
**HARD SAFETY GATE:** this scaffold cannot inspect the task text filled in above.
If the task will start, stop, delete, restart, profile, or otherwise drive Herdr lifecycle behavior, stop and regenerate the brief with `--herdr-lab` before dispatch.
Do not add Herdr lifecycle commands to this unguarded brief by hand.

# Setup
You are in a disposable git worktree of ~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7, at a detached HEAD on a clean default branch.

**Verify isolation before anything else.** Run `pwd -P` and `git rev-parse --show-toplevel`; both must resolve to the disposable task worktree you were launched in, such as a treehouse pool path or an Orca-managed worktree, not the primary checkout firstmate operates from.
The path check is authoritative: `git rev-parse --git-dir` and `git rev-parse --git-common-dir` can help inspect the repo, but they do not prove you are outside the primary checkout.
If the top-level path is the primary checkout or not the worktree you were launched in, STOP - do not branch or commit here - append `blocked: launched in primary checkout, not an isolated worktree` to the status file and stop.

1. First action: create your branch: `git checkout -b fm/live-pr`
2. Run `no-mistakes doctor`; if it reports the repo is not initialized here, run `no-mistakes init`.

# Rules
1. Never push to the default branch. Never merge a PR.
2. Stay inside this worktree; modify nothing outside it.
3. Use gh-axi for GitHub operations and chrome-devtools-axi for browser operations.
4. Report status by appending one line:
   `echo "{state}: {one short line}" >> '~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/state/live-pr.status'`
   States: working, needs-decision, blocked, paused, done, failed.
   Each append wakes firstmate, so report sparingly: only phase changes a supervisor
   would act on (setup done, bug reproduced, fix implemented, validation passed) and the
   needs-decision/blocked/paused/done/failed states. No step-by-step FYI progress lines;
   firstmate reads your pane for that.
   A mid-task `working:` line (including setup complete) is nonterminal: do not end the
   turn after it; continue the same stage until a defined `done:` gate under Definition of done.
   Whenever a turn ends while the task's board row is still in flight, the last status line
   must be terminal (`done:`, `failed:`, `needs-decision:`, `blocked:`) or `paused:`,
   landing within 600s of turn-end - never end on silence or a bare `working:`.
   Firstmate's watcher escalates a pane left idle past that bound with its row still in
   flight as `idle-with-open-work`. A `done:` is the delivery claim and must name the
   artifact the Definition of done requires; completion recording and teardown refuse a
   `done:` that carries none.
   Use `paused: {why}` - distinct from `blocked:` - ONLY when you are deliberately idling on a
   known external wait you expect to clear on its own (an upstream release, a rate-limit reset,
   a scheduled window): firstmate then leaves your idle pane alone and rechecks it on a long
   cadence instead of treating it as a possible wedge. Use `blocked:` when you are stuck and need help.
5. If you hit the same obstacle twice, append `blocked: {why}` and stop; firstmate will help.
6. If a decision belongs above the implementation worker (product choices, destructive actions, ask-user findings),
   append `needs-decision: {summary of options}` and stop. Firstmate will reply with the decision.
   A decision or blocker you opened stays open until a `resolved` line carrying its exact key lands; a later `done:` or `working:` line never closes it, even when the answer is what started that work.
   Firstmate's reply normally writes that closing line at answer time; when a blocker or wait clears WITHOUT a firstmate reply, append `resolved: {how it cleared}` yourself (same `[key=<slug>]` if you opened it with one) as you resume.
7. Never stop, restart, or update the shared `no-mistakes` daemon - it is one instance serving
   every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
   daemon error, append `blocked: {the daemon error}` and stop; only firstmate manages the daemon.

# Firstmate instruction inbox
Firstmate steers you through durable message files in '~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/state/live-pr.inbox'.
When a terminal message says an instruction is waiting there - and at any natural checkpoint when you are unsure - list '~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/state/live-pr.inbox'/*.msg, read and act on each message in numeric order, then acknowledge each handled message by moving it: `mv '~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/state/live-pr.inbox'/NNN.msg '~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/state/live-pr.inbox'/handled/`.
The move IS the acknowledgement: without it firstmate rings again and eventually treats you as stuck. An empty or absent inbox needs no action.

# Delegating read-only scouting
When the task benefits from bounded read-only scouting - mapping files, tracing call paths, gathering evidence, or broad pattern searches - delegate that scouting to native subagents instead of grinding through it solo.
On OMP, `omp agents unpack` ships the `scout`/`task`/`reviewer`/`security-reviewer`/`sonic` subagents; `scout` is read-only, `@smol`, and built for parallel search - prefer it for this work.
On other harnesses, use the read-only subagent surface the harness provides; where it provides none, do the scouting yourself.
Subagents scout only: keep every edit, verification run, and evidence receipt in your own main trajectory. You stay accountable for integrating and verifying their output and for recording the receipts your deliverable requires.

# Project memory
If `AGENTS.md` or `CLAUDE.md` already exists, or if this task produced durable project-intrinsic knowledge, run `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-ensure-agents-md.sh .` in the worktree.
Record only project knowledge useful to almost every future session.
For anything the codebase already shows, prefer a pointer to the authoritative file, command, or doc over copying the detail.
If you touch a project `AGENTS.md` that lacks `## Maintaining this file`, add that short self-governance section from `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-ensure-agents-md.sh` in the same pass.
Keep it proportionate: skip `AGENTS.md` edits for trivial tasks that produced no durable project knowledge.

# Acceptance evidence
Before reporting implementation complete, record at least one compact receipt for every acceptance criterion with `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt.sh live-pr <criterion> <type> <summary> <result> --outcome <success|failure|negative|zero|skipped|empty|placeholder|weak|accepted-blocked> [options]`.
Only `--outcome success` evidences a criterion; `accepted-blocked` requires a non-empty `--captain-exception "<text>"` (the date plus the captain's own words or the board key that holds them) and accounts for the criterion without evidencing it; every other structured outcome records an unevidenced negative or inconclusive result.
A task with any accepted-blocked criterion is never auto-merged; state those criteria and their exception references plainly in the PR description.
Run `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh live-pr` and do not append `done:` unless its JSON status is `complete`.
After the implementation is committed and evidence is complete, run `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh live-pr --implementation-complete` before any validation plan or implementation-complete `done:` report.
Receipts are audit inputs rather than proof that every claim is trustworthy; keep summaries and results compact and point to commands or artifacts when useful.
When a cited artifact lives inside this scratch worktree (for example `.qa/evidence/<run_id>/report.json`), copy it into `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/.phase-test/home/data/live-pr/artifacts/` (gitignored, survives teardown) before `done:` and cite the copied path; worktree-relative paths die with the worktree.

# Definition of done
Delivery contract: mode=no-mistakes
The task is complete only when committed on your branch and every declared acceptance criterion has a receipt.
When you believe it is complete, append `done: {summary}` to the status file and stop.
Firstmate will then classify validation risk; follow the receipt checker's plan output and help for the exact recorded receipts-mechanical or full No-Mistakes path.

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.
When starting no-mistakes, make `--intent` preserve all relevant content from this brief's `# Task` section plus every later accepted Firstmate requirement, clarification, constraint, exclusion, and supersession, carrying only each requirement's current accepted form; retain direct requirements instead of substituting a diff summary, and exclude generic operational, status, delivery, and other scaffold boilerplate unless it is task-specific.
Include the exact line `Firstmate-Validation-Generation: <plan-generation>` in the No-Mistakes `--intent`, then immediately bind the returned run id with `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh live-pr --bind-run <run-id> --generation <plan-generation>` so completion can prove that exact run, generation, path, and head.
If binding refuses because the run predates the plan or a mid-run rebase moved the base, do not replan - reconcile the branch to the run's own pushed head and retry the same `--bind-run`; the checker binds by content identity once run ownership is proven.
Do not hand-edit, commit, or fix findings yourself while a run is active; fix ordinary findings from any validation tier only after Firstmate directs the supported abort and branch-custody return sequence.

Two firstmate-specific rules layer on top of that guidance:
- ask-user findings are never yours to answer: escalate to firstmate (rule 6) and stop.
  Report each parked gate as `needs-decision [key=nm-<run>-<step>]: ask-user findings=<id1>,<id2>,...` naming every ask-user finding id the gate presents; the completion gate refuses any recorded ask-user resolution that lacks a matching firstmate `resolved [key=nm-<run>-<step>]` record.
  Firstmate applies `ask-user-authority` and obtains any required captain decision.
  When the decision comes back, feed it to the gate with `no-mistakes axi respond` and let the pipeline apply it - do not route the question to "the user" or implement the fix yourself.
- Avoid `--yes`: it would silently bypass firstmate's authority check and any required captain escalation.

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` to the status file, then run `~/.no-mistakes/worktrees/dd71c22cc6d7/01M45W8PP4XV4YSSJ69JH301E7/bin/fm-receipt-check.sh live-pr --complete --terminal-evidence no-mistakes-passed`, and stop. You are finished.
The `done:` line must carry the PR URL - it is the delivery artifact - and completion recording and teardown refuse a `done:` that names none.
  • Evidence: Generated local-only brief (local file: ~/.no-mistakes/evidence/01M45W8PP4XV4YSSJ69JH301E7/live-local-brief.md)
Evidence: Parent commit rejects required AC99
Parent scaffold receipt parser --require AC99
Exit: 1

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed (2) ✅
  • 🚨 bin/fm-brief.sh:481 - AC99 creates a circular dependency for fresh Firstmate tasks in both no-mistakes and direct-PR modes. After local checks pass, no PR CI receipt exists yet. The generated evidence instructions require every criterion before implementation completion and planning (bin/fm-brief.sh:141-145), while direct-PR plans before pushing/opening the PR (:157) and no-mistakes starts validation after evidence and planning (:179-186). bin/fm-receipt-check.sh:639-647 rejects both operations while AC99 is missing. Thus neither path can reach the CI that would satisfy AC99 without an exception or an inaccurate success receipt. The insertion at bin/fm-brief.sh:627 makes this criterion mandatory. Reconcile pre-validation evidence with CI evidence required before PR-ready at the shared receipt-check boundary. The remedy needs authorization because introducing phased criterion handling extends the stated scaffold-only change.
  • ⚠️ bin/fm-brief.sh:464 - Simplification: lines 464-466 introduce physical-path equality as a second detection path when Git resolution fails, allowing a non-git copy of the code root to receive AC99. The accepted decision specifies detection when the directory's 'git common dir equals the code root's git common dir'; no requirement needs this fallback. Remove it and the associated dir_abs/root_abs variables at bin/fm-brief.sh:453, retaining only successful git-common-dir equality.

🔧 Fix applied.
3 issues (1 error, 2 warnings) still open:

  • 🚨 bin/fm-brief.sh:481 - AC99 creates a circular dependency for fresh Firstmate tasks in both no-mistakes and direct-PR modes. After local checks pass, no PR CI receipt exists yet. The generated evidence instructions require every criterion before implementation completion and planning (bin/fm-brief.sh:141-145), while direct-PR plans before pushing/opening the PR (:157) and no-mistakes starts validation after evidence and planning (:179-186). bin/fm-receipt-check.sh:639-647 rejects both operations while AC99 is missing. Thus neither path can reach the CI that would satisfy AC99 without an exception or an inaccurate success receipt. The insertion at bin/fm-brief.sh:627 makes this criterion mandatory. Reconcile pre-validation evidence with CI evidence required before PR-ready at the shared receipt-check boundary. The remedy needs authorization because introducing phased criterion handling extends the stated scaffold-only change.
  • ⚠️ bin/fm-brief.sh:464 - Simplification: lines 464-466 introduce physical-path equality as a second detection path when Git resolution fails, allowing a non-git copy of the code root to receive AC99. The accepted decision specifies detection when the directory's 'git common dir equals the code root's git common dir'; no requirement needs this fallback. Remove it and the associated dir_abs/root_abs variables at bin/fm-brief.sh:453, retaining only successful git-common-dir equality.
  • ⚠️ bin/fm-brief.sh:476 - Round 1's fix introduces an inaccurate CI-enforcement claim for direct-PR briefs. A Firstmate documentation task can satisfy local AC99, open its PR, and complete while CI is pending or failing: bin/fm-pr-check.sh publishes direct-PR completion, and bin/fm-receipt-check.sh's direct-PR completion checks the PR head without checking CI. The receipts-mechanical path likewise lacks a checks-green requirement. The same claim appears at bin/fm-brief.sh:58 and is asserted in tests/fm-brief.test.sh:1040. Narrow the wording to the full-no-mistakes path where this enforcement exists. This needs review because the accepted R1 decision explicitly requested the enforcement claim; adding CI enforcement to other paths would exceed that decision.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Generate Firstmate no-mistakes and direct-PR briefs; both append parseable AC99 with targeted verification and CI ownership wording ✅ pass live Live scaffold and receipt-parser transcript; generated Firstmate PR brief
Generate a local-only Firstmate brief; AC99 binds evidence to branch readiness and omits CI ✅ pass live Generated local-only brief; live scaffold and receipt-parser transcript
Resolve a Firstmate checkout through FM_HOME/projects; the generated brief includes AC99 ✅ pass live Live scaffold and receipt-parser transcript: projects/firstmate alias
Target an unrelated Git repository, unresolved name, or non-Git code copy; none receives AC99 ✅ pass live Live scaffold and receipt-parser transcript; focused test_firstmate_repo_ship_brief_prefills_verification_criterion
Fill task criteria AC1 through AC98; the real receipt parser accepts all 99 unique criteria with AC99 last ✅ pass live Live scaffold and receipt-parser transcript: 98-criteria.md
Request scaffold help; it exposes the reserved criterion, detection boundary, and no-local-full-suite contract ✅ pass live Live scaffold and receipt-parser transcript: bin/fm-brief.sh --help
  • TMPDIR=&#34;$PWD/.phase-test/tmp&#34; bash .phase-test/focused.sh — executed the existing AC99 regression function against real scaffold and parser commands.
  • Drove bin/fm-brief.sh with isolated FM_HOME for no-mistakes, direct-PR, local-only, projects alias, foreign repository, and unresolved-name targets.
  • Executed bin/fm-receipt-check.sh --parse-criteria on generated briefs and an AC1..AC98 brief; required AC99 through --require AC99.
  • Executed the parent commit's scaffold and confirmed the real parser rejected its missing AC99.
  • Executed bin/fm-brief.sh --help, preserved generated CLI evidence, and removed disposable setup; final git status was clean.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

dnth added 4 commits October 5, 2026 17:28
…o ship briefs

Firstmate-repo briefs asked for a local full suite, contradicting .no-mistakes.yaml where ci.yml owns broad regression. The scaffold now appends reserved AC99 with targeted local tests, lint, and PR CI evidence when the repo argument resolves to this repository.
@dnth
dnth merged commit f16f3a2 into main Oct 5, 2026
32 of 33 checks passed
@dnth
dnth deleted the fm/fm-brief-firstmate-verification-ac branch October 5, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant