Skip to content

chore(chat): backfill assistant turns into sessions damaged before #13214 #13293

Open

Description

@mrveiss

Context

#13214 (PR #13291) fixes the code path: streamed assistant replies are now persisted to the GUI-facing store. It does not repair sessions damaged before the fix.

This carries forward item 4 of #13214, which would otherwise be lost when that issue closes.

Scope

Every conversation held before the fix landed reads back as a monologue of user turns in the GUI. The replies are not lost — the workflow store still holds them:

  • damaged store: chat:session:<id> (chat_history/session.py:84) — user turns only
  • intact store: chat:conversation:<id> (chat_workflow/conversation.py:33) — {user, assistant} pairs per turn

Suggested work

A one-shot repair that, for each affected session, walks the chat:conversation:* turns and inserts the missing assistant turns into the chat-history session in order, matched to their user turn.

Requirements:

  • idempotent — re-running must not duplicate turns (dedupe on sender + normalized text, matching _get_message_signature in api/chat.py:201)
  • never drops or rewrites existing entries (no data loss on repair)
  • writes through add_messages_batch / save_session, not raw Redis
  • dry-run mode reporting counts before writing

Note the two stores use different message shapes (text/messageType from _build_message_dict vs content/type from _to_persisted_message); the repair must emit the shape the session store already uses.

Acceptance: a session known to be damaged reads back with its assistant turns after the repair, and a second run is a no-op.

Related

Activity

  1. mrveiss commented on Aug 3, 2026

    @mrveiss
    OwnerAuthor

    Ordering note from PR #13334 (merged as 53d455ea6), so a repaired turn is never later misread as evidence that fix regressed.

    #13295 changed freshly-persisted turns to interleave per-iteration: user, assistant(prose1), system(tool output), assistant(prose2).

    A backfilled turn cannot match that shape. compute_backfilled_messages only fires when a turn window has zero assistant entries, and its source (chat:conversation:* pairs, or the durable transcript file) carries one combined assistant string per exchange with no per-iteration breakdown to interleave. So a repaired turn reads user, system(tool output), assistant(combined) — the pre-#13295 shape.

    The insertion point (turn_end) is unaffected and needs no change; review confirmed this independently. The inconsistency is unavoidable given the source data, and is recorded here rather than left silent.

    This issue still cannot close: the module has never been run against real damaged sessions with before/after evidence, which is the operator step.

  2. modified the milestones: Backlog, v0.14.0 on Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: chat-tenancyWave 3 · cluster F — Chat tenancy & session ownershipbackendbugSomething isn't workingfrontend

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions