Project 000, 19:21/20:27: the engine recorded its assistant reply in
session_messages, but the post-turn transcript sync never surfaced it in the
ui_state channel, and nothing reconciled afterwards — the user watched an
empty conversation while the reply sat in the DB. And at 19:13 the same reply
was persisted twice in one channel under `<id>` and `<id>::<project>::<channel>`.
Two fixes:
- _ensure_reply_projected: after the transcript sync, if the session's newest
persisted top_level_reply row is absent from the chat store (checked by
transcript message id, so nothing user-visible is ever duplicated or leaked),
insert and broadcast it directly. Reproduced by test: with the sync disabled
the reply previously never reached the channel.
- backfill_messages: a live insert racing the backfill snapshot now merges into
the existing same-scope row (new _merge_into_same_scope_row, also used by the
IntegrityError fallback) instead of minting a `::`-scoped alias id in the
message's own channel.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>