diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-31 03:00:46 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-31 03:04:20 +0300 |
| commit | 3acd499ffb1119e8032bbcba3f1f46d4ff5f3da9 (patch) | |
| tree | 4e30e82ccbc821e8930b03addfd1542d91ee8705 /src/pane.rs | |
| parent | 4e1fbf410b844749dcddae775806e1cce01ef442 (diff) | |
fix: keep codex visible approval review working
Diffstat (limited to 'src/pane.rs')
| -rw-r--r-- | src/pane.rs | 181 |
1 files changed, 155 insertions, 26 deletions
diff --git a/src/pane.rs b/src/pane.rs index 97aeb9cb..ddf70b1b 100644 --- a/src/pane.rs +++ b/src/pane.rs @@ -110,6 +110,7 @@ const PROCESS_ACQUISITION_WINDOW: std::time::Duration = std::time::Duration::fro const PROCESS_ACQUISITION_FAST_WINDOW: std::time::Duration = std::time::Duration::from_millis(1500); const PROCESS_ACQUISITION_FAST_RECHECK: std::time::Duration = std::time::Duration::from_millis(500); const PROCESS_ACQUISITION_SLOW_RECHECK: std::time::Duration = std::time::Duration::from_secs(2); +const STABLE_VISIBLE_SIGNAL_REFRESH: std::time::Duration = std::time::Duration::from_millis(800); #[derive(Debug, Clone, Copy)] struct AgentDetectionPresence { @@ -282,6 +283,7 @@ fn should_publish_detection_update( next: DetectionPublishState, agent_changed: bool, process_exited: bool, + stable_visible_signal_refresh_due: bool, ) -> bool { next.state != previous.state || next.visible_blocker != previous.visible_blocker @@ -289,7 +291,28 @@ fn should_publish_detection_update( || next.visible_working != previous.visible_working || agent_changed || process_exited + || (stable_visible_signal_refresh_due + && ((next.visible_blocker && previous.visible_blocker) + || (next.visible_idle && previous.visible_idle) + || (next.visible_working && previous.visible_working))) +} + +fn stable_visible_signal_refresh_due( + previous: DetectionPublishState, + next: DetectionPublishState, + last_refresh: Option<std::time::Instant>, + now: std::time::Instant, +) -> bool { + // TODO: Evaluate expanding agent-specific visible_* predicates so more + // detectors can use screen-authoritative refreshes safely. + let stable_visible_signal = (next.visible_blocker && previous.visible_blocker) || (next.visible_idle && previous.visible_idle) + || (next.visible_working && previous.visible_working); + + stable_visible_signal + && last_refresh.is_none_or(|last_refresh| { + now.duration_since(last_refresh) >= STABLE_VISIBLE_SIGNAL_REFRESH + }) } fn spawn_basic_detection_task( @@ -313,6 +336,7 @@ fn spawn_basic_detection_task( let mut last_visible_blocker = false; let mut last_visible_idle = false; let mut last_visible_working = false; + let mut last_visible_signal_refresh = None; let mut last_process_check = std::time::Instant::now(); let mut last_foreground_pgid = None; let mut has_process_probe = false; @@ -328,6 +352,7 @@ fn spawn_basic_detection_task( last_visible_blocker = false; last_visible_idle = false; last_visible_working = false; + last_visible_signal_refresh = None; last_process_check = std::time::Instant::now(); last_foreground_pgid = None; has_process_probe = false; @@ -402,26 +427,41 @@ fn spawn_basic_detection_task( let visible_idle = detection.visible_idle && new_state == AgentState::Idle; let visible_working = detection.visible_working && new_state == AgentState::Working; + let previous_publish = DetectionPublishState { + state, + visible_blocker: last_visible_blocker, + visible_idle: last_visible_idle, + visible_working: last_visible_working, + }; + let next_publish = DetectionPublishState { + state: new_state, + visible_blocker, + visible_idle, + visible_working, + }; + let stable_refresh_due = stable_visible_signal_refresh_due( + previous_publish, + next_publish, + last_visible_signal_refresh, + now, + ); + if should_publish_detection_update( - DetectionPublishState { - state, - visible_blocker: last_visible_blocker, - visible_idle: last_visible_idle, - visible_working: last_visible_working, - }, - DetectionPublishState { - state: new_state, - visible_blocker, - visible_idle, - visible_working, - }, + previous_publish, + next_publish, agent_changed, false, + stable_refresh_due, ) { state = new_state; last_visible_blocker = visible_blocker; last_visible_idle = visible_idle; last_visible_working = visible_working; + if visible_blocker || visible_idle || visible_working { + last_visible_signal_refresh = Some(now); + } else { + last_visible_signal_refresh = None; + } publish_state_changed_event( state_events.clone(), pane_id, @@ -1647,6 +1687,7 @@ impl PaneRuntime { let mut last_visible_blocker = false; let mut last_visible_idle = false; let mut last_visible_working = false; + let mut last_visible_signal_refresh = None; tokio::time::sleep(Duration::from_millis(50)).await; @@ -1677,6 +1718,7 @@ impl PaneRuntime { last_visible_blocker = false; last_visible_idle = false; last_visible_working = false; + last_visible_signal_refresh = None; } } @@ -1828,21 +1870,31 @@ impl PaneRuntime { let visible_working = detection.visible_working && new_state == AgentState::Working; + let previous_publish = DetectionPublishState { + state, + visible_blocker: last_visible_blocker, + visible_idle: last_visible_idle, + visible_working: last_visible_working, + }; + let next_publish = DetectionPublishState { + state: new_state, + visible_blocker, + visible_idle, + visible_working, + }; + let stable_refresh_due = stable_visible_signal_refresh_due( + previous_publish, + next_publish, + last_visible_signal_refresh, + now, + ); + if should_publish_detection_update( - DetectionPublishState { - state, - visible_blocker: last_visible_blocker, - visible_idle: last_visible_idle, - visible_working: last_visible_working, - }, - DetectionPublishState { - state: new_state, - visible_blocker, - visible_idle, - visible_working, - }, + previous_publish, + next_publish, agent_changed, process_exited, + stable_refresh_due, ) { debug!( pane = pane_id.raw(), @@ -1856,6 +1908,11 @@ impl PaneRuntime { last_visible_blocker = visible_blocker; last_visible_idle = visible_idle; last_visible_working = visible_working; + if visible_blocker || visible_idle || visible_working { + last_visible_signal_refresh = Some(now); + } else { + last_visible_signal_refresh = None; + } publish_state_changed_event( state_events.clone(), pane_id, @@ -2798,29 +2855,101 @@ mod tests { #[test] fn stable_visible_idle_republishes_for_stale_hook_deadline() { + let now = std::time::Instant::now(); let previous = DetectionPublishState { state: AgentState::Idle, visible_blocker: false, visible_idle: true, visible_working: false, }; + let refresh_due = stable_visible_signal_refresh_due( + previous, + previous, + Some(now - STABLE_VISIBLE_SIGNAL_REFRESH), + now, + ); assert!(should_publish_detection_update( - previous, previous, false, false + previous, + previous, + false, + false, + refresh_due )); } #[test] fn stable_plain_idle_does_not_republish() { + let now = std::time::Instant::now(); let previous = DetectionPublishState { state: AgentState::Idle, visible_blocker: false, visible_idle: false, visible_working: false, }; + let refresh_due = stable_visible_signal_refresh_due( + previous, + previous, + Some(now - STABLE_VISIBLE_SIGNAL_REFRESH), + now, + ); assert!(!should_publish_detection_update( - previous, previous, false, false + previous, + previous, + false, + false, + refresh_due + )); + } + + #[test] + fn stable_visible_working_republishes_for_hook_override_refresh() { + let now = std::time::Instant::now(); + let previous = DetectionPublishState { + state: AgentState::Working, + visible_blocker: false, + visible_idle: false, + visible_working: true, + }; + let refresh_due = stable_visible_signal_refresh_due( + previous, + previous, + Some(now - STABLE_VISIBLE_SIGNAL_REFRESH), + now, + ); + + assert!(should_publish_detection_update( + previous, + previous, + false, + false, + refresh_due + )); + } + + #[test] + fn stable_visible_blocker_republishes_for_hook_override_refresh() { + let now = std::time::Instant::now(); + let previous = DetectionPublishState { + state: AgentState::Blocked, + visible_blocker: true, + visible_idle: false, + visible_working: false, + }; + let refresh_due = stable_visible_signal_refresh_due( + previous, + previous, + Some(now - STABLE_VISIBLE_SIGNAL_REFRESH), + now, + ); + + assert!(should_publish_detection_update( + previous, + previous, + false, + false, + refresh_due )); } |
