diff --git a/codex-rs/ext/guardian-reviewer/src/pool.rs b/codex-rs/ext/guardian-reviewer/src/pool.rs index 6956f06b68..5c3a2db10a 100644 --- a/codex-rs/ext/guardian-reviewer/src/pool.rs +++ b/codex-rs/ext/guardian-reviewer/src/pool.rs @@ -329,6 +329,19 @@ impl ReviewerPool { (outcome, analytics) } + /// Reviews in a temporary session without reading or changing the reusable reviewer. + /// The request builds its context without a previous session or cached snapshot. + pub async fn review_isolated( + &self, + request: &R, + ) -> (GuardianReviewSessionOutcome, GuardianReviewAnalyticsResult) + where + R: ReviewerRequest, + { + let context = request.context(/*previous*/ None); + Box::pin(self.review_ephemeral(request, context, /*snapshot*/ None)).await + } + async fn review_ephemeral( &self, request: &R, diff --git a/codex-rs/ext/guardian-reviewer/src/pool_tests.rs b/codex-rs/ext/guardian-reviewer/src/pool_tests.rs index 7c1c6305eb..9580b57b33 100644 --- a/codex-rs/ext/guardian-reviewer/src/pool_tests.rs +++ b/codex-rs/ext/guardian-reviewer/src/pool_tests.rs @@ -188,3 +188,38 @@ async fn fresh_attempt_bypasses_cached_session_and_snapshot(busy: bool) { .await; assert_eq!(selections.recv().await, Some(if busy { 0 } else { 1 })); } + +#[tokio::test] +async fn isolated_review_preserves_reusable_session() { + let spawns = Arc::new(AtomicUsize::default()); + let pool = ReviewerPool::new( + Arc::new(ReviewerTasks::default()), + move |_, _, _, snapshot, _| { + assert_eq!( + snapshot, None, + "isolated review must not inherit a snapshot" + ); + let id = spawns.fetch_add(/*val*/ 1, Ordering::SeqCst); + Box::pin(async move { Ok(Session(id)) }) + }, + ); + pool.prewarm(Arc::new(()), ()).await.expect("prewarm trunk"); + let (selected, mut selections) = tokio::sync::mpsc::unbounded_channel(); + + pool.review_isolated(&Request { + fresh: false, + selected: selected.clone(), + release: None, + }) + .await; + assert_eq!(selections.recv().await, Some(1)); + + pool.review(Request { + fresh: false, + selected, + release: None, + }) + .await; + assert_eq!(selections.recv().await, Some(0)); + pool.shutdown().await; +}