feat(bin): add bead lifecycle closing with fm-ledger safety net - #25
Conversation
Wire the --beads <id> flag end to end (it was documented but never implemented: no arg parsing, no beads_id= meta write, fm-bead-stamp.sh was dead code). fm-spawn.sh now records beads_id= in task meta and invokes fm-bead-stamp.sh after launch. fm-teardown.sh closes a task's linked bead automatically once its work is confirmed landed, and skips closing on a --force or refused teardown. The close call is fail-open: a missing task CLI or a rejected close warns and never blocks teardown. Add bin/fm-ledger.sh as the safety net for beads that fall outside that automatic close: claimed, unclosed beads that have gone quiet past --stale-days are surfaced as likely_dropped and can be closed individually or in bulk. Clarify fm-brief-hooks.d/beads.sh's Bead Closure section so a crewmate that cannot reach its own close step knows firstmate's teardown will close the bead for it. Cross-reference beads_id= in AGENTS.md's state/<id>.meta field list.
…r.sh in AGENTS.md and docs/scripts.md
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Intent
Implement bead lifecycle CLOSING structure: agents close self-contained work on landing, and beads whose work landed but were never closed are surfaced as closeable. Wire the documented --beads spawn flag end to end (beads_id= meta, fm-bead-stamp.sh invocation), make fm-teardown.sh auto-close a linked bead only on confirmed landed teardown (never on --force or a refused teardown), clarify the brief hook's claim-first/close-last contract, and add bin/fm-ledger.sh to surface and close likely_dropped (claimed, unclosed, stale) beads as a safety net.
What Changed
--beads <id>spawn flag end-to-end:bin/fm-spawn.shnow writesbeads_id=to task metadata and invokesfm-bead-stamp.shto mark the beaddispatch=sent/lifecycle=sent.bin/fm-teardown.shnow auto-closes a task's linked bead once teardown confirms the work landed, and explicitly never does so on--forceor a refused teardown; clarified the claim-first/close-last contract inbin/fm-brief-hooks.d/beads.sh.bin/fm-ledger.sh, a new fleet-wide safety net that lists and closes "likely dropped" beads (claimed, still open, gone stale), plus documentation updates inAGENTS.mdanddocs/scripts.md.Reviewer Finding Resolution
The pipeline's review step flagged (finding
review-1, info/ask-user) that scout and secondmate teardown skip the git-level "PR merged or content in default branch" landed check before auto-closing a linked bead, relying instead on their own pre-existing completion gates (a scout's report plus decision-hold, a secondmate having no in-flight children).This is confirmed correct, intended, pre-existing behavior, not a gap introduced by this change.
Those completion gates are each kind's landed-equivalent condition, so bead auto-close on their teardown is right as-is; only ship tasks need the git-landed check.
No code change was made in response to this finding.
Risk Assessment
✅ Low: The change is additive, fail-open, and well-tested (landed-close, --force-skip, and refused-teardown-skip paths are each covered by new tests); I independently verified the beads query DSL semantics (label format, relative-date comparison direction) against the live task/bd CLI help and a real query run, and found no correctness issues.
Testing
Ran the existing fm-ledger and fm-teardown behavior-test suites (all passing, including the 3 new teardown cases the author added for the close-on-landed/never-on-force/never-on-refused contract), and wrote a new tests/fm-spawn-beads.test.sh to close a real coverage gap — the --beads flag's end-to-end wiring (meta beads_id= and fm-bead-stamp.sh invocation) previously had zero test coverage since it was documented but unimplemented before this change; both new cases pass, confirming the flag now works as documented.
Evidence: Bead lifecycle test run transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-teardown.sh:1406- Auto-close only requires reaching this line without --force. For kind=scout/secondmate, validate_worktree_teardown_safety short-circuits to true (pre-existing line ~816:secondmate|scout) return 0), so the git-level PR-merged/content-in-default "landed" check never runs for those kinds — their own completion gates (scout: report + decision-hold; secondmate: no in-flight children) stand in for "landed" instead. That's a defensible reading consistent with how those kinds already define done, but is a looser bar than the header comment's "confirmed work landed" language implies for ship tasks. Worth confirming auto-close across all three kinds (not just ship) matches intent.✅ **Test** - passed
✅ No issues found.
bash tests/fm-ledger.test.sh— all 10 cases pass (list/--json/--stale-days/--close/--close-all/--yes/CLI-reject/CLI-missing)bash tests/fm-teardown.test.sh— all 39 cases pass, incl. 3 new bead-close-on-landed, no-close-on-force, no-close-on-refused casesbash tests/fm-spawn-beads.test.sh— new test added by this run; confirms --beads <id> writes beads_id= to task meta and invokes fm-bead-stamp.sh (task show / set-state dispatch=sent / set-state lifecycle=sent); also confirms no --beads flag means neither happensbash tests/fm-beads-backend.test.shandbash tests/fm-brief.test.sh— unaffected adjacent suites still pass✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.