From 8aeffdcd867802f67361cd63780a0538923c38c2 Mon Sep 17 00:00:00 2001 From: harshitsinghbhandari <24b4506@iitb.ac.in> Date: Tue, 19 May 2026 20:48:42 +0530 Subject: [PATCH] fix(agent-claude-code): tighten waiting_input regex to ignore static UI footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing `/bypass.*permissions/i` regex matched Claude's persistent UI footer `⏵⏵ bypass permissions on (shift+tab to cycle)` — which is visible on EVERY active Claude session. As long as native JSONL classification returned a definitive answer, this didn't matter. The previous noise-skip commit on this branch (faf43042) made many more sessions fall through to the AO JSONL pipeline, which exposed the bug: ao-143/144/151 all flipped to waiting_input even though they were genuinely dormant. Tightened the regex to require "all future" — matching the actual permission-bypass prompt ("bypass all future permissions for this session") rather than the footer toggle ("bypass permissions on"). The other two waiting_input regexes (`Do you want to proceed?`, `(Y)es...(N)o`) are unchanged. Verified: dashboard's stored AO activity-JSONL entries had `state: "waiting_input"` with trigger snippets containing the persistent footer text. With this fix, classifyTerminalOutput on the exact same terminal capture returns active instead. Tests: existing `bypass all future permissions for this session` test still passes (the prompt phrase contains the new tighter pattern). Added a regression test confirming the static footer alone does NOT match waiting_input. --- .../agent-claude-code/src/activity-detection.ts | 8 +++++++- .../plugins/agent-claude-code/src/index.test.ts | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/plugins/agent-claude-code/src/activity-detection.ts b/packages/plugins/agent-claude-code/src/activity-detection.ts index 776fbe084..678357a52 100644 --- a/packages/plugins/agent-claude-code/src/activity-detection.ts +++ b/packages/plugins/agent-claude-code/src/activity-detection.ts @@ -310,7 +310,13 @@ export function classifyTerminalOutput(terminalOutput: string): ActivityState { const tail = lines.slice(-5).join("\n"); if (/Do you want to proceed\?/i.test(tail)) return "waiting_input"; if (/\(Y\)es.*\(N\)o/i.test(tail)) return "waiting_input"; - if (/bypass.*permissions/i.test(tail)) return "waiting_input"; + // Match the ACTUAL permission-bypass prompt — "bypass all future permissions + // for this session" — not the persistent UI footer "bypass permissions on + // (shift+tab to cycle)" which is visible on EVERY Claude session. The + // earlier `/bypass.*permissions/i` was too broad and false-fired on every + // session that fell through to the AO JSONL pipeline (real-world repro: + // ao-143/144/151 all flipped to waiting_input on dormant sessions). + if (/bypass\s+all\s+future\s+permissions/i.test(tail)) return "waiting_input"; return "active"; } diff --git a/packages/plugins/agent-claude-code/src/index.test.ts b/packages/plugins/agent-claude-code/src/index.test.ts index c6a54ac8d..9ea46c009 100644 --- a/packages/plugins/agent-claude-code/src/index.test.ts +++ b/packages/plugins/agent-claude-code/src/index.test.ts @@ -538,6 +538,23 @@ describe("detectActivity", () => { ); }); + it("does NOT match Claude's persistent UI footer 'bypass permissions on (shift+tab to cycle)'", () => { + // Regression test: the old `/bypass.*permissions/i` regex matched this + // footer toggle (visible on EVERY Claude session) and falsely fired + // waiting_input for every session that fell through to the AO JSONL + // pipeline. ao-143/144/151 all flipped to waiting_input on dormant + // sessions until this was tightened to require "all future". + const footerOnly = [ + "✻ Crunched for 11s", + "", + "──────────────────────────────────────────────────────────", + "❯ ", + "──────────────────────────────────────────────────────────", + " ⏵⏵ bypass permissions on (shift+tab to cycle)", + ].join("\n"); + expect(agent.detectActivity(footerOnly)).not.toBe("waiting_input"); + }); + it("returns active when queued message indicator is visible", () => { expect(agent.detectActivity("Press up to edit queued messages\n")).toBe("active"); });