From 8aec608586dbb4ba11505fe2ddef8e916fe344d8 Mon Sep 17 00:00:00 2001 From: Simon Heimlicher Date: Fri, 7 Aug 2026 11:52:51 +0200 Subject: [PATCH 1/4] Detect two live Claude states the typed profile still reports idle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both survived the #684-#688 profile migration because no captured screen reaches the rules that carry them. `claude.elapsedStatus` and `claude.backgroundWork` are exercised only by inline synthetic screens written from the same assumptions as the predicates, so those screens cannot falsify them, and `claude.spinner` matches first on every captured working fixture. Captured live against Claude Code 2.1.224 with `prowl read --source detection`, sampling `prowl agents` at the same instant: ● Perusing… (1m 38s · ↓ 187 tokens) -> agents reported done ✻ Waiting for 1 background agent to finish -> agents reported done The status label is free text and is not always one word; the elapsed segment becomes several tokens past a minute, so a correctly shaped row detects for 59 seconds and then flips to idle for the rest of the turn. The background wait row carries a spinner glyph but no ellipsis, which hasSpinnerActivity requires, and the old marker matched the literal "agents done" that only the workflow variant of the row prints. The switcher block below the prompt looks like a better signal and is not one: a subagent that returns control while awaiting collection keeps its row with the elapsed frozen, so matching the row shape holds the pane at working after the work stopped. Observed live, and pinned by a test. Add AgentScreenRuleCoverageTests, which fails when a typed rule has no captured witness. It would have flagged both rules the day the corpus landed. One Codex rule is carried as explicit, documented debt. --- docs/components/agent-detection.md | 36 +++-- .../AgentDetection/ClaudeScreenProfile.swift | 74 +++++++-- .../AgentDetection/ScreenHeuristics.swift | 19 ++- .../AgentScreenRuleCoverageTests.swift | 61 ++++++++ .../ClaudeBackgroundAgentDetectionTests.swift | 143 ++++++++++++++++++ supacodeTests/ClaudeScreenProfileTests.swift | 6 + .../676-background-agent-wait.metadata.json | 16 ++ .../working/676-background-agent-wait.txt | 59 ++++++++ .../676-compound-elapsed-status.metadata.json | 16 ++ .../working/676-compound-elapsed-status.txt | 35 +++++ 10 files changed, 430 insertions(+), 35 deletions(-) create mode 100644 supacodeTests/AgentScreenRuleCoverageTests.swift create mode 100644 supacodeTests/ClaudeBackgroundAgentDetectionTests.swift create mode 100644 supacodeTests/Fixtures/AgentScreenDetection/claude/2.1.224/working/676-background-agent-wait.metadata.json create mode 100644 supacodeTests/Fixtures/AgentScreenDetection/claude/2.1.224/working/676-background-agent-wait.txt create mode 100644 supacodeTests/Fixtures/AgentScreenDetection/claude/2.1.224/working/676-compound-elapsed-status.metadata.json create mode 100644 supacodeTests/Fixtures/AgentScreenDetection/claude/2.1.224/working/676-compound-elapsed-status.txt diff --git a/docs/components/agent-detection.md b/docs/components/agent-detection.md index f32fbc92..8c29a9b4 100644 --- a/docs/components/agent-detection.md +++ b/docs/components/agent-detection.md @@ -48,10 +48,18 @@ at a `~/.grok/` install (so Cursor's own `agent` entrypoint stays Cursor). Other agent families keep their own patterns (including Oh My Pi's `Working… ⟦esc⟧` loader, braille frames, symbol cycles, Cursor's hexagons, Kimi's moon phases, etc.). - For Claude, a running **background workflow** keeps a status line *below* the - input box (e.g. `3/5 agents done · 7m 29s · ↓ 288.5k tokens`) after the turn has - ended; Prowl reads that footer as **Working**, so a churning workflow isn't - mistaken for idle. + Claude's live status row (`●