mirror of
https://github.com/openai/codex.git
synced 2026-11-09 20:50:33 +00:00
Consolidate Guardian reviewer lifecycle ownership (#45672)
## What changed - Use cancellation guards to tie reusable reviewers and temporary forks to their lifetimes, including when a review future is dropped. Replace cancelled reusable reviewers before reuse. - Share `ReviewerTasks` between the pool and `ThreadManager`, and wait for tracked cleanup during pool shutdown. Remove the separate session shutdown protocol. - Move denial cleanup from core task handling into Guardian's turn start, stop, and abort hooks. Expose `install_reviewer` to register both thread and turn lifecycle contributors together. ## Testing Add an integration test that exercises stale denial cleanup at turn start, completion, and interruption, including starting another turn after interruption. GitOrigin-RevId: 85badb235309c1e1576547d1746f7ee9fc66d545
This commit is contained in:
@@ -1330,48 +1330,3 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {
|
||||
);
|
||||
drop(io);
|
||||
}
|
||||
|
||||
#[test_case(TerminalEventKind::TurnComplete; "completion")]
|
||||
#[test_case(TerminalEventKind::TurnAborted; "interruption")]
|
||||
#[tokio::test]
|
||||
async fn terminal_turn_clears_extension_owned_denials(terminal: TerminalEventKind) {
|
||||
let (session, turn, events) = make_session_and_context_with_rx().await;
|
||||
let finish = Arc::new(tokio::sync::Notify::new());
|
||||
session
|
||||
.spawn_task(
|
||||
Arc::clone(&turn),
|
||||
Vec::new(),
|
||||
HeldStepTask {
|
||||
kind: TaskKind::Regular,
|
||||
finish: Arc::clone(&finish),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let denials =
|
||||
codex_guardian_reviewer::ReviewDenials::for_thread(&session.services.thread_extension_data);
|
||||
for _ in 0..2 {
|
||||
assert_eq!(
|
||||
denials.record_denial(&turn.sub_id, turn.model_info()).await,
|
||||
None
|
||||
);
|
||||
}
|
||||
match terminal {
|
||||
TerminalEventKind::TurnComplete => finish.notify_one(),
|
||||
TerminalEventKind::TurnAborted => {
|
||||
session.abort_all_tasks(TurnAbortReason::Interrupted).await
|
||||
}
|
||||
}
|
||||
recv_terminal_event(&events, terminal).await;
|
||||
// Delivery precedes accounting cleanup. Wait for the runtime to finish the turn.
|
||||
timeout(Duration::from_secs(/*secs*/ 5), async {
|
||||
while session.active_turn.lock().await.is_some() {
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
})
|
||||
.await
|
||||
.expect("turn becomes idle");
|
||||
assert_eq!(
|
||||
denials.record_denial(&turn.sub_id, turn.model_info()).await,
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user