From 5b8e3c6d4017ea24087a8755017b3a7ecf495f07 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 12 Jun 2026 08:58:08 -0700 Subject: [PATCH] Reject transcript backtrack in side conversations (#27791) ## Why Fixes #27735. Side conversations are ephemeral forks, and thread rollback currently requires persisted thread history. The normal backtrack path already rejected editing previous prompts in side conversations, but transcript-mode backtrack could still call the rollback path and surface the core `thread/rollback` failure as a TUI error. ## What changed - Moved the existing side-conversation edit rejection message into `app_backtrack.rs` so backtrack rollback code can reuse it. - Added a side-conversation guard in `apply_backtrack_rollback` so transcript-mode confirmation is rejected before submitting `thread/rollback`. ## Verification - `just test -p codex-tui app::tests::side_backtrack_rejection_reports_unavailable_message_snapshot` --- codex-rs/tui/src/app/input.rs | 4 +--- codex-rs/tui/src/app_backtrack.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/codex-rs/tui/src/app/input.rs b/codex-rs/tui/src/app/input.rs index f6530cad2..5d891c128 100644 --- a/codex-rs/tui/src/app/input.rs +++ b/codex-rs/tui/src/app/input.rs @@ -4,9 +4,7 @@ //! entry, Ctrl-L clear, external editor launch, and agent navigation shortcuts. use super::*; - -const SIDE_EDIT_PREVIOUS_UNAVAILABLE_MESSAGE: &str = - "Editing previous prompts is unavailable in side conversations."; +use crate::app_backtrack::SIDE_EDIT_PREVIOUS_UNAVAILABLE_MESSAGE; impl App { pub(super) async fn launch_external_editor(&mut self, tui: &mut tui::Tui) { diff --git a/codex-rs/tui/src/app_backtrack.rs b/codex-rs/tui/src/app_backtrack.rs index c44047d00..b03d4fdba 100644 --- a/codex-rs/tui/src/app_backtrack.rs +++ b/codex-rs/tui/src/app_backtrack.rs @@ -47,6 +47,8 @@ use crossterm::event::KeyEvent; use crossterm::event::KeyEventKind; const NO_PREVIOUS_MESSAGE_TO_EDIT: &str = "No previous message to edit."; +pub(crate) const SIDE_EDIT_PREVIOUS_UNAVAILABLE_MESSAGE: &str = + "Editing previous prompts is unavailable in side conversations."; /// Aggregates all backtrack-related state used by the App. #[derive(Default)] @@ -191,6 +193,13 @@ impl App { /// The composer prefill is applied immediately as a UX convenience; it does not imply that /// core has accepted the rollback. pub(crate) fn apply_backtrack_rollback(&mut self, selection: BacktrackSelection) { + if self.chat_widget.side_conversation_active() { + self.reset_backtrack_state(); + self.chat_widget + .add_error_message(SIDE_EDIT_PREVIOUS_UNAVAILABLE_MESSAGE.to_string()); + return; + } + let user_total = user_count(&self.transcript_cells); if user_total == 0 { return;