cmux NEXT: persist Chief reports and show agent messages in Channels
Chief's messages to agents and their reports stay visible in the Channels conversation when the run card is folded. Tell rows retain the full stored input, and received reports are persisted as completed report records anchored to the assignment question, including after the original run ends or is pruned. Completed turns that post no reply keep their message rows beside the question.
Leo's request:
"I'm still using you right now instead of Chief because the interface of this current thing I feel, like, allows me to do a bit more, especially with, like, the communicating back and forth. I don't know how that, like, messaging back and forth works in Chief. Is it? It's even visible? If we want it to be visible. Because, I don't know, I feel like they hide a lot of tool codes, but I need to, like, see the messages coming in back and forth at the very least."
This is the first of two changes: it persists inbound reports for both Home clients and renders agent messages in Channels. The follow-up adds these same rows to default native Home; this PR does not change which Home view opens.
The existing run card and run sheet remain available. The message rows reuse the transcript components and localized labels, following Claude's transcript-peer-session-message reference: a quiet sender/recipient row that expands its message inline. Only synthetic fleet captures are included here. Refused tells show the existing not-delivered label and reason. A follow-up assignment routes its report to that assignment’s conversation and question. Its dedicated completed record never changes the original turn’s status. Run history pages back to loaded questions so older silent turns survive reload and scrolling. Reports use stable step IDs to avoid duplicate rows; long reports are split on UTF-8 boundaries to preserve their text within the owner's existing step limit.
Local history paging retains every timestamp boundary tie. Cloud rows returned by the endpoint are rendered, but more than 100 runs sharing one timestamp cannot all be paged until the backend supports a composite (timestamp, id) cursor. This is an existing endpoint limitation; the local owner is corrected here. Historical step reads are serialized and limited to loaded transcript anchors, cached by run revision, and cancelled on conversation/lifecycle changes. New summaries refresh changed steps even at unchanged counts; Cloud summaries without freshness clocks refresh at a history lookup. A failed unversioned read can retry at the next history refresh without card-load retry loops. Pagination continues until loaded reply keys resolve, even when a run began before the oldest visible message.
Related issue audit: #25570 covers broader history/reconnect behavior; this change is limited to persisted run messages and does not close that broader issue.
Risk: report routing crosses turn completion and restored run history. Regression coverage includes long tells, refused sends, folded and restored runs, silent completed turns beyond the first history page, cross-conversation follow-up assignments, and report generation IDs. The native client is split into its own PR. This change stays together because the persisted report format, Channels consumer, and regression cases exercise one message-delivery path; the added regression coverage takes it above the approximate 800-line target.
Validation at integrated head 0fc0f4f86410e7c3293f6e6cd333834dee84b5d9: independent Astra review passed; 33 focused web tests plus full web checks, Chief Rust checks, and fast gates passed. The strict fresh-home launch passed on the exact build: Home tab visible, first frame at 4576.1 ms, 30.2 seconds alive, zero crash reports or exceptions. The Chief area's teammate owner was requested for review and notified. Localization reuses existing translated labels.
Named base comparisons: SDK test_ir fails on new-pane-right on base too (fixed by #27505; rerun fast gates pass). The SwiftUI check reports the same two ChatColors files with identical errors on head and base, with byte-identical macOS sources, checker, and allowlist; it hides no subsequent check. SigningHooksInStepWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check reproduces the same failure in base run 40937170212. None is introduced by this change.
Performance
A per-card cache classifies only new or revised steps; unchanged message rows also retain their render result. The cache drops removed steps, resets on run identity changes, and disappears when the card unmounts. Revision-zero Cloud replacements remain refreshable. No timer or observer is added.
| Metric | Before | After | Delta | Harness or run link |
|---|---|---|---|---|
| Classification, 30 appends over 300 × 35,000-character historical inputs | 641.15 ms | 0.93 ms | −640.22 ms (−99.9%) | Same-process fleet harness, home-run-message-cache.test.ts |
The first pass is excluded from both measurements. A deterministic serialization counter checks that appending a step never reparses older input. The final revision also checks that a folded card does not rebuild previews for a large historical tell and report. Integrated head 0fc0f4f86410 passed 33 focused tests plus the full web checks in the linked run. Exact-head validation and fresh-home receipts are linked above.
Before and after
Real fleet app captures with the same synthetic conversation; Channels is enabled only in the capture settings. Before (ff9b0d38, baseline plus gallery-only fixture code), the tell and report records have no visible message rows. After (0fc0f4f86410), both message bodies are visible while their separate run cards remain folded. Every after-capture selector assertion passed, including both directions and both open bodies under folded cards. All images passed the capture privacy checks.
| Before | After |
|---|---|
![]() | ![]() |
![]() | ![]() |
Changelog
Fixed: Chief's messages to agents and incoming reports remain visible in Channels when a run is folded.
Agent session: agent session



