fix: keep backstop delivery receipts usable after task teardown - #209
Merged
Merged
Conversation
…tatus teardown The wake drain's STATUS OUTCOME BACKSTOP printed a single deliver --through hint, which refuses once merge reconciliation or scout teardown deletes state/<id>.status, leaving the owed completion obligation open. Print one --endpoint receipt per shown undelivered event instead; it is identity-keyed, records after teardown, and names only owed endpoints.
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 the delivery-receipt command the wake drain prints after a task's status file is gone. The STATUS OUTCOME BACKSTOP in bin/fm-wake-drain.sh printed
bin/fm-branch-outcome.sh deliver --task <id> --status-ident <ident> --through <N>. Merge reconciliation (bin/fm-todo-project.sh --check --reconcile) and scout teardown delete state/.status, after which --through refuses ("status file is missing or unreadable"; bin/fm-branch-outcome.sh deliver). On 2026-10-05 this happened for two tasks, and the obligation stayed open until the --endpoint form was used by hand. Make the owed receipt recordable after the status file is gone, with the smallest correct change. Keep the identity check and never mark events that were not owed. bin/fm-branch-outcome.sh's header contract owns the ledger.Chosen approach (deliberate): the backstop now prints one
deliver --task T --status-ident I --endpoint Nreceipt line per shown undelivered captain-facing event, instead of a single --through hint per task. --endpoint is identity-keyed and records after teardown; because the drain only prints endpoints that are owed obligations, no non-owed endpoint is ever named. deliver's --through and --endpoint semantics are intentionally unchanged (--through still refuses on a missing file or mismatched identity; --endpoint still refuses a non-event endpoint while the named-identity file exists). Only the deliver header comment in bin/fm-branch-outcome.sh was updated to describe which form survives teardown. Supervision docs already say to run the printed deliver receipt for each backstop entry, so no doc change.Acceptance criteria:
Tests run the wake drain only with FM_TASK_ID unset (the drain refuses inside a task worker). Run lint with FM_LINT_JOBS=1.
Firstmate-Validation-Generation: 3c956fea2703f65bb22d6831ad18cf09
What Changed
deliver --endpointcommand for each shown undelivered backstop event, so its receipt remains recordable after status-file teardown.--throughreceipts after teardown.Risk Assessment
✅ Low: Captain, this bounded change preserves complete identity-keyed receipts, names only shown owed events, and leaves delivery semantics unchanged.
Testing
The focused regression script and four isolated live CLI scenarios passed. The parent command reproduced the reported failure. CLI transcripts and ledger state were captured; disposable files were removed. The broad changed-test selection was inspected only; lint and CI remain outside this assigned test phase.
Evidence: Live CLI receipts, refusals, ledger state, and parent regression
Evidence: Targeted regression tests
Evidence: Reproducible live CLI driver
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed ✅
bin/fm-wake-drain.sh:323- The new receipt command still passes through a 219-character prose cap. For the valid 56-character task IDfm-delivery-backstop-receipt-after-scout-status-teardown, identity16777234:123456789, and endpoint 27, the command is 223 characters; truncation cuts the identity and removes--endpoint. Relaying the shown completion, tearing down its status file, and executing the printed command therefore still leaves the obligation undischarged. Task creation permits IDs up to 64 characters (bin/fm-pr-lib.sh:113). Preserve the complete executable command at bin/fm-wake-drain.sh:322–323 and count its full length in the paired output budget at bin/fm-wake-drain.sh:324–326; cap only descriptive event text.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bin/fm-test-run.sh --list --changed --base 13507173930a06c8f242c8c10a156ec2b3af83caenv -u FM_TASK_ID TMPDIR="$PWD/.receipt-validation/tmp" FM_HOME="$PWD/.receipt-validation/home" bin/fm-test-run.sh tests/fm-wake-drain-unread-status.test.shpython3 .receipt-validation/drive.py: real isolated CLI checks, persisted ledger assertions, and parent failure reproductionRemoved disposable validation homes and copied runtime files; verified clean working tree.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.