fix(agent-claude-code): tighten waiting_input regex to ignore static UI footer
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.
This commit is contained in:
parent
faf43042bd
commit
8aeffdcd86
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue