Skip to content

fix(bin): gate no-mistakes done-line check on the line's own URL, not recorded pr= - #7

Merged
cm-maple7 merged 5 commits into
mainfrom
fm/fm-brief-nomistakes-done-drift-v2
Sep 1, 2026
Merged

cm-maple7 merged 5 commits into
mainfrom
fm/fm-brief-nomistakes-done-drift-v2

Conversation

@cm-maple7

@cm-maple7 cm-maple7 commented Sep 1, 2026 •

Copy link
Copy Markdown
Owner

Intent

Follow-up fix on top of the done-drift PR: fm-status-append.sh's guard required state/.meta's pr= to already be recorded before allowing a done: line, but firstmate only writes pr= (via fm-pr-check.sh) after seeing the worker's own done: PR checks green report, so the guard could never be satisfied by a legitimate first report and refused every real completion. Gate on the line's own content instead: accept a done: line on a mode=no-mistakes ship task only when it names a real http(s) URL (the DOD's one prescribed final-done shape), refusing everything else including the retired done: {summary} wording. Also fixes the pipeline's own promoted-worker regression test in tests/fm-task-delivery.test.sh, whose sed-style backslash-escaped test URL was left as literal backslash characters by bash parameter substitution rather than a real https:// prefix, so it only passed under the old meta-only check. Update tests/fm-status-append.test.sh to match the corrected behavior and add coverage proving a recorded pr= does not exempt a URL-less done line.

What Changed

  • Add bin/fm-status-append.sh, a guarded status-append helper that only refuses a done: line on a mode=no-mistakes ship task when the line itself names no real http(s):// URL (rejecting the retired done: {summary} wording), instead of requiring a pr= that firstmate can't have written yet at that point.
  • Wire the guard into the delivery path: bin/fm-dod-lib.sh gains fm_status_report_line/fm_status_report_guard_note helpers that render the correct status-report command per mode, consumed by both bin/fm-brief.sh (fresh briefs) and bin/fm-promote.sh (promoted scouts), so a promoted no-mistakes worker gets the same guarded command as a briefed one.
  • bin/fm-crew-state.sh reclassifies a no-mistakes ship task's unattributed done: status line as parked (not terminal done) when no validated pr= is recorded, prompting a run of /no-mistakes instead of reporting false completion.
  • Fix the pipeline's own promoted-worker regression test in tests/fm-task-delivery.test.sh (its test URL was left as literal backslash characters instead of a real https:// URL, masking a check that only passed under the old meta-only guard); update tests/fm-bearings-snapshot.test.sh's done fixture and add tests/fm-status-append.test.sh plus new tests/fm-crew-state.test.sh coverage proving a recorded pr= does not exempt a URL-less done line.

Risk Assessment

✅ Low: The commit correctly fixes the identified bug (gating on meta pr= made the guard unsatisfiable for a legitimate first report), is internally consistent across fm-brief.sh, fm-dod-lib.sh, fm-status-append.sh, fm-promote.sh (via the shared helper), docs, and tests, and the regression test's backslash-escaping bug is genuinely fixed; the only gap found is a minor substring-match looseness with no realistic exploitation path given the guard's purpose (a mechanical backstop against a cooperative LLM worker's known bad phrasings, not an adversarial boundary).

Testing

Both targeted test files (fm-status-append.test.sh and fm-task-delivery.test.sh) pass in full under the target commit, and I independently reproduced the pre-fix bug (a legitimate first done report with a real PR URL was wrongly refused because meta's pr= wasn't recorded yet) and confirmed the fix resolves it end-to-end by running the pre-fix and post-fix versions of fm-status-append.sh side by side against identical inputs; I also reproduced the sed-style backslash-escape defect in the old promoted-worker test and confirmed it would have failed under the new content-based gate, validating that the test correction in this commit is a genuine regression fix rather than a tautological source-grep. No issues found.

Evidence: fm-status-append.test.sh full run (9/9 pass)
ok - fm-status-append.sh: bash -n succeeds
ok - fm-status-append.sh: refuses a premature no-mistakes done that names no PR URL
ok - fm-status-append.sh: refuses the retired done: {summary} wording
ok - fm-status-append.sh: allows a nonterminal working: line on a no-mistakes task
ok - fm-status-append.sh: allows a done: PR <url> ... line with no pr= recorded in meta yet
ok - fm-status-append.sh: a recorded pr= does not exempt a done line that names no URL
ok - fm-status-append.sh: direct-PR and local-only tasks are never gated on a recorded pr=
ok - fm-status-append.sh: a missing meta file never gates a done line
ok - fm-status-append.sh: every non-done verb always passes through unguarded
all fm-status-append tests passed
Evidence: Repro: pre-fix code refuses a legitimate first done report naming a real PR URL (the exact bug the intent describes)
=== OLD behavior: legitimate first done report (no pr= recorded yet) with a real URL in the line ===
refused: this is a mode=no-mistakes task, so "committed, gates green" is not done.
Run /no-mistakes now and respond to its gates until it reports CI green, then
report done as: done: PR {url} checks green
exit code: 1
status file exists: no

=== NEW behavior (fd34cfe): same legitimate first done report ===
exit code: 0
status file contents:
done: PR https://github.com/x/y/pull/9 checks green
Evidence: Repro: old test's sed-style backslash-escaped URL produces literal backslashes, which the new content-based gate correctly rejects
Resulting command string:
fm-status-append.sh statusfile.status "done: PR https:\/\/github.com\/x\/y\/pull\/1 checks green"

=== NEW gate against the OLD test's malformed backslash-escaped line ===
refused: this is a mode=no-mistakes task, so "committed, gates green" is not done.
...
exit code: 1

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 info
  • ℹ️ bin/fm-status-append.sh:54 - The gate accepts any done: line containing the bare substring "http://" or "https://" anywhere, with nothing required after it (e.g. "done: http://" or "done: see https:// for context" both pass). This is a looser check than "names a real http(s) URL" as stated in the comment and commit message. In practice this only matters against a cooperative LLM worker deliberately trying to game the exact prescribed DOD wording, not an adversarial input, so the risk is low, but a minimal tightening (e.g. requiring at least one non-whitespace character after the scheme, such as *http[s]://?*) would make the check match its own documented contract exactly.
✅ **Test** - passed

✅ No issues found.

  • bash tests/fm-status-append.test.sh (9/9 pass, including the two new tests test_refuses_the_old_dod_summary_wording and test_recorded_pr_does_not_exempt_a_urlless_done_line)
  • bash tests/fm-task-delivery.test.sh (11/11 pass, including test_promoted worker guarded exactly like a fresh brief's)
  • Manual repro: extracted bin/fm-status-append.sh@23f58af (pre-fix) into /tmp and ran it against a fresh state/<id>.meta with kind=ship, mode=no-mistakes, no pr= - confirmed a done: PR https://github.com/x/y/pull/9 checks green line was wrongly refused (exit 1)
  • Manual repro: ran the same scenario against bin/fm-status-append.sh@fd34cfe (fixed) - confirmed the same line is now accepted (exit 0) and appended verbatim to the status file
  • Manual repro: reconstructed the old test's bash parameter-substitution replacement string in isolation and showed it yields literal backslash characters ('https:\/\/...'), then fed that malformed string to the new gate and confirmed it is correctly refused - validating why the test needed the unescaped-URL fix
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Nine ship workers in two days reported done at "committed, gates green"
without ever starting /no-mistakes, including three that carried an explicit
capitalized DEFINITION OF DONE paragraph and still stopped short, so prose
alone cannot close this gap.

- fm-dod-lib.sh: make invoking /no-mistakes the literal next step after the
  implementation commit instead of something the worker waits for firstmate
  to instruct; there is exactly one done state left (CI green with a PR).
- fm-status-append.sh (new): guarded status-append helper that a
  mode=no-mistakes ship brief now routes its status report through; it
  refuses a done: line until state/<id>.meta records a validated pr=
  (bin/fm-pr-check.sh), printing the required next step instead. Every
  other mode, kind, and status verb passes through exactly like a bare
  echo.
- fm-crew-state.sh: a mode=no-mistakes ship task with no run ever attributed
  and no recorded pr= now reads as parked ("implementation complete,
  pipeline not started"), never done, so a heartbeat or absorb read is not
  fooled by the same premature done line.
…art 3 of the intent) reclassifies a mode=no-mistakes/kind=ship child's `done:` status line as `parked` when its meta lacks a validated `pr=`. The pre-existing (untouched by this PR) test `test_nonprogressing_child_states_are_explicit` in tests/fm-bearings-snapshot.test.sh had a "done" child fixture with mode=no-mistakes and no pr=, intended to test unrelated "terminal state despite in-flight backlog" detection. That fixture now correctly reclassifies as parked instead of terminal done, breaking the test's terminal_in_flight assertion (which expected both done and failed to be flagged as terminal). Both failing checks (Behavior portable serial 2, Stock macOS Bash snapshot compatibility) failed for this identical reason - confirmed via CI logs, each showing exactly one failing subtest matching this exact test/assertion. Fix: added `pr=https://github.com/sample/sample/pull/1` to that fixture's done.meta, mirroring the pattern the PR's own new test (test_no_run_no_mistakes_done_with_pr_reports_done) establishes - a validated pr= is what keeps a no-mistakes ship task's done: line genuinely terminal. This preserves the original test's unrelated purpose and assertions while representing a truly-completed child per the new mechanical rule. Verified locally: tests/fm-bearings-snapshot.test.sh now passes 42/42 under both stock macOS /bin/bash 3.2 and default bash (previously failing subtest now passes); tests/fm-crew-state.test.sh passes 76/76; tests/fm-fleet-snapshot-view.test.sh (15/15) and the public-followup bash-3.2 regression (1/1) still pass; bin/fm-lint.sh is clean. Also reproduced the exact CI shard (portable-serial-2of4) locally and confirmed the fix resolves the reported failure (only pre-existing environment-related noise from missing local tooling remained, unrelated to CI which showed failed=1 matching this single issue)
…ot meta

fm-status-append.sh required state/<id>.meta's pr= to already be recorded
before allowing a done: line, but firstmate only writes pr= (via
fm-pr-check.sh) after seeing the worker's own done: PR <url> checks green
report - so the guard could never be satisfied by a legitimate first report
and refused every real completion, including this task's own.

Gate on the line's own content instead: a done: line on a mode=no-mistakes
ship task is accepted only when it names a real http(s) URL, matching the
DOD's one prescribed final-done shape; anything else (including the retired
"done: {summary}" wording) is still refused. Also fixes the pipeline's own
promoted-worker regression test, which built its "URL" with sed-style
backslash-escaped slashes that bash's parameter substitution left as literal
backslash characters rather than a real https:// prefix - it only passed
under the old meta-only check, which never looked at the line's content.
@cm-maple7 cm-maple7 changed the title fix(bin): mechanically require the no-mistakes pipeline before a ship task can report done fix(bin): gate no-mistakes done-line check on the line's own URL, not recorded pr= Sep 1, 2026
@cm-maple7
cm-maple7 merged commit 7833594 into main Sep 1, 2026
14 checks passed
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