Commit Graph
16002 Commits
Author SHA1 Message Date
Neil d4a71c7c82 fix(runtime): resume a server's status only after its action replaced the transport (#38532)
An explicit Update, Rollback, Recover or Restart resumed the server's
status before invalidating its transport, so the first probe could ride
the connection about to be dropped. The action now includes its own
invalidation and note clearing, and status resumes after both. A test
also covers the SSH host's Disconnect being lifted for a managed server.

Refs #38347
2026-11-05 14:43:02 -08:00
Kelvin Amoaba ce3fe75891 feat(mobile): set, pause, resume and clear a chat's goal from the phone (#38447)
* feat(mobile): set, pause, resume and clear a chat's goal from the phone

The phone sent /goal to the agent as plain text and showed no goal. It now
has desktop's goal mode (Goal chip, goal placeholder) and a goal strip on the
composer's top edge that expands to Pause/Resume and Clear goal.

The goal logic desktop and mobile share moves to src/shared: the goal report
(journal rows over the options answer), status labels, elapsed format, the
goal-mode pick rule and the goal row filter. agentSession.threadGoal joins the
phone allowlist behind agent-session.thread-goal.phone.v1, so older hosts keep
showing the goal without offering changes.

* fix(mobile): open each new goal's strip collapsed

* fix(mobile): keep goal sends' delivery choice and scope goal locks per chat

* fix(mobile): offer goal changes only when the paired desktop relays them

* test(mobile): pin which goal changes the phone offers per host

* refactor(mobile): reuse the queued box style and keep the goal strip stable per chunk

* fix(mobile): set phone goals through the composer's changeThreadGoal
2026-11-05 22:42:44 +00:00
NeilandClaude 375abec523 fix(github): route PR comment edit/delete through the repo's credential owner (#38691)
Checks sidebar edit/delete of PR conversation comments always used desktop
IPC, so server-owned repos and SSH workspaces behind a paired server edited
and deleted with this computer's GitHub credentials while reads and posts
used the server's. Add one owner-aware client for slug-addressed GitHub
operations and move every slug caller onto it, so ownership is resolved at
the client boundary instead of in each component. An unknown owner now
fails explicitly instead of falling back to desktop credentials, and a
result that lands after the panel moved on no longer touches the list.

Refs STA-13254. Reported by Jinjing.

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-05 14:41:06 -08:00
Brennan Benson 1e5e6df6dc Remove Fork Agent Session from the Chat UI menu (#38646)
* Remove whole-session fork action from chat menus

* test: drop a terminal menu test this change can't fail
2026-11-05 14:38:10 -08:00
NeilandClaude cc91e5d17e fix(new-workspace): restore right-click "Set as default" on the agent picker (#38680)
* fix(new-workspace): restore right-click "Set as default" on the agent picker

The shared agent picker (#35802) replaced the combobox in the new-workspace
composer and dropped the context menu that set the default agent. Wire
defaultAgent/onSetDefault through AgentLaunchPicker so agent rows, the
Blank Terminal row, and the closed field offer it again.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(agents): keep the "Set as default" menu open when the mouse moves

The context menu was non-modal, so hovering the agent rows beneath it
moved focus to them and dismissed the menu. Make it modal so focus stays
in the menu until the user picks or dismisses.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(agents): keep the row highlighted while its "Set as default" menu is open

Row highlight follows focus, which moves into the context menu. Mark the
trigger with data-context-menu-open and style it like the hovered row.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(agents): address review on the Set as default context menu

- Keep the context menu non-modal; prevent focus-outside dismissal instead,
  so combobox callers keep one-click selection and scrolling.
- Drop the field-level context menu: it clobbered the dropdown trigger's
  data-state/data-slot, ignored the disabled gate, and doubled up on long-press.
- Pass onSetDefault through unchanged so memoized rows stay stable.
- Reset the open marker when the menu unmounts while open.
- Stop asserting the CSS-only highlight marker in tests.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-05 14:33:16 -08:00
Neil 520af920c0 fix(pickers): open only one native file picker at a time (STA-14006) (#38688)
Repeated clicks on the native chat composer + (Attach file) button opened
one OS file picker per click because shell:pickAttachments opened a
parentless (modeless) dialog with no in-flight guard. Route all shell:pick*
and repos:pick* handlers through a single-flight wrapper; overlapping
requests resolve as canceled, which every caller treats as a no-op.
2026-11-05 14:31:32 -08:00
Brennan Benson e4d07cf937 Keep prices readable in chat (#38651)
* fix(chat): keep shell paths and prices as written

* Use the common inline dollar rule in chat
2026-11-05 14:28:37 -08:00
Kelvin Amoaba d68dc03582 feat(mobile): Sign in from a signed-out chat, and name the offline host above the composer (#38295)
* feat(mobile): offer Sign in on a signed-out chat via a host terminal login

* feat(mobile): say which host is out in the chat composer, with Reconnect for the desktop link

* refactor(mobile): fit the host outage line beside main's chat changes
2026-11-05 22:27:44 +00:00
Jinwoo Hong 4794651e39 Let workers start their own workers by default (nested worker depth 4) (#38348)
Default nested worker depth to 4; a stored 1 from the old default moves to 4 once, later choices stay. Fixes #24970. Fixes #30141.
2026-11-05 17:24:26 -05:00
Brennan Benson dbb9a270d4 Keep long chats responsive: stop rescanning whole history on each status update and subagent name (#38627)
* perf(native-chat): stop rescanning whole chat history on every status update and subagent label

Status re-derived after every journal write built a map of every item body in the
chat to find conversation-command turns; index only command entries instead.
Same-named sibling subagents restarted their ordinal search at 2 for each sibling
(quadratic); resume each label's search where it stopped. Output is unchanged.

* perf(native-chat): find command turns through an indexed read on each status update

Status re-derived after every journal write still walked the whole history to
learn which turns belong to conversation commands. The host now passes a by-key
read of the same status rows (same display state, presentation membership and
stop-note projection, limited to the current /clear context), and the request,
preview and interruption readers check only the turns their backward scans reach,
the way the usage-limit reader already does. Clients without an index keep the
scan. A contract test drives real journal writes at 10x history and pins both the
constant indexed reads and the remaining per-row work.

* test(native-chat): count status body reads without Reflect.get or casts

* chore: drop accidental lockfile churn

* perf(native-chat): read the status display state once and pin indexed status parity

The host's status lookup now reads the journal's display state once per projection.
The status contract test covers the /clear boundary, an interruption verdict behind
a skipped command turn, a revised command turn, and the journal's per-row render
budget; the context-rows test expects the returned /clear sequence.

* test(native-chat): bound status work on the write that records an Orca stop

* test(native-chat): status follows a turn that becomes a command turn

* fix(native-chat): take the status lookup from the status read itself

Status read the journal's display state directly, which journals without queued
messages (test stand-ins, older wiring) do not have. The status read now returns
the by-key lookup bound to the state it rendered; readers whose status read has
none keep the scan.
2026-11-05 14:20:44 -08:00
Kelvin AmoabaandErfan Samieyan f6b9944289 fix(native-chat): name a chat resumed from a session after that session (#38679)
Fixes #28763

Co-authored-by: Erfan Samieyan <25950587+erfoon@users.noreply.github.com>
2026-11-05 22:17:30 +00:00
Kelvin Amoaba 5201c378f8 fix(native-chat): keep closed chats out of the phone's agent rows (#38683) 2026-11-05 22:15:24 +00:00
Jinjing b5b6e01a09 Add collapse and expand all projects controls (#38634)
* Add collapse and expand all projects controls

Support a sidebar button, keyboard shortcut, and Alt-click on project
headers, with a contextual tip to introduce the feature.

* rm mockup file

* Clean up project header toggle handling and fixtures
2026-11-05 22:09:40 +00:00
OrcaWinandOrcaWin da0ba0dc70 test: remove 216 low-value browser network and session tests (#38681)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 14:09:12 -08:00
Kelvin Amoaba b9f988be22 feat(mobile): continue a chat that Orca's stop cut off (#38287)
* feat(mobile): continue an interrupted chat from the phone

Desktop offers Continue on a turn Orca's own stop cut off; the phone only
showed the words. The offer and failure rules move to
src/shared/native-chat/native-chat-interrupted-continue.ts, desktop uses
them unchanged, and the phone drives them from its session over
agentSession.continueInterrupted when the host advertises it.

* refactor(native-chat): type the Continue answer instead of casting it

* fix(mobile): let a phone call agentSession.continueInterrupted

The host refused the method from phones, so Continue on the phone always
failed. Allow it on the execution-host route and advertise
agent-session.continue-interrupted.phone.v1, which the phone gates on:
hosts that advertise only continue-interrupted.v1 still refuse phones.

* fix(mobile): hide Continue when an older paired desktop relays the chat

A newer page on a server routed through an older desktop would offer
Continue that the desktop refuses to forward. Gate it on the relaying
desktop too; the workspace server context moves to a react-native-free
module so session hooks can read it. Long failure text now shrinks so
the banner's dismiss stays on screen.

* refactor(mobile): reuse the chat's Try Again look and shared Continue wording

The Continue button takes the Try Again pill styles and common.continue,
the shared helper takes the RPC's answer instead of a call wrapper, and
the phone hook memoizes its result and keys late answers in one place.

* fix(i18n): keep the Continue failure copy inline so catalogs rebuild it

* refactor(mobile): keep the structured session hook under its line cap

* fix(native-chat): check the session's agent audience before continuing a turn
2026-11-05 22:08:45 +00:00
Jinjing c75538441d Add child worktree creation to the context menu (#38410)
* Add child worktree creation to the context menu

Preselect the clicked parent and its owning host when opening the
workspace composer, including nested SSH worktrees.

* Fix child worktree creation across local and remote hosts
2026-11-05 13:58:47 -08:00
Kelvin Amoaba 4fbb1ccd97 feat(native-chat): color chat links with the theme's link color (#38676)
Chat links used the body text color, so a link only showed as a faint
underline and a theme's textLink.foreground had no effect. They now
paint --chat-link: the theme's link color, else the built-in note blue
for the chat's own scheme, mixed toward the chat foreground like the
other chat hues. Code and bold link labels follow the link color.

When the chat paints a terminal palette the app theme doesn't match,
the app theme's link color is cleared, as its bubble already is. The
theme contrast check now measures the chat link on the theme's user
bubble and drops only the bubble when it fails.
2026-11-05 21:57:27 +00:00
OrcaWinandOrcaWin 2abe03b96d test: remove 237 low-value browser tests (#38678)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 13:55:52 -08:00
Kelvin Amoabaandphatloi0010 52b8a24d27 fix(editor): stop rich editor links at CJK punctuation after a URL (#38672)
* fix(editor): end rich editor urls at CJK prose punctuation

Co-authored-by: phatloi0010 <316136531+phatloi0010@users.noreply.github.com>

* refactor(editor): simplify prose-split paste finder and trim boundary test

---------

Co-authored-by: phatloi0010 <316136531+phatloi0010@users.noreply.github.com>
2026-11-05 21:49:45 +00:00
Jinwoo Hong 9fbad42864 Stop a worker's helpers when the worker is stopped (#38373)
Stopping a worker also stops the helpers it started, across levels and paired hosts; kept-open helpers are skipped and listed.
2026-11-05 16:35:59 -05:00
OrcaWinandOrcaWin cfacdfb7c0 test: remove 129 low-value browser extension tests (#38668)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 13:35:06 -08:00
Jinwoo Hong c53f5cd23f fix(orchestration): hold mail for a draft typed before an Orca restart (#38398)
Hold orchestration mail behind a composer draft typed before an Orca restart.
2026-11-05 16:31:25 -05:00
Kelvin Amoaba 9055eb9344 feat(mobile): desktop chat links and code wrap on the phone (#38294)
* refactor(native-chat): move chat link rules and the file-existence checker to shared

GitHub reference linking, the reference-repo rule, chat file-path linkification,
the per-chat existence checker and the path-existence batcher are platform-free.
Move them to src/shared so the phone's chat can use the same rules; desktop keeps
its host adapters and behaves the same.

* feat(mobile): link #123 refs, check file paths and wrap code in chat

* test(mobile): pin which chat paths and refs become links

* refactor(mobile): parse repo link fields instead of casting

* refactor(mobile): own chat link state in the chat overlay

* fix(mobile): keep unchecked chat paths as precise as before

* fix(mobile): only peek at known paths while reasoning streams

* test(mobile): leave #123 splitting rules to the shared transform's tests

* refactor(native-chat): tidy shared link helpers and skip separator-free text

* test(native-chat): import the existence type from its shared home

* style(mobile): fold the code-span link handler onto one line
2026-11-05 21:24:09 +00:00
Kelvin Amoaba 0ede32b0b8 fix(ai-vault): keep a reply that matches the session title in Latest turns (#38666) 2026-11-05 21:23:12 +00:00
OrcaWinandOrcaWin f89114ab65 test: remove 171 low-value browser preview tests (#38664)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 13:15:36 -08:00
OrcaWinandOrcaWin 8f7921032e test: remove 109 low-value browser cookie tests (#38659)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 13:09:15 -08:00
Brennan Benson 26e8f961a3 Resume working chats after restart by default for new users (#38649)
* feat(chat): resume working chats after restart by default for new users

New profiles start with automatic resume on. Profiles saved before this
change that never chose keep it off, so existing users see no change.

* fix(chat): decide launch resume only after settings load

The launch reads the resume preference once. When held chats enabled it
before settings loaded, it read the preference as off and opened the
review dialog for the session. Also drop the web storage pin: the web
client never runs the launch resume.
2026-11-05 13:05:54 -08:00
Kelvin Amoaba 7860261d18 feat(mobile): paste images and long text into the chat composer (#38591)
* feat(mobile): paste images and long text into the chat composer

* test(mobile): pin which composer pastes attach

* fix(mobile): keep a long paste as text when no upload can start

* fix(mobile): re-encode pasted images agents can't read as PNG

* test(mobile): pin composer paste routing at the composer field

* refactor(mobile): fold composer paste routing into its hook

* fix(mobile): read pasted images in the uploader so the composer needs no shell bridge

* test(mobile): stub the context ring in the composer paste test
2026-11-05 20:59:54 +00:00
OrcaWinandOrcaWin 649dd09de3 test: remove 229 low-value browser host tests (#38656)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 12:50:40 -08:00
Jinjing 3fc348d9fa fix(sidebar): keep project header actions stationary (#38655) 2026-11-05 12:45:25 -08:00
Kelvin Amoaba 9b2f3105ee feat(mobile): show the context usage ring and its breakdown in the chat composer (#38371)
* feat(mobile): show the context usage ring in the chat composer

Desktop's ring reads the structured session's context facts; the phone
never read the host's contextUsage answer. The summary rules move to
src/shared so both read the same numbers, and the title card's anchored
card machinery is generalized so the ring's breakdown opens above the
composer without dropping the keyboard.

* refactor(native-chat): share the context ring's critical threshold

* test(mobile): stub the context ring where composer tests stub its siblings

* fix(mobile): keep the context card with the composer and the keyboard up

Touching the card no longer takes focus from the draft, the open card
moves with the composer as the keyboard or draft resizes it, and the
composer's own menu closes it.

* fix(mobile): close the context card when the composer hides, and let long titles wrap

* refactor(mobile): share the anchored card layer and the ring readout

* test(e2e): pass the new options arg in the permission publication test
2026-11-05 20:44:10 +00:00
Brennan Benson f5b6f76f99 feat(native-chat): show the chat's Codex usage card for /usage (#38352)
* feat(native-chat): show the chat account usage for /usage

* fix(native-chat): derive usage card lifetime from its owning turn

* test(native-chat): keep runtime manifest coverage additive

* fix(native-chat): advertise usage from the host options reader

* fix(native-chat): read cold chat usage through the chat's own Codex launch

- Cold /usage starts a short-lived app-server the way the chat launches
  (configured command, args, environment, pinned home), as Codex rename does;
  the status-bar probe returns to its original path.
- Report each reset outcome inline after the card refreshes.
- Send the chat's account as a typed kind plus email; the client owns copy.
- API-key accounts are recognised by a typed error, not message text.
- Keep the caret after kept text; drop unreachable WSL matching.

* refactor(native-chat): share the at-rest Codex app-server launch between rename and usage

* fix(native-chat): keep a reset's outcome when the usage refresh fails; label accounts by kind

* fix(native-chat): drop stale usage replies by request id instead of a render-time ref

* test(native-chat): keep the usage card test inside the web project

* fix(native-chat): clear the usage card when a waiting prompt changes; retire its callbacks on unmount

* chore: drop accidental pnpm lockfile churn from the main merge

* fix(native-chat): put the caret after kept text on /usage; offer the reset once the host's first Codex read lands

* fix(native-chat): type the usage snapshot wait and its test state

* fix(native-chat): re-read the usage offer when the chat host's Codex state changes, instead of forcing a host read

* fix(native-chat): watch the usage host from the card's opening and keep one background re-read at a time

* fix(native-chat): bind the usage card's background re-read to its opening

* feat(native-chat): open /usage as a modal like /resume

The chat's Codex usage card now opens in a root-hosted dialog with the
same surface, width and dismissal as /resume's Session History, instead of
a full-width card docked above the composer. Closing the modal retires its
reads; docked-only clearing on turn, prompt and session changes is gone.

* fix(native-chat): give the /usage modal /resume's fixed height and drop a replayed mount's first read

* fix(native-chat): size the /usage modal to its card and keep the card's layout while loading

* fix(native-chat): pin the /usage modal's top where /resume's sits so loading never moves its title

* chore(native-chat): describe the /usage loading placeholder accurately
2026-11-05 12:42:27 -08:00
Kelvin Amoaba a3f08b4075 feat(mobile): pin the agent's plan above the chat composer (#38359)
* feat(mobile): dock the chat's plan above the composer

Desktop docks the latest plan above the composer; the phone only drew it
inline in the transcript. Move desktop's docked-plan rule to src/shared and
draw it on the phone as a collapsible strip in the background-tasks box.

* perf(native-chat): keep the docked plan's identity until the plan changes

* refactor(native-chat): read the docked plan from the newest message back

* refactor(mobile): drop a cast in the docked plan's open memory

* test(mobile): pass the tray's new taskList in the recovery test
2026-11-05 20:31:10 +00:00
OrcaWinandOrcaWin 31569e9b20 test: remove 156 low-value browser tests (#38650)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 12:29:55 -08:00
Kelvin Amoaba 585c32da22 feat(mobile): name and link the sending agent on queued chat messages (#38309)
* feat(mobile): name and link agent senders on queued chat messages

Queued cards and the queued-message editor drew the sender from the saved snapshot name as plain text. They now share the transcript card's sender row, so a queued message names its sender's chat by its current title and taps through to it, as desktop does.

* fix(mobile): keep the queued sender line on one row

* refactor(mobile): tidy the queued sender row and editor heading

* fix(mobile): bound the queued sender row to its container width
2026-11-05 20:28:18 +00:00
Brennan Benson 28f18547dd fix(cmd-j): list native chats in recents and title search (#38574)
Cmd+J and the new-tab search built open-tab rows only for a hand-kept
list of tab kinds, which never included native chats. Workspace tab
kinds are now every kind except browser and simulator (which have their
own rows). Chat rows use the tab strip's chat name and provider icon,
and selecting one activates it the way clicking its tab does, including
dismissing a paired-device page placeholder over it. The new-tab search
reads only its own workspace's chat names.

Tracked in STA-13638.
2026-11-05 12:24:13 -08:00
Brennan BensonandAJIADb9 bcaa60a54f fix(tabs): renamed sessions show their new name within seconds (#38628)
* fix(tabs): show the agent session's name on terminal tabs

The tab strip rebuilt each terminal tab without its session title and then re-ranked it, so the first-prompt title won over the session's own name. Carry the session title through the projection, and give the tab strip, unified tab label and sidebar agent row one shared name order so they cannot drift.

Co-authored-by: AJIADb9 <ajiadb9@bgd.team>

* fix(tabs): paired desktops take the host's session name for mirrored terminal tabs

The host projection now forwards the window's session title to paired clients, and the client's rebuild adopts it (older hosts omit it, so the client keeps its own). Without it a mirrored tab re-ranked to the client's first-prompt title.

* fix(tabs): one writer per session for a mirrored tab's session name

The paired client's own title sync keeps a session it already tracks current; the host's name only fills a session the client doesn't know, so a stale host snapshot can't revert a rename the client already read.

* fix(tabs): a paired host is the only writer of a session name it publishes

* fix(tabs): only a host window that resolves session names speaks for them

* fix(tabs): derive session title authority from live publishers

* fix(tabs): keep the session title publisher check concrete for runtime subclasses

* fix(tabs): one publication when a closing window drops browsers and title authority

* test(tabs): follow main's runtime test helper layout

* fix(tabs): paired desktops keep a quick-command name ahead of the session name

* fix(tabs): a name the host cleared doesn't come back as the idle pane's title

* test(tabs): build the idle-pane fixture as its own surface variant

* fix(tabs): refresh live session names from their authoritative source

* fix(tabs): preserve title recovery and bound refresh retries

* fix(tabs): preserve Codex index names at EOF

* fix(tabs): track the observed Codex index end

* fix(tabs): point the moved session-title projection at its new shared path

---------

Co-authored-by: AJIADb9 <ajiadb9@bgd.team>
2026-11-05 12:23:06 -08:00
Kelvin Amoaba de7fa2addb feat(mobile): show background task rows in the chat transcript (#38264)
* feat(mobile): show background task rows in the chat transcript

* fix(mobile): truncate the task output path like desktop

* fix(mobile): scale and select task rows like the rest of the transcript

* fix(mobile): translate the task output line

* refactor(mobile): read task rows from the shared row content

* test(mobile): restore the text reader for task row tests
2026-11-05 20:16:34 +00:00
OrcaWinandOrcaWin aeda9fadd8 test: remove 180 low-value scanner, password and browser tests (#38647)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 12:15:00 -08:00
OrcaWinandOrcaWin 9af8f63538 test: remove 79 low-value cloud, hook and search tests (#38642)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:58:24 -08:00
Brennan Benson ab8ae366b7 Use one-line cards for all agent messages on desktop and phone (#38615)
* Use one-line agent message cards for every variant

* Remove obsolete agent message preview translations
2026-11-05 11:53:55 -08:00
OrcaWinandOrcaWin 87631616a8 test: remove 60 low-value storage and CLI tests (#38631)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:34:32 -08:00
Brennan Benson 5efad8477c Show model and effort before a folder chat’s first message (#38498)
* fix(native-chat): show defaults for chats that have never started

* fix(native-chat): share default projection across controls and picks

* test(native-chat): prove controls recover from cached discovery

* test(native-chat): type deferred catalog as its wire result

* test(native-chat): preserve the catalog origin literal

* test(native-chat): remove duplicate RPC work-count cases
2026-11-05 11:25:58 -08:00
OrcaWinandOrcaWin 64cd31458d test: remove 31 low-value interaction and state tests (#38629)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:21:57 -08:00
14bc9fef26 fix(mobile): show history scan notices separately from skipped transcripts (#38626)
* Show source scan notices accurately in mobile Agent History

Reuse the existing desktop presentation policy in shared code, keep host failures and source notices separate from skipped transcript files, and retain their scanner-authored messages.

Adapted from the remaining mobile presentation in original PR #15671. Rebased onto main: the classifier now lives in src/shared/ai-vault/scanning/, desktop keeps its translated skip reasons, and mobile reuses its existing skipped-transcript notice.

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>

* refactor(ai-vault): share the scan issue row key between desktop and mobile

---------

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-11-05 19:11:35 +00:00
Brennan BensonandAJIADb9 239a70040c Terminal tabs show the agent session's name instead of the first-prompt title (#38518)
* fix(tabs): show the agent session's name on terminal tabs

The tab strip rebuilt each terminal tab without its session title and then re-ranked it, so the first-prompt title won over the session's own name. Carry the session title through the projection, and give the tab strip, unified tab label and sidebar agent row one shared name order so they cannot drift.

Co-authored-by: AJIADb9 <ajiadb9@bgd.team>

* fix(tabs): paired desktops take the host's session name for mirrored terminal tabs

The host projection now forwards the window's session title to paired clients, and the client's rebuild adopts it (older hosts omit it, so the client keeps its own). Without it a mirrored tab re-ranked to the client's first-prompt title.

* fix(tabs): one writer per session for a mirrored tab's session name

The paired client's own title sync keeps a session it already tracks current; the host's name only fills a session the client doesn't know, so a stale host snapshot can't revert a rename the client already read.

* fix(tabs): a paired host is the only writer of a session name it publishes

* fix(tabs): only a host window that resolves session names speaks for them

* fix(tabs): derive session title authority from live publishers

* fix(tabs): keep the session title publisher check concrete for runtime subclasses

* fix(tabs): one publication when a closing window drops browsers and title authority

* test(tabs): follow main's runtime test helper layout

* fix(tabs): paired desktops keep a quick-command name ahead of the session name

* fix(tabs): a name the host cleared doesn't come back as the idle pane's title

* test(tabs): build the idle-pane fixture as its own surface variant

* fix(tabs): point the moved session-title projection at its new shared path

---------

Co-authored-by: AJIADb9 <ajiadb9@bgd.team>
2026-11-05 11:04:58 -08:00
Brennan Benson 799b60b074 Keep orchestration messages tied to their actual agent identity (#37966)
* Show background completion mail as its command source

* Use minted sender handles in identity regression fixtures

* Verify command source labels in translated chat views

* Preserve command-only queued source regression coverage

* Use a minted terminal identity in host sender coverage

* Reuse command sender labels across unchanged message and queue reads

* Keep sender performance contract within the shared typecheck boundary

* Keep command reports in the background surface and preserve observed sender identity

* Use the shipped phone background report translation namespace

* Settle the prior dispatch before testing terminal reuse

* Keep live worker status tied to its recorded agent invocation

* Withdraw worker invocation proof when identity refresh fails

* Drop unproved worker associations at the failed refresh boundary

* Cover ordinary and remote sender rows during failed refresh

* Assert preserved session and peer content on failed sender reads

* Align sender navigation and relay tests with observed provenance

* Keep background report sources neutral and bound sender snapshot caches

* Construct readonly phone report fixture without mutation

* Keep callback-free federated transport assertions exact

* Keep orchestration sender identity separate from endpoint activity

* Validate mailbox receipt fixture shapes without casts

* Keep current Crew endpoint status separate from saved message activity

* Keep sender activity fixtures within lint contracts

* Avoid repeated serialization for fitting relay pages

* Use the valid workspace sidebar value in scale coverage

* Keep operation-count SQL expectation in sync with main
2026-11-05 11:00:15 -08:00
Brennan Benson 1a5e8ad2e6 fix(native-chat): make file links in terminal-backed plan approvals actionable (#38495)
* fix(native-chat): make file links in terminal-backed plan approvals actionable

Each chat view now provides its link handler through one per-chat
context that link-drawing components read themselves, replacing the
onLinkClick/allowFileUriLinks props threaded by hand through rows and
cards. The terminal-backed approval card was the surface that never got
them; any card inside a chat view now gets links without wiring.

Tracked in STA-13722.

* native-chat: correct link context comment

* native-chat: fixture for a terminal-backed plan approval with file links

* native-chat: drop stray blank line in turn-diff rollup
2026-11-05 10:43:26 -08:00
Brennan Benson dd1784f55b Keep partial check details from replacing complete PR status (#38514)
* Keep PR check status tied to complete observations

* Correct checks presentation types and count import

* Preserve localized empty states and declared runtime support

* Correct discovery fixture stack types

* Omit empty failed-check subtitles

* Preserve check identity through refresh and row publication

* Withhold row identity for malformed check errors

* Limit local capability wakes to local task sources

* Correct PR check regression fixtures

* Preserve browser APIs in PR check regression fixture

* Settle PR check adoption after failed detail reads

* Use the parsed PR check detail type during refresh

* Preserve PR metadata across checks discovery and committed query lifetimes

* Keep complete checks proof separate from legacy publication policy

* Keep PR lookup fixtures independent from complete checks collection

* Keep complete-check fixtures within lint contracts

* test: align PR recordings with source check discovery
2026-11-05 10:39:54 -08:00
Brennan Benson 85a68bfa4f Codex subagent rows show their task names instead of all saying "worker" (#38491)
* fix(agents): tell Codex subagent rows apart by task name instead of role

A Codex subagent's task name only reached the sidebar when one early read of its rollout succeeded; otherwise every child fell back to its role, so two workers both read "worker". The child poll now re-reads an unnamed child's own rollout, the first-line read allows the existing 256 KiB line cap, and a child with no task name or nickname carries the tail of its id, as Codex's own agent list does. Labels keep the path below the root so nested children with the same leaf stay distinct.

* fix(agents): retry an unnamed Codex child's own rollout without a parent transcript

A relay restart can leave a child hook as the only evidence, sent before the child's rollout was readable. Keep that path as pending identity work and retry it through the existing transcript poll, which now stays scheduled while a child still owes its name.

* fix(agents): carry the id tail to every child-row surface and bound identity retries

- Full-mode sidebar rows and dashboard subagent cards use the same suffixed label as compact rows.
- A role a host publishes as the name (Claude's subagent_type) no longer counts as a name.
- A final identity miss no longer re-arms polling; retries take turns, eight children per poll.
- Replace an error cast with a type guard.

* fix(agents): keep every identity read inside the per-poll budget

The parent-rollout poll now queues an unnamed child for the bounded, rotating identity retries instead of reading it directly, and full-mode rows keep the id tail for a child with no name or role.

* fix(agents): keep plain names on task-only rosters and guard the queued rollout path

A host that publishes only a task roster carries no role, so its names can't be told from roles and get no id tail. Update the sidebar lineage test for a role-only child's id tail.

* fix(agents): tell role-named tasks apart on task-only rosters

A host that publishes only a task roster sends Claude's subagent_type as the task name, so two such tasks read identically. A named agent task with no description now carries its id tail; an unnamed one keeps its kind label.

* fix(agents): a task path found meanwhile wins over a queued header read

Placeholder labels (e.g. unknown) count as unnamed when queueing, and a child the parent rollout named before its turn drops its pending read instead of being overwritten by the header's nickname.
2026-11-05 10:26:01 -08:00