From 95cc3f7eb2378fa134c68dc86a2cac0b66d60978 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 17 Jul 2026 05:36:25 -0700 Subject: [PATCH] fix(tui): heal alternation at the remaining live-replay resume sites Sibling-site audit on top of #65672: the interactive TUI resume, the profile-scoped resume, and the /undo history reload also feed LIVE REPLAY (raw_history -> sanitize_replay_history -> working conversation; session['history'] after rewind). Pass repair_alternation=True on the model-fed copies; display_history stays verbatim so inspection/export show what is actually stored. Display-only consumers (session.history RPC, formatted transcript output) intentionally unchanged. --- tui_gateway/server.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tui_gateway/server.py b/tui_gateway/server.py index f83b4486b5fd..a70ead871a6b 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -6069,7 +6069,11 @@ def _(rid, params: dict) -> dict: _enable_gateway_prompts() try: db.reopen_session(target) - raw_history = db.get_messages_as_conversation(target) + # repair_alternation on the model-fed copy only: this resume feeds + # LIVE REPLAY (raw_history → sanitize_replay_history → the resumed + # session's working conversation). display_history stays verbatim — + # inspection/export must show what is actually stored. + raw_history = db.get_messages_as_conversation(target, repair_alternation=True) display_history = db.get_messages_as_conversation(target, include_ancestors=True) except Exception as e: if lease is not None: @@ -6143,7 +6147,9 @@ def _(rid, params: dict) -> dict: ) try: db.reopen_session(target) - raw_history = db.get_messages_as_conversation(target) + # repair_alternation on the model-fed copy only (see the interactive + # resume above): this loads LIVE REPLAY history; display stays verbatim. + raw_history = db.get_messages_as_conversation(target, repair_alternation=True) display_history = db.get_messages_as_conversation( target, include_ancestors=True ) @@ -12715,8 +12721,12 @@ def _(rid, params: dict) -> dict: return _err(rid, 5008, f"undo: {e}") # Reload the active-only transcript into the in-memory session # history so subsequent turns see the truncated view. + # repair_alternation: this reload feeds LIVE REPLAY — session["history"] + # is the working conversation for subsequent turns, and a rewind that + # lands on a durable user;user pair would otherwise re-fire the + # pre-request repair on every request from here on. try: - active = db.get_messages_as_conversation(session_key) + active = db.get_messages_as_conversation(session_key, repair_alternation=True) except Exception: active = [] with session["history_lock"]: