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"); });