Repository navigation
fix: verify archived captain answers in scout completion - #263
Merged
Merged
Conversation
The scout completion gate (fm-captain-hold.sh complete/verify) read an inventoried captain call only from the live backlog. tasks-axi's done_keep trim moves answered calls into the configured Done archive, so: - an origin whose inventoried call was answered and then archived failed with "no captain-held task <id>" (aceh-prod-continuous-ingest -> aceh-nul-owed-redo); - a self-held origin whose answered row was archived and then re-added as a fresh cleanup row failed with "neither held for the captain nor closed with a recorded captain answer" (aceh-prod-deploy-1e22). An entry no live row carries, or whose live row never carried a captain hold, is now judged by the newest archived row of that id that did. It is durable only when that row records a resolution. Archived calls with no recorded answer still refuse, and a live row with captain-hold provenance is always judged on its own, so an older archived answer cannot settle a newer lifecycle. complete names each entry the archive evidenced.
The Done-archive reader parsed only checked rows, so a newer captain lifecycle archived unanswered from the Queued or In flight section was skipped and an older archived answer of the same id settled it. Normalize every archived open bullet before parsing so the newest captain row decides. An archived row also now counts as answered only when its resolution record settles its latest lifecycle: a re-held row opens with a fresh hold-set stamp, so an earlier lifecycle's record below it no longer settles the call.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Fix a bug in the shared scout completion gate,
bin/fm-captain-hold.sh complete/verify(shared tracked firstmate material; follow.agents/skills/firstmate-coding-guidelines/SKILL.md).Observed (19 Oct, scout
aceh-prod-deploy-1e22):fm-captain-hold.sh complete aceh-prod-deploy-1e22 --nonefails with "captain-held task aceh-prod-deploy-1e22 is neither held for the captain nor closed with a recorded captain answer", sofm-teardown.shrefuses the scout forever. Its metadata carriesdecisions_reviewed=1/decision_keys=followed bydecisions_reviewed=1/decision_keys=aceh-prod-deploy-1e22. The task originally had no backlog row (legacy scout) and now has a fresh queued row.Second real case (firstmate): scout
aceh-prod-continuous-ingestcarriesdecision_keys=aceh-nul-owed-redo; that captain call WAS answered (captain answer A, 18 Oct) but its row was later archived out of the configured backlog by Done retention, so complete/verify fail with "no captain-held task aceh-nul-owed-redo ... in this home's configured backlog".Accepted requirements and corrections from firstmate (current form):
decision_keysis legitimate (captain-hold-lifecycle prefers holding the originating work item). Self-keys must NOT be prevented.decisions_reviewed/decision_keyslines are deliberately append-only; do not change that.--nonewhile the origin has an open keyed status decision.tasks-axi prune --state queued --keep 0) must not be settled by an older archived answer; unchecked archived rows are provenance-bearing refusal candidates.Root cause found: tasks-axi Done retention (
done_keeptrim /prune) moved the answered captain-held rows intodata/done-archive.md(aceh-prod-deploy-1e22archived 2026-10-16 with hold-kind captain and resolution records;aceh-nul-owed-redoarchived 2026-10-18), and the gate read only the live backlog. The self-key on 1e22 was written legitimately by the scout's owncomplete aceh-prod-deploy-1e22 aceh-prod-deploy-1e22while it held itself; the 19 Oct row is a fresh never-held cleanup row reusing the id.Design decisions:
<origin>-decision-<entry>identity) that did.duealready uses), with every## Archivedheading and open bullet normalized so rows pruned from any section are read in file order.completenames each entry the archive evidenced. Live-row semantics are unchanged.Before/after evidence for the PR body:
test_self_held_call_answered_then_archived_still_verifiesandtest_archive_never_settles_an_unanswered_call.complete: aceh-prod-deploy-1e22 captain-call inventory reviewed (aceh-prod-deploy-1e22) [answered calls read from the configured Done archive: aceh-prod-deploy-1e22], verify passed;complete: aceh-prod-continuous-ingest captain-call inventory reviewed (aceh-nul-owed-redo) [answered calls read from the configured Done archive: aceh-nul-owed-redo], verify passed.The PR must state the exact post-merge commands firstmate runs in the main home after it fast-forwards to the merge commit (do not run them from the PR):
cd ~/Desktop/firstmate
bin/fm-captain-hold.sh complete aceh-prod-deploy-1e22 --none && bin/fm-teardown.sh aceh-prod-deploy-1e22
bin/fm-captain-hold.sh complete aceh-prod-continuous-ingest --none && bin/fm-teardown.sh aceh-prod-continuous-ingest
Teardown's other checks are unchanged and were not exercised against the live home.
What Changed
Make
completeandverifyrecognize answered captain calls in the configured tasks-axi archive, including self-held calls shadowed by fresh rows reusing their ids;completenames the archive-backed entries.Require archived answers to settle the newest captain-hold lifecycle, refusing unanswered or re-held calls; add lifecycle regressions and document archive-backed verification.
After firstmate fast-forwards the main home to the merge commit, run:
Teardown's other checks are unchanged and were not exercised against the live home.
Risk Assessment
✅ Low: Captain, the archive fallback is bounded, preserves live-row semantics, and rejects archived lifecycles without a matching resolution.
Testing
Live CLI checks and selected regressions passed, with transcripts proving base failures and target recovery. The initial lifecycle-file run hit an unrelated secondmate nesting restriction imposed by workspace isolation. Temporary fixtures were removed; production data remained untouched.
Evidence: Live CLI scenarios and persisted archive records
Evidence: Base failures versus target success
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
bash .test-phase-tmp/live-check.sh: real captain-hold and tasks-axi CLIs against disposable homes.bash .test-phase-tmp/baseline-check.sh: base and target commands against identical archived-answer records.TMPDIR="$PWD/.test-phase-tmp" bash tests/fm-captain-hold-lifecycle.test.sh: stopped at an unrelated secondmate fixture nesting restriction.TMPDIR="$PWD/.test-phase-tmp" bash tests/.test-phase-selected.test.sh: both new archive regressions plus terminal-status and out-of-band-close checks passed.Removed disposable homes and temporary runners; confirmed the working tree was clean.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.