Commit Graph
20022 Commits
Author SHA1 Message Date
Kelvin Amoaba f29226ef20 feat(dictation): load the speech model ahead of the first dictation, with an unload setting (#39327)
* feat(dictation): pre-warm the speech model and make the unload timeout a setting

The first dictation after launch, or after the idle recognizer unloaded,
waited for the speech host to spawn and load the model. The host now loads
the selected on-device model when voice is on: after the first window (or
at orca serve start), when the voice settings change, and when an Orca
window regains focus after an unload. A dictation started meanwhile binds
to the loading recognizer instead of loading a second one.

Voice settings gain Unload Speech Model: Never, Immediately, 5, 15 (the new
default, was 60) or 60 minutes. Immediately also turns pre-warm off, voice
off frees an idle recognizer, and a model that failed to load is retried
only on a settings change or after a dictation loads it.

* fix(dictation): don't mark a model failed when its warm-up was torn down on purpose, and stop a warm-up that voice-off superseded
2026-11-07 07:16:57 +00:00
Neil 0e88d863a1 fix(agent-launch): paste Copilot launch drafts as soon as its composer is ready (#39317)
* fix(agent-launch): paste Copilot launch drafts when its composer row draws, not after the loading spinner settles

* chore(plugins): regenerate declarative runtime for the Copilot composer signal
2026-11-06 23:16:42 -08:00
Neil 3108219ee3 fix(runtime): hide retained folder rows from process listings (#39332) 2026-11-06 23:13:55 -08:00
OrcaWinandOrcaWin 0069492b94 refactor(tab-bar): derive drag label and active simulator tab from subscriptions instead of getState in render (#39335)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 23:10:17 -08:00
OrcaWinandOrcaWin b77409ddf4 refactor(agent-status): subscribe to live-agent derivations with epoch-keyed selectors instead of getState in render (#39329)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 23:09:51 -08:00
OrcaWinandOrcaWin a3ec4e3c61 refactor(terminal): read pane snapshots from the projection instead of refs in render (#39323)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 23:09:17 -08: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
Jinjing 2ed0633a4a Fit file and browser tabs to their content (#39328)
* Fit file and browser tabs to their content

Keep terminal tabs at their preferred width and reserve stable editing
space while renaming tabs.

* Remove obsolete tab rename width hook
2026-11-06 22:58:41 -08:00
Jinjing 9a6edae4a1 fix(agent-session): preserve original task after restart (#39322) 2026-11-06 22:56:57 -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
OrcaWinandOrcaWin 6de93713ef test: remove 439 low-value browser and runtime tests (#39318)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 22:33:46 -08:00
a1ef5269b9 perf(renderer): derive state instead of syncing it in effects (panels) (#38801)
* perf(renderer): derive state instead of syncing it in effects (panels)

* perf(renderer): keep Linear team reconcile in an effect

Render-phase reconcile re-renders the task page without settling.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-06 22:22:51 -08:00
OrcaWinandOrcaWin de4cacd3a6 refactor(terminal): declare pane lifecycle refs as top-level hook calls (#39315)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-06 22:20:00 -08:00
Neil 9f054bf264 feat(ai-vault): reveal an Antigravity session's artifacts folder (#39295)
* feat(ai-vault): reveal an Antigravity session's artifacts folder

* fix(ai-vault): detect agy artifacts from the discovery walk and open inside the folder

* test(e2e): pass onRevealArtifacts in the OMP child history fixture
2026-11-06 22:17:51 -08:00
Neil 20c8b848e3 fix(agent-status): keep an Antigravity run working while its background command finishes (#39301)
When an agy parent ends its turn waiting on a backgrounded run_command,
agy sends Stop with fullyIdle=false and OSC 7501 done, and sends that
command's PostToolUse only when it exits. Orca held the row open only for
invoke_subagent helpers, so after two minutes of hook silence the
program's done ended automation runs while the command still ran.

Track parent run_command steps whose PostToolUse has not arrived
(daemons excluded) and hold a busy Stop as monitoring. The program's done
settles that hold only after 30 minutes of hook silence, so a command
that never exits cannot pin a run until the 6h watch limit.

Fixes #35234 (STA-12678)
2026-11-06 21:38:04 -08:00
Neil 97f2de9913 refactor(renderer): organize runtime clients and feature state owners (#39292)
* refactor(renderer): organize runtime clients and feature state owners

* fix(refactor): preserve incoming consumers and validation routing

* fix(refactor): consolidate defining-owner type imports
2026-11-06 21:32:59 -08:00
Kelvin Amoaba 11cad93421 fix(speech): run on-device dictation in its own process so an engine crash or hang can't take Orca down (#39297)
* fix(speech): run the on-device recognizer in its own process

A native crash in sherpa-onnx took Orca down with it, and a decode stuck
in native code could not be stopped. The recognizer now runs in an
Electron utility process (a forked child under orcad), is killed when a
stop or cancel goes unanswered, and a dead process ends the dictation
with an error instead of a silent stop.

* fix(speech): let a loading model finish when its dictation is canceled

* fix(speech): never leave a speech child behind or crash main on its fatal error

* refactor(speech): drop the teardown message now that terminate kills the process

* fix(speech): fork the orcad speech child through process-host with a typed request
2026-11-07 05:28:41 +00:00
Neilandseonghobae 0fd39beedf fix(runtime): hold an agy composer whose draft reads like an edit mode (#39296)
A draft such as `dark mode: fix the toggle`, or agy's plan placeholder typed
verbatim, matches the composer caret row's edit-mode alternative. agy hides
`? for shortcuts` while the composer holds text, so composer_ready refused,
but composer_ready_custom_status_line (#38930) took agy's own
`[mode · ]model · effort` footer for a custom status row and answered idle.
Orca would then paste into the operator's unsent text.

Status rows may no longer be agy's built-in footer. The captured agy 1.2.7
screen of the plan placeholder typed as a draft comes from #23402.

Split from #23402.

Co-authored-by: seonghobae <8172694+seonghobae@users.noreply.github.com>
2026-11-06 21:21:39 -08: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 f736cab7d7 feat(dictation): resample desktop dictation to 16 kHz in an AudioWorklet with an anti-alias filter (#39290)
* feat(dictation): capture desktop audio in an AudioWorklet at 16 kHz

Desktop dictation captured with a ScriptProcessorNode on the renderer's
main thread and shipped hardware-rate buffers, which main then decimated
to 16 kHz with linear interpolation and no low-pass, folding everything
above 8 kHz back into the speech band.

An AudioWorklet now resamples to 16 kHz with a windowed-sinc low-pass,
posts 100 ms frames, and sends a level every 50 ms for the meter and
silence auto-stop. Desktop and the web client share it.

* refactor(dictation): share the sinc resampler and meter window, one frame sink

Move the resampler to src/shared beside the meter it feeds, share the
50 ms meter window with the phone's, drop the constant per-chunk sample
rate from buffered audio, and send frames through one deliverFrame so
the speech-host port can replace it later.
2026-11-07 05:07:31 +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
Jinwoo Hong c912144aae Show the machine on folder workspace cards (#39280)
* Show the machine on folder workspace cards, as other workspace cards do

* Build folder fixture rows without passing the array index

* Add a fixture for a folder card on another machine

* Drop the folder card screenshot fixture

* Put an unstamped folder card on the host it runs on

A folder workspace with no host stamp resolved to its project group's host for
labels and sections but to local for its card row. Stamp it the way catalog
adoption does so the card, label and section agree with runtime dispatch.
2026-11-07 00:02:39 -05: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 b26ad4bd58 perf(runtime): resume a phone terminal from what it already received (#39156)
* perf(runtime): resume a phone terminal from what it already received

* fix(runtime): carry a missed cwd change on resume and keep points the ring covers

* fix(runtime): resume only onto the grid the missed output was written for

* test(runtime): type the resume token without a cast
2026-11-07 04:57:33 +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
NeilandShemYu 1712936c29 feat(usage): show Muse subscription quota in the status bar (#38907)
* feat(usage): show Muse subscription quota in the status bar

Reads `muse usage --json` (Muse Code 1.4.13+), which reports the
subscription allowance without a model turn, and maps `allowance.window`
to the five-hour session meter and `allowance.weekly` to the weekly meter.
`rateLimits.muse` now appears in `orca account list --json`.

- Gate on `muse --help` listing `usage`: older builds treat an unknown
  subcommand as a prompt, so Orca never sends `usage` to them.
- Run with MUSE_NO_AUTO_UPDATE=1 and MUSE_LOGIN=0 so a background poll
  never self-updates the launcher or starts a device sign-in.
- Missing CLI, signed out, API-key login / no allowance, non-JSON output,
  and timeouts each map to an explicit unavailable/error snapshot.
- Hidden meters skip the spawn, and Muse publishes after the sibling batch
  so a slow CLI cannot delay Grok/Cursor/ZCode/Antigravity.
- Default-on status-bar item with a one-shot migration, CLI-detection
  gating, visibility menu and Settings toggle, remote-owner mapping.

Based on the design in #34232 by ShemYu.

Co-authored-by: ShemYu <11490047+ShemYu@users.noreply.github.com>

* fix(usage): cap Muse usedPercent and date readings by fetch time

Muse can report over-quota usage above 100; clamp to the 0-100 meter
contract like the other providers. Use the fetch time for updatedAt so a
cached older asOfMs cannot make every window focus trigger a refresh.

* fix(usage): prevent Muse launcher installation during polling

* fix(usage): gate Muse on its version file and run the active build directly

- Read the launcher's `.muse-version` and require 1.4.13 or newer (the
  release that added `muse usage`); only installs without that file fall
  back to `muse --help`, cached by launcher path, mtime and size.
- Execute `muse-bin-<version>` directly when it exists, so the launcher's
  update, sign-in and install paths never run; the env guards stay for
  the launcher fallback. A version change during the call discards the
  reading as stale.
- Start the Muse fetch at the beginning of the full cycle and cap it near
  8s (6s usage, 2s help), so a slow CLI holds the shared queue far less.

---------

Co-authored-by: ShemYu <11490047+ShemYu@users.noreply.github.com>
2026-11-06 20:53:57 -08:00
Kelvin Amoaba b051519599 refactor(dictation): run the desktop dictation controller on a shared session state machine (#39284)
* refactor(dictation): run the desktop controller on a shared session state machine

* test(dictation): assert session machine behaviour, not run numbering

* refactor(dictation): allow a new start from the error phase

* test(dictation): drop the error-restart case no desktop path depends on yet

* refactor(dictation): derive stop-during-start from the phase and share the start teardown
2026-11-07 04:53:39 +00:00
buf0-bot[bot] 3d8a285132 Update README downloads badge (#39291)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-07 04:51:25 +00:00
Neil ab6d40a9df revert: onboarding Antigravity installer (#39172) (#39282)
This reverts commit 88fa7ed2a9.

Also drops the agyInstall strings a later locale sync added to the
non-English locale files, so no orphaned keys remain.
2026-11-06 20:50:07 -08: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
Neil 121e8ba354 fix(muse): keep panes working while spawned background subagents run (#38911)
Hold the lead Stop through the shared child-work fold while UUID children
are live between SubagentStart and SubagentStop. A child that sends no hook
for 10 minutes stops holding the row. Interrupt (subscribed async, as Muse
requires), SessionStart and SessionEnd clear tracked children, and the
existing transcript-poll replay of the held Stop then reaches done.

Fixes #28090
2026-11-06 20:36:59 -08:00
Neil 4ced677eba Stop polling a Muse session log that has gone silent (#38902)
* fix(agent-hooks): bound Muse transcript polling when the session goes silent

A Muse session that ended without Stop kept its 1s session-log poll alive
until the pane closed or another hook arrived. Idle polls now probe the
owner's process after 60s without log growth (an exited owner is reconciled,
which clears the poll) and stop after 30 min of silence; the next hook
re-arms polling.

Linear: STA-8313

* fix(agent-hooks): re-arm the Muse poll after a presence probe restates the row

A live owner's suspension flip (Ctrl-Z/fg) makes the idle presence probe write
a new row; the next poll tick saw a superseded row and stopped, and no hook
re-armed it. Re-arm on the restated row, keeping the idle clock, unless a newer
hook already owns the pending poll.

Linear: STA-8313

* fix(muse): back off quiet transcript polling safely

* fix(muse): replace the presence probe with a 5s quiet-log back-off

Back a quiet Muse log off from 1s to a 5s cadence instead of probing
presence; log growth, a status change, or any hook for the session
(including ignored ones) restores 1s. Removes the idle presence probe and
the row-restatement re-arm, which Muse rows never needed: Muse hooks carry
no trusted process identity, so the probe always returned early.
2026-11-06 20:36:52 -08: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