Agent chat: fold consecutive received messages
Consecutive agent messages now share one quiet fold in the transcript. A burst of two or more received messages is represented by the existing waiting-message disclosure; opening it restores each message's shared row, sender identity, Reply actions and Find target. Single messages and non-message rows keep their existing presentation.
Leo asked on Chief/coordinator chats:
"I need to, like, see the messages coming in back and forth at the very least."
The open nx-chat message-row work is #26373/#25683, with #26424 as its stacked shared presentation integration. This PR takes the remaining consecutive-message fold gap and does not modify those branches or their files. It reuses WaitingMessagesCard and the existing IncomingMessageLine renderer, so there is one row implementation. The fold is only for consecutive received agent messages; an ordinary transcript row ends it. Waiting steers retain their separate step batching. The turn builder folds only the suffix it already rebuilds, reusing its existing history copy and boundary checkpoints; there is no separate whole-transcript grouping pass. The existing queue/step folds remain unchanged.
Gallery: agent-pane.agent-message-row/folded-run, agent-pane.agent-message-row/folded-run-mixed, agent-pane.agent-message-row/folded-run-opened
Gallery variants in agent-pane.agent-message-row:
folded-run: four messages from claude-sr2 collapsed to one quiet count.folded-run-mixed: a burst from two senders, retaining both names in the disclosure head.folded-run-opened: the same burst opened, with every received row visible.
Before and after: the gallery advisory renders the literal merge-base and head at the exact PR SHA and publishes the PNG stills in its artifact. The selected states are listed above; no synthetic or private screenshots are used.
Validation:
python3 scripts/cmux-next/prepush-gate.py --base origin/feat-cmux-next --head HEADpasses with no new violations.git diff --checkpasses.- Node 24
bash scripts/web-lint.shpasses. Focused Bun tests cover singleton rows, reusable folds, interruption boundaries, frozen inputs, changed messages, streaming visit counts, earlier edits, turn-boundary reuse, waiting queues, Find, background calls and long-chat layout. Readonly arrays propagate through transcript, layout and minimap inputs; cached folds are explicitly checked before reuse.
Follow-up: hb-acpmux will journal an explicit _acpmux/message event in both directions with {sessionId, sender, text, at, messageId, reportTo?}. The fold is detection-agnostic so it can consume that event when available.
Risk: normal transcript rows and queue/step batching are unchanged; the new chat fold only wraps adjacent received agent rows and preserves their original objects inside the disclosure.
Performance
| Metric | Before | After | Delta | Harness |
|---|---|---|---|---|
| Fold input visits over 100 fresh streaming tails, 3,000 history rows | 300,300 | 300 | -300,000 (-99.9%) | waitingMessages.test.ts, same turn fixture replayed against ca0eb90 and this head |
The count isolates folding work; it does not claim that existing turn shaping or layout is constant-time. No new timers, observers or animation loops. Fold caches use weak row keys and are released with discarded rows.
Fixed: consecutive agent-to-agent messages are visible as compact rows without making a chat read like a wall of cards.
Agent session: agent session