summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-02 18:00:44 +0300
committerGitHub <noreply@github.com>2026-09-02 18:00:44 +0300
commit987b070fbfa187e85009b45cd7e208fc6175ff6a (patch)
treec1a189d0d8667bcd84eb2ea1ebd34b3606128bf2
parentda49cb8a9dac6facc8f77671376914ee0ef47291 (diff)
fix: stop treating claude background shells as working (#3468)
-rw-r--r--distribution/agent-detection/claude.toml12
-rw-r--r--src/detect/manifest/tests.rs79
-rw-r--r--src/detect/manifests/claude.toml12
3 files changed, 83 insertions, 20 deletions
diff --git a/distribution/agent-detection/claude.toml b/distribution/agent-detection/claude.toml
index 55adacd6..2a26a334 100644
--- a/distribution/agent-detection/claude.toml
+++ b/distribution/agent-detection/claude.toml
@@ -1,7 +1,7 @@
id = "claude"
-version = "2026.08.29.1"
+version = "2026.08.31.1"
min_engine_version = 2
-updated_at = "2026-08-29T00:00:00Z"
+updated_at = "2026-08-31T00:00:00Z"
aliases = ["claude-code"]
[[rules]]
@@ -25,14 +25,6 @@ any = [
]
[[rules]]
-id = "background_shell_working"
-state = "working"
-priority = 965
-region = "bottom_non_empty_lines(5)"
-visible_working = true
-line_regex = ['^\s*[⏸⏵].*·\s+[1-9]\d*\s+shells?\s+(?:·|$)']
-
-[[rules]]
id = "background_agents_working"
state = "working"
priority = 965
diff --git a/src/detect/manifest/tests.rs b/src/detect/manifest/tests.rs
index 8eb3b612..63345636 100644
--- a/src/detect/manifest/tests.rs
+++ b/src/detect/manifest/tests.rs
@@ -660,6 +660,85 @@ fn osc_explain(
// --- Claude OSC rules ---
#[test]
+fn claude_idle_prompt_with_background_shell_is_idle() {
+ // Captured from Claude Code 2.1.251 after its foreground turn ended while
+ // a long-lived background shell remained active (issue #3414).
+ let screen = concat!(
+ "✻ Sautéed for 10s · 1 shell still running\n\n",
+ "──────────────────────────────────────────────────────── WINDOWS ─\n",
+ "❯\n",
+ "────────────────────────────────────────────────────────────────\n",
+ " ⏵⏵ auto mode on · 1 shell · ← for agents /rc\n",
+ );
+ let result = osc_explain(Agent::Claude, screen, "", "");
+
+ assert_eq!(result.state, AgentState::Idle);
+ assert_eq!(
+ result.matched_rule.as_ref().map(|rule| rule.id.as_str()),
+ Some("live_prompt_box")
+ );
+ assert!(result.visible_idle);
+ assert!(!result.visible_working);
+}
+
+#[test]
+fn claude_background_shell_without_foreground_evidence_is_idle_fallback() {
+ let result = osc_explain(
+ Agent::Claude,
+ " ⏵⏵ auto mode on · 1 shell · ← for agents\n",
+ "",
+ "",
+ );
+
+ assert_eq!(result.state, AgentState::Idle);
+ assert_eq!(result.matched_rule, None);
+ assert_eq!(
+ result.fallback_reason.as_deref(),
+ Some(DEFAULT_KNOWN_AGENT_IDLE_FALLBACK)
+ );
+ assert!(!result.visible_working);
+}
+
+#[test]
+fn claude_live_turn_with_background_shell_remains_working() {
+ let screen = concat!(
+ "────────────────────────────────────────────────────────────────\n",
+ "❯\n",
+ "────────────────────────────────────────────────────────────────\n",
+ " ⏵⏵ auto mode on · 1 shell · esc to interrupt\n",
+ );
+ let result = osc_explain(Agent::Claude, screen, "", "");
+
+ assert_eq!(result.state, AgentState::Working);
+ assert_eq!(
+ result.matched_rule.as_ref().map(|rule| rule.id.as_str()),
+ Some("live_turn_working")
+ );
+ assert!(result.visible_working);
+}
+
+#[test]
+fn claude_blocker_with_background_shell_remains_blocked() {
+ let screen = concat!(
+ "do you want to proceed?\n",
+ "bash command: rm -rf /tmp/test\n",
+ "❯ 1. Yes\n",
+ " 2. No\n\n",
+ "Esc to cancel · Tab to amend · ctrl+e to explain\n",
+ " ⏵⏵ auto mode on · 1 shell · ← for agents\n",
+ );
+ let result = osc_explain(Agent::Claude, screen, "", "");
+
+ assert_eq!(result.state, AgentState::Blocked);
+ assert_eq!(
+ result.matched_rule.as_ref().map(|rule| rule.id.as_str()),
+ Some("bash_permission_prompt")
+ );
+ assert!(result.visible_blocker);
+ assert!(!result.visible_working);
+}
+
+#[test]
fn claude_osc_title_braille_prefix_is_working() {
// "⠂" is U+2802, in the braille block U+2800-U+28FF
let result = osc_explain(Agent::Claude, "", "⠂ project", "");
diff --git a/src/detect/manifests/claude.toml b/src/detect/manifests/claude.toml
index 55adacd6..2a26a334 100644
--- a/src/detect/manifests/claude.toml
+++ b/src/detect/manifests/claude.toml
@@ -1,7 +1,7 @@
id = "claude"
-version = "2026.08.29.1"
+version = "2026.08.31.1"
min_engine_version = 2
-updated_at = "2026-08-29T00:00:00Z"
+updated_at = "2026-08-31T00:00:00Z"
aliases = ["claude-code"]
[[rules]]
@@ -25,14 +25,6 @@ any = [
]
[[rules]]
-id = "background_shell_working"
-state = "working"
-priority = 965
-region = "bottom_non_empty_lines(5)"
-visible_working = true
-line_regex = ['^\s*[⏸⏵].*·\s+[1-9]\d*\s+shells?\s+(?:·|$)']
-
-[[rules]]
id = "background_agents_working"
state = "working"
priority = 965