Transcript: a finished Claude turn folds per run, as Claude desktop does (Codex unchanged)

TE
5d ago
+492-50

Leo, 2026-11-01: "do we have the claude style tool call/interim chatter collapse restored yet the 7:11 nightly didnt' seem to have that nor the expanding tool calls doesn't push chats up yet"

Then, on how: "separate it per harness/model family. claude gets claude behaviour, codex gets codex".

Why Claude lost it. Replaying a real Claude Code turn through the pane's client and turnView showed the calls folding under Worked for but every interim note left outside it. #29802 turned the interim fold off for Claude chats (preserveAssistantText). Leo wants #29802 kept for Codex, so this keeps it and gives Claude its own behaviour.

What changes, keyed on the session family App.tsx already passes (snapshot.summary?.family):

  • Codex / ChatGPT: unchanged. The whole turn's work and chatter fold under one Worked for, and the final answer stays below it.
  • Claude, as Claude desktop draws it: no Worked for. Each run of calls folds into its own summary line ("Ran 5 commands, read 2 files"), along with the short notes inside that run, edit runs included. The line opens on a click anywhere on it (the existing run disclosure). A longer message between runs stays in place, and the final answer stays last.
  • Both: a steer and the reply before it are never folded (#29740), and for Claude that reply never joins a run. Interim text has no per-reply copy row (hasReplyActions is off app-wide; the footer copies the turn).

Tests

  • transcript-claude-turn-groups.test.ts replays one real Claude Code turn as acpmux recorded it (fixtures/claude-turn-groups.ndjson: 81 calls, 17 messages, every word and command replaced with neutral text of the same short or long kind). For Claude it checks: no Worked for, every run folded, no short note left between runs, the 3 long messages in place, the answer last. For Codex it checks that the same events still give one Worked for and the answer.
  • A steered turn for both families: for Claude, u, run(b1+note), r1, run(b3), s1, run(b4+note), answer, summary. For Codex, u, Worked for, r1, s1, answer, summary (today's output, pinned).
  • transcript-steer-continuous.test.tsx: the two #29802 Claude expectations move to the new behaviour, and the one-fold steer test runs as Codex.
  • Fleet run of the transcript and conversation suites at this tree: 1118 pass, 0 fail. tsc is clean apart from test/latency/probe.ts, which this PR doesn't touch. vp fmt and vp lint are clean.

Risk: transcript shaping only (turns.ts shapeTurn and mergeShortNotes), and every new branch is gated on the Claude family. No Swift, no persistence.

Agent session: agent session

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

A finished Claude chat turn now folds per run, as Claude desktop draws it, while Codex and ChatGPT keep today's behavior of folding the whole turn under one "Worked for".

Behavior

  • Claude turns no longer draw a "Worked for" card; each run of calls folds into its own summary line that opens on a click, with the short notes inside that run (edit runs included).
  • Longer messages stay in place between runs, and the final answer stays last.
  • Codex/ChatGPT turns are unchanged.
  • Both families keep a steer and its preceding reply in sight, and that reply never joins a run.

Tests

  • Adds transcript-claude-turn-groups.test.ts, which replays one real Claude Code turn (81 calls, 17 messages) and a steered turn for both families, checking the per-run fold for Claude and the single "Worked for" for Codex.
  • Updated the Claude expectations in transcript-steer-continuous.test.tsx to the new per-run behavior.
  • Updated browser tests to open a Claude turn's run line where they used to open "Worked for"; the history paging tests now use Codex-family chats to keep reading the "Worked for" label.