Stuck-busy agents leave coverage silently: unsubmitted prompt text pins idle=false, 14h measured uncovered, no alert
An agent with unsubmitted text sitting at its CC prompt reads BUSY to the scanner forever, so the idle-compact path can never fire and the agent silently leaves actuator coverage. Measured on pm-llmmsgsrv-cc 2026-08-08 14:10 -> 2026-08-09 04:07: 1,392 consecutive busy observations, 14h uncovered, nudge_pending_since never consumed, ctx crept 72.8 -> 82.0%, and nothing anywhere alerted. Detection signature is cheap and already proven by hand: reads busy AND ctx spread <0.5pt over an hour AND transcript's last assistant turn is hours old. analyze-agent-context.sh v1.2 already computes exactly this as its VERDICT block - the work is moving it into tick.py as an alert (same shape as the v4.63 dark-agent alert, DM Elazar, once per agent per 6h). NOTE the wedge variant: such a session accepts printable keys and Backspace but IGNORES Enter/C-m/Escape, so no keystroke clears it - the alert must say 'needs a human call on restarting', not 'poking it'.
Questions
Activity
-
Fixed in tick.py v4.66 (sh.git, 2026-08-09). check_stuck_busy() on the busy path: fires when an agent has read busy on every context_samples row for STUCK_BUSY_S=3600 with a ctx spread under STUCK_BUSY_SPREAD_PCT=0.5 and at least STUCK_BUSY_MIN_SAMPLES=60 samples, DMs Elazar once per STUCK_BUSY_REALERT_S=21600. The spread test is the load-bearing part - real work moves ctx, so it is what separates a wedge from a genuinely long turn; a duration threshold alone would flag every slow agent. Alert reports the FULL busy run (from the last idle sample), not the detection window, and says 'needs a human call on restarting' rather than promising a poke, since a wedged session ignores Enter/Escape. Defect found by the replay and fixed before shipping: the window had no upper bound, so a replay swept forward into the present and a wedge that later recovered read as 'went idle' - both queries now bounded by ts. Verified by replaying the measured pm-llmmsgsrv-cc wedge: silent at 15:00 (50min in, under the window), FIRED at 20:00 (5.8h in, 106 samples, spread 0.0pt) - roughly 8h before I found it by hand - silent at 00:00/02:00 under the 6h dedupe, silent at 05:29 after recovery. FLEET FINDING from the false-positive sweep: 6 of 31 agents are wedged RIGHT NOW, all confirmed genuine by pane inspection (unsubmitted text at the prompt) - coder-llmmsgsrv-cc 71.6%, pm-mars-cc 77.2%, pm-terra-cc 70.4%, coder-terra-cc 64.4%, pm-enamel-cc 45.2%, coder02-mars-cc 37.6%. Zero false positives. pm-terra-cc's unsubmitted text is this actuator's own PRE-COMPACT PERSIST, which means the keystroke landed as text and was never submitted - relevant to OPS-115 and the send path.
-
RETRACTED as diagnosed. All 6 first-run alerts were CC autosuggest ghosts (dim SGR-2) misread as typed text by scan-context.py's capture_prompt_line_is_real_input(), which iterated FORWARD and returned on the first prompt-glyph line (a submitted scrollback echo, real by definition) instead of the last (the live composer). is_idle() consults it, so a ghost pinned idle=false permanently. Fixed by reversing the iteration; the 4 affected agents flipped to idle immediately. The instance this WI was written from - pm-llmmsgsrv-cc 2026-08-08, '1,392 consecutive busy observations, 14h uncovered' - does not survive either: it logged 10 idle samples in 1,494 and stepped ctx 80.8->81.2->81.6->82.0 during the window. It was working. ZERO confirmed instances of a genuinely stuck-busy agent now exist. Detector kept in v4.70 (the failure is real if it ever happens and nothing else would catch it) but the remedy text is stripped of confidence and now tells the reader to verify the text is not dim FIRST, and that a ghost means the classifier regressed. The v4.68/v4.69 class-A/class-B model is withdrawn entirely: 'class B, Enter inert' was Enter doing nothing to an EMPTY composer, which is correct behaviour.