* 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
* 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
* 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
* 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
* 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.
* 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>
* 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'.
* 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
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.
* 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
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>
* 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
* feat(mobile): bring back the terminal key row and one live input
Every terminal tab, shell or agent, gets the dock from before #36166:
the scrolling key row (desktop width, Paste, the built-in keys, custom
keys, add) above one live field that types straight into the terminal,
with the attach and mic buttons beside it. The field keeps today's 3:1
outline and focus ring, and the keys use today's chips and press styles.
The Keys/Message toggle, the Message composer, the arrow pad, the ⋯
sheet on the row and the per-terminal mode preference go. A stored mode
from an older build is never read. Sticky ctrl/alt/shift and the More
keys sheet stay only behind the iPhone Duo rail, which shipped shells
still draw; the page reports no composer, so shipped shells grey their
input-mode key and newer shells hide it.
* refactor(mobile): delete the buffered terminal line
With one live input there is no way to write a terminal line first and
send it, so the per-terminal drafts and their storage, the Send path,
command-field dictation, draft restoration and the terminal setting for
autocomplete and autocorrect (which only applied to that line) go.
Dictation in a terminal always types into it live. Drafts and the setting
saved by older builds are never read.
* Add Ultracode to Claude chat effort
* Correct Ultracode test type annotations
* Keep Claude workflow effort observations consistent
* Make effort picker test follow async option contract
* Keep effort coverage at its owning behavior layer
* Exercise workflow readback with recorded native settings
* Preserve configured workflow during effort reapplication
* fix: respect manual workspace order around primary checkouts
* test: consolidate manual primary-order coverage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: name twin-reorder cases after the dragged linked worktree
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: read worktree ID from mobile workspace row
* test: exercise primary checkout drops in reorder cases
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Show cancelled PR checks as Cancelled with separate counts on desktop and mobile, preserving genuine failures, pending checks, existing action permissions and older-client fallback. Carry complete provider summaries through caches and presentation; preserve Azure source completeness, folder attention priority and muted cancellation details.
Tracked in #15847 and STA-5102.
Backport upstream matching and abort fixes plus safe deepmerge property handling across the independent workspaces. Includes installed-package regression tests and audit-tool fixture repair. Agent-reviewed at 83ca381d519e6247d7c1b3f0a52ce2907a9f9a19; CI aggregate passed. Version-based scanner alerts remain open pending documented disposition or compatible upstream releases.
Keep orchestration start, handoff and mail notices in one-line bordered cards on desktop and phone. Expand each card to read the original message and attachments, while Copy and sender navigation remain independent.
Credit to Vyacheslav Scherbinin (@gentslava) for the community contribution in #33403.
Co-authored-by: Vyacheslav Scherbinin <gentslava@mail.ru>
* refactor(mobile): keep phone list facts beside the desktop's worktree row
The phone wrote its own list facts (lineage depth, host labels, list keys
and so on) onto the worktree.ps row object it got from the desktop, so a
desktop field with one of those names would be read as the phone's own.
List items are now { row, view }: the row is the desktop's, typed from the
shared RuntimeWorktreePsSummary contract, and view holds what the phone
works out. Host labels are a lookup beside the rows instead of fields on
them. A type test fails if the desktop row gains a view field's name or a
type the phone row would not accept, and a contract test feeds rows from
the desktop's own worktree.ps builder through the phone list.
* fix(mobile): type desktop replies from shared contracts and reject unchecked rows (#37923)
* wip: contract guards
* fix(mobile): type desktop replies from the shared contracts and ban unchecked z.custom
Session tabs, the createSupport reply and native-chat frames were typed by
hand on the phone, so a desktop change could leave the phone compiling
against a stale shape. They are now Pick/Partial of shared types; the
createSupport reply and native-chat transcript frames gain shared types the
desktop uses too, which also gives the phone the 'chat-program' reason it
was missing. Type tests fail when a desktop tab gains a phone-only name or
a field type the phone would not accept.
Catalog rows were admitted with z.custom<Worktree>() and no check. They now
need a string worktreeId, and an ast-grep rule rejects a z.custom with no
check anywhere in mobile/src.
* test(mobile): the desktop contract check also catches a null the phone would not accept
* Keep async question answers stable until delivery
* Cover pending answers with recorded question input
* Cancel delayed answers when question controls disable
* Scope pending question answers to their form and journal order
* Verify revised questions and handover ordering through production sources
* Use typed phone answer fixtures
* Reuse answer delivery evidence and skip unquoted queue matching
* Supply derived journal scope in the translator regression
* Use named type imports for mobile question contracts
* Exercise canonical pending rows and buffered phone read coverage
* Align phone controller assertions with optional send intent
* Supply transcript metadata for phone question test fixtures
* Fix question prompt test literal typing
* fix(claude): reflect model fallback in chat and composer
* test(claude): reproduce fallback display before and after
* fix(i18n): ship the model fallback notice in the runtime catalog
* fix(mobile): ship the model fallback notice in the runtime catalog
* fix(claude): accept unnamed init models in response observations
* fix(claude): keep fallback observations display-only
Response model metadata must not satisfy delayed input evidence or
change saved launch preferences.
* test(claude): type fallback regression fixtures
* test(claude): expect init model display reports
---------
Co-authored-by: Vyacheslav Scherbinin <gentslava@mail.ru>