Commit Graph
1960 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin 92ef9440db test: remove 221 low-value cloud, mobile and journal tests (#39449)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 02:12:41 -08:00
Kelvin Amoaba 1283e070e3 feat(mobile): transcribe dictation on iPhone with Apple's on-device speech model (#39410)
* feat(mobile): transcribe dictation on device with SpeechTranscriber on iOS 26

* fix(mobile): fall back to the dictation model, reserve locales and stop a finishing session on cancel

* fix(mobile): resolve on-device speech locales deterministically and report the simulator unsupported

* refactor(mobile): simplify the on-device speech engine and skip conversion when formats match
2026-11-07 09:51:50 +00:00
Kelvin Amoaba ffaf887e78 feat(mobile): transcribe dictation on the phone, with the computer as fallback (#39386)
* feat(mobile): define the on-device speech contract for the native audio module and page bridge

* feat(mobile): dictate on the phone first and replay to the computer when the phone fails

* refactor(mobile): type the on-device speech module without a cast

* fix(mobile): point dictation's finish ref at the committed callback

* test(mobile): wait on the takeover request instead of a fixed sleep

* fix(mobile): release each dictation request's own share of a replayed backlog

* fix(mobile): let the computer's text replace the phone's after a fallback
2026-11-07 09:37:45 +00:00
Kelvin Amoaba 5adbcac511 feat(mobile): transcribe dictation on Android phones on-device (#39428)
* feat(mobile): recognize dictation on-device on Android with ML Kit

* feat(mobile): fall back to Android's on-device recognizer on phones without AICore

* fix(mobile): keep on-device speech events and finishes tied to the current session

* fix(mobile): let an ended on-device session release the recognizer before the next starts

* refactor(mobile): trim the Android on-device speech engines
2026-11-07 09:32:22 +00:00
Kelvin Amoaba 6da544b757 feat(speech): number the text so far in phone and web dictation replies, split into committed and tentative (#39396) 2026-11-07 08:56:50 +00:00
Neil 31e7f86c3f fix(mobile): give list screens' create button the accent fill in dark mode (#39359)
The New workspace and New issue discs on the host and Tasks screens were
a pale #e5e5e5 fill that glared on the dark page. Dark mode now uses the
same accent fill as the Home + button; light mode keeps its dark fill.

Refs #37401
2026-11-07 00:20:26 -08:00
Neil 6547009e18 feat(mobile): exchange the scanned pairing code for a token kept on the phone (#38938)
* feat(mobile): exchange the scanned pairing code for a token kept on the phone

When the desktop advertises pairing.ticket-exchange.v1, the phone sends a
token it generated as the last call on the winning pairing socket and saves
that token instead of the scanned one. For Relay pairings the journal is
rewritten first so recovery republishes the same token. Any failure keeps
the scanned code, which the desktop still accepts.

* fix(mobile): say a refused pairing code may already have been used

Single-use pairing codes are refused once another device signs in with
them, so the scan error now mentions that case alongside expiry and
replacement, and still asks for a new code from the desktop.
2026-11-07 00:04:36 -08:00
Neil 111bedc290 feat(antigravity): run Chat on the host's agy acp when compatible (#39006)
* feat(antigravity): run Chat on the host's agy acp when compatible

New Antigravity chats prefer a compatible host-local `agy acp` (initialize
must answer as "Antigravity ACP Server" >= 1.5.2, protocol 1, loadSession and
session/resume) and fall back to Orca's managed runtime otherwise. The chat's
account home pins its backend, so resume and auth failures never switch it.
Managed chats and their <userData>/antigravity-chat sign-in are unchanged.

Refs #38833, STA-14062

* test(acp): launch an attached host rig with its spec

* fix(antigravity): keep Orca's Chat sign-in, back off a hung agy, and never downgrade permissions

The host's agy takes a new chat only when nobody is signed in to Orca's own
Chat and agy has its own credential. A failed check waits 5 minutes before
retrying (5 s timeout). Full-access chats stay on Orca's runtime, and a host
chat refuses a permission mode agy lacks instead of asking.

* fix(antigravity): check agy's sign-in without a keychain prompt, ignore inherited API keys, allow own mode

agy falls back to an inherited GEMINI_API_KEY, which its models reject, so
host chats drop it. The macOS presence check reads only the keychain item's
attributes. Chats in agents' own permission mode may use the host's agy.

* fix(native-chat): show Orca's install card only for chats on the managed runtime

The status summary marks chats pinned to a host program (hostProgram), so a
chat on the host's agy is no longer blocked when Orca's runtime is missing.

* fix(mobile): show host agy sign-in copy for Antigravity chats

The desktop host now reports antigravitySystemNotSignedIn when a chat on the
host's agy is signed out; give the phone the same copy so its failure table
stays complete.
2026-11-06 23:44:54 -08:00
OrcaWinandOrcaWin ff416c2f6c test: remove 181 low-value mobile, CI and runtime tests (#39351)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 23:39:35 -08:00
Kelvin Amoaba 64d811bde0 feat(mobile): send phone dictation audio every 150 ms with at most four chunks in flight (#39341)
Each chunk RPC holds one of the page bridge's 60 desktop request slots until
the host answers, through a reconnect too, so the page drained the microphone
only every 500 ms. Cap chunk sends at four per dictation and merge audio
captured meanwhile into the next request, then drain every 150 ms.
2026-11-07 07:25:10 +00:00
OrcaWinandOrcaWin f5f45784e2 test: remove 212 low-value mobile shell and routing tests (#39334)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 23:07:50 -08:00
OrcaWinandOrcaWin 4468deb34e test: remove 76 low-value fork and UI tests (#39321)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 22:49:58 -08:00
Jinwoo Hong 0e36bfa4a7 fix(automations): send managed SSH host automations to its Orca server (#39160)
* fix(automations): send managed SSH host automations to its Orca server

A managed SSH host's automations live on its Orca server (#24863), but the
create dialog, CLI and mobile still saved desktop copies that never ran.

- Desktop dialog: the host's desktop SSH entry is no longer offered; its
  key resolves to the host's server entry.
- CLI create routes to the server by project id, or asks to move the
  project there first; mobile hands the create to the server's editor.
- Existing desktop copies skip with "{host} now runs automations on its
  Orca server" and offer "Move to {host}" through the editor's move save.

STA-13422

* fix(automations): address review on managed SSH host routing

- CLI: refuse a desktop copy when the desktop reports a managed host this
  CLI holds no server for; pass the workspace by id to the server; check
  field support on the server too.
- Main: the skip follows the owner selector, so local rows pinned to a
  managed host's workspace skip too.
- Editor: a destination host whose project table loads after open keeps
  the chosen project.

* fix(automations): refuse new desktop rows on a managed SSH host and move leftovers

Per review and the owner's follow-up:
- The desktop's automation create/update refuses a row on a managed SSH
  host ("Move this project to {host} first."), covering CLI, mobile, raw
  RPC and older clients.
- Existing desktop copies move to the host's Orca server on startup, on
  managed connect and on their due tick: created there keyed by the
  desktop row id, then removed here. A server without the project leaves
  the skip and the Move button.
- Mobile drops the Save-time hand-off; its picker no longer offers a
  managed host's desktop SSH setup.
- CLI routes only for a local client, using that client's profile.

* fix(automations): drop the automatic leftover move

A managed host's leftover desktop rows keep the skip reason and the
Move to {host} button; moving them automatically will extend the existing
managed-host migration in a follow-up.

* fix(cli): resolve an automation's SSH destination from the repo's routing id

* chore: prune the repo host read baseline for the CLI destination

* fix(automations): migrate a leftover automation in one click

The detail banner's Migrate runs the editor's own move-to-server save without
opening the dialog. Leftovers show Needs migration instead of Enabled, and
their skipped runs read Needs migration to {host}.

* fix(automations): wrap the Needs migration status instead of cutting it off

* fix(automations): name a leftover's project from its migrated copy

* fix(automations): save a host move against the project table loaded after the editor opened

Migrate loads the server's repo table first, but the save transaction read the
destination captured before that load, so the first click on a cold catalog was
refused. Save now reads the same derived destination the form already shows.

* fix(automations): drop the leftover project-name fallback

The global id lookup could name another host's project. Scoping it to the
leftover's server is not worth the code for a display-only label, so a leftover
whose project moved shows Unknown project again.

* fix(automations): name a leftover's project from its migrated copy

A managed SSH leftover's project always moves to the host's Orca server with
the same id, so only those rows fall back to the id lookup; any other row with a
missing project stays Unknown project.
2026-11-07 01:47:06 -05:00
Kelvin Amoaba 7fdb80ac21 feat(dictation): let the computer, phones and web client dictate at the same time (#39305)
* feat(speech): let several devices dictate at once on one recognizer

The host ran one dictation at a time, so a phone dictating blocked the
desktop, the web client and every other phone. Each dictation now opens
its own stream on the one loaded recognizer, capped at four, and a start
that needs a different model is refused while others use the loaded one.

* feat(dictation): explain the device limit and a busy model on desktop and phone

* docs(web): say the host has several dictation slots

* fix(speech): free an idle recognizer for cloud dictation and drop canceled starts from the device count

* test(speech): drop a deletion test that only pinned the old single-session limit

* refactor(speech): drop a canceled start from the map instead of flagging it

* refactor(speech): tag stop, discard and feed requests with their stream on the new base

* fix(speech): satisfy the type-aware lint on waiting for stopping sessions

* fix(speech): copy only the fed view of a sub-buffer, and call it a speech model in the busy copy

* fix(speech): bind a starting session to its recognizer in the step that picks it
2026-11-07 06:37:58 +00:00
Kelvin Amoaba e956b1902e fix(mobile): keep an unconfirmed Tasks comment draft when someone else posts the same text (#39259)
An unconfirmed send settled as posted when the refreshed thread had any new
comment with the same text, so another person's identical comment cleared the
draft. The host now passes GitHub's viewerDidAuthor, and the phone settles only
on a comment the viewer wrote. Without it (GitLab, REST fallbacks, older hosts)
the draft stays with the check-the-thread notice.
2026-11-07 05:20:48 +00:00
Kelvin Amoaba df38124cce refactor(mobile): drop the unused playback path from the dictation audio module (#39293) 2026-11-07 05:03:22 +00:00
Kelvin Amoaba f89638f2b4 perf(mobile): return to LAN soon after joining Wi-Fi (#39165)
* perf(mobile): return to LAN soon after joining Wi-Fi

* perf(mobile): allow one arrival per dwell and keep 12 s for Tailscale probes

* perf(mobile): defer a second arrival to the dwell and keep 12 s for non-private hosts

* refactor(mobile): share one network read across hosts and build the fingerprint once
2026-11-07 04:58:07 +00:00
Kelvin Amoaba 1813a01fa6 perf(browser): credit screencast frames to the phone (#39189) 2026-11-07 04:57:47 +00:00
Kelvin Amoaba f9b95a7b6f perf(mobile): ack terminal output after xterm parses it (#39151)
* perf(mobile): ack terminal output after xterm parses it

* fix(mobile): retry refused terminal acks and share one ack across echoes

* fix(mobile): retry a refused terminal ack on the timer, never inline

* test(mobile): keep only terminal credit tests that fail without it

* refactor(mobile): key terminal ack settles by stream token

* test(mobile): type the credit test timer steps

* test(mobile): use T[] for the parsed callback list
2026-11-07 04:57:18 +00:00
Kelvin Amoaba a319c0eccb fix(mobile): bring attachments back with an unconfirmed chat send (#39258)
* fix(mobile): bring attachments back with an unconfirmed chat send

* refactor(mobile): share the draft chip removal and build the send intent once
2026-11-07 04:56:26 +00:00
Kelvin Amoaba f29c96745c perf(mobile): stop recomputing chat row keys and projection on every commit (#39216)
* perf(mobile): stop recomputing chat row keys and projection on every commit

* refactor(mobile): drop write-only grouped field from chat projection
2026-11-07 04:56:12 +00:00
Kelvin Amoaba 0e5d2cb5ea fix(mobile): keep a parked chat reader steady while a reply streams (#39209)
React Native Web repeats the last scroll event 100 ms after scrolling
stops. The page list cleared its record of its own scroll write on the
first matching event, so the repeat after each place-keeping correction
counted as the reader scrolling. For a parked reader that froze the
streaming reply below for 300 ms about every 0.7 s and released it in
one step, which showed as lurches of 20-40 px.
2026-11-07 04:55:58 +00:00
Kelvin Amoaba 2980a713c8 perf(mobile): use mobile-only chat coalesce and reveal timings (#39183) 2026-11-07 04:55:44 +00:00
Kelvin Amoaba 6708f76690 perf(mobile): show the model picker's models as soon as a chat opens (#39152)
* perf(mobile): show the model picker's models as soon as a chat opens

* fix(mobile): retry skill scans and trailing command reads through the query

* fix(mobile): keep menu-read commands across a re-probe and rescan skills on demand

* refactor(mobile): read chat query state from the client and give the model catalog query its own module

* test(mobile): give the reopen seed catalog its fetchedAt

* fix(mobile): keep the query layer out of the phone options hook's module graph
2026-11-07 04:55:30 +00:00
Kelvin Amoaba 9d32a61bb4 perf(mobile): load the new-tab agent list with the session and share it with "Fix with" labels (#39148)
* perf(mobile): load the new-tab agent list with the session and share it with "Fix with" labels

* fix(mobile): wait for host status before detecting agents

* fix(mobile): read the agent list again on each open after a failed read

* refactor(mobile): name the source control agent through the shared label hook

* chore(mobile): type the new-tab recording adapter with a type import
2026-11-07 04:55:16 +00:00
Kelvin Amoaba b0cd6d391c perf(mobile): open a session with its last tab strip (#39158) 2026-11-07 04:55:01 +00:00
Kelvin Amoaba 1763014bea perf(mobile): reopen Files folders from memory (#39175)
* perf(mobile): reopen Files folders from memory

* test(mobile): re-record Files explorer goldens for query reads

* fix(mobile): paint cached Files rows before the host client attaches

* refactor(mobile): share query observer options and Files' empty-state rules

* test(mobile): type the Files explorer test host
2026-11-07 04:41:21 +00:00
Kelvin Amoaba 51f532115e perf(mobile): open Review with the Changes data already loaded (#39159)
* perf(mobile): open Review with the Changes data already loaded

* fix(mobile): keep the open diff through re-keys and wait for Review rebuilds

* fix(mobile): release Review writes once their files show, retry only fixed diffs

* fix(mobile): follow language switches in Review's diff states

* fix(mobile): keep Changes' compare key out of render and type the Review adapters
2026-11-07 04:41:07 +00:00
Kelvin Amoaba c108ee4ea7 fix(mobile): reread Source Control settings when a screen opens or the app returns (#39266)
* fix(mobile): reread Source Control settings when a screen opens or the app returns

* test(mobile): use the shared hook harness for the settings reread test
2026-11-07 04:05:49 +00:00
Kelvin Amoaba 93187e7d66 feat(mobile): show a thin refresh line under the header while cached data refreshes (#39170)
* feat(mobile): show a thin refresh line under the header while cached data refreshes

* fix(mobile): start the refresh line still under unknown motion and key it by execution host

* fix(mobile): draw the refresh line only once the motion preference is known

* fix(mobile): start the refresh sweep at the left edge on each reveal

* refactor(mobile): drive the refresh line from the screen's own refetch and keep its timers in the header

* test(mobile): give the Changes content fixture the new refreshing field
2026-11-07 04:05:35 +00:00
Kelvin Amoaba 309b9b66e6 perf(mobile): stop a hidden host list refetching on every change (#39210)
* perf(mobile): stop a hidden host list refetching on every change

The host list's change-event path fetched worktree.ps (and the server rows read) on every worktreesChanged or reposChanged with no throttle, even while the page was buried under a session or the app was backgrounded. Hidden pages now note what they owe and the foreground refresh catches up once; visible pages read at most once per 3 s.

* perf(mobile): count poll reads in the change throttle and queue the catch-up read

* perf(mobile): leave the poll out of the change throttle and queue the catch-up only after skipped notices

* test(mobile): drop the throttle timing test

* refactor(mobile): one owed flag and one full catch-up read for a hidden host list
2026-11-07 04:05:20 +00:00
Kelvin Amoaba c158c82c71 perf(mobile): skip the Suspense fallback on page boot (#39184)
* perf(mobile): skip the Suspense fallback on page boot

* fix(mobile): keep open-target boots on the lazy path

* test(mobile): pin that the page waits for its held route chunk

* refactor(mobile): preload every page layout and keep screens apart
2026-11-07 04:04:45 +00:00
Kelvin Amoaba 0f854c5209 perf(mobile): render the cached page build first and talk only after the connection's verdict (#39174)
* perf(mobile): render the cached page build first and talk only after the connection's verdict

* test(mobile): give ready shell states their page window
2026-11-07 04:04:32 +00:00
Kelvin Amoaba 22f09f4257 refactor(mobile): read host capabilities from one status read per connection (#39157) 2026-11-07 04:04:19 +00:00
Kelvin Amoaba cc6a66ed01 feat(mobile): let pages read and write the device store (#39147)
* feat(mobile): let pages read and write the device store

* fix(mobile): import zod as a namespace in the page store verb

The page bundle check rejects `import { z }`: it ships zod's locale tables.
2026-11-07 04:02:52 +00:00
Kelvin Amoaba bd88cdeca8 perf(mobile): trim the page bundle back under its old budget (#39182)
* perf(mobile): trim the page bundle back under its old budget

* build(mobile): simplify the route entry anchors and zod table guard

* fix(mobile): import zod as a type in the RPC result reader
2026-11-07 03:28:04 +00:00
Brennan Benson c6f07596ad Phone chat: empty Cmd/Ctrl+Enter steers the first queued message, and holding Cmd/Ctrl shows what it will do (#39215)
* fix(mobile): Cmd/Ctrl+Enter on an empty chat composer steers the first queued message

Matches desktop (#38732) in the paired web page: with nothing typed, the
chord steers the head waiting card through that card's own Steer, only
where its other way is steer.

* fix(mobile): empty Cmd/Ctrl+Enter sends the first queued card after a Stop, as desktop does

Desktop's rule (#38877) also sends the head card when no turn runs, and
goal mode keeps the empty chord inert. The queue list's handle now runs the
head card's own Send when idle, and steers mid-turn only where the chord's
other way is steer.

* test(mobile): type the queued-card handle refusal cases

* feat(mobile): holding Cmd/Ctrl in the phone chat composer shows what Cmd/Ctrl+Enter will do, as desktop does

Desktop's held-modifier preview moves into src/shared so the phone web
composer runs the same rule: Send becomes Queue, Steer or Steer queued
and the head queued card lights while the chord's modifier is held
alone on a hardware keyboard. The queue's empty-chord rule is one
function the preview and the press both read.

* fix(mobile): build the held-chord preview with the phone's own React, and offer only presses that act

The shared hook now takes its React hooks from the caller, as the shared
attachment preview does: the phone bundle resolves a different React copy
than the repo root, so importing react from src/shared broke every phone
web composer (Invalid hook call).

The preview also matches what a press does: one pill press per hold (a
double-click can't send a card after the draft went), a picked /plan-style
skill counts as a message, a head card whose own action is on its way shows
no Steer queued, and the lit state lives in the tray so a chat switch keeps it.

* fix(mobile): held-chord pill takes one click like desktop, keeps busy state per chat, lights only the head row

- The pill ignores a click whose detail is above 1, as desktop does, so a
  deliberate later click in the same hold still acts.
- In-flight card ids are kept per chat with functional updates, so a chat
  settling after a switch can't clear the current chat's record.
- The lit state is a small store only the head row subscribes to, so a hold
  re-renders one row, not the whole queue.
- The desktop preview test moves back beside the desktop wrapper it drives.

* refactor(mobile): one owner for queued-card actions, read by both the list and the held-chord cue

The queue list owned its in-flight guard per mount and the tray mirrored it
for the composer's Steer queued cue; each mirror leaked (cross-chat and
same-chat remount overwrites, an all-chats copy per change). As desktop's
queued-messages controller does, the tray now owns one action store: pending
keys per chat, admitted synchronously, released per action, published by
copying only the changed chat. The list takes those actions as a prop (it
keeps its own only when mounted alone), and the empty chord presses the head
through the same run, so the cue and the press can't disagree. The list's
imperative handle goes away.

Also replaces a type assertion on the pill's click detail with an in guard.

* test(native-chat): desktop chord-preview wrapper re-exports the hold delay its test reads
2026-11-06 18:17:24 -08:00
Kelvin Amoaba 8038fed16c feat(dictation): stop desktop dictation after a minute of silence (#39131)
* feat(dictation): stop desktop dictation after a minute of silence

A toggle dictation left running keeps the mic open indefinitely. Stop it
a minute after the last speech, with a toast, like the phone's tap mode.
A held push-to-talk key is never stopped; its release ends the session.

Mobile's timer moves into src/shared so both apps use the same rule, and
the shared meter now records when it last heard speech.

* fix(dictation): gate the silence stop on hold mode, as the phone does

* refactor(dictation): let the desktop silence hook own the hold-mode rule, as mobile's does

* refactor(dictation): move the capture meter into its own hook

* refactor(dictation): initialise the capture meter ref without a render write
2026-11-07 02:11:20 +00:00
Kelvin Amoaba 9dacf1e6db fix(mobile): make dictation start reliably on a slow or sleeping desktop (#39142)
* fix(mobile): keep speech said while dictation starts and fail fast on a dead host

* fix(mobile): let a tap or long-press end dictation while it starts

* fix(mobile): wait for the host's cancel before the next dictation starts

* fix(mobile): let a start wait out the previous start on the host too

* refactor(mobile): track host dictation work per client, not per screen

* test(mobile): read the start's dictation id without a cast

* fix(mobile): finish instead of cancel when a held mic is released while starting
2026-11-07 01:25:34 +00:00
Kelvin Amoaba 1740dc3e34 fix(dictation): space dictated text from existing text and copy what can't be inserted (#39111)
* fix(dictation): space dictated text from its neighbours and keep text that can't be inserted

* fix(dictation): don't report a contentEditable insert as landed when nothing was inserted

* refactor(dictation): read caret neighbours per block and trim the spacing helpers
2026-11-07 01:24:19 +00:00
Jinjing 1f1eb76593 fix(i18n): translate recent desktop and mobile copy (#39233) 2026-11-06 16:33:34 -08:00
Neil bb5f37c916 feat(pairing): unscanned desktop pairing codes expire (QR 10 min, link 60 min) (#37957)
* feat(pairing): unscanned desktop pairing offers expire (QR 10 min, link 60 min)

Headless serve/orcad mint offers without a TTL, so they never expire.
Paired rows and rows without offerExpiresAt are unaffected.

* feat(pairing): refresh the mobile QR before it expires and show runtime link expiry

The QR re-mints a minute before expiry while visible; an unused runtime
link shows its expiry and, once expired, is replaced by a notice. Web
clients rejected while pairing now suggest asking for a new link.

* feat(mobile): say a refused pairing code expired or was replaced

A first pairing the desktop refuses (direct or Relay) now asks for a new
code instead of showing the raw transport error.

* refactor(pairing): replace type assertions in code-refusal detection and tests

* test(mobile): re-record pairing race golden for refused-code error

* fix(pairing): keep pairing codes valid across sleep and stale registry writers

- QR refresh rechecks the wall clock every 15 s and on window focus, so a
  computer waking from sleep never keeps showing an expired code.
- A registry save from a process with an older copy can no longer reset a
  paired row back to unscanned (which would let its offer expire).
- The QR caption says how long a copied code works.

* test(pairing): annotate the IPC handler stub cast
2026-11-06 16:23:44 -08:00
Brennan Benson d84abfb4f5 Offer terminal sign-in recovery in native agent chats (#39012)
* Offer terminal sign-in from native chats and retain refused worker tasks

* Handle sign-in terminal failures and complete failed-start cleanup callers

* Read retry task identity from its dispatch context

* Assert retained transcript identity through the bounded worker read

* Remove obsolete private structured retry teardown assertion

* Use real signed-out Pi and OMP error frames in regression coverage

* Route chat sign-in through explicit host terminal creation

* Keep paired agent launch owner explicit in the tightened terminal contract

* Keep focus baseline pruning limited to the removed reads

* Keep terminal login recovery available for unresolved model notices

* Keep the Grok diagnostic assertion scoped to its refused delivery

* Limit chat sign-in subscriptions to eligible failure rows

* Pass the execution host in terminal creation fixtures

* Scan Pi OAuth failures linearly and verify shared sign-in bounds

* Assert failure metadata and diagnostic routing without translated copy

* Bound diagnostic matcher steps at the Pi failure boundary

* Type the diagnostic matcher receiver explicitly

* Check sign-in button elements with a DOM type guard

* Recognize Pi credential failures and keep one recovery action

* Keep Pi sign-in diagnostics behind failure details

* Verify recovery action changes while refusal wording stays stable

* Use the recorded refusal sentence in the recovery fixture

* Type the recovery fixture as a submission rejection

* Make chat sign-in actions large primary controls

* Reuse primary action styles without duplicate notice subscriptions

* Keep translated primary chat actions within narrow notices
2026-11-06 16:06:14 -08:00
Jinwoo Hong 555bd481bc Let multi-repo folder workspaces parent and nest workspaces, including on other machines (#38904)
Multi-repo folder workspaces can parent workspaces on this machine and on paired servers, and their children nest under them in the sidebar and on the phone. Task parents are inferred at creation instead of on every lineage refresh.
2026-11-06 19:03:51 -05:00
Brennan BensonandGuderlilian dbf56346e8 Keep phone chat menus above the keyboard (#38834)
Slash and mention suggestion menus in the phone chat composer stay reachable above the on-screen keyboard while typing.

Co-authored-by: Guderlilian <73724370+qq2144@users.noreply.github.com>
2026-11-06 15:05:05 -08:00
Neil fc67787090 feat(mobile): sign Android release builds with a dedicated release key (#38924)
* feat(mobile): sign Android release builds with a dedicated release key

Add an Expo config plugin that gives the generated app/build.gradle an
env-driven release signing config, and have the Android release workflow
require the keystore secrets, fail before building when they are missing,
and check the APK's signing certificate against a pinned fingerprint.

* fix(mobile): keep the signing setup hint intact in the workflow error

* test(mobile): type the plugin import without a cast

* feat(mobile): keep debug signing until release signing is enabled

Release signing now turns on when the ORCA_ANDROID_RELEASE_CERT_SHA256
(or ORCA_ANDROID_REQUIRE_RELEASE_SIGNING) repository variable is set.
Until then the workflow keeps today's debug-signed build and adds a
warning and job summary note; once enabled, missing secrets fail.

* feat(mobile): enable v2 and v3 APK signing for the release key
2026-11-06 14:33:18 -08:00
Jinwoo Hong 01f65352d8 fix(automations): run lists send byte-bounded previews; Run Details reads one full row (#38218)
* fix(automations): run lists send byte-bounded previews; Run Details reads one full row

* fix(automations): retry a failed full run read on the next history read

* fix(automations): show a full-output read failure with Retry in Run Details
2026-11-06 15:49:45 -05:00
Jinwoo Hong 16f2d38acb fix(automations): Run now returns the saved pending row; launcher parity (#38217)
* fix(automations): Run now returns the saved pending row; quiet, titled, retained run terminals

Run now answers with the durable pending row instead of waiting behind
the automation's lane; one detached handler records a launch failure.
Existing-workspace launches no longer surface their owner, a new
workspace's startup tab carries the run title, and finished-run cleanup
keeps a terminal a user opened after its process started.

* fix(automations): keep launched runs and user-opened run terminals intact

A failed flush after a launch no longer rewrites a dispatched run as a launch failure.
A user tab open marks the pane activation shows, read after any spawn it starts.

* fix(automations): own launch-failure recording in the service; quiet pending pane notice on mobile
2026-11-06 15:46:47 -05:00
Brennan Benson 969c5ddd3a Support native Plan mode in chat (#38286)
* Add session Build and Plan choices to native chat

* Refresh planning choices across connected composers

* Give composer catalog tests a complete transport fixture

* Preserve planning choices through fresh turns and older hosts

* Type planning delivery fixture choices explicitly

* Honor mode capability for retained queued command picks

* Update existing native mode contract expectations

* Keep proposed plans visible in completed chat turns

* Group chat mode with permissions and goal controls

* Keep chat composer controls accessible in narrow panes

* Preserve composer overflow ownership and editor focus

* Complete composer localization catalog and subscription checks

* Keep chat composer controls contained in narrow panes

* Use the button spacing for compact Save

* Place chat mode immediately before Goal

* Restore Plan status test dependencies after main sync

* Show an exit pill only while chat Plan mode is active

* Remove obsolete composer tooltip translations

* Remove unused Build toggle catalog entries

* Apply Plan commands immediately from composer picks

* Preserve picked skill origin in composer admission

* Supply phone platform to composer regression fixture

* Preserve mode picks until their writer admits them

* Narrow the phone mode command before its draft transform

* Document the option fixture mutation shape

* Match phone Plan controls to the composer mode pills

* Assert optimistic mode feedback in the phone fixture

* Retain the phone mode pick recovery regression proof

* Use the relocated observation imports after the main merge

* Restore the composer IME module import after merging

* Read the queue assertion helper from its relocated owner

* Point the mode fixture at the relocated selection controller

* Register the phone Plan pill localization keys
2026-11-06 12:42:48 -08:00
Jinwoo Hong 60834fb1b6 fix(mobile): a failed page remounts instead of re-downloading; deadlines count only foreground time (#38868)
* fix(mobile): a failed page remounts instead of re-downloading; deadlines count only foreground time

Page deadlines now pause in the background and restart on return, so React Native firing overdue timers on resume no longer reads as a page failure. A failed document remounts the same files once, then shows the failure screen; it never deletes and re-downloads on its own. Try again after a page failure or an unreadable generation deletes the host cache first, so it downloads fresh. Replaces #34550 without its file-size check.

* fix(mobile): drop reports a remounted page's retired view already queued

A failed page remounts at once, minting the replacement's session before
React commits it. A fault or ready the old view had already queued then
landed on the replacement: a second fault showed the failure screen
before the new page loaded, and a late ready marked it ready and
cancelled its load deadline. Each report now carries the session of the
view that rendered it and is dropped once that view is retired.
2026-11-06 15:31:57 -05:00