fix(chat): identify message senders by session, not machine

TE
1d ago
+640-23

A received message can currently show a machine as its sender, and body signatures can override the recorded session name. Resolve the session name, harness, machine and known parent relationship from session metadata. A peer-qualified review-box/design-check reads as design-check, with the machine secondary. The same resolver drives web session cards and an explicit sender designation inside minimap previews; existing ticks and scrolling stay intact. Received-message disclosures use the same resolver for the visible name, family relation, Open chat tooltip, accessibility label, and reply editor. The current per-message folding and Open chat action are preserved.

Leo, 2026-10-27: “Is this Claude from another session? Is this Codex from another session? Is this your own sub-agents?”

A sender-name match can resolve its existing chat link, but does not establish parentage: a child relationship requires an explicit sender session ID or recorded family role. Qualified short names and blank name candidates are normalized through the same peer-aware path.

A reviewer role is not guessed from “review” in a name or message. The current producer reports harness and parentage, but no authenticated review-purpose field; that role remains unknown until it supplies one.

Gallery: agent-pane.sender-identity compares inline identity (chosen), a separate identity line, and the plain preview. The chosen label stays within the existing capped title; no new rail marks or scroll compensation. The gallery variants remain below. Fresh Chromium captures of the actual received-message disclosure use matched fictional data and identical 900 × 700 viewports in light and dark.

Reference: Claude received-message attribution, with session identity primary and machine context secondary. Claude Code agent teams distinguishes in-session subagents from independent teammates. OpenAI Subagents exposes separate threads/activity and summaries in the main chat. These inform the distinction; the inline card designation is our design choice.

Observed / Not run

Independent whole-diff Astra review: SHIP at 3b986b95f723925d5ed0ef81e99f583596991e4c. The coordinator also reviewed the full source diff and all four fresh captures.

At 3b986b95f723925d5ed0ef81e99f583596991e4c, focused fleet verification passed 78 unit tests, seven Chromium disclosure tests, and full bun run check (3,040 files). The runner's validated tree 61d379e21652c2cba175b50e9071c0fda2dd889f exactly matches the committed tree. The scoped pre-push gate passed against merged base 4e5b6675d6ac1ffd6fbfb7a18b4b12c38a2df337.

Red/green command: CMUX_BROWSER_TESTS=1 bun test test/incoming-message-disclosure-browser.test.ts --test-name-pattern 'qualified sender identity'. Both light/dark cases fail on literal base 4e5b6675d6ac1ffd6fbfb7a18b4b12c38a2df337 (raw qualified sender, no canonical sender label) and pass on the head. The test fixture is copied to base for the comparison. Unit suites run in separate processes to isolate the dock test's localization globals. Native builds were not run; this change touches web surfaces only.

Current-base compatibility: preserves the per-message disclosure, independent expansion, full message content, and separate Open chat action introduced by #27312. No deleted message batch is restored. Risk is limited to sender display and metadata lookup; no defaults, rail geometry, or scrolling semantics change.

Current disclosure before and after

Synthetic sender and message text only. Both themes use the same production theme payload path as the gallery.

ThemeBase 4e5b6675d6acHead 3b986b95f723
LightBefore, lightAfter, light
DarkBefore, darkAfter, dark

Original preview before and after

The base is 22ca012dc4b346250cbffe3fa8bd75a2c00feef0. Both arms render the production PreviewCard with the same prompt, reply and sender metadata; base does not yet expose that sender. A capture-only fixture was added to the detached base worktree. No private chat screenshots were published.

ThemeBeforeAfter
DarkBefore, darkAfter, dark
LightBefore, lightAfter, light
Inline identity (chosen)Separate identity linePlain preview
InlineSeparate linePlain

Changelog

Fixed: Agent-message labels show the session name and known harness, with the machine secondary.

Agent session: agent session