Skip to content

fix(bin): fall through unknown busy verdicts to terminal status-log verbs in fm-crew-state - #7

Merged
Bloh09 merged 2 commits into
mainfrom
fm/fm-crew-state-terminal-fallthrough
Aug 10, 2026
Merged

fix(bin): fall through unknown busy verdicts to terminal status-log verbs in fm-crew-state#7
Bloh09 merged 2 commits into
mainfrom
fm/fm-crew-state-terminal-fallthrough

Conversation

@Bloh09

@Bloh09 Bloh09 commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Intent

Close audit gap 2 in bin/fm-crew-state.sh: when the busy-verdict source returns unknown, fall through to the terminal status verbs instead of reporting a dead-end unknown.

Current behavior: fm-crew-state.sh consults the busy source (bin/fm-busy-lib.sh) and, when the verdict is unknown (unverified harness, unreadable pane, no busy source), it can report unknown even when the task's own status log already carries a terminal verb (done:, failed:, blocked:, needs-decision:) that answers the supervisor's actual question.

Fix: when and only when the busy verdict is unknown, let the classifier fall through to the durable status log's latest terminal verb and report that state with its source attributed as status-log (the existing done/failed reporting already has this shape). A live busy/idle verdict must keep winning over the status log; this fallthrough is strictly for the unknown case. Keep the source attribution honest in the output line so a supervisor can tell a run-step read from a status-log inference.

Extend the colocated tests (tests/fm-crew-state*.test.sh) with: unknown busy + terminal status -> terminal state reported from status-log source; unknown busy + only nonterminal status -> unknown preserved; live busy verdict + stale terminal status -> live verdict wins.

Acceptance: unknown busy-verdict falls through to terminal status verbs with honest source attribution, live verdicts still win, regression tests cover the three cases above, no-mistakes pipeline green with a PR on origin (Bloh09/firstmate) against main.

What Changed

  • bin/fm-crew-state.sh now handles an unknown busy verdict by falling through to the status log's latest terminal verb (done/failed/blocked/needs-decision/paused) and reporting that state with source: status-log, instead of emitting a dead-end unknown. A nonterminal log line (working) still reports unknown with the pane source, and a live busy verdict still wins over any status log.
  • tests/fm-crew-state.test.sh adds three regression tests covering unknown busy + terminal log (terminal state from status-log), unknown busy + nonterminal log (unknown preserved), and live busy + stale terminal log (live verdict wins); the existing footer-text test now uses a nonterminal log line so it keeps asserting the no-promotion rule.
  • docs/architecture.md documents the terminal-only fallthrough as the single path that reports a finished-style state on an unknown verdict, with the answer attributed to the status log rather than the unavailable busy read.

Risk Assessment

✅ Low: The change is a small, well-bounded state-classifier adjustment that precisely implements the stated intent - live verdicts still win, only the unknown-busy dead end gains a terminal-verb fallthrough with honest source attribution - and it ships behavioral regression tests covering all three required cases plus updated docs, with no consumer-facing format change.

Testing

Ran the full colocated fm-crew-state suite on the target commit (all 52 tests pass, including the three new fallthrough cases), proved the new regression test fails against the base-commit script, and captured a before/after CLI transcript demonstrating all three acceptance behaviors end-to-end: unknown busy + done log now reports done from status-log, nonterminal logs keep unknown with pane source, and a live busy record still outranks a stale terminal log. No visual artifact applies since the end-user surface is the CLI output line, which the transcript shows directly.

Evidence: Before/after CLI transcript: unknown-busy fallthrough behavior

## BEFORE (base a2ba0ef) $ fm-crew-state.sh feat-evidence state: unknown · source: pane · harness state unavailable (unknown missing) ## AFTER (target 6f2f4e4) $ fm-crew-state.sh feat-evidence state: done · source: status-log · PR https://example.test/pr/42 checks green ## AFTER - nonterminal log keeps unknown state: unknown · source: pane · harness state unavailable (unknown missing) ## AFTER - live busy record beats stale done: log state: working · source: pane · harness busy (claude-hook)

# fm-crew-state.sh: unknown busy verdict falls through to terminal status-log verbs

Scenario: crew "feat-evidence" (kind=ship, harness=claude), no attributed run,
pane paints "esc to interrupt" but there is NO verified semantic busy record
(busy verdict = unknown). The durable status log last line is:
    done: PR https://example.test/pr/42 checks green

## BEFORE (base a2ba0ef) - dead-end unknown hides the answered question
$ fm-crew-state.sh feat-evidence
state: unknown · source: pane · harness state unavailable (unknown missing)

## AFTER (target 6f2f4e4) - terminal verb reported, honestly attributed to status-log
$ fm-crew-state.sh feat-evidence
state: done · source: status-log · PR https://example.test/pr/42 checks green

## AFTER - nonterminal log (working:) keeps unknown, pane source stays honest
$ fm-crew-state.sh feat-evidence   # status log: 'working: still implementing'
state: unknown · source: pane · harness state unavailable (unknown missing)

## AFTER - live busy verdict still wins over a stale terminal log
$ fm-crew-state.sh feat-evidence   # status log: 'done: stale completion event', live busy record present
state: working · source: pane · harness busy (claude-hook)
Evidence: Regression proof: new test fails on base commit

not ok - unknown busy + done log -> done (missing: 'state: done') --- output --- state: unknown · source: pane · harness state unavailable (unknown missing)

Regression proof: new test run against BASE commit a2ba0ef (fix reverted in
bin/fm-crew-state.sh only, target test file kept):

  ok - a converted adapter never reads working from rendered footer text
  not ok - unknown busy + done log -> done (missing: 'state: done')
  --- output ---
  state: unknown · source: pane · harness state unavailable (unknown missing)

Same suite against TARGET commit 6f2f4e4: all 52 tests pass, including:
  ok - unknown busy falls through to a terminal status-log verb
  ok - unknown busy preserves unknown for a nonterminal status-log verb
  ok - live busy verdict wins over a stale terminal status-log line

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 2 infos
  • ℹ️ bin/fm-crew-state.sh:579 - The terminal fallthrough set (bin/fm-crew-state.sh:578-580) includes paused in addition to the intent's enumerated terminal verbs (done/failed/blocked/needs-decision). This is a documented, deliberate superset - paused is a declared external wait and belongs to the same wake-worthy verb family per the status-log taxonomy in the script header - and nothing in the intent forbids it, but the author should confirm the extension since the intent enumerated exactly four verbs.
  • ℹ️ bin/fm-crew-state.sh:587 - Minor redundancy: BUSY_FALLTHROUGH=all at bin/fm-crew-state.sh:552 is unconditionally assigned, so the re-assignment in the idle) case arm (line 557) and the ${BUSY_FALLTHROUGH:-all} default in the final guard (line 587) are dead defensive duplicates. Harmless; could be simplified to one assignment plus a plain $BUSY_FALLTHROUGH reference.
✅ **Test** - passed

✅ No issues found.

  • bash tests/fm-crew-state.test.sh on target commit 6f2f4e4 - all 52 tests pass, including the three new g2 cases (test_unknown_busy_falls_through_to_terminal_status_log, test_unknown_busy_preserves_unknown_for_nonterminal_status_log, test_live_busy_wins_over_stale_terminal_status_log)
  • Regression proof: re-ran the suite with the base-commit (a2ba0ef) version of bin/fm-crew-state.sh swapped in - the new test fails with not ok - unknown busy + done log -> done, output state: unknown · source: pane; script restored to target afterward, worktree clean
  • Manual end-to-end CLI check: staged a crew scenario (real git worktree on branch, meta, fake tmux pane painting 'esc to interrupt' with no semantic busy record) and ran base vs target fm-crew-state.sh - base reports dead-end unknown, target reports state: done · source: status-log
  • Manual end-to-end CLI check: nonterminal working: status log under unknown busy stays state: unknown · source: pane
  • Manual end-to-end CLI check: armed and applied a live busy record via real bin/fm-busy-event.sh with a stale done: log - target reports state: working · source: pane
  • Verified needs-decision: maps to parked in map_log_state, so the terminal fallthrough set covers all four intent verbs
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

When the busy-verdict source returns unknown, prefer a durable terminal
status-log verb (done/failed/blocked/needs-decision/paused) over a
dead-end unknown so supervisors still see answered questions. Live busy
and idle verdicts keep winning; nonterminal working logs stay unknown.
@Bloh09
Bloh09 merged commit bf7e9d0 into main Aug 10, 2026
13 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.

2 participants