Timothy July 10, 2026 ~3 min read

Timothy Part 7: Sessions That Survive, Resumable UI and Replay

Once the server had a durable event log and UITranscript projection, several questions had to be answered for reliable resume and search:

  • How does paging through sessions avoid lost or duplicate rows on ties?
  • How does a resumed session see the same transcript shape (including compactions and partials) as the original stream?
  • How do in-flight streams acquire a permanent ID without loss?
  • How are compaction points and interrupted turns represented in the durable view?

The server projection is the source

Why fetch a UITranscript projection instead of re-streaming the raw event log?

The single source of truth is the event log. Replicating the projection logic outside the backend creates divergence after compactions or restarts. The projection produces the same transcript shape used for live streaming (compaction dividers and interrupted turns included). All compaction and interruption semantics stay in the backend.

Composite cursor for paging

Why a composite (updated_at, id) cursor instead of a simple timestamp?

The list endpoint returns pages ordered by (updated_at, id) DESC. Simple timestamps lose or duplicate rows on ties. The API requires both halves of the cursor; callers (including any client) must echo the exact pair received. The rule is enforced at the API.

Resume from projection, not re-stream

Why return the projected transcript rather than re-streaming the raw events?

Re-streaming would force the consumer to re-simulate compactions and partials. The transcript endpoint returns the authoritative UITranscript projection (mapped to the same shape live streams use). The session route is stable, so an in-flight stream can adopt its permanent ID. Compaction boundaries and interrupted turns are first-class in the projection.

Mid-stream session adoption

When a chat begins, the brain creates the session row and emits the ID in the first meta event and the X-Session-Id header (before any body bytes). The same address works for resume. An in-flight stream adopts its permanent ID without loss; error bodies carry the id when a session was created. Guards prevent a resume from clobbering a live stream.

Last category as session state

The category chosen for a turn is stored on the session row and restored on resume. It is updated atomically with the turn.

Honest rendering of compaction and interruption

Compaction boundaries and interrupted turns are first-class in the projected transcript (a divider for compactions, an interrupted item for pending partials). The consumer sees the same boundaries the model did.

Tradeoffs accepted

  • More code in the two projection functions.
  • Consumers must understand the event kinds and compaction/pending rules.
  • Replay IDs are synthetic (replay- prefix).

In return: single source of truth, faithful resume from the projection, no duplication of compaction or interruption logic, and the ability to evolve the backend projection independently.

Invariants the transcript contract preserves

  • The model context is derived only from the LLM projection, never from UI state.
  • Streams are read to the terminal meta (or the error body carrying session_id).
  • The composite cursor is propagated exactly for paging.
  • Resume uses the server’s transcript projection.

These keep sessions continuous and trustworthy after restarts and long histories.

Next: letting the model act, a tool registry, a permission chain, and skills that load only when needed.


The backend projection contract is in internal/brain/session/projection.go. Consumers map the UITranscript.*

// end of article — process exited with code 0

// share:Twitter / XLinkedIn

// comments

loading...