aboutsummaryrefslogtreecommitdiff
path: root/src/detect
diff options
context:
space:
mode:
Diffstat (limited to 'src/detect')
-rw-r--r--src/detect/manifest/tests.rs40
-rw-r--r--src/detect/manifests/codex.toml6
2 files changed, 44 insertions, 2 deletions
diff --git a/src/detect/manifest/tests.rs b/src/detect/manifest/tests.rs
index e1073f3c..c5522952 100644
--- a/src/detect/manifest/tests.rs
+++ b/src/detect/manifest/tests.rs
@@ -1195,6 +1195,46 @@ fn codex_weak_blocker_ignores_wrapped_current_prompt_text() {
}
#[test]
+fn codex_sparkle_prompt_preserves_live_states() {
+ for marker in ["› ", "›⠁", "›⠂", "›⠄", "›⠈", "›⠐", "›⠠", "›⡀", "›⢀"]
+ {
+ let screen = format!("Do you want to proceed? [y/n]\n{marker}unsent draft\n");
+ let result = osc_explain(Agent::Codex, &screen, "project | Ready", "");
+ assert_eq!(result.state, AgentState::Idle, "{marker}");
+
+ let working = format!(
+ "Do you want to proceed? [y/n]\n• Working (4s • esc to interrupt)\n{marker}draft\n"
+ );
+ let result = osc_explain(Agent::Codex, &working, "project", "");
+ assert_eq!(result.state, AgentState::Working, "{marker}");
+
+ let approval = format!("{screen}Press enter to confirm or esc to cancel\n");
+ let result = osc_explain(Agent::Codex, &approval, "project", "");
+ assert_eq!(result.state, AgentState::Blocked, "{marker}");
+ assert!(result.visible_blocker);
+
+ for response_marker in ['•', '■', '✗', '✓'] {
+ let response = format!("{screen}{response_marker} Do you want to proceed? [y/n]\n");
+ let result = osc_explain(Agent::Codex, &response, "project", "");
+ assert_eq!(
+ result.state,
+ AgentState::Blocked,
+ "{marker} {response_marker}"
+ );
+ }
+ }
+}
+
+#[test]
+fn codex_weak_blocker_does_not_ignore_arbitrary_prompt_suffixes() {
+ for line in ["›text", "›⠋draft", "›⠀draft", " ›⠁draft", "quoted ›⠁draft"] {
+ let screen = format!("Do you want to proceed? [y/n]\n{line}\n");
+ let result = osc_explain(Agent::Codex, &screen, "project", "");
+ assert_eq!(result.state, AgentState::Blocked, "{line}");
+ }
+}
+
+#[test]
fn codex_transcript_viewer_outranks_working_fallback() {
let screen = "• Working (4s • esc to interrupt)\n\
› transcript\n\
diff --git a/src/detect/manifests/codex.toml b/src/detect/manifests/codex.toml
index 884492c4..7840ca6f 100644
--- a/src/detect/manifests/codex.toml
+++ b/src/detect/manifests/codex.toml
@@ -1,7 +1,7 @@
id = "codex"
-version = "2026.09.05.1"
+version = "2026.09.12.1"
min_engine_version = 3
-updated_at = "2026-09-05T00:00:00Z"
+updated_at = "2026-09-12T00:00:00Z"
[[rules]]
id = "osc_title_blocked"
@@ -69,6 +69,8 @@ id = "weak_blocker"
state = "blocked"
priority = 600
region = "whole_recent_without_current_prompt_marker"
+# Sparkles can replace the space after ›. A later response marker makes that prompt stale.
+not = [{ regex = ['(?m)^›[⠁⠂⠄⠈⠐⠠⡀⢀][^\n]*(?:\n(?:[^•■✗✓\n][^\n]*)?)*\z'] }]
any = [
{ contains = ["[y/n]"] },
{ contains = ["yes (y)"] },