fix: prevent false wedge escalations for healthy workers - #10
Open
josh-padnick wants to merge 5 commits into
Open
josh-padnick wants to merge 5 commits into
josh-padnick wants to merge 5 commits into
Conversation
josh-padnick
force-pushed
the
fm/fm-wedge-timer-grok-pause
branch
from
August 21, 2026 22:53
c0e81fc to
f83118a
Compare
This was referenced Aug 28, 2026
fix(bin): stop stale-alarm churn on declared-paused and acked-quiet panes
kunchenguid/firstmate#3214
Closed
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
Stop the Firstmate stale/wedge detector from falsely escalating healthy workers in both observed defect classes. First, preserve the mechanism-level diagnosis: declared-pause harness bias caused an idle Grok pane with a durable paused: status to wedge-escalate while equivalent Claude pauses used the intended long cadence, and active-turn false idle caused productive Claude xhigh-thinking panes rendering token spinners and Grok panes rendering Waiting for response… token spinners to accumulate repeated wedge escalations. Declared paused: status must select the long-cadence recheck path regardless of pane harness while allowing authoritative newly active work to supersede an older pause. Positive active-turn evidence, whether from a verified native or semantic source or Grok's isolated rendered fallback, must clear or freeze the wedge ladder through the existing fm-busy-lib.sh ownership; do not add a parallel detector, and preserve verification gates so unverified, unknown, or genuinely uncertain harness state still escalates fail-safe. Remove the invalid completed-turn-age proxy that ages a new active turn from an older completed turn. Keep Grok rendered matching structural, isolated, and live-verified with independent signals. Preserve the fail-safe direction: this targets the two proven false-positive classes, not general quieting. Add non-vacuous executable regression tests with realistic declared-pause status files and realistic captured Grok waiting-spinner and Claude thinking/token-spinner fixtures that reproduce both classes, prove the wedge timer and escalation count are cleared for active turns and declared pauses, prove idle and unknown panes still surface or escalate, and include a real-harness drift guard for unavoidable rendered signals. Update the authoritative contracts, configuration, harness guidance, verification evidence, and test-family selection without duplicating ownership. Review may perform at most two fix rounds; a third fix-round request must stop for firstmate escalation. Yolo is off: every ask-user finding must be escalated to firstmate, and the PR must not be merged without the captain's explicit approval.
What Changed
Risk Assessment
🚨 High: The source review is clean, but the authoritative intent explicitly requires the captain's approval before merge, so this change must not merge automatically.
Testing
No prior baseline results were supplied. Focused classifier, watcher subprocess, test-family selection, and real Grok 1.0.5 checks passed, demonstrating that active Claude and Grok turns clear wedge state, declared Grok pauses use long cadence, settled or uncertain panes remain fail-safe, and both independent live Grok signals survive harness drift.
Evidence: Busy-state behavioral transcript
Source: Busy-state behavioral transcript
Evidence: Watcher end-to-end behavioral transcript
Source: Watcher end-to-end behavioral transcript
Evidence: Real Grok drift guard
Source: Real Grok drift guard
ok - Grok (grok 1.0.5 (5115b46bc909) [stable]): each live signal independently classifies busy, then settles idlePipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed (3) ✅
bin/fm-busy-lib.sh:94- Intent requires, “Keep Grok rendered matching structural, isolated, and live-verified with independent signals” and preservation of fail-safe escalation. The new alternatives are not structurally constrained: recent completed output quotingWaiting for response… 12m 07s ⇣33.4kis classified busy, clearing the wedge ladder indefinitely, while\[stop\][[:space:]]*$does not match the realistic bordered fixture ending[stop] ... │. The live guard waits for both strings and classifies only the combined capture, so it can pass solely through the waiting-response arm. Constrain both alternatives to verified UI structure atfm_busy_grok_tail_busy, then exercise each live signal independently and verify copied footer text remains idle.docs/architecture.md:24- Intent requires, “Declared paused: status must select the long-cadence recheck path regardless of pane harness” and “Update the authoritative contracts.” The architecture contract still says an ordinarypaused:endpoint gets that cadence only after the backend confirms the agent dead, contradicting the new harness-neutral branch atfm-watch.sh:362. Update this paragraph to distinguish directpaused:handling from death-gatedcaptain-heldhandling.🔧 Fix: Constrain Grok signals and clarify pause contract
1 error still open:
bin/fm-busy-lib.sh:94- Intent requires “Keep Grok rendered matching structural.” The[stop]alternative matches any bordered line containing[stop], including ordinary Grok transcript content such as│ use [stop] to continue │within the last 12 lines. This incorrectly returnsbusy grok-regex, clears the wedge ladder, and can hide an idle worker. The negative test covers only unbordered text, while the live guard derives its stop-only sample from an active footer. Constrain this arm to the verified footer structure atfm_busy_grok_tail_busyand cover bordered completed output.🔧 Fix: Constrain Grok stop matching to verified footer
2 errors still open:
bin/fm-busy-lib.sh:94- Intent requires “Keep Grok rendered matching structural,” and the approved correction requires copied or completed footer text to remain idle. Both alternatives still accept a single bordered transcript row:│ Waiting for response… 12m 07s ⇣33.4k │matches the waiting arm, while│ copied ⇣33.4k [stop] │matches the stop arm. Grok transcript rows use the same│...│framing, so completed output can returnbusy grok-regexand indefinitely clear the wedge ladder. After two same-theme fix rounds, stop for firstmate escalation. The matcher needs verified footer position or adjacency infm_busy_grok_tail_busy, plus a bordered copied-footer regression.docs/verification/supervision.md:217- Intent requires Grok signals to be “live-verified with independent signals” and verification evidence to be updated. The recorded output predates the fix-round logic that isolates each signal and no longer matches the current guard's output text (each live signal independently...). Therefore the evidence only proves the earlier combined-capture guard ran, not that the current independent arms passed against a real Grok pane. After correcting the structural matcher, rerun the current opt-in guard and record its actual versioned output.🔧 Fix: Match Grok busy detection to live footer
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
tests/fm-busy-state.test.shtests/fm-watch-triage.test.shFM_GROK_BUSY_LIVE_E2E=1 tests/fm-grok-busy-live-e2e.test.shtests/fm-test-run.test.sh✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.