Skip to content

feat(native-chat): show which agent a chat message is from, and open it - #25888

Merged
brennanb2025 merged 9 commits into
mainfrom
brennanb2025/agent-message-sender
Oct 6, 2026
Merged

brennanb2025 merged 9 commits into
mainfrom
brennanb2025/agent-message-sender

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 37 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1430 $\color{#cf222e}{\Huge{\mathbf{−}}}$​124 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1306
Prod 57 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1084 $\color{#cf222e}{\Huge{\mathbf{−}}}$​242 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​842

ELI5

When another agent sends a message into your native chat (today: the "You have N orchestration messages" notice), the chat showed it as if you had typed it. Now it says which agent sent it, and clicking the agent's name takes you to that agent.

The problem

Since #25078, Orca delivers an agent's orchestration notice to a native chat through the chat's own send and queue. In the chat, that notice looked exactly like your own message: a right-hand bubble, and, while the agent was busy, a queued card identical to yours. You couldn't tell that an agent wrote it, or which one.

The cause was where the sender was recorded. #25078 stored it only on the queued card's database row. So:

  • a notice sent while the chat was idle never queued, and recorded no sender at all;
  • when a queued card was sent, the sent message didn't keep the sender; the card row, and its sender, was deleted about a day later;
  • the sender never reached any screen: it wasn't on the message, the transcript, or the card the app draws.

What changes for you

Before After
An agent's message in the conversation A right-hand bubble, like yours A left-aligned row, "Message from name", with the message under it
Its card while the chat is busy Looks like your queued card The same card, with a small "From name" line
Clicking the sender's name (no name shown) Opens that agent's chat or terminal, switching worktree if needed. A worker running on another computer is named but not clickable yet
The sender no longer exists (no name shown) The name stays readable; clicking shows Orca's existing "no longer available" message for that chat or pane
The mobile app A right-hand bubble, like yours "Message from name" above the bubble, and "From name" on the card (not clickable yet)
Rewind on an agent's message Offered, and put the agent's text in your message box Not offered on an agent's message; your own messages are unchanged
Your own messages Unchanged

The name is what Orca showed for the sender when it wrote: the task it is working on (or just reported done), else its tab's name, else the agent's name (for example "Codex"). A notice that covers mail from several agents names each of them; two different agents with the same name stay two.

How it works

The sender now lives on the message itself. A chat message gained one optional field, from: the senders (each with its Orca session ID or terminal handle and a name snapshot) and the orchestration record it points at (mailbox, dispatch, run and message ids). It is written once, by the host, when the agent's message is sent, on both the idle path and the queued path. The message carries it into the queued card, the sent message, the transcript, every client and /clear. Every display reads it from there. Nothing keeps a second copy: the queued-card column #25078 added (source_json) is removed. It never shipped in a release.

  • Only the host can set it. A client's send (desktop, paired client, mobile) is checked by a strict schema, and a body that carries from is refused. A test covers this.
  • The agent never sees it. The providers receive only the message text and images, as before.
  • It doesn't change message identity. Orca matches a sent message to the agent's echo of it, and recognises retries, by a fingerprint of the message. One shared function builds that fingerprint without from, at every place one is computed. A message without from fingerprints exactly as before; a test pins the value.
  • The queue still treats every card the same. The queue code reads nothing about senders; it carries the message body as written.
  • Held cards after a quit or crash (fix(native-chat): keep a message accepted before a quit or crash as a held card #24660) are unchanged. That feature records whether each send was the person's; it now reads that from the same place (a person's send, or a message with from is an agent's), and a card no longer stores a separate copy of who wrote it.
  • Clicking asks the computer running the chat where the sender is now (orchestration.partyLocation). A chat that was /cleared has a new session; the host follows that. A terminal has a new handle after an Orca restart; the host finds it from the pane the mail was sent from, which never leaves the host. The app then opens the chat with its existing open-chat flow, or focuses the terminal with the existing terminal-link path, and reuses their existing messages when something can't be opened.

Why this approach

The alternative was to show the sender from the queued card's row. That fails for any notice sent to an idle chat, and for every message once it's sent. Recording the sender on the message is the only place it survives, and it matches the common pattern: the sender's identity is stored on the message record, and the screen derives the label from it.

Differences from the common pattern

  • The common pattern derives the sender's label from a live list of threads. This PR also stores a name snapshot with the sender. Intended: Orca's senders are often short-lived workers. Once one is gone there is no live name left to show, and without the snapshot every row would read just "an agent".
  • The common pattern's link opens the sender's page even when it is gone, and the page then says so. Here the click asks the host, and when the sender is gone it shows Orca's existing "no longer available" message instead. Intended: Orca has no page for a missing chat to land on.
  • On mobile the name is not clickable yet. Temporary: the follow-up adds mobile navigation.
  • A worker running on another computer through orchestration (its mail arrives as dispatch:<id>) is named by its task but is not clickable. Temporary: this host doesn't track where that worker runs, and saying it is gone would be wrong; the follow-up opens it on its own computer.
  • On a paired computer with no desktop window open, a chat sender is named by its agent ("Codex Chat"), not by a tab name you gave it there. Temporary: that host keeps no tab names; follow-up.
  • The agent's message isn't prefixed with the sender's name in what the model sees. Intended: this matches one of the two common designs, and the notice already tells the agent to run check, which names each sender.

Compatibility

  • Older desktop, paired or mobile clients ignore the new field and show the message as they do today: a right-hand bubble.
  • A newer client on an older host sees no from and shows the same.
  • orchestration.partyLocation is a new method. On a host that predates it, clicking shows Orca's existing "needs a newer Orca on the computer running this chat" message.
  • A message kind this build doesn't know (the coming dispatch task, for example) still reads as from its agent; only its orchestration details read as unknown.
  • Downgrading. If you downgrade to v1.4.221 while an agent's card is waiting, and then /clear, that one message can show twice. The older build fingerprints the whole message, including from. Intended: this only happens on a downgrade, and only for cards already waiting.

What you might notice

  • The message rail outline and the sidebar's "latest request" quote still count an agent's notice as your request. Temporary: that is a follow-up.
  • Editing an agent's queued card moves its text into your message box as your own, as it did before. Unchanged.
  • Messages rebuilt from the agent's own history (an imported conversation, for example) have no sender recorded, so they show as before.
  • An agent's message has no "Rewind to here". Rewinding to it would put the agent's text in your message box as yours; rewind from your own message instead.
  • The sender's name is what its tab showed. A terminal's tab name can also be set with orca terminal rename, including by an agent.

Linked Issue

N/A: maintainer change, no issue.

Visual Proof

Live run on macOS (an M4 MacBook Air): real orchestration mail from two plain terminal agents into a live native Codex chat. The chat's model was a stand-in, because the isolated test profile has no account. Before = main; after = this branch.

Before After
Agent's message in the conversation before row dark: after row dark light: after row light
Its queued card while the chat is busy before card dark: after card dark light: after card light

Clicking a name opens that agent's terminal, switching worktree when it's in another one: same worktree, other worktree. Sender closed: one "no longer available" message. Rewind is offered only on your own messages: agent's row, your row.

Testing

Live run (macOS), at the last commit before the final merge from main. That merge only brought in main's reasoning-row change.

Case Result
Mail to an idle chat: a "Message from name" row; your own messages stay right-hand bubbles Pass
Mail while the chat is busy: the card shows "From name", not clickable; Steer, Edit and Delete work Pass
Clicking the name opens the sender's terminal, in another worktree too Pass
Sender's terminal closed: the name stays; one click gives one "no longer available" message Pass
Rewind offered only on your own messages Pass
Light and dark themes Pass

Not run live:

  • a real model provider;
  • a chat (rather than a terminal) as the sender;
  • a worker on another computer;
  • mobile;
  • a paired or SSH host;
  • behaviour after a restart, and /clear.

Those paths are covered by the tests below.

Automated tests. Every behaviour test added here was checked by removing the code it covers and watching it fail.

  • Sender recorded on the message: an idle send and a queued send both record the sender, through to the sent message and the transcript, on the real host. The provider's echo folds into the same row. A retry under the same id replays. /clear and Codex rewind keep the sender. The provider never receives it.
  • Fingerprints: pinned bytes for a message without from; the same message with from fingerprints identically.
  • No forgery: a client send whose body carries from is refused.
  • Old data: a database that still has the never-released source_json column keeps working.
  • Held cards after a crash (fix(native-chat): keep a message accepted before a quit or crash as a held card #24660): that feature's tests pass unchanged except one assertion (params.source became params.personsMessage). A new test proves a launch's first prompt is still kept as yours.
  • Naming:
    • a worker by its current task, or by the task its own completion report names;
    • never by a task it never ran;
    • a chat by its tab name;
    • two senders with the same name stay two.
  • Clicking:
    • a chat after /clear, and a terminal after an Orca restart (found from the pane its mail came from);
    • a gone sender versus an unreachable host versus an older host, each with its existing message;
    • a worker on another computer is not called gone.
  • Mobile: the label logic, and the queued-card projection.

The node, web and CLI typechecks, oxlint, the anti-slop audit and the changed-code quality gate pass locally. About 3,200 tests across the touched areas pass. The mobile component tests can't run on this machine; CI's Mobile Checks pass.

A message another agent sends into a native chat (today the orchestration
mail notice) looked exactly like the person's own: a right-hand bubble and a
queued card identical to theirs. The sender was recorded only on the queue
row, so a message sent to an idle chat, or a card once it was sent, had no
sender at all.

The sender now lives on the message itself (`from` on the message body):
- The send path carries it on both deliveries; an idle chat records it too,
  and it survives the queue, /clear's carry, restart and history.
- No fingerprint covers it: one shared payload projection leaves it out at
  every fingerprint site, so stored digests are unchanged and the provider's
  echo still folds into the same bubble. The provider never receives it.
- A client cannot set it: its send params stay strict.
- One reader normalizes it where it is read (journal load, queued row,
  client projection); a newer message kind keeps the sender an agent's.
- Each sender keeps a name snapshot from names Orca controls: a chat's
  conversation name or agent label, a terminal's own tab title or agent,
  a federated sender's task name. Never an agent-set terminal title.
- The separate queued-row sender column and its plumbing are removed; it
  never shipped.

Desktop shows such a message as a left-aligned "Message from <name>" row;
the name opens the sender: its chat through the existing open-chat flow
(after a host lookup that follows /clear and dispatch addresses), or its
terminal through the terminal-link path, with the existing feedback when
it is gone. A queued card shows a plain "From <name>" line. Mobile shows
the same attribution, not yet clickable.
…ssage-sender

# Conflicts:
#	src/shared/native-chat-types.ts
#	src/shared/structured-agent-session-projection.ts
… for it

Review fixes for showing who an agent message is from.

- Names: a sender is named by its dispatch's task (local workers too, not
  only federated ones), else a chat by the label its tab shows, else a
  terminal by its tab's stored title, else its agent. The conversation
  name the snapshot read before has no writer, so every chat read
  "<Agent> Chat".
- One sender builder (agentMessageSender) and a public runtime naming
  object (orchestrationSenderNames) any send site can use; the terminal
  naming moves out of the unrelated runtime layer into its own module.
- Opening a terminal sender always asks the chat's host: a terminal handle
  is issued per run, so the host finds an earlier run's terminal again
  through the pane its mail was sent from. The pane key never leaves the
  host.
- Feedback follows what the host found: a gone chat or a gone pane by the
  kind it lost, "pane no longer available" only when the terminal answer
  proves it, and the existing "couldn't reach" / "needs a newer Orca"
  words otherwise.
- Another agent's message is not offered rewind (it would put the
  agent's text in the person's composer), and a Codex rewind keeps the
  sender on the messages it retains.
- The queued card and mobile name every sender, two that share a name
  included, and count in "+N" only those left out; the transcript row
  separates names with ", ".
- The host no longer normalizes the sender when loading the journal or
  the queue: nothing on the host reads it, and clients read it through
  the one reader at their projections.
…pen-sender failures

- A worker's own worker_done settles its dispatch before the mail lane
  names who the report is from, so a terminal worker's completion read
  "Codex". A local worker is now named by the dispatch it holds, else the
  one it last held (handles are per run, so that is this run's). The
  coordinator mail rig now attests the worker's process, so its report is
  accepted and settles as it does in production.
- Opening a sender: a version block or an unknown answer says "Update Orca
  to open it.", since either side may be the older one; "This needs a
  newer Orca on the computer running this chat" stays only for a host
  that predates the lookup. "Orca couldn't reach the agent." is followed
  by "Try again.", each sentence translated on its own. No new copy.
…essage

#24660 records on each submission who it is from (`source.kind`) so a restart
or a close keeps only a person's unsent send as a card. That record and its
keep rule are kept exactly; the kind is now read off what the send carries,
in one place (sendPlan): a person's send ('user': a client's, or a launch's
first prompt the host sends for them), another agent's message whose body
names its sender ('agent'), or neither (a dispatch preamble, a restart
continuation). The queued card's own source column is dropped again: the
sender is on the card's body, and kept cards are written without it.
A worker with no active dispatch was named by the newest dispatch ever
assigned to its terminal, at any status and any age: one that failed before
it ran, or a task finished long ago that its later, unrelated mail kept
showing. Now a worker is named by its active dispatch, else by the dispatch
its own worker_done in the announced mail names (only if that dispatch is
its own), else by its tab or agent as any terminal is.
…d body; mobile card fixtures name their attribution

- The rewind's held-sender restore lives with the retained rows and reads both
  bodies through the journal's message-body check, instead of a shared helper
  taking any object (anti-slop: no-object-parameters).
- Mobile queued-card test fixtures carry the attribution field the card gained.
…builder moves out of the mail lane

- A federated sender (dispatch:<id>) runs on another host, which the chat's
  host cannot open: its name is plain text, and the host's lookup answers
  'not found' rather than 'gone' for a dispatch it does not run. Not seeing a
  worker is no evidence it stopped.
- The lookup calls a chat gone only when the identity is proven lost; any
  other failure reaches the client as 'could not reach'.
- A sender open that throws shows 'couldn't reach the agent' instead of an
  unhandled rejection.
- agentMessageSender, the one sender builder, lives in its own module, so the
  runtime's naming no longer imports from the mail lane.
…ssage-sender

# Conflicts:
#	mobile/src/session/MobileNativeChatMessage.tsx
#	src/shared/agent-session-journal-types.ts
#	src/shared/structured-agent-session-projection.ts
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review summary

The problem. An agent's message into a native chat (today the "You have N orchestration messages" notice) looked exactly like the person's own: a right-hand bubble, and an identical queued card. The sender was recorded only on the queued card's database row. So a notice sent to an idle chat had no sender at all, and once a card was sent its sender was lost.

What changes for the user.

  • An agent's message shows as a left-aligned "Message from name" row, and its queued card shows "From name".
  • Clicking the name opens that agent's terminal or chat, switching worktree if needed.
  • If the sender is gone, the name stays readable and a click shows Orca's existing "no longer available" message.
  • Mobile shows the same label, not clickable yet.
  • Rewind isn't offered on an agent's message.
  • Older clients show what they show today.

How. The sender is stored once, on the message itself (from). Only the host writes it: a client send that carries it is refused. No fingerprint covers it, and the agent never sees it. The labels and the click are derived from it.

Fixed during review (four review rounds, an architecture challenge, a readiness pass):

  • Senders were all named "Claude Chat" or "Codex Chat": the naming read a field nothing writes. Naming now uses the worker's task, else the tab's name, else the agent's name. A worker is never named by a task it never ran.
  • A terminal sender couldn't be opened after an Orca restart, because terminal handles change per run. The host now finds it from the pane its mail came from.
  • Failure messages:
    • lost contact is never reported as "gone";
    • each failure picks the existing message that matches what the host actually found;
    • a worker on another computer is never called gone.
  • Rewind on an agent's message would have put its text in the person's message box; it is no longer offered there. A Codex rewind keeps the sender on earlier messages.
  • Two different agents with the same name stay two, and the "+N" count is correct.
  • Main's held-cards-after-a-crash change (fix(native-chat): keep a message accepted before a quit or crash as a held card #24660) landed meanwhile and used the separate sender field this PR removes. It now reads authorship from the message, and its behaviour and tests are unchanged.
  • The source_json column from feat(orchestration): a native chat gets the orchestration pointer a CLI agent gets, through the same send as your messages #25078 (never released) is removed, so there is no second copy of the sender.

Deferred (none blocks this PR):

  • the message rail outline and the sidebar's "latest request" quote still count an agent's notice as the person's;
  • mobile click-to-open;
  • opening a worker that runs on another computer: it is named but not clickable;
  • on a paired computer with no desktop window open, a chat sender gets its agent's default name;
  • downgrading to v1.4.221 and then using /clear can show a waiting agent card twice;
  • a type-name tidy-up (AgentSessionMessageSource vs AgentMessageSource), left until the dispatch-task PR lands.

Verified:

  • A live run on macOS on an M4 MacBook Air: real orchestration mail into a live native chat (with a stand-in model), before and after, light and dark. The idle row, the queued card, click-to-open across worktrees, a closed sender, and rewind all pass.
  • The node, web and CLI typechecks; about 3,200 targeted tests; CI green, including Mobile Checks.

Not verified live:

  • a real model provider;
  • a chat (rather than a terminal) as the sender;
  • a worker on another computer;
  • mobile UI on a device;
  • paired, SSH or remote hosts;
  • behaviour after a restart, and /clear.

Each of these is covered by unit or integration tests only.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 6, 2026 17:48
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

Walkthrough

Message provenance now resides on message bodies, and queued-message storage no longer persists a separate source value. Runtime code resolves sender names and party locations. Native and mobile chat project and display sender labels on transcript messages and queued cards. Attributed messages use agent-specific presentation and are excluded from rewind eligibility.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to c24fd

Agent sender labels can be truncated or fail to scale with chat text size, which makes some senders harder to identify. These are cosmetic and can be fixed in follow-up work. Core messaging and fingerprinting behavior is unaffected.

🚥 Pre-merge checks | ✅ 4 | ❓ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ❓ Inconclusive Docstring coverage is 54.10% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 61 functions across 50 files. (40 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: native chat shows which agent sent a message and lets users open that agent.
Description check ✅ Passed The description is detailed and covers the change, motivation, compatibility, visual proof, and testing. It addresses the linked-issue requirement with the template’s maintainer exception. Some checkl…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 54.10% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 61 functions across 50 files. (40 skipped: 6 unsupported, 34 over the file limit.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 620cadad-fa9d-4bd4-869e-b7634c240912
📥 Commits

Reviewing files that changed from the base of the PR and between 7faa9f7 and c24fd4d.

⛔ Files ignored due to path filters (1)
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (93)
  • mobile/src/session/MobileNativeChatMessage.test.ts
  • mobile/src/session/MobileNativeChatMessage.tsx
  • mobile/src/session/MobileNativeChatQueuedMessages.test.tsx
  • mobile/src/session/MobileNativeChatQueuedMessages.tsx
  • mobile/src/session/mobile-agent-message-attribution.test.ts
  • mobile/src/session/mobile-agent-message-attribution.ts
  • mobile/src/session/mobile-native-chat-message-styles.ts
  • mobile/src/session/mobile-structured-queued-message-cards.test.ts
  • mobile/src/session/mobile-structured-queued-message-cards.ts
  • mobile/src/session/use-mobile-native-chat-queued-slot.test.tsx
  • mobile/src/session/use-mobile-structured-agent-session-queued.test.tsx
  • src/main/native-chat/agent-session-journal/journal-queued-messages.ts
  • src/main/native-chat/agent-session-journal/journal-reducer.test.ts
  • src/main/native-chat/agent-session-journal/journal-reducer.ts
  • src/main/native-chat/agent-session-journal/journal-row-builders.ts
  • src/main/native-chat/agent-session-journal/journal-submission-queued-link.test.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold.test.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold.ts
  • src/main/native-chat/agent-session-journal/queued-message-bookkeeping-failure.test.ts
  • src/main/native-chat/agent-session-journal/queued-message-delivered-echo.test.ts
  • src/main/native-chat/agent-session-journal/queued-message-delivered-echo.ts
  • src/main/native-chat/agent-session-journal/queued-message-pause.test.ts
  • src/main/native-chat/agent-session-journal/queued-message-schema.ts
  • src/main/native-chat/agent-session-journal/queued-message-store.test.ts
  • src/main/native-chat/agent-session-journal/queued-message-stored-row.ts
  • src/main/native-chat/agent-session-journal/queued-message-table.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-mutations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-mutation-plans.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-message-rig.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-mutations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-send.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restore-without-import.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unsent-send-hold.test.ts
  • src/main/native-chat/agent-session-wire/structured-rewind-retained-host-rows.test.ts
  • src/main/native-chat/agent-session-wire/structured-rewind-retained-host-rows.ts
  • src/main/runtime/orca-runtime-stop-requested-pty-ids.ts
  • src/main/runtime/orchestration/agent-facing-parity.test.ts
  • src/main/runtime/orchestration/agent-message-sender.ts
  • src/main/runtime/orchestration/orchestration-party-location.test.ts
  • src/main/runtime/orchestration/orchestration-party-location.ts
  • src/main/runtime/orchestration/orchestration-party.ts
  • src/main/runtime/orchestration/orchestration-sender-name.ts
  • src/main/runtime/orchestration/send-agent-turn-host.test.ts
  • src/main/runtime/orchestration/send-agent-turn.test.ts
  • src/main/runtime/orchestration/send-agent-turn.ts
  • src/main/runtime/orchestration/structured-mail-source.test.ts
  • src/main/runtime/orchestration/structured-mail-source.ts
  • src/main/runtime/orchestration/structured-mailbox-pointer-delivery.test.ts
  • src/main/runtime/orchestration/structured-mailbox-pointer-delivery.ts
  • src/main/runtime/orchestration/structured-mailbox-pointer-host.test.ts
  • src/main/runtime/orchestration/structured-mailbox-pointer-host.ts
  • src/main/runtime/rpc/methods/agent-launch-structured-prompt.test.ts
  • src/main/runtime/rpc/methods/agent-launch-structured-prompt.ts
  • src/main/runtime/rpc/methods/orchestration/caller-show.ts
  • src/main/runtime/rpc/orchestration-party-addressing.test.ts
  • src/main/runtime/rpc/orchestration-session-caller.test.ts
  • src/main/runtime/runtime-orchestration-sender-names.test.ts
  • src/main/runtime/runtime-orchestration-sender-names.ts
  • src/main/runtime/structured-chat-coordinator-mail-queue.test.ts
  • src/main/runtime/structured-chat-coordinator-mail-rig.test-fixture.ts
  • src/renderer/src/components/native-chat/NativeChatAgentMessageRow.test.tsx
  • src/renderer/src/components/native-chat/NativeChatAgentMessageSenders.tsx
  • src/renderer/src/components/native-chat/NativeChatMessageRow.tsx
  • src/renderer/src/components/native-chat/NativeChatQueuedMessageCard.tsx
  • src/renderer/src/components/native-chat/native-chat-agent-message-sender-label.ts
  • src/renderer/src/components/native-chat/native-chat-rewind-eligibility.ts
  • src/renderer/src/components/native-chat/structured-agent-session-queued-cards.test.ts
  • src/renderer/src/components/native-chat/structured-agent-session-queued-cards.ts
  • src/renderer/src/components/native-chat/use-native-chat-rewind.test.tsx
  • src/renderer/src/components/terminal-pane/stale-agent-row.ts
  • src/renderer/src/components/terminal-pane/terminal-handle-links.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/lib/activate-ai-vault-structured-session.ts
  • src/renderer/src/lib/open-agent-message-sender.test.ts
  • src/renderer/src/lib/open-agent-message-sender.ts
  • src/shared/agent-session-journal-types.ts
  • src/shared/agent-session-message-source.test.ts
  • src/shared/agent-session-message-source.ts
  • src/shared/native-chat-types.ts
  • src/shared/orchestration-caller-status.ts
  • src/shared/rpc-contract/orchestration-params.ts
  • src/shared/structured-agent-session-projection-sender.test.ts
  • src/shared/structured-agent-session-projection.ts
  • src/shared/structured-agent-session-send-mutation.test.ts
  • src/shared/structured-agent-session-send-mutation.ts
  • tests/e2e/cross-version-wire/kept-card-downgrade.unit.test.ts
💤 Files with no reviewable changes (3)
  • src/main/runtime/orchestration/structured-mailbox-pointer-host.ts
  • src/main/native-chat/agent-session-journal/journal-queued-messages.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-send.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

Comment on lines +219 to +220
<Text selectable={INLINE_TEXT_SELECTION} style={styles.agentAttribution}>
{attribution}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Scale the sender label with fontScale.

When a person enlarges chat text, Prose scales but this new label stays at typography.metaSize. Apply fontScale to the attribution text so the sender remains readable at the selected size.

Comment on lines +124 to +125
<Text style={styles.caption} numberOfLines={1}>
{card.attribution}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the full sender attribution readable.

When an agent has a long task name or a card lists multiple senders, numberOfLines={1} truncates the new caption. The mobile card has no hover title to reveal the hidden names. Let this caption wrap, or provide another way to read its full text.

Comment on lines +40 to +43
<span className="max-w-48 truncate">{agentMessageSenderLabel(sender)}</span>
</Button>
) : (
<span className="max-w-48 truncate px-2">{agentMessageSenderLabel(sender)}</span>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make full sender names available when labels truncate. Long task-derived names can share a visible prefix. When truncation hides the rest, a user cannot identify the sender before opening it or reading its queued card.

  • src/renderer/src/components/native-chat/NativeChatAgentMessageSenders.tsx#L40-L43: expose each full name for both the button and plain-text label; support focus as well as hover for the button.
  • src/renderer/src/components/native-chat/NativeChatQueuedMessageCard.tsx#L149-L152: expose the full sender line on hover, as the card already does for message text.
📍 Affects 2 files
  • src/renderer/src/components/native-chat/NativeChatAgentMessageSenders.tsx#L40-L43 (this comment)
  • src/renderer/src/components/native-chat/NativeChatQueuedMessageCard.tsx#L149-L152

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Mobile QA (iOS Simulator)

Orca Mobile on the iOS Simulator, paired to an isolated Orca built from this branch (c24fd4d): real orchestration mail into a live native chat, with a stand-in model.

Case Result Screenshot
App loads and pairs Pass loaded, paired
Mail to an idle chat: a left-aligned row with a muted "Message from Release checker" label. Your own message stays a right-hand bubble Pass row
Mail while the chat is busy: the queued card shows "From Docs writer" (not tappable); Steer, Delete and More are unchanged Pass card
Once sent, it shows as a "Message from Docs writer" row Pass sent
No error screen, and no errors in the bundler log Pass

The six mobile test files this PR touches pass (99 tests), and the mobile test-typecheck ratchet passes.

Not covered on mobile: Android, a real provider, a chat as the sender, and several senders on one notice.

@brennanb2025
brennanb2025 merged commit c893048 into main Oct 6, 2026
77 of 79 checks passed
brennanb2025 added a commit that referenced this pull request Oct 6, 2026
…r-stop

Main's #25888 shows which agent a queued message is from: the sender moves onto
the message body (`from`), and a person's send carries `userSend`. The card
keeps this branch's Steer/Send rule beside main's sender line; the queue's card
projection imports both. The test rig and its card test take main's `from`;
a card-holds test no longer passes the removed `source` field. Locale catalogs
keep both sides' new keys.
Jinwoo-H added a commit that referenced this pull request Oct 6, 2026
#26010)

#25888 and #25766 added tests that import the orchestration database or the
structured session runtime without registering them in the Node runtime list,
so vitest-sqlite-runtime-boundary fails on main and every PR.
brennanb2025 added a commit that referenced this pull request Oct 7, 2026
…ard-ordinary

The sender moved off the queued row onto the message body on main (#25888): the row's source plumbing goes, this branch's derived holds stay.
brennanb2025 added a commit that referenced this pull request Oct 7, 2026
…ueue-after-stop

Rebuilt as main plus this branch's own changes against its old base: the branch carried #24586's
unsquashed history, so main's squash conflicted on every shared file. The person's-Stop mail
check now reads the message body's sender (`from`, from #25888) and the separate card `source`
field is gone; the moved queue step takes main's fingerprint and its replay answer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant