Skip to content

fix(bin): name the task in watcher wedge and dead-endpoint stale reasons - #6761

Open
dsdevq wants to merge 2 commits into
kunchenguid:mainfrom
dsdevq:fm/fm-f3-stale-reason-names-task
Open

dsdevq wants to merge 2 commits into
kunchenguid:mainfrom
dsdevq:fm/fm-f3-stale-reason-names-task

Conversation

@dsdevq

@dsdevq dsdevq commented Oct 7, 2026 •

Copy link
Copy Markdown

Intent

The owner approved on 2026-10-07 (his words: "2. yes") three proposals to the firstmate maintainer as public PRs, this being the second: a stale notification from the watcher names the task it is about, not only the terminal pane.
Context from the fleet friction audit (data/fleet-friction-audit/report.md, fix F3): on this fleet the supervisor looked a pane name up to find its task about 99 times per week and reported 8 refusals on a bare pane name. The task id is already in scope at each site in bin/fm-watch.sh: $id near line 1493 and the <task> argument of wedge_timer_check near line 1517; today only the pane is printed, at the format strings near lines 1487, 1545 and 1547 on current main.

What Changed

  • In bin/fm-watch.sh, the possible-wedge escalation (including the demand-deep-inspection variant) and the dead-endpoint report from wedge_dead_record now end with task=<id> after the parenthetical. Previously they named only the terminal pane. The header comment documents the suffix and notes that consumers read the window up to the first ( and ignore it.
  • In tests/fm-watch-triage.test.sh, three watcher tests now assert that the escalation or gone-endpoint output contains the task name.
  • In tests/fm-daemon.test.sh, the synthetic wedge reasons in test_enriched_wedge_under_declared_wait_uses_pause_cadence now carry the task=$task suffix, so they match the new format the daemon handles.

Risk Assessment

✅ Low: The change appends " task=$task" to the three watcher stale reasons that the intent names (possible-wedge escalation, demand-deep-inspection escalation and dead-endpoint report). The daemon's parsing cuts at the first " (" and matches the wedge detail with a trailing glob, so the suffix is ignored there. The branch dispatcher keys on the window, not the reason text.

Testing

I drove a real fm-watch.sh subprocess through the test fixtures, covering the possible-wedge escalation, the demand-deep-inspection escalation and the dead-endpoint report. Each now prints task=&lt;id&gt; after the parenthetical. The daemon test confirms the downstream consumer handles the suffixed reason. The new assertion fails on the base watcher and passes on the change. The full watcher triage file ran out of time, so only the three changed tests were run on their own. I did not exercise a Herdr lab or a real harness primary.

  • Live validation: ✅ go - 4 of 4 scenarios driven live against the product
Scenario Result Live Evidence
A watcher run that wedge-escalates a stale pane emits a stale wake ending in ' task=<id>' ✅ pass live targeted-after.log: test_stale_terminal_status_overridden_by_active_run and the undeclared-lane escalations in test_wedge_threshold_defers_to_a_declared_wait... passed with the ' task=' assertions
The once-only dead-endpoint report names its task, including after the endpoint comes back and dies again ✅ pass live targeted-after.log: test_gone_report_rearms_when_the_endpoint_comes_back passed with the ' task=wedge' assertion
Adversarial: the new assertion fails on the base watcher, so it proves the change ✅ pass live targeted-base-fails.log shows 'not ok - the wedge escalation did not name its task: stale: test:fm-validating (idle 503s, possible wedge, escalation 1)'
The daemon still classifies a wedge wake carrying the ' task=' suffix, including the demand-deep-inspection form, under a declared wait ✅ pass live daemon.log: 'ok - an enriched wedge under a declared wait uses the pause cadence and restores wedge detection on resume'; the daemon file reported no 'not ok'
Evidence: Targeted watcher triage run on the change (passing)

Source: Targeted watcher triage run on the change (passing)

ok - a stale terminal-looking status is overridden and absorbed while a run is actively working, then wedge-escalated
ok - a declared wait is not wedge-escalated by a working verdict, while an elapsed declaration and an undeclared lane both keep the unchanged ladder
ok - the once-only gone report re-arms when the endpoint comes back, and reports a later death again

real	2m28.066s
user	0m44.989s
sys	1m13.124s
Evidence: Same test on the base watcher (fails, no task id in the reason)

Source: Same test on the base watcher (fails, no task id in the reason)

not ok - the wedge escalation did not name its task: stale: test:fm-validating (idle 503s, possible wedge, escalation 1)
Evidence: Daemon test file run

Source: Daemon test file run

ok - fm-afk-start.sh fails before daemon startup when the afk flag cannot be written
ok - fm-afk-start.sh ignores stale pidfile-only live pids
ok - fm-afk-start.sh reclaims stale daemon locks whose live pid identity no longer matches
ok - supervise daemon state root is scoped by FM_HOME
ok - routine signal self-handles
ok - captain-relevant status verbs escalate
ok - check + unknown escalate; heartbeat self-handles
ok - a delivered unknown wake is acknowledged once per away session; a new one and ordinary escalations still fire
ok - a failed unknown-wake acknowledgement write does not re-inject a delivered digest
ok - transient stale self-handles and records a persistence marker
ok - enriched stale wedges bypass status absorption except under a declared wait, without disturbing busy workers
ok - an enriched wedge under a declared wait uses the pause cadence and restores wedge detection on resume
ok - stale + terminal status escalates immediately
ok - stale escalation and current wait cadence remain independent
ok - paused reasons with captain phrases remain pause-classified
ok - a foreign resolved line keeps a pause, while the worker's own resolved line retracts it
ok - a captain-held transfer classifies as pause, not as a wedge candidate
ok - handle_wake on a paused stale records a pause marker, drops the wedge marker, and does not escalate
ok - handle_wake records a declared pause from a routine signal for long-cadence rechecks
ok - a terminal signal clears pause and stale tracking across both supervisors
ok - housekeeping migrates a normal-watcher's declared pause into daemon tracking
ok - housekeeping clears an already-resumed watcher pause across both supervisors
ok - housekeeping seeds pause tracking from status without a watcher marker
ok - persistent stale escalates after threshold and clears its marker
ok - resumed (busy) stale clears its marker without escalating
ok - housekeeping re-surfaces a stale declared pause on the long cadence and resets its window
ok - housekeeping re-surfaces a forgotten captain hold on the long cadence and resets its window
ok - housekeeping silences a captain hold only under an away record, never under quiet mode's
ok - a busy pane cannot gate the pause clear once its crew's status no longer declares the wait
ok - housekeeping matures a busy pane's declared-wait window into exactly one recheck per window
ok - housekeeping bounds a distant declared time, defers to a near one, and rechecks a passed one at once
ok - housekeeping clears a paused marker once the crew is no longer declaring the pause
ok - housekeeping clears the pause marker once a captain hold is answered
ok - housekeeping moves an existing stale marker to pause before wedge escalation
ok - housekeeping moves a captain hold's existing stale marker to pause before wedge escalation
ok - housekeeping clears tracking when a crew leaves pause
ok - persistent herdr stale resolves the target from metadata and escalates
ok - herdr idle busy-footer stale clears through capture corroboration
ok - resumed herdr stale clears through backend-aware busy state
ok - persistent Orca stale resolves the terminal from metadata
ok - multiple escalations flush as a single batched digest
ok - batch flush measures max-delay from the first append, not the last
ok - catch-all scan escalates a missed terminal once, not twice
ok - handle_wake routes routine->self and captain->escalate
ok - a decision-owned queued row escalates once as the decision, then suppresses until the status changes
ok - a captain-held decision-owned row is self-handled without escalation, now and on repeat
ok - INJECT_SKIP forces self-handle, bypassing captain-relevant classification
ok - is_wake_reason distinguishes watcher wake reasons from singleton-status stdout
ok - terminal-stale escalate removes its marker so housekeeping does not re-escalate
ok - captain signal escalate marks seen so the catch-all scan does not re-fire
ok - _collapse_newlines replaces newlines with literal separator
ok - afk flag absent: daemon does not inject, buffer preserved
ok - busy-guard defers injection when supervisor pane is busy
ok - marker detection: marker -> stay afk, no marker -> exit afk
ok - /afk invocation is exempt from afk exit (no self-cancel)
ok - should_exit_afk returns false when afk is not active
ok - strip_injection_marker removes the sentinel marker cleanly
ok - a marker-preserving primary still receives the typed U+2063 away-supervisor envelope and no record
ok - record-backed doorbell: only a doorbell naming this home's own record stays afk; a bare ASCII label, a missing record, and another home's record exit
ok - pane_input_pending detects partial input on the cursor line
ok - pane_input_pending: a blank unidentified cursor row defers (strict container-proof rule)
ok - pane_input_pending: only proven empty agent prompts pass
ok - fm_tmux_composer_state: a bare shell prompt ($/%/#/>) reads unknown, never empty (dead-shell injection safety)
ok - fm_tmux_composer_state: a bordered composer box and bare agent glyphs (❯/›) still read empty
ok - fm_tmux_composer_state: only matching edge borders form a composer box
ok - pane_input_pending preserves bright placeholder-like drafts in styled captures
ok - classify_signal dedupes against the catch-all scan seen marker
ok - turn-end markers stay routine while mixed actionable status batches escalate
ok - an actionable event is escalated to an away captain despite later routine appends
ok - the daemon commits exactly the endpoint captured by classification
ok - a stale wake escalates a blocker hidden by later progress
ok - a stale span read failure surfaces without advancing its marker
ok - a recreated status rejects the old captured identity
ok - an unverifiable status identity surfaces without advancing markers
ok - a status read failure surfaces without advancing the daemon suppressor
ok - catch-all routine scans advance before later actionable appends
ok - failed escalation writes retain durable wakes and classification positions
ok - stuck inbox escalation reaches supervision in away mode and survives buffering failure
ok - stuck inbox escalation reaches supervision in quiet mode and survives buffering failure
ok - write inbox escalation reaches supervision in away mode and survives buffering failure
ok - write inbox escalation reaches supervision in quiet mode and survives buffering failure
ok - reset inbox escalation reaches supervision in away mode and survives buffering failure
ok - reset inbox escalation reaches supervision in quiet mode and survives buffering failure
ok - inbox dispatch preserves ordinary stale, busy-turn, and other doorbell routing
ok - catch-all markers advance only after escalation buffering succeeds
ok - classification failure retains the complete durable wake batch
ok - missing-status stale wakes remain ordinary and acknowledgeable
ok - transient unreadable signals recover without advancing their position
ok - daemon catch-all reclassifies permission-recovered status content
ok - a permanent classification failure is reported, acknowledged, and never advances its position
ok - the away-mode catch-all scan surfaces a masked event once
ok - classify_stale dedupes against the signal path seen marker
ok - AFK nonterminal working:+merged keeps wedge aging and re-escalates at bound
ok - genuine done: and merge-check events still escalate
ok - pane_input_pending: an idle bordered composer is NOT pending (afk-invx-i5)
ok - pane_input_pending: text inside a bordered composer is still pending
ok - submit-ACK confirms a submit when the composer returns to a bordered-empty box
ok - submit-ACK reports pending on a persistently swallowed Enter (type-once)
ok - max-defer on an empty stuck pane types once, alarms, and preserves the buffer
ok - max-defer flushes and clears the buffer on an empty bordered pane
ok - max-defer on a pending composer alarms without typing
ok - normal flush clears a stale wedge marker
ok - an oversized buffered digest is delivered bounded, with the full text kept durable
ok - a digest past its byte budget counts the omitted events and keeps them in the full text
ok - an initial-send failure logs its stage, bytes, and stderr, and the wedge alarm names it
ok - an Enter-confirmation failure logs its own stage and byte count
ok - a bounded digest's full-text file survives a failure after typing, and a deferral writes none
ok - below MAX_DEFER: no inject, no alarm, buffer preserved
ok - max-defer does not flush or alarm while afk is inactive
ok - library mode: sourcing the daemon defaults FM_WEDGE_ALARM_EXEC to discard (no test can fire a real notification)
ok - wake helpers replace inherited notifier overrides with the safe recorder
ok - the discard seam suppresses every notifier, including command: (fires nothing)
ok - direct notifier helpers honor the discard seam, including command:
ok - osascript channel routes through the notifier seam with the summary (never a real notification)
ok - herdr channel routes through the notifier seam with the summary (never a real notification)
ok - command channel runs the captain command with the summary on $1 and on stdin
ok - command channel failures redact configured commands while logging their exit status
ok - unknown channel directives are redacted while the alarm keeps running
ok - off disables every active alert regardless of directive position (marker and tmux flash are unaffected)
ok - auto resolves to the macOS osascript notifier on Darwin (default-on)
ok - auto on a non-macOS platform selects no built-in OS channel (the marker or a configured command carries it)
ok - config/wedge-alarm selects every configured channel and skips comment and blank lines
ok - a failing channel logs and falls back to the next channel, never crashing the alarm
ok - a hung notifier is bounded, logged, and falls through to the next channel
ok - a backgrounded command notifier remains bounded until its process group is reaped
ok - a hung notifier override is bounded, logged, and proceeds to the next channel
ok - daemon shutdown stops and reaps the active notifier process group
ok - inject_wedge_alarm writes the marker AND emits the active alert even with no tmux status-line (herdr backend)
ok - in-process wedge throttle prevents alert spam when the marker cannot persist
ok - fm-send returns 3 with a non-error no-resend warning when confirmation stays pending
ok - fm-send exits non-zero when initial text send fails
ok - fm-send exits non-zero unless delivery is proven empty
ok - discover_supervisor_backend: override > TMUX_PANE > HERDR_ENV+HERDR_PANE_ID > tmux fallback
ok - discover_supervisor_target: override > TMUX_PANE > herdr '<session>:<pane-id>' composition > firstmate:0 fallback
ok - pane_is_busy: herdr native busy_state='busy' short-circuits without a capture fallback
ok - primary busy guard isolates rendered signatures by detected harness
ok - pane_is_busy: omitted backend defaults to tmux for Grok's isolated fallback
ok - pane_input_pending: dispatches through fm_backend_composer_state for backend=herdr
ok - inject_msg: herdr busy-guard defers before ever attempting a submit
ok - inject_msg: herdr composer-guard defers before ever attempting a submit
ok - inject_msg: herdr pane-gone check defers before any busy/composer/submit call
ok - inject_msg: dispatches busy-guard/composer-guard/submit through the herdr backend and succeeds on a confirmed empty composer
ok - inject_msg: defers on a dead-shell/unreadable composer (unknown), never typing the escalation into a shell
ok - inject_msg: unrecognized composer states defer by default

real	2m3.018s
user	0m31.844s
sys	0m57.786s
Evidence: Partial full-file watcher triage run (timed out)

Source: Partial full-file watcher triage run (timed out)

ok - status_span_has_actionable: benign absorbed, captain events surfaced, classified events not re-fired
ok - an actionable event is not hidden by later routine appends, and is named as itself
ok - span classification retires closed decisions and surfaces rejected transitions for reconciliation
ok - span classification from an offset keeps closed decisions closed and live ones live
ok - a malformed seen signature causes the whole status log to be classified
ok - stale_is_terminal: terminal status surfaces, non-terminal and no-status are benign
ok - classifier primitives: keyed decisions and activity phases, captain relevance, window-to-task, and overrides
ok - unrecognized status prefixes are visible and recognized prefixes are unchanged
ok - crew_is_provably_working: only working+run-step/pane is provable; idle/finished/parked/failed/unknown surface
ok - status_is_paused: only the leading paused verb matches, paused is not captain-relevant, and the two declared-wait verbs stay separable
ok - crew_absorb_class: working/paused/none from one read; crew_is_paused and crew_is_provably_working agree
ok - crew_worktree_written_since: real writes are evidence; no worktree, no anchor, quiet trees, .git churn and a mate's own home are not
ok - an empty FM_WORKTREE_WRITE_PRUNE widens the probe to the whole depth-bounded tree instead of disabling it
ok - an empty FM_WORKTREE_WRITE_PRUNE exported into the environment prunes nothing, widening the probe
ok - the worktree write probe is wall-clock bounded, and hitting the bound reads as no write evidence
ok - signal_crew_provably_working: benign only when every referenced crew is provably working
ok - a secondmate's unmarked routine progress absorbs when provably working; routed, terminal, note, marked, and unknown lines surface
ok - a no-verb signal whose crew is provably working is absorbed (no exit, no queue, suppressor advanced, beacon present)
ok - a bare turn-end whose crew is provably working (busy pane) is absorbed
ok - a bare turn-end whose crew is not provably working is surfaced (the swallowed-finish fix)
ok - a bare turn-end from a pane that churned since the previous poll is absorbed
ok - pane churn starts a fresh stale-classification interval before a stopped render returns
ok - pane churn resets prior wedge escalation state before the stale-path poll
ok - a churning turn-end inside an already-open deferral window is absorbed without re-marking
ok - a bare turn-end from a pane unchanged since the previous poll still surfaces
ok - a bare turn-end backed by a malformed prior hash surfaces
ok - a bare turn-end backed by a newline-terminated prior hash surfaces
ok - a churning secondmate turn-end surfaces without a stale resurface path
ok - a turn-end whose marker key matches another recorded endpoint surfaces
ok - two metadata records sharing one endpoint make churn evidence ambiguous
ok - a batch may satisfy positive evidence independently per task
ok - per-task evidence composition stays off until the home opts in
ok - a status-bearing batch never falls through to pane-churn evidence
ok - pane-churn turn-end absorb is off until a home opts in
ok - a perpetually churning pane surfaces once its bounded deferral window is spent
ok - an unrecordable pane-churn deadline surfaces the turn-end
ok - an invalid pane-churn bound surfaces the turn-end
ok - an oversized pane-churn bound surfaces the turn-end
ok - invalid existing pane-churn deadlines surface without mutation
ok - a surfaced batch opens no partial pane-churn deadline
ok - a no-verb working: note whose crew is idle with no running pipeline is surfaced
ok - a secondmate's status note surfaces even while its own agent is busy
ok - a busy secondmate's routine working: is absorbed while its later note: still surfaces
ok - a secondmate blocker wakes despite busy evidence and later unrelated appends
ok - a self-announced close never wakes its own home, and the next real note still does
ok - a close after OPEN DECISIONS fold never wakes its own home, and the next real note still does
ok - a folded worker decision with no home append still wakes
ok - separate answers over unclassified decisions wake once, and the next real note still does
ok - a close after OPEN DECISIONS fold still surfaces a worker failure inside the folded span
ok - a close after OPEN DECISIONS fold still surfaces unlisted secondmate lines inside the folded span
ok - captain-relevant signal is surfaced (queue + exit) and marked surfaced
ok - a needs-decision signal row's queued payload is marked needs-decision: for branch exclusion
ok - a reconciliation-required needs-decision row's queued payload is still marked needs-decision:
ok - a captain-held signal stays actionable while the crew is still working
ok - a pending-reply second-mate escalation is marked for main-only routing
ok - an ordinary blocked event remains branch-eligible
ok - a routine event containing a needs-decision phrase keeps its ordinary payload, unmarked
ok - a captain event hidden behind a later routine append is still surfaced (queue + exit)
ok - a keyed decision signal reads only the newly appended span, not the whole log
ok - a finished release reported before routine cleanup chatter is still surfaced
ok - a routine append after an already-classified event is absorbed (no re-wake)
ok - unreadable status reports are bounded without advancing classification
ok - permission recovery surfaces content from the unadvanced position
ok - a stale pane sitting on a terminal status is surfaced (queue + exit)
ok - a stale terminal-looking status is overridden and absorbed while a run is actively working, then wedge-escalated
ok - provably-working non-terminal stale is absorbed on first sight, then wedge-escalated past the threshold
ok - consecutive wedge escalations on the same pane accumulate and demand deep inspection at the threshold
ok - a pane becoming active again resets the consecutive wedge-escalation counter
Terminated

real	9m40.644s
user	3m31.653s
sys	5m55.651s

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.

  • Live validation: ✅ go - 4 of 4 scenarios driven live against the product
Scenario Result Live Evidence
A watcher run that wedge-escalates a stale pane emits a stale wake ending in ' task=<id>' ✅ pass live targeted-after.log: test_stale_terminal_status_overridden_by_active_run and the undeclared-lane escalations in test_wedge_threshold_defers_to_a_declared_wait... passed with the ' task=' assertions
The once-only dead-endpoint report names its task, including after the endpoint comes back and dies again ✅ pass live targeted-after.log: test_gone_report_rearms_when_the_endpoint_comes_back passed with the ' task=wedge' assertion
Adversarial: the new assertion fails on the base watcher, so it proves the change ✅ pass live targeted-base-fails.log shows 'not ok - the wedge escalation did not name its task: stale: test:fm-validating (idle 503s, possible wedge, escalation 1)'
The daemon still classifies a wedge wake carrying the ' task=' suffix, including the demand-deep-inspection form, under a declared wait ✅ pass live daemon.log: 'ok - an enriched wedge under a declared wait uses the pause cadence and restores wedge detection on resume'; the daemon file reported no 'not ok'
  • bash tests/fm-daemon.test.sh (full file, passed, including the enriched-wedge test with the new suffix)
  • Targeted run of test_stale_terminal_status_overridden_by_active_run, test_wedge_threshold_defers_to_a_declared_wait_under_a_working_verdict and test_gone_report_rearms_when_the_endpoint_comes_back from tests/fm-watch-triage.test.sh against the new bin/fm-watch.sh (all passed)
  • The same wedge-escalation test against the base fm-watch.sh (failed: 'the wedge escalation did not name its task: stale: test:fm-validating (idle 503s, possible wedge, escalation 1)')
  • Full bash tests/fm-watch-triage.test.sh hit the 580s timeout after 68 passing results and no failures; the three changed tests were then run on their own
✅ **Document** - passed

✅ No issues found.

⚠️ **Lint** - 1 warning
  • ⚠️ linter found issues (exit code 1)
✅ **Push** - passed

✅ No issues found.

The possible-wedge escalation and the dead-endpoint report printed only the
terminal pane, so the supervisor had to look the pane up to find its task.
Both reasons now end with task=<id> after the parenthetical. Consumers read
the window up to the first ' (' and ignore the suffix, so the daemon's stale
classification is unchanged.
@greptile-apps

greptile-apps Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Low risk] Adds task identifiers to watcher log messages.

The PR appears safe to merge; the previous test gap is fixed.

Reviews (2) · Last reviewed commit: "no-mistakes(ci): Fixed the Greptile find..." · Reviewed by Greptile

Comment thread tests/fm-watch-triage.test.sh Outdated
…scalation round's `task=wedge` assertion must be satisfied only by that round's own output. The old check grepped the whole accumulated output file, so escalation 1's suffix let rounds 2 and 3 pass. In test_wedge_threshold_defers_to_a_declared_wait_under_a_working_verdict, tests/fm-watch-triage.test.sh now greps the `possible wedge, escalation $n` line and pipes it into `grep -F ' task=wedge'`. bin/fm-watch.sh prints the suffix on that same line, including the demand-deep-inspection variant on escalation 3 (lines 1549 and 1551). It is the only test site with this pattern and no other changes were made. Verification: the edited test passes when run on its own (the full file times out at 600s, so I ran a temp copy that calls only that function and then removed it)
@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thanks for this, @dsdevq. I read the whole diff of head e126a11b against main.

What I checked: bin/fm-watch.sh appends task=<id> after the parenthetical in three stale reasons: the possible-wedge escalation, its demand-deep-inspection form, and the once-only dead-endpoint report from wedge_dead_record. $task is already a local in both wedge_dead_record and wedge_timer_check on main, so the value is always the right task. I traced the consumer in bin/fm-supervise-daemon.sh. It takes the window up to the first ( and matches the wedge detail with idle *s, possible wedge, escalation *, a trailing glob, so the suffix doesn't change window resolution, classification, or the declared-wait pause override. The tests now assert the suffix on the same line as each escalation (Greptile's P2 on the earlier commit is fixed, and it's 5/5 now). No workflow changes, no network calls, no secrets. The no-mistakes attestation matches this head.

CI: I approved this head's fork runs 37600852659 (CI) and 37600852601 (Require no-mistakes). Results are pending. The PR is MERGEABLE. The #6762 watcher change that just landed on main touches different lines.

Contract-class: new-default. This is a small, sensible change. Still, nothing on main promised that these wakes name the task, so this isn't restoring a broken default. It changes the text of a default-on wake that every home's supervisor reads, and there's no setting. By the rules I triage under, that's a new default, so it goes to Kun for a merge-or-leave decision once it's green rather than auto-merging. That part is on him, not you.

VISION.md, rule by rule

  • One captain, one interface: aligns. The supervisor no longer has to look up a pane to know which task a wedge is about, so there's less below-deck churn. The captain-facing text is unchanged in kind.
  • Authority is explicit and never inferred: aligns. No new action or autonomy. It only adds information to an existing report.
  • Scripts own the mechanics, agents own the judgment: aligns. The script supplies an exact fact it already has, which saves agent tokens on a lookup.
  • A restart is a non-event: aligns. No state changes.
  • Delegation with a spine: aligns. No change to contracts.
  • The fleet outlives any vendor: aligns. Backend- and harness-agnostic.
  • Scope: aligns. Command-layer supervision text.

Overlap note for Kun: #6682 ("name the Claude exit picker on stale and wedge wakes") also enriches these same wedge and stale reasons in bin/fm-watch.sh and bin/fm-supervise-daemon.sh. Whichever lands second will likely need a small rebase.

Next step: waiting on CI (CI and Require no-mistakes) for e126a11b. Nothing is needed from you unless something comes back red. Once it's green, it goes to Kun.

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