# Wall-E Transcript Display Projection

Wall-E keeps the raw provider transcript as the durable source of truth. CTM
does not rewrite historical JSONL just because a provider emitted markdown
structure or text-form tool-control markup. The session UI and review UI render a
display projection of that transcript instead.

## Projection Rules

- Visible assistant text is normalized before history leaves
  `lib/walle-ctm-history.js`.
- Text-form DSML/tool-control blocks are removed from visible content. Structured
  `toolCalls` remain available and render as activity groups.
- Markdown thematic-break-only lines such as `---`, `***`, and `___` are removed
  from Wall-E display content outside fenced code blocks. Wall-E coding sessions
  use headings and activity groups for structure; visible horizontal rails have
  repeatedly looked like stuck output.
- The browser renderer still removes any `<hr>` and raw control markup it sees.
  That is defense in depth for live responses and old cached payloads, not the
  primary source of correctness.

## Turn Boundaries

Transcript replay accumulates skill/tool events until an assistant response can
own them. A terminal event (`cancelled`, `error`, `runtime_error`, `aborted`) or
a new user prompt closes the pending activity bucket. This prevents cancelled
skill/tool progress from leaking into the next assistant message during replay.

## Why This Shape

OpenCode-style agent transcripts separate typed parts from visible markdown:
tool calls are stateful records, while assistant text is user-facing prose. Wall-E
uses the same boundary in CTM:

- Raw JSONL remains auditable.
- History/review payloads expose normalized display text.
- Tool execution history is carried by `toolCalls`, not by raw DSML embedded in
  the assistant text.

When adding a new Wall-E transcript source, route assistant text through
`normalizeWalleDisplayContent()` before exposing it to session or review
surfaces, and preserve structured activity separately.
