Commit Graph
1846 Commits
Author SHA1 Message Date
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
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
Kelvin Amoaba 78ff857c88 feat(mobile): render PR descriptions and comments with the shared Markdown renderer (#38611)
* feat(mobile): render PR bodies and comments with the shared Markdown renderer

The PR view drew PR bodies, comments and review threads with its own small
parser, so strikethrough, footnotes, task lists, entities, nested lists and
quotes, images and bare links came out raw or mangled, and nothing could be
selected. It now uses MobileMarkdown, like chat, file preview and Tasks.

MobileMarkdown gains collapsible <details> sections (closed unless authored
open), the one thing only the PR parser had. Images without alt text no
longer draw the word "image".

* fix(mobile): keep <details> parsing bounded and browser-like

Cap section nesting, keep each markup scan linear on hostile input, leave
markup inside HTML comments alone, read open as a real attribute, and close
a section whose </details> sits inside a list item with that list.

* fix(mobile): close <details> at an inline </details> and ignore <details-*> tags

A </details> at the end of a paragraph or list item ends the section with
that block, as in a browser. Custom <details-menu>-style tags no longer
open a section, and heading markup in a summary keeps only its text.

* refactor(mobile): simplify <details> parsing and reuse DisclosureChevron

Keep the close-with-container mark on the node instead of a module set,
skip HTML blocks with no details markup up front, scan inline HTML once,
and turn the summary chevron the way other disclosures do.

* chore(mobile): register the <details> mdast node in a declaration file both lint gates accept

* chore(mobile): keep the lint config plain JSON
2026-11-05 21:30:33 +00: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 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
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
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
Kelvin Amoaba 35720d4e55 feat(mobile): keep unsent chat drafts and skill picks across an app restart (#38268)
* feat(mobile): keep unsent chat drafts across an app reload

Chat drafts and their skill picks lived only in the page document's
memory, so killing the app or an OTA reload lost them. Each
workspace's tab drafts are now saved in the page storage slot shells
since 0.0.59 already allow (left unused by #37900). A clear saves at
once so a sent draft never returns, and tabs the host stops listing
or the phone closes are dropped from storage. A restored draft that
leads with a skill loads the skill catalog so its chip shows again.

* fix(mobile): let a pre-load send win and keep skill scan retries

A send or clear made before a workspace's saved drafts finished
loading no longer gets overwritten by the saved text. A page whose
shell refuses the key stops re-reading it, a dropped write is retried
on the next save, and a failed skill scan is still retried the next
time the menu opens.

* fix(mobile): save pending chat typing when the app goes to the background

A write that fails partway no longer leaves a remembered value that
makes the next clear look already saved, and typing still inside the
250 ms window saves when the page is hidden.

* refactor(mobile): simplify chat draft persistence

Read the saved value back once per write through persistMirroredReadBack,
build the key with the allowlist's own workspaceScopedKey, keep tab-scope
parsing in one place, track the load as one state, stop holding
retirements once the load lands, and skip the per-draft size loop when
the whole value fits. Drops the test-only settle export.
2026-11-05 20:29:11 +00: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 6717c2887d mobile: open file paths in agent questions like the rest of chat (#38620)
* mobile(native-chat): render agent questions through chat markdown so their file paths open

Question cards, multi-step asks, awaiting-input rows and answer receipts drew the
agent's question as plain text, so paths in it did nothing. They now render through
one shared question text on the chat's markdown adapter, like desktop.

* mobile(native-chat): keep question numbers, selection and announcements in the awaiting row

Numbers sit beside each question instead of inside its markdown, transcript questions stay
selectable like transcript prose, and a pending question stays inside the row's live region.

* mobile(native-chat): key awaiting-row questions by their text, like desktop

* test(mobile): mock markdown leaves in the ask card test and match question text by content

* mobile(native-chat): keep repeated questions' keys unique in the awaiting row

* mobile(markdown): keep bold weight inside strong-toned text, so bold in a question title still stands out

* test(mobile): flatten the question title style without a type assertion
2026-11-05 12:23:26 -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
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 8e46e2066d test: remove 98 low-value mobile tests and 15 entire suites (#38637)
* test: remove 98 low-value mobile tests

* test: drop stale typecheck allowance for removed browser budget test

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 11:45:58 -08:00
c2494f891b feat(mobile): ask where to open a link tapped in chat (#33525)
* feat(mobile): ask where to open a link tapped in chat

Tapping a web link in a chat message went straight to the system browser.
It now opens a sheet with Open in Orca browser (a browser tab on the host,
like terminal links), Open in Safari, and Copy link. The Orca option is left
out where a browser tab can't open (floating workspace, host without
browser streaming). Other markdown screens keep opening links directly.

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

* fix(mobile): label the external link action "Open in browser"

The action hands the URL to the phone's default browser, which is not
always Safari, so it now says so on every platform, like the browser
setting does. The chat link routing moves into openMarkdownLink so
openMarkdownHref keeps its upstream signature.

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

* fix(mobile): open mail links in chat directly instead of the link sheet

The Orca browser rejects mailto: URLs, so the sheet's first choice failed with "Enter a valid URL". Also folds openMarkdownLink back into openMarkdownHref and drops the label-list test.

* fix(mobile): send chat web-search result taps to the link sheet too

* chore(mobile): allowlist the chat link sheet strings until session screens are localized

* fix(mobile): offer the Orca browser for a link only on a connected host known to stream it

Before the screencast probe answered, while reconnecting, or with no host client, the link sheet
offered Open in Orca browser and the tap ended in a refusal toast or nothing. It now offers only
the phone's choices until the host is connected and supports it. Tests cover the sheet's three
actions, its two-action form and a failed copy.

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

* fix(mobile): name the link sheet's phone choice "Open in system browser"

It opens whichever browser the phone is set to use, not a particular one.

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

* fix(mobile): keep the chat link sheet with the chat it was opened from

The sheet's URL lived in the session screen, so it survived a notification
switching chats and reopened when returning from a file tab. It now lives in
the chat's row overlays next to the message actions sheet, which already
resets per conversation, and stays mounted until it has slid away. The Orca
browser choice now checks the live connection; showOfflineState is never
true while a chat is on screen.

* refactor(mobile): confirm a copied chat link like other copy actions

Copy link now flips to Copied with a success haptic, as the PR menu does,
instead of a session toast, so the chat overlay no longer threads showToast.
The link handler context defaults to the system browser, which drops the
null fallbacks from its readers.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-05 19:45:51 +00:00
Kelvin Amoaba facb32d74f feat(mobile): copy a file's name or relative path from the file explorer (#38622)
* feat(mobile): copy a file's name from the file explorer

Long-pressing a file or folder row opens a sheet with Copy Name and
Copy Relative Path, named like the desktop File Explorer menu.

* fix(mobile): keep a slow copy from closing a later file's sheet

* refactor(mobile): close the file actions sheet at once, like sibling copy actions

* refactor(mobile): own the file row actions state beside its sheet
2026-11-05 19:45:35 +00:00
Kelvin Amoaba 818fb8d683 fix(mobile): keep iPad page headers clear of the window controls (#38635)
* fix(mobile): keep iPad page headers clear of the window controls

The reserved-regions probe reported the window's plain safe area, which on
iPadOS 26+ windowed mode does not cover the window controls. On iOS 27.1+
pages take their top inset from that value, so the host header sat under the
controls while native screens, which get the corner-adapted inset, cleared
them.

* fix(mobile): only raise the page's top inset for window controls
2026-11-05 19:35:07 +00: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 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 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 15caa932bc fix(mobile): make file links in phone plan approvals actionable (#38510)
* fix(mobile): make file links in phone plan approvals actionable

The phone chat view now provides its file opener through one per-chat
context. Chat markdown renders through a shared adapter that reads it,
and tool, diff and attachment targets read it directly, replacing the
onOpenFile props threaded by hand through rows and cards. The plan
approval card was the surface that never got it.

Tracked in STA-13722.

* fix(mobile): open attached files while editing a queued message

Composer attachment chips read the chat's file opener from the per-chat
context instead of the structured composer config, which the queued
message editor built without it.

* test(mobile): provide the chat file opener to the attachment preview test
2026-11-05 10:26:43 -08:00
Brennan Benson e076a683a3 fix(acp): permission prompts from an agent's own work wait for you (#38488)
* fix(acp): permission prompts from an agent's own work wait for you

A permission or question that an ACP agent (OMP, Grok, OpenCode, others)
asks during work it started itself, such as picking up a finished
background job, was answered "cancelled" at once and never shown. It now
shows as a card, raises the needs-input alert, and waits for the answer,
unless Stop, a steer or teardown cuts it short.

While OMP refuses a sent message as busy, a request from its own turn now
appears at thread level instead of being cancelled, so it never lands in
the held message's turn.

Tracked in STA-13625.

* fix(acp): keep later requests askable after a Stop, and honor the agent's withdrawal

A Stop or a card's Cancel left the chat refusing every later permission
request until the session ended; the stop now covers only the work it
interrupted. A request the agent withdraws with $/cancel_request now
withdraws its card. Cancel on a card from the agent's own work reaches the
agent even when no message is running.

* test(acp): narrow approval rows before reading their resolution

* fix(acp): a live request's card outlives its turn instead of being cancelled with it

Requests group with the active turn again, as before. A permission or question
the agent is still waiting on now stays pending and answerable when its turn
ends, is replaced, or is settled by the host; only the person's answer, the
agent's withdrawal, Stop, a steer or the session ending settles it. Settled
requests are pruned at turn end.

Stop covers only Orca's running message, so later requests from the agent's
own work can still ask. Cancel on a card with no running turn now reaches the
host from desktop and phone for every agent, and a question the agent
withdraws before its card opens no longer leaves a stuck card.

* fix(acp): never strand a live request without a card, and scope Cancel to it

A request the agent still waits on now always gets an answerable card, even
when its turn settled before the card was written, and answering it releases
the timeline's hold. Cancel on a card from an agent's own turn refuses further
requests from that turn until it ends. Desktop never turns Cancel on a card
into a whole-chat Stop on hosts that can't take a card cancel.

* fix(acp): a new message is never covered by a Stop of the agent's earlier turn

* fix(native-chat): a card's Cancel with no running turn passes the RPC schema

The cancel params required a turn whenever a card was named, so Cancel on a
card from an agent's own work (and Pi's turnless card Cancel) was rejected
before it reached the host. A background-task cancel still names its turn.

* test(rpc): a card with no running turn cancels by itself
2026-11-05 10:25:23 -08:00
OrcaWinandOrcaWin 0b5a3a4ad9 test: remove 209 low-value tests and 20 entire suites (#38605)
* test: remove low-value mobile browser tests

* test: remove low-value mobile browser tests

* test: remove native build capability replays and pin inventories

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 10:08:14 -08:00
OrcaWinandOrcaWin 90113c2265 test: remove low-value mobile browser tests (#38598)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 09:18:49 -08:00
Neil 18bab90efa refactor(main): group client RPC pairing and host runtime owners (#38584)
* refactor(main): group client RPC pairing and host runtime owners

* test: target concrete mobile notification owner in headless fixture

* test: retarget dynamic quit mocks to runtime metadata owner
2026-11-05 09:16:47 -08:00
Neil ebd724b2f8 refactor(main): group browser runtime code by defining owner (#38576) 2026-11-05 07:44:10 -08:00
OrcaWinandOrcaWin 00b56535c6 test: remove low-value native helper tests (#38552)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 05:25:57 -08:00
Neil 99b1b81feb refactor(runtime): group integration commands by concrete owner (#38504) 2026-11-05 02:43:31 -08:00
Brennan Benson 61c069aac0 Keep a Claude chat's effort changeable after its first reply (#38272)
* fix(native-chat): keep a Claude chat's effort changeable after its first turn

After its first turn a Claude chat saves the model id Claude reports it ran
(claude-opus-5-5), while the model list names that model only by its alias
(opus). Every capability lookup matched on the row id, so the chat's model
had no effort choices and effort turned into display-only text on desktop
and phone.

A listed row now describes a model id by its own id or by the model it
resolves to. The match supplies capabilities only; the chat keeps showing and
sending the exact model it ran, so it never drifts when the alias moves. The
host applies the same rule to the row it adds for the chat's model, for
clients that read the answer's models.

* test(native-chat): cover exact-row precedence for a described model id

* fix(native-chat): remember an after-reply effort without changing the new-chat model

An effort pick in a chat on the resolved id it ran is remembered under the
listed row that runs that model and leaves the new-chat model untouched, as
the common pattern keeps the sticky model and updates only its options. The
resolved id is never stored as a default.

* refactor(native-chat): move the remembered-pick model choice into its own module

* fix(native-chat): keep a held effort pick from adopting a new-chat model

* test(native-chat): run the held-effort case as a Claude launch

* revert(native-chat): drop the host-side capability copy no live answer can use

Claude's live session listing carries no resolvedModel, so the host never matched there, and phones draw the host-served chat bundle, so every client already runs the shared lookup.

* Key Claude's model rows by the model each one runs

Claude's listing named rows by alias (opus), while a chat saves the model
it ran (claude-opus-5-5) after its first turn, so equivalent chats held two
kinds of model value and a chat's effort could go read-only. Rows are now
keyed by the versioned model they run, the common pattern: a pick saves the
same id the CLI reports. Aliases stay as their own rows with their own
effort levels; the picker lists one only while the chat is on it or a
search matches it, and the phone list leaves them out. A saved alias is
kept as the user picked it. A configured alias default marks the versioned
row it runs, and an effort picked in an existing or resumed chat no longer
changes the model new chats start on, whatever ids the chat and listing use.

* test: give the delayed-report alias test's timeout its reason

* Remember a new chat's picks by its first turn, and keep aliases reachable everywhere

- A chat counts as existing once it has a turn or a send, or when it was
  opened rather than launched here, not once its launch published: an empty
  new chat's effort pick adopts its model for new chats again, and every
  agent's existing chat keeps the remembered new-chat model.
- Only a row that names itself as the model it runs covers an alias, so an
  older host's alias rows stay listed beside a chat's stand-in row.
- The phone lists an alias of a listed model behind a More models toggle.
- The terminal-chat and commit-message model lists carry each row's
  resolvedModel, so they list aliases the same way; an older remote that
  omits it keeps its full list.

* fix(mobile): keep the More models toggle's state without an effect reset

* Keep commit-message aliases selectable and their resolved model out of saved settings

The Source Control model Select has no search, so it lists alias rows after
the versioned ones instead of hiding them. Discovered models are saved
without an alias row's resolvedModel, and the refresh compares that same
saved shape, so the settings cache gains no field.

* Drop an unrelated audit-tools lockfile change; reset the phone's More models toggle when its drawer closes

* test: build the saved-models test's settings without a cast
2026-11-05 00:43:23 -08:00
Neil 9bd6272fdf refactor(tooling): organize build, CI, and test owners (#38130)
* refactor(tooling): organize test runtime and maintenance owners

* test(tooling): preserve relocated runtime fixture dependency edges

* refactor(tooling): preserve xterm routing owner checks

* ci(tooling): include routing owner in sparse checkout

* test(tooling): preserve copied workflow dependency closures

* fix(tooling): normalize hashed JSON assets in release parity

* fix(tooling): distinguish asset aliases from literal references

* fix(tooling): frame normalized asset reference payloads

* fix(tooling): normalize decoded JSON asset references

* refactor(tooling): organize build, CI and release owners

* fix(tooling): align moved generator and workflow path contracts

* fix(tooling): update generated plugin bundle owner banners

* test(tooling): create relocated mobile verifier fixture directories

* test(tooling): copy headless detector dependency closure

* test(tooling): align native batch policy fixtures with owner path

* fix(tooling): link moved reliability command to historical evidence

* fix(tooling): preserve nested sandbox owners and canonical guide source

* fix(tooling): target release version owners in checkout fixture
2026-11-04 21:08:19 -08:00
Brennan Benson 274b99919f Keep the phone's chat Send button the same as desktop while the agent works (#38317)
* fix(mobile): the chat Send button keeps desktop's arrow while the agent works

#36588 swapped the phone's send icon and label for Queue or Steer while
a turn ran; desktop keeps the plain Send arrow and offers the other way
through Cmd/Ctrl+Enter. The phone now matches, with hold as its
alternate.

* test(mobile): the send button keeps its arrow while the agent works
2026-11-04 19:30:11 -08:00
Brennan Benson 025c79b05c New chats run the agent's configured model when you haven't picked one (#38252)
* New chats run the agent's configured model when no model was picked

A new chat with no model pick sent the default Orca had learned from an
earlier chat on its first message, so the agent ran that remembered model
instead of the one its own configuration now chooses (STA-13542: OMP chats
ignoring config.yml). Unpicked defaults are now shown but never sent, for
model as already for effort; the Claude create/send fallback no longer
turns a shown default or an agent report into the chat's own model.

* Phone declared-effort test: only saved models are sent
2026-11-04 18:01:06 -08:00
Brennan Benson e5a960cbf9 Show changed files directly in chat turns (#38256)
* Show changed files directly in chat turns

* Use the fixture frame for the diff interaction

* Keep changed filenames readable and preserve file actions

* Keep unconfirmed file changes in tool activity

* Capture changed files in completed transcript fixtures

* Preserve patch data with authoritative history status

* Keep mobile diff interaction coverage beside its card

* Assert the decoded patch line contract

* Exercise full returned history in catch-up coverage

* test(chat): target file summary when reopening patches
2026-11-04 17:53:16 -08:00
Brennan Benson da904ad40c Say where to switch back from Chat UI wherever Orca turns it on (#38243)
* Say where to switch back from Chat UI wherever Orca turns it on

The Chat UI tip pointed to Settings → Agents, which users did not guess, and turning
Chat UI on from the tip or picking it in onboarding gave no reminder of where to undo it.
Point every surface at the Chat UI is on / Turn off switch in Settings → Chat UI, and
confirm the switch with a toast that names that path.

* Point browser and phone users at their own switch-back control, and word the toast as a default change

The browser client has no Chat UI launch switch, so its onboarding note names the
Onboarding checklist. Phone onboarding names Settings → Chat UI. The toast after Use
Chat UI says Chat UI became the default for new agents, since agents with their own
choice keep it.
2026-11-04 16:15:17 -08:00
Brennan BensonandJames Hart 776917931b fix(mobile): send chat with Cmd/Ctrl+Enter (#38267)
* fix(mobile): send chat with the hardware keyboard modifier shortcut

Co-authored-by: James Hart <hjhart@gmail.com>

* test(mobile): provide attach icons for keyboard completion cases

* test(mobile): use a named native type import in keyboard coverage

---------

Co-authored-by: James Hart <hjhart@gmail.com>
2026-11-04 16:14:32 -08:00
OrcaWinandCodex 129999a4a7 Remove 382 low-value test cases and 46 whole suites (#38238)
* Remove low-value renderer and main tests

382 registrations removed; 46 whole suites deleted.

* Remove deleted-suite exclusions and use deterministic cache timestamp

---------

Co-authored-by: Codex <codex@openai.com>
2026-11-04 14:19:36 -08:00
Kelvin Amoaba 30c7dc022f chore(mobile): bump to 0.0.64 and Android versionCode 28 (#38230) 2026-11-04 21:23:41 +00:00
Kelvin Amoaba aaf4a95166 fix(mobile): address android auto quit (#38226)
* fix(mobile): address android auto quit

Android has no 'tabbar' accessibility role and throws when the Home tab bar mounts, killing the app on every launch of 0.0.63. Use 'tablist', which both platforms support.

* fix(mobile): keep the tab-bar accessibility trait on iOS

'tablist' maps to no trait on iOS, so VoiceOver stopped announcing the Home tabs as a tab bar. Only Android lacks 'tabbar'.
2026-11-04 21:18:59 +00:00
OrcaWinandCodex 31d0f53cd9 Remove 230 low-value main, renderer, and mobile test cases (#38223)
Delete 19 whole suites and update coverage metadata and reduced flaky-pattern counts.

Co-authored-by: Codex <codex@openai.com>
2026-11-04 12:59:51 -08:00
Kelvin Amoaba b8969c9c53 feat(mobile): split Home into Feed, Usage, Automations and Settings tabs (#38206)
* revert(mobile): drop the details card on session tab taps

Reverts 852391da0f (#36395). The card popped up on every tab switch.
Tapping a tab switches tabs again, and the session title card goes back
to its own owner from #30389. Keeps later changes to these files: tab
press feedback, the compact top bar's + button, and #36866's keyboard
keep-focus for title taps.

* fix(mobile): hide branch and folder when the setting is off

The phone's workspace row always printed the branch or folder path, so the
Branch name / Branch / folder path toggle under Card display did nothing.
The shared card details now carry that rule, and the row reads it.

* fix(mobile): centre the chevron on Home list rows

* fix(mobile): scroll sheets taller than the screen

Content-sized sheets ride the keyboard by translation, but their height cap ignored that lift, so a tall sheet pushed its top off screen with no way to scroll back to it. The cap now gives back the keyboard lift. Sheets that scroll their own list can now shrink to the cap instead of clipping it, and the GitHub Pages picker no longer nests its list inside the drawer's ScrollView.

* feat(mobile): show each desktop's machine kind and model

The desktop now reports whether it is a laptop, desktop or server, and its
model, on status.get. The phone stores it with the other last-known host
fields and turns it into a line like "MacBook Pro · macOS".

* feat(mobile): edit a host from its screen and align the Automations bar

The host screen's menu gains Edit host and Network diagnostics. Edit host moves
onto the standard bar and gains Remove host. Automations uses the standard bar
with its switcher pinned under it, as Source Control does.

* feat(mobile): arrange Home and bring back stats and account usage

Home drops the Jump back in times, names the repo on every Jump back in row
(#37642), shows each desktop's machine kind, and adds stats and account usage
at the bottom. A new Arrange button reorders and hides sections, saved on the
phone.

* fix(mobile): keep the page bundle within budget and show the machine on the host screen

The edit route gets a web stub so its native-only removal flow stays out of
the page's chunks, and Automations keeps its own segment style. The host
screen header shows the machine line like Home does.

* fix(mobile): give the edit route's page stub its own module

A bare re-export of the catch-all route compiled to the same asset as
[...page], so the page manifest listed it twice and the desktop template's
inventory check refused the build.

* feat(mobile): turn Home into Feed, Usage, Automations and Settings tabs

Feed keeps agents (needs-you first, five then Show all), desktops with a
needs-you count, and Tasks; New workspace moves to a floating button.
Usage shows stats and per-desktop account usage, Automations a per-desktop
summary with on/off switches that opens the page for editing (new=1 opens
its editor). Settings becomes a tab. Arrange Home is removed: tabs replace
the long scrolling Home it was for.

* style(mobile): darken the accent blue slightly

* style(mobile): give the Home Tasks row the desktop tile icon

* style(mobile): condense the Home Feed

Smaller tiles, type and gaps; a desktop is two lines with its needs-you
count as an amber pill; the Tasks row drops its duplicate heading.

* style(mobile): drop the Last known prefix on Home desktop rows

* chore(mobile): bump to 0.0.63 and Android versionCode 27

* test(mobile): re-record Linear task recordings for the darker accent blue

* test(mobile): check the page Back stack on Tasks now that Edit host is native

* fix(mobile): pass the Usage tab's limit window to the shared usage helpers

* fix(mobile): type the Usage tab test to the account-slot limits and keep the tab under 400 lines
2026-11-04 20:35:53 +00:00
Kelvin Amoaba a71ad90883 fix(mobile): keep reasoning effort as segments for every level count (#38200) 2026-11-04 19:30:25 +00:00
Kelvin Amoaba 18fa4f8a6d feat(mobile): title Jump back in rows with the conversation name (#38194)
Rows named only the workspace, so with several agents in one workspace they didn't say which conversation needed you. The newest live top-level agent in the row's dot state now gives the title, the workspace moves to the subtitle, and tapping the row opens that conversation's tab. Older desktops send no names and keep the workspace title.
2026-11-04 19:30:09 +00:00
Kelvin Amoaba 0ffb87fc18 feat(mobile): show usage for every agent desktop tracks on the Accounts screen (#38187)
* feat(mobile): show every desktop usage provider on Accounts

* refactor(status-bar): import moved usage helpers from shared

* refactor(mobile): reuse shared usage rules for provider names and data checks

* test(mobile): type account-slot fixtures as Claude/Codex limits
2026-11-04 19:29:54 +00:00
d3d157756a fix(mobile): make the app icon full-bleed so iOS masks it cleanly (#37074)
icon.png shipped its own rounded corners, transparent corners and a bright
bevel. iOS applies its own corner mask on top, so the bevel showed as a sharp
light outline, most visibly on Spotlight's search results.

Replace the bevel and corners with the icon's existing vertical gradient,
extended to a square opaque 1024x1024 RGB image. The logo is unchanged.

Verified by pixel checks (no alpha channel; rows outside the logo are uniform;
no logo-region pixel moved by more than 6/255) and a simulated iOS mask. Not
yet checked on a device.

Fixes #26834

Co-authored-by: Rongzheng Liu <tianlrz@users.noreply.github.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-04 19:29:38 +00:00
OrcaWinandOrcaWin 25cd81665e test: remove 675 low-value test declarations (#38129)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-04 04:51:57 -08:00
OrcaWinandOrcaWin b17646a5d9 test: remove 2191 low-value test declarations (#38113)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-04 03:40:25 -08:00
Brennan Benson 974bb4a7ca Preserve chat inputs through uncertain delivery and Stop (#32267)
* Give unconfirmed chat messages explicit recovery actions

* Resolve receipt settlement code quality findings

* Complete recovery copy localization and callback types

* Align send lifecycle contracts with explicit recovery actions

* Include the unconfirmed opener in the restart fixture type

* fix(chat): preserve recovery ownership across lifecycle boundaries

* Preserve send ownership across context replacement and recovery

* Separate history ingestion from live send settlement

* Preserve original send truth and reconcile acquired history

* Use summary-shaped history responses in acquisition coverage

* Preserve queued image recovery for released readers

* Prove independent late receipt recovery across reopen

* Preserve queued image sources in bounded catch-up projection

* Keep queued input and explicit chat retries in their original domains

* Preserve reader lifetime across main session interfaces

* Fix static checks after main integration

* Migrate retained recovery Stop contracts to current lifecycle

* test: use typed access for journal population counters

* fix: consolidate history page bounds type imports

* test: exercise legacy snapshot reuse through selected handoff

* Fix attachment draft typing and document test boundary casts

* Repair current journal integration types and contract fixtures

* Keep uncertain send recovery in queue reorder reopen contract

* Repair mobile contract boundaries and exact queue lookup

* Align input finalization contracts with current Stop ordering

* Keep recovery copies independent of queued message barriers

* Reconcile Stop and replay contracts with current lifecycle

* Update recovery tests for current module and draft APIs

* Align Stop recovery contracts with independent queue policy

* Expose independent recoveries to current queue controls

* Cover sending-only queue Resume visibility

* Adapt recovery contracts to shared queue projection

* Use current history and failure-word contracts in recovery tests

* test: retain released reader source contracts through queue settlement

* Keep uncertain sends in ordinary history and preserve saved queue choices

* test: prove mobile draft leaf subscription isolation

* Use typed operation instrumentation in mobile recovery test

* Align lifecycle test boundary typing with static rules

* Repair test module typing and retained runtime copy catalog

* Remove unused chat delivery notice translations

* test(chat): retain legacy handback without uncertainty notice

* fix(chat): omit saved uncertainty card captions

* test: bind released readers to exact queue wire and proof

* Replace archived reader evaluator with exact recorded contracts

* Mark queued edit test hook import as type-only

* Isolate queued card tests from native inline composer imports

* Complete structured mobile resolution in queued edit test

* Align mobile attachment cleanup lifetime test with send outcomes

* fix: restore journal prototype delegation methods

* Keep uncertain sends as ordinary messages in memory

* Release notes admission after uncertain opening completes

* fix: end opening selection operations at uncertain completion

* fix: derive selection admission from live requests and repair integration tests

* test: consolidate send imports and use a supported locale

* Fix CI test types and synchronize retired delivery catalogs

* Type exported test fixture mocks through the public Vitest API

* test: align selection and journal verification contracts

* Reconcile acquired history before journal projection

* Preserve saved invocation facts during history catch-up

* Repair journal recovery consumers and CI contracts

* Keep failed legacy import displays serializable and bounded

* Preserve journal owner boundaries in CI import cleanup

* Fix typed test fixtures for session recovery contracts

* fix: align history and recovery contract types

* test: verify logical rewind across released chats

* Bound retained queue and status reads

* Bound Stop and delivery reads to relevant journal inputs

* Bound subscriber catch-up and stopped-history reads

* test: align journal read fixtures and operation counts

* Bound automatic chat reads to current input evidence

* fix: align journal reader contracts and test fixtures

* test: type historical dispatch rejection fixtures

* fix: restore merged session projection and fixture types

* fix: preserve resumed queues across logical fork rewind

* Preserve queue pause chronology across logical rewinds

Keep original Stop and Resume coordinates while retaining matching warm failure evidence in the journal owner. Keep historical fixture authoring separate from current production writes.

* End historical fixture authoring before current queue actions

* Keep answer operations separate from retained messages

* Fix resting chat attention context

* Fix attention regression fixture provenance

* Validate retained RPC test frame reads

* Fix retained attention and RPC contract fixtures

* Keep send observations on canonical delivery evidence
2026-11-04 02:40:10 -08:00
OrcaWinandOrcaWin 6792990b83 test: remove 1015 low-value test declarations (#38087)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-04 01:39:49 -08:00
OrcaWinandOrcaWin 25994e0b94 test: remove 1460 low-value test declarations (#38082)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-04 00:25:44 -08:00