The runtime has several views of the same conversation. The screen shows messages. The transcript persists records. The API view is projected for the next provider call. Resume code rebuilds session state. Those views overlap, but they are not interchangeable.

transcript rows
  -> loadConversationForResume(sessionId)
  -> clean incomplete tail / tool_use pairs
  -> run SessionStart resume hooks
  -> processResumedConversation()
  -> restore AppState, session pointer, worktree, agent, replacement state
Source shape: resume reads durable evidence, then reinstalls the runtime state that can affect the next model request and tool call.

1. UI messages are optimized for the current turn

Stream events update what the user sees: assistant text, tool progress, compact boundaries, status, and tombstones. This path is interactive. It is allowed to care about rendering and responsiveness.

Context ledger with UI messages, transcript, model view, and compact state
The same session facts appear in different ledgers for different readers.

2. Transcript records durable evidence

The transcript path writes durable rows that can be inspected or loaded later. That does not mean every UI detail becomes future prompt content. Transcript is an audit and recovery surface; model-visible context is a request projection.

durable row
  -> validated conversation item
  -> incomplete tail removed
  -> unmatched tool_use / tool_result pair removed
  -> recovered runtime state
  -> next API view can be projected coherently
Before/after shape: resume cleanup is not for making the old UI prettier; it prevents the next provider request from inheriting a broken tool-call boundary.

3. Resume loads more than messages

loadConversationForResume() pulls together messages, file history snapshots, content replacement information, compact-collapse state, and session metadata. The loader is preparing a runtime, not just rebuilding a transcript display.

Survival map showing what survives in UI, transcript, compact summary, and resume state
Resume depends on the state that survived in the right store, not on memory of the previous terminal screen.

4. Session restore reattaches behavior

processResumedConversation() reconstructs session-level facts such as cost state, worktree information, content replacement state, and collapse snapshots. That work is what lets a later query() call continue with coherent permissions, files, and context projection.

5. Compact and resume are linked

Once compact has introduced a boundary, resume must preserve enough metadata to keep that boundary meaningful. Otherwise an old session could load with an attractive transcript but a broken model-visible route back into earlier work.

Compact boundary feeding resume loader and future model-visible context
Resume has to remember how old context was reshaped, not merely that it existed.

6. The invariant

Resume is state reconstruction. The transcript gives evidence, but the recovered session also needs content replacement, compact metadata, files, cost state, and configuration. If a feature writes only to the screen, resume cannot depend on it later.

That reconstruction has a performance consequence. A resumed session is a fresh runtime starting point, so the next provider request depends on which prefix material was reloaded, which large results stayed replaced, and which fork-only suffixes were kept out of the mainline. The prompt-cache chapter reads the same boundary from the cost side.

Sources

The source-code claims in this article are based on the public mirror and the linked official documentation. Server-side behavior and private feature-gate policy are treated only as client-visible request shape.