fix: stop treating claude background shells as working (#3468)

This commit is contained in:
akbash
2026-09-02 18:00:44 +03:00
committed by GitHub
parent da49cb8a9d
commit 987b070fbf
3 changed files with 83 additions and 20 deletions
+79
View File
@@ -659,6 +659,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
+2 -10
View File
@@ -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]]
@@ -24,14 +24,6 @@ any = [
{ line_regex = ['^\s*[\x{002A}\x{00B7}\x{2722}\x{2736}\x{273B}\x{273D}]\s+\S.*…(?:\s+\(\d+[smh](?:\s|·)|\s*$)'] },
]
[[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"