From 1bbbad1bca123dbe02c6aee7e7cdef2a5706f788 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jun 2026 21:25:59 -0400 Subject: [PATCH] Block nested review after replay --- codex-rs/tui/src/chatwidget/slash_dispatch.rs | 3 ++- .../tui/src/chatwidget/tests/mcp_startup.rs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/codex-rs/tui/src/chatwidget/slash_dispatch.rs b/codex-rs/tui/src/chatwidget/slash_dispatch.rs index b75eea6196..f4ba8c953b 100644 --- a/codex-rs/tui/src/chatwidget/slash_dispatch.rs +++ b/codex-rs/tui/src/chatwidget/slash_dispatch.rs @@ -141,7 +141,8 @@ impl ChatWidget { fn slash_command_blocked_by_active_task(&self, cmd: SlashCommand) -> bool { let foreground_work_active = self.bottom_pane.is_foreground_task_running() || (cmd == SlashCommand::Review - && (self.input_queue.user_turn_pending_start + && (self.review.is_review_mode + || self.input_queue.user_turn_pending_start || self.has_queued_follow_up_messages())); let blocked_by_task = if foreground_work_active { !cmd.available_during_task() diff --git a/codex-rs/tui/src/chatwidget/tests/mcp_startup.rs b/codex-rs/tui/src/chatwidget/tests/mcp_startup.rs index 1f42fb9088..f0d484a59c 100644 --- a/codex-rs/tui/src/chatwidget/tests/mcp_startup.rs +++ b/codex-rs/tui/src/chatwidget/tests/mcp_startup.rs @@ -256,6 +256,23 @@ async fn replayed_active_review_keeps_mcp_startup_in_background() { assert!(chat.mcp_startup_status.is_some()); } +#[tokio::test] +async fn replayed_active_review_blocks_nested_review_during_mcp_startup() { + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.set_mcp_startup_expected_servers(["alpha".to_string()]); + replay_entered_review_mode(&mut chat, "current changes"); + notify_mcp_status(&mut chat, "alpha", McpServerStartupState::Starting); + + assert!(chat.review.is_review_mode); + assert!(!chat.bottom_pane.is_foreground_task_running()); + assert_bare_review_rejected( + &mut chat, + &mut rx, + "'/review' is disabled while a task is in progress.", + ); + assert!(op_rx.try_recv().is_err()); +} + #[tokio::test] async fn completed_replayed_review_does_not_hide_fresh_mcp_round() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;