Repository navigation
fix: surface newly ready gated backlog work - #48
Merged
Merged
Conversation
Queued backlog work gated on a hold date or on blockers could become ready without any turn in the home - a date passing, or a blocker closed by a captain answer, a hand-run tasks-axi done, or work elsewhere - and nothing noticed until the next teardown or session start. bin/fm-ready-work.sh owns the backstop: the watcher runs a ready-work scan on the base heartbeat cadence and wakes once per readiness transition, teardown names the work its own close unblocked and records it as surfaced, and live-gated queued work (a future hold date, or blockers that are in flight or live-gated themselves) now counts as supervision need while undated holds never keep a watcher alive.
…e supervision limit
…e-library load and stopping ShellCheck from recursively analyzing the new ready-work import through watcher and supervision callers. The ready-work script remains linted as its own root. Local lint, source-aware checks, and ready-work behavior tests pass
This was referenced Sep 29, 2026
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
please create a proper fix based on the stall scout finding.
please put them as teo separate pull requests.
also ensure that the fixes generalize across the firstmate repo.
also ensure that before you create a pull request on the upstream repo please also ensure we properly follow the upstream repo contribution rules if there are any and the standards it has defined?
Context the ask refers to: a scout investigated why a remote second mate stalled on dependency-gated follow-on work.
Its report found two gaps and the captain asked for them as two separate pull requests.
The first (a wording fix to AGENTS.md section 10 and the second-mate charter so authorized gated phases are filed as backlog items at once) is a separate task.
This task is the second pull request: the mechanical monitoring gap.
In substance, from the report: queued work is re-evaluated only at this home's own teardown (a printed reminder to run
ready) and at session start.The watcher heartbeat wakes only on an unsurfaced actionable status, never on a backlog item that has newly become ready, and supervision need counts in-flight metadata, sources, checks, and Relay but not queued, held, or date-gated items, so an otherwise idle home runs no watcher at all.
So a captain hold with
--untilwhose date passes, or a blocker cleared by anything other than this home's own teardown (a captain answer or release, a manualtasks-axi done, cross-home work), is not noticed until the next teardown or session start, even though the hold feature promises the item "resurfaces on its date".The proposed fix: surface newly ready backlog items (date gate passed, or every blocker closed) as a wake from the watcher's routine heartbeat, and count date-gated or blocked queued items as supervision need so an idle home keeps a watcher while such items exist; optionally, have teardown list the dependents the closed item just unblocked instead of only telling the agent to run
ready.What Changed
Risk Assessment
Testing
The baseline ready-work check passed; after the lock fix, the ready-work, guard, teardown, and captain-hold checks passed. The final watcher check used an isolated real tmux server. No graphical screenshot was produced because the changed product surface is CLI output and persisted wake state.
tests/fm-ready-work.test.shexercises a real tasks-axi backlog and confirms one durable wake when a dated hold becomes due.tests/fm-ready-work.test.shcloses a blocker through the supported task wrapper and checks the dependent wake and deduplication.tests/fm-captain-hold-lifecycle.test.shanswers a captain hold and checks for exactly one persisted dependent wake.tests/fm-ready-work.test.shruns the watcher against an isolated real tmux server and checks its output and wake queue.tests/fm-ready-work.test.shandtests/fm-turnend-guard.test.shcheck live supervision need for dated gates and no continuing need for undated holds.tests/fm-teardown.test.shchecks the wake queued when teardown closes a blocking item.Known limit
A bare
tasks-aximutation that bypassesbin/fm-tasks-axi.sh(or a hand edit of the backlog) is an unsupported path: AGENTS.md routes every backlog read and mutation through that wrapper, which now surfaces work its close, release, or unblock made ready.Backlog blockers are home-local, so such a missed transition is picked up by the watcher's next ready-work scan when a watcher is running, and otherwise by the next session start.
No permanent watcher is kept for work blocked only by an undated captain hold or by queued work this home has not dispatched; date gates keep the watcher until their due date.
Upstream applicability
Upstream kunchenguid/firstmate main (52fca51) has the same gap:
bin/fm-supervision-lib.shcounts only in-flight metadata, process-event sources, registered checks, and Relay,bin/fm-watch.shnever reads the backlog, and teardown only prints a reminder to runready.Upstream's
bin/fm-watch.shhas diverged from this fork, so an upstream port needs a rebase of the watcher hunk and must be raised through no-mistakes per upstream CONTRIBUTING.md.Harness and runtime-backend compatibility review
bin/fm-claude-stop-autoarm.sh) and the Stop turn-end guard both read the shared supervision predicate, so live-gated queued work arms or demands a watcher.bin/fm-turnend-guard.sh; Cursor'sbin/fm-turnend-guard-cursor.shcallsfm_supervision_needed. All inherit the new need through the one predicate, andbin/fm-guard.shnames it in its watcher-down banner.shouldArm(in-flight metadata and Relay only, not sources, checks, or gated work); its turn-end guard still enforces the shared need. That drift predates this change and is left for a follow-up.check:row, which stays main-only while attended and is offered to the branch under the away posture, like every other check row.classify_checkescalates it.bin/fm-tasks-axi.sh, never a pane or endpoint.config/backlog-backend=manualsteps aside rather than blocking.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 5 issues found → auto-fixed (3) ✅
bin/fm-ready-work.sh:127- The intent requires counting blocked queued items as supervision need. Here, a dependent blocked by an undated captain hold or a queued ready item is excluded; the same exclusion appears at bin/fm-ready-work.sh:128 and in the supervision verdict at bin/fm-supervision-lib.sh:92. If a captain answer releases the hold or a manual command closes the blocker while the home is idle, no watcher is running to surface the dependent. The diff narrows the stated criterion to blockers classified as live-gated; restore supervision for these blocked items.bin/fm-ready-work.sh:207- With no.ready-work-surfacedrecord, this branch silently treats the current ready set as surfaced. A date or blocker that clears before the watcher's first scan therefore gets no wake. The same suppression occurs in the optional teardown path: bin/fm-ready-work.sh:256 commits before it prints, and bin/fm-teardown.sh:1562 captures that output, so an interrupted delivery can leave the item marked surfaced. The silent seed and teardown suppression are not required by the intent; remove them so an unreported ready item remains eligible for the watcher.bin/fm-ready-work.sh:151- The scanner derives the home from the state directory even whenFM_STATE_OVERRIDEpoints elsewhere. That override is supported by the watcher at bin/fm-watch.sh:141 and both supervision callers at bin/fm-guard.sh:47 and bin/fm-turnend-guard.sh:97. With an alternate state directory and the normal data directory, scans read the wrong home's backlog or return zero supervision need. Use the establishedFM_HOMEand directory overrides for these reads.bin/fm-ready-work.sh:117- The scan also wakes for a newly filed task that was ready from creation. The intent specifies transitions caused by a date passing or blockers closing, and does not require this additional wake path. Narrow the matching path to those gate-clearing transitions.bin/fm-watch.sh:239-FM_READY_SCANintroduces a separate cadence option. The intent calls for scanning on the routine heartbeat cadence and gives no requirement for a configurable second schedule. Remove the option and use the base heartbeat interval.🔧 Fix applied.
6 issues (3 errors, 3 warnings) still open:
bin/fm-ready-work.sh:127- The intent requires counting blocked queued items as supervision need. Here, a dependent blocked by an undated captain hold or a queued ready item is excluded; the same exclusion appears at bin/fm-ready-work.sh:128 and in the supervision verdict at bin/fm-supervision-lib.sh:92. If a captain answer releases the hold or a manual command closes the blocker while the home is idle, no watcher is running to surface the dependent. The diff narrows the stated criterion to blockers classified as live-gated; restore supervision for these blocked items.bin/fm-ready-work.sh:207- With no.ready-work-surfacedrecord, this branch silently treats the current ready set as surfaced. A date or blocker that clears before the watcher's first scan therefore gets no wake. The same suppression occurs in the optional teardown path: bin/fm-ready-work.sh:256 commits before it prints, and bin/fm-teardown.sh:1562 captures that output, so an interrupted delivery can leave the item marked surfaced. The silent seed and teardown suppression are not required by the intent; remove them so an unreported ready item remains eligible for the watcher.bin/fm-ready-work.sh:151- The scanner derives the home from the state directory even whenFM_STATE_OVERRIDEpoints elsewhere. That override is supported by the watcher at bin/fm-watch.sh:141 and both supervision callers at bin/fm-guard.sh:47 and bin/fm-turnend-guard.sh:97. With an alternate state directory and the normal data directory, scans read the wrong home's backlog or return zero supervision need. Use the establishedFM_HOMEand directory overrides for these reads.bin/fm-ready-work.sh:117- The scan also wakes for a newly filed task that was ready from creation. The intent specifies transitions caused by a date passing or blockers closing, and does not require this additional wake path. Narrow the matching path to those gate-clearing transitions.bin/fm-ready-work.sh:128- The fix round added wake calls tofm-tasks-axi.shandfm-captain-hold.sh, but left the stated bare manualtasks-axi donepath uncovered. If an idle home has a dependent blocked only by a queued item, line 128 excludes it from supervision; closing that blocker directly produces no wake, and no watcher is running to scan it. The same gap applies to an external or cross-home close of such a blocker. The intent requires noticing blocker clears outside teardown, while the fix-round instruction forbids a permanent watcher for this case. Resolve which mechanism should cover bare external closes; wrapper hooks cannot intercept them.bin/fm-ready-work.sh:239- The newsurfacemode is an additional output and commit path that no production caller uses. The intent requires a durable wake, and the optional teardown behavior useswake. Removesurfaceand its test-only callers; this also avoids marking work surfaced merely because printing to stdout succeeded.🔧 Fix applied.
7 issues (3 errors, 4 warnings) still open:
bin/fm-ready-work.sh:127- The intent requires counting blocked queued items as supervision need. Here, a dependent blocked by an undated captain hold or a queued ready item is excluded; the same exclusion appears at bin/fm-ready-work.sh:128 and in the supervision verdict at bin/fm-supervision-lib.sh:92. If a captain answer releases the hold or a manual command closes the blocker while the home is idle, no watcher is running to surface the dependent. The diff narrows the stated criterion to blockers classified as live-gated; restore supervision for these blocked items.bin/fm-ready-work.sh:207- With no.ready-work-surfacedrecord, this branch silently treats the current ready set as surfaced. A date or blocker that clears before the watcher's first scan therefore gets no wake. The same suppression occurs in the optional teardown path: bin/fm-ready-work.sh:256 commits before it prints, and bin/fm-teardown.sh:1562 captures that output, so an interrupted delivery can leave the item marked surfaced. The silent seed and teardown suppression are not required by the intent; remove them so an unreported ready item remains eligible for the watcher.bin/fm-ready-work.sh:151- The scanner derives the home from the state directory even whenFM_STATE_OVERRIDEpoints elsewhere. That override is supported by the watcher at bin/fm-watch.sh:141 and both supervision callers at bin/fm-guard.sh:47 and bin/fm-turnend-guard.sh:97. With an alternate state directory and the normal data directory, scans read the wrong home's backlog or return zero supervision need. Use the establishedFM_HOMEand directory overrides for these reads.bin/fm-ready-work.sh:117- The scan also wakes for a newly filed task that was ready from creation. The intent specifies transitions caused by a date passing or blockers closing, and does not require this additional wake path. Narrow the matching path to those gate-clearing transitions.bin/fm-ready-work.sh:128- The fix round added wake calls tofm-tasks-axi.shandfm-captain-hold.sh, but left the stated bare manualtasks-axi donepath uncovered. If an idle home has a dependent blocked only by a queued item, line 128 excludes it from supervision; closing that blocker directly produces no wake, and no watcher is running to scan it. The same gap applies to an external or cross-home close of such a blocker. The intent requires noticing blocker clears outside teardown, while the fix-round instruction forbids a permanent watcher for this case. Resolve which mechanism should cover bare external closes; wrapper hooks cannot intercept them.bin/fm-ready-work.sh:239- The newsurfacemode is an additional output and commit path that no production caller uses. The intent requires a durable wake, and the optional teardown behavior useswake. Removesurfaceand its test-only callers; this also avoids marking work surfaced merely because printing to stdout succeeded.bin/fm-ready-work.sh:166- The newFM_READY_WORK_TIMEOUToption controls both backlog reads and lock waits (also at bin/fm-ready-work.sh:197). The requested heartbeat backstop needs bounded operations, but no intent requirement needs a configurable timeout. Remove the option and use a fixed bound.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
tests/fm-ready-work.test.shexercises a real tasks-axi backlog and confirms one durable wake when a dated hold becomes due.tests/fm-ready-work.test.shcloses a blocker through the supported task wrapper and checks the dependent wake and deduplication.tests/fm-captain-hold-lifecycle.test.shanswers a captain hold and checks for exactly one persisted dependent wake.tests/fm-ready-work.test.shruns the watcher against an isolated real tmux server and checks its output and wake queue.tests/fm-ready-work.test.shandtests/fm-turnend-guard.test.shcheck live supervision need for dated gates and no continuing need for undated holds.tests/fm-teardown.test.shchecks the wake queued when teardown closes a blocking item.tests/fm-ready-work.test.shbefore the fix and after the final test changetests/fm-turnend-guard.test.shtests/fm-teardown.test.shtests/fm-captain-hold-lifecycle.test.shgit diff --check✅ **Document** - passed
✅ No issues found.
🔧 **Lint** - 1 issue found → auto-fixed ✅
🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Push** - passed
✅ No issues found.