* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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.
* 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
* 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
* 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
* 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>
* 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>
* 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
* 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
* 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
* 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>
* 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
* 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
* 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
* 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