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:
jif
2026-09-15 10:45:16 +00:00
committed by copyberry
parent 4415f985dc
commit a113f3e063
15 changed files with 231 additions and 315 deletions
-16
View File
@@ -306,12 +306,6 @@ impl Session {
let cancellation_token = CancellationToken::new();
let done = Arc::new(Notify::new());
codex_guardian_reviewer::ReviewDenials::clear_turn(
&self.services.thread_extension_data,
&turn_context.sub_id,
)
.await;
let (pending_items, _) = self.input_queue.drain_mailbox_input_items().await;
let turn_state = {
let mut active = self.active_turn.lock().await;
@@ -812,11 +806,6 @@ impl Session {
})
};
self.send_event(turn_context.as_ref(), event).await;
codex_guardian_reviewer::ReviewDenials::clear_turn(
&self.services.thread_extension_data,
&turn_context.sub_id,
)
.await;
let cleared_active_turn = {
let mut active = self.active_turn.lock().await;
@@ -968,11 +957,6 @@ impl Session {
duration_ms,
});
self.send_event(task.turn_context.as_ref(), event).await;
codex_guardian_reviewer::ReviewDenials::clear_turn(
&self.services.thread_extension_data,
&task.turn_context.sub_id,
)
.await;
// Regular items were flushed before this terminal event was appended; buffering
// thread writers may not flush it without another explicit barrier.
if let Err(err) = self.flush_rollout().await {