refactor: follow-up for salvaged PR #81692

- warn (not debug) on final text-turn flush failure: a failure here
  reopens the exact #81641 data-loss window with _persist_session as
  the only remaining retry, unlike the verify siblings which retry
  in-loop; include session id for triage
- trim the flush-site comment to sibling proportion, pointing to the
  test module for the full incident narrative
- test: assert _persist_session presence before indexing, so a wiring
  change fails with a clean assertion instead of ValueError from max()
This commit is contained in:
kshitij 2026-08-09 22:29:47 +05:30
parent 6c2c77efba
commit e4b2a90dad
2 changed files with 20 additions and 17 deletions

View File

@ -7613,25 +7613,23 @@ def run_conversation(
continue
messages.append(final_msg)
# Make the completed answer durable before leaving the loop.
# The text already reached the user through the streaming /
# interim display path, which is display-only and never writes
# to state.db; the next durable write would otherwise be
# finalize_turn's _persist_session, behind post-turn work that
# can include micro-compaction's aux-LLM call. A session torn
# down inside that window (ws_orphan_reap after a remote 1006
# close, container stop) lost a reply the user had already
# seen (#81641). Same contract the tool-call exit gets from
# #49045 and the verify-on-stop exits above; the
# _DB_PERSISTED_MARKER dedup keeps _persist_session idempotent.
#
# Unlike the tool-call exit, a failed flush must NOT abort the
# turn: no side effect runs after this point, the answer is
# already produced, and _persist_session retries the write.
# Make the completed answer durable before leaving the loop —
# a session torn down before finalize_turn's _persist_session
# otherwise loses a reply the user already saw (#81641). Same
# contract as the tool-call exit (#49045) and the verify exits
# above; _DB_PERSISTED_MARKER keeps _persist_session idempotent.
# Unlike the tool-call exit, failure must NOT abort the turn:
# no side effect follows and _persist_session retries the write.
# Full incident narrative: tests/run_agent/test_81641_*.py.
try:
agent._flush_messages_to_session_db(messages, conversation_history)
except Exception:
logger.debug("final text-turn flush failed", exc_info=True)
logger.warning(
"final text-turn flush failed (session=%s) — reply is "
"not yet durable; relying on finalize_turn retry",
getattr(agent, "session_id", None) or "none",
exc_info=True,
)
_turn_exit_reason = f"text_response(finish_reason={finish_reason})"
if not agent.quiet_mode:

View File

@ -138,9 +138,14 @@ class TestCompletedTextTurnIncrementalPersistence:
f"transcript tail; observed events: {events!r}"
)
final_persist = max(
persist_indices = [
i for i, (kind, _) in enumerate(events) if kind == "persist_session"
]
assert persist_indices, (
"finalize_turn must call _persist_session after the loop exits; "
f"observed events: {events!r}"
)
final_persist = persist_indices[-1]
assert answer_flushes[0] < final_persist, (
"The assistant row must be durable BEFORE post-loop finalization, "
f"but the answer flush at index {answer_flushes[0]} did not precede "