The saved-password detector re-scanned every credential form on each
mutating page twice a second (forcing layout per input and walking the
page's buttons), but main only reads those snapshots for 2.5 s after a
login navigates. Main now tells each document at enable whether it wants
them.
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(ssh): stop restarting a managed orcad that keeps crashing, and say why
orcad now reports, in its health, a previous run that died on this boot
without releasing its instance lock. Graceful stops (idle exit, explicit
stop, update activation, rollback) release the lock, and a reboot changes
the boot id, so none of those count. After 3 such exits in 10 minutes the
desktop stops waking the server until an explicit Connect, and shows the
reason with orcad.log's path and tail instead of timing out.
Refs #37538
* fix(ssh): count fatal stops and failed starts; brake every automatic wake
- A fatal orcad stop (uncaught exception) keeps its instance lock, so the
next start reports it.
- A launch that never becomes ready counts once, not again when the next
orcad reports it.
- The tunnel port-recovery wake goes through the same brake.
- macOS and Windows hosts use OS uptime as boot evidence.
- Connect also drops a cached serving verdict.
Refs #37538
* fix(ssh): serialize crash-loop brake admission per host
Refs #37538
* fix(ssh): count reported Windows launch failures toward the crash-loop brake
Refs #37538
* fix(orcad): read the Windows launch report when the launcher exits nonzero
Refs #37538
* fix(ssh): ignore brake accounting from wakes begun before a reconnect
Refs #37538
* fix(ssh): count only launches that failed readiness, not inspection failures
Refs #37538
* fix(orcad): keep the command error when a Windows launch left no report
Refs #37538
* fix(ssh): surface the crash-loop reason from tunnel port recovery
Refs #37538
* fix(ssh): take the brake's reset epoch when a wake is requested
Refs #37538
* test(ssh): keep the cast on its SAFETY line
Refs #37538
* fix(ssh): tighten what the crash-loop brake counts and when it lets go
- A Windows host-policy refusal is not counted; its own guidance stays.
- The braked detail names the last failed start.
- A latch set on a run that served is released once that run's lock shows
it stopped cleanly.
- The update path's already-active wake goes through the brake.
- The fatal-stop test drops its shutdown timer.
Refs #37538
* fix(ssh): brake only a new launch, and count the wake after an automatic release
Refs #37538
* fix(ssh): refuse a braked launch at the fenced launch decision itself
Refs #37538
* fix(ssh): a refused launch also skips fence recovery, which can relaunch
Refs #37538
* test(ssh): a refused launch leaves fence recovery alone
Refs #37538
* fix(ssh): count failed recovery launches; dedupe only runs that ran
Refs #37538
* fix(ssh): explicit Update and Restart re-arm the crash-loop brake; release it after a reboot
- Update and Restart are user actions like Connect: they clear the brake.
- An auto-update that meets the brake on an already-current host is a
skip, never a recorded update failure that would block retries.
- The brake releases once the latched run's lock comes from an earlier boot.
Refs #37538
* fix(ssh): every explicit server action re-arms the brake; count failed candidate launches in recovery
Refs #37538
* fix(ssh): only gated wakes can return launch-refused
Ungated callers (version adoption, stale-lock reclaim, WSL, restart) pass no
launch gate, so their wake type no longer includes a refusal they cannot get.
Refs #37538
* fix(ssh): reboot evidence also releases a brake raised by failed starts
Refs #37538
* fix(ssh): release the brake only on a new boot of the machine that answered when it engaged
A leftover lock's boot id cannot tell a reboot from a shared-home lock
written by another login node or one older than the loop.
Refs #37538
* fix(ssh): a braked host seen serving can be released by that run's clean exit
Refs #37538
* fix(ssh): identify the rebooted machine by hostname and machine id
Login nodes behind one hostname share it, so the hostname alone cannot tell
them apart. Without a machine id the brake does not auto-release.
Refs #37538
* fix(ssh): only an answered run counts as served; a reboot must postdate the brake
A clone with the same hostname and machine id that booted earlier is a
different backend, not a reboot. Boot and read times come from the host's
own clock.
Refs #37538
* fix(ssh): only an answer received after the brake engaged marks its run served
A control-socket pong up to 20 s old may come from a run that has since
exited cleanly; counting it would let failed starts release the brake.
Refs #37538
* fix(ssh): say what to do when a host's server setup stops on a known cause
A managed SSH host whose server setup deferred always showed "Orca couldn't
start its server on this host. Try connecting again.", even when a retry
can't help (full disk, an interrupted update needing Recover, another Orca
runtime on the host's data). The deferral code was dropped before it reached
the host status.
Carry the code as an optional field on the unserved status, keep the retry
line only for codes a later connect clears, and name the fix for the ones a
user can act on. Older hosts and thrown errors carry no code and keep the
retry line.
Refs #38347
* fix(ssh): drop the Recover advice a first setup can't act on
Connect already runs activation recovery before deploying, and an unregistered
host has no Recover control, so that code now points at Details. Soften the
live-runtime line, keep waiting causes in the warning tone, and test the
published code and its remedy rather than English copy.
Refs #38347
* fix(ssh): treat an unreadable server build as needing Details, not a retry
Refs #38347
orca account list called accounts.list with refreshUsage:false, so on an
idle headless host the JSON's rateLimits stayed null. JSON output now
asks the host to refresh only stale usage windows (the same
refresh-if-stale an accounts.subscribe stream runs), via a new optional
refreshStaleUsage param. The host waits at most 10s for it, so slow
inactive-account probes can't push the CLI past its request timeout;
they keep running and land on the next call. Older hosts strip the unknown field and keep
their prior no-refresh behavior; human output still skips the refresh.
Fixes#37256
* 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(agents): paired-host agent tabs use the host's launch settings
Agent tabs opened on a paired host were replacing that host's permissions and Arguments with the desktop's settings. Let the host plan fresh launches, carry the user's choices separately, and preserve existing prepared launches when an older host cannot express them. Action Arguments replace configured Arguments while inheriting the host's permission settings; resumed sessions keep their recorded recipe.
* fix(agents): paired-host agent tabs use the host's launch settings
Preserve per-launch permissions on older paired hosts by compiling picks they cannot apply from their own settings. Keep authored Arguments separate from saved model defaults so a command's pinned model wins. Use the host's reported shell and execution platform for argument quoting, and remove unused prompt-delivery wrappers.
* fix(agents): paired-host agent tabs use the host's launch settings
Replace recognized permission flags from older paired hosts when a launch picks another permission, while preserving unrelated Arguments and ambiguous prepared launches. Keep multiline drafts working on Command Prompt hosts and omit chat-only permissions from terminal requests.
* fix(agents): paired-host agent tabs use the host's launch settings
Preserve per-launch permission choices that suppress the paired host's Full access flag even when the choice emits no flag itself. Compile these choices from the host snapshot when older launch preferences cannot carry them, while keeping unsupported OpenCode terminal permissions filtered out.
* test: merge duplicate imports in paired launch options test
* test: drop type assertions in paired launch options test
* chore: lower focus-read ratchet baseline after removing creation wrappers
* fix(agents): paired-host agent tabs use the host's launch settings
Keep accepted inline fork drafts delivered when their mirrored tab is unavailable, and cancel launches whose pairing changes during negotiation. Keep action Arguments metadata on the tab route so injected workspace launch callbacks retain their contract. Update consumer fixtures to run lazy compatibility preparation and verify the final launch inputs and cancellation boundary.
* fix(agents): paired-host agent tabs use the host's launch settings
Keep pairing changes during legacy launch preparation silent and preserve the prompt for retry. Make picker tests exercise structured model picks on modern hosts while retaining prepared-command coverage for older hosts.
* fix(agents): paired-host agent tabs use the host's launch settings
A permission pick on an older paired host could turn desktop-configured Arguments into a launch override, including the desktop's model. Keep settings-seeded text out of the paired picker request so the host snapshot supplies defaults, while preserving explicitly edited launch Arguments.
* fix(agents): paired-host agent tabs use the host's launch settings
Keep permission-control choices separate from Arguments the user edited.
Fresh paired terminal launches now share that ownership projection in the
new-tab picker and continuation dialog, so a control change preserves the
host's executable and environment settings. Explicit Arguments edits,
including clearing the field, keep their existing launch behavior.
Cover old-host and modern requests, explicit terminal/chat edits, and the
continuation Start handler. Workspace creation keeps its existing path.
* fix(agents): paired-host agent tabs use the host's launch settings
Older paired hosts could inherit the desktop's model and permission defaults when the launch picker was configured or reopened. Read picker defaults and prepared launch recipes from the executing host, and compile edited Arguments using its settings. Preserve explicit empty edits, narrower permissions and draft prompts.
Keep inherited choices neutral while host settings are unavailable, retaining the existing compatibility launch when no usable host recipe exists.
* chore: merge duplicate type import and drop dead test branch
* fix(agents): paired-host agent tabs use the host's launch settings
Actions with explicit permission choices could unnecessarily read host settings and fall back to desktop preparation when those reads failed. Keep representable action Arguments on the host's authoritative launch path, and read inherited permissions only when the action needs them.
Cover an explicit empty Arguments override and Ask with unavailable settings, preserving the host executable and environment without a permission bypass.
* fix(agents): paired-host agent tabs use the host's launch settings
Supply the paired host's default agent in the shortcut test instead of
assuming the desktop's default applies. Keep a conflicting desktop default
so the shortcut continues to verify the paired host owns its selection.
Use the shared agent picker for Source Control Customize and AI-author setup. Preserve existing Arguments, templates, Custom commands, model/effort choices and settings ownership; keep nested menus and tooltips within their dialog portal.
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Courtenay <1909814+hdsheena@users.noreply.github.com>
Co-authored-by: Andy Zhang <hiandyzhang@gmail.com>
Use the shared searchable agent picker in Quick Commands while preserving the full catalog, disabled-agent explanations, independent form drafts and saved commands.
Keep dialog search focused through opening and host-preference reloads, and avoid setup-only cleanup for agent-only menus.
Rows show their project, two-line layout with fixed time/size columns and hover actions; Ignore can be undone per row; delete confirmation reads 'Delete N workspaces?'. Fixes Ignore/Stop ignoring being reverted by streamed scan frames or scan settlement, and the git-unknown flash on open/close.
Co-authored-by: Jingyue-Wu <75918217+Jingyue-Wu@users.noreply.github.com>
* fix(native-chat): run Codex /goal pause|resume|clear and /usage from chat
Codex app-server has no slash parser, so a chat's /goal pause set the goal's text to "pause" and /usage reached the model as prose. /goal pause|resume|clear now change the current goal through the host, and /usage opens the Codex usage section in Settings for the chat's host.
* fix(codex): say a chat has no goal when /goal pause or resume finds none
Codex rejects a status change without a goal in words naming the thread id; read the goal after that rejection and show Orca's copy instead.
* fix(native-chat): address review on Codex /goal controls and /usage
Look goal words up without inherited properties, keep text after a picked /usage, let Send run what Enter runs on a held host, name Codex when there is no goal (clear included), and drop the shared /goal hint that phones and goal-less hosts would show for words they send as text.
* fix(native-chat): keep the draft after a picked /usage and hold goal-mode Send
Picking /usage opens Settings and leaves the text typed after the command; Enter on the row no longer sends /usage to the agent. Goal mode submits its draft as an objective, so a held host keeps Send held there, and an enabled Send is not labelled with the hold.
* test(native-chat): build the picker state instead of casting it
* fix(native-chat): honor Stop before naming a missing goal, and own any Codex /usage row
A canceled pause or resume no longer reads the goal to word a refusal, and an agent-reported /usage row gives way to Orca's, as /resume already does.
* revert(native-chat): leave /usage for its own change
Brennan wants /usage to show the status bar's Codex usage panel for the chat's account, in a separate PR; this PR keeps the /goal controls and the held-chat Send fix.
* feat(browser): save and fill passwords in Orca's browser (experimental)
Off by default under Settings > Experimental > Saved passwords.
* fix(browser): secure saved passwords and fix login lifecycles
* fix(browser): keep the guest preload self-contained so saved passwords load
The shared uuid import split into a chunk the sandboxed preload can't require, so the
whole preload failed on every page. Element tokens now come from crypto.getRandomValues.
* fix(browser): fill a saved login on mouse press so clicking a row works
Pressing Orca's UI blurs the page field, which closed the list before the click landed.
* feat(browser): manage saved passwords from a Passwords section in Settings › Browser
Replaces the Manage passwords dialog with an inline section: save and Touch ID
switches, import menu, a searchable list grouped by site with last-used times and
hover actions in a capped scroll box, delete confirmations, and an Add/Edit dialog.
* feat(browser): turn saved passwords on for everyone instead of behind Experimental
Drops the experimental flag, its Experimental toggle and the badge; the Passwords section in
Settings › Browser now shows on desktop for the local host without opting in. With no toggle,
the guest disable message and the apply-to-open-pages step had nothing left to trigger them.
* fix(browser): refuse protected password actions when Touch ID is set up but unavailable, and keep fills on the matched page
Touch ID lockout or a closed lid made canPromptTouchID() false, which counted as a Mac without
Touch ID, so show, copy and protected fill went through unchecked. Enrollment from bioutil now
tells the two apart. A fill also kept no hold on the page across the Touch ID prompt, so a page
that navigated meanwhile got the password; it now goes only to the frame and origin it was matched for.
* fix(browser): keep a browser profile when its saved logins can't be deleted
Profile deletion removed the profile first and only logged a failed vault delete, so the
encrypted vault could stay on disk with nothing left to retry it. The vault now goes first,
and the profile stays (deletion reports failure) when it can't.
* 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
The remote host relays commands for desktop-hosted pages back to the
desktop, which ran every relayed command as the orca CLI. A terminal
link's follow-up browser.goto therefore marked the page agent-driven.
The host now tags relayed commands with whether its caller was an agent,
and the desktop only uses the agent identity for those.
* fix(sidebar): show hidden discovered worktrees outside project grouping
* fix(sidebar): place hidden-worktree lines from the rendered rows in one pass
* fix(sidebar): keep shared-anchor hidden-worktree lines in row order
* fix(sidebar): count row visits without Reflect and drop a cast
* test(sidebar): build typed fixtures instead of casts
* fix(sidebar): show one hidden-worktrees line for all projects outside project grouping
* Add Chat UI choice to onboarding and tailor agent tours
* Add setup guide controls for Chat UI and Yolo permissions
* Refresh native chat agents and improve surface radio controls
- Re-read the host inventory alongside workspace refreshes, including WSL
- Recognize downloaded, ready chat runtimes without a CLI on PATH
- Standardize onboarding and checklist surface choices on accessible radio variants
* Show full-access agent overrides in Yolo mode settings
* Polish Chat UI onboarding and clarify terminal fallbacks
- Group agents by launch surface and refresh selection previews
- Add scroll-edge fades to reveal clipped onboarding content
* Recognize ready custom Chat commands and nested scroll changes
* Advance agent tour after selecting a new tab type
* Install onboarding skills for selected chat providers
- Route Chat UI setup to local provider-specific skill roots
- Improve tour focus, Escape handling, and delayed target transitions
* Keep split lesson while a new pane mounts; update renamed skill in test
* Assert agentDefaultSurface in Chat UI onboarding e2e
* Open the chosen Chat UI agent when a new project's default checkout opens
* Make the onboarding chat preview match native chat
- Soften the selected preview tile styling.
- Accept a leading separator in dev:fresh arguments.
* Fix scrolling in the onboarding agent step
* Preserve initial working directory when opening empty workspaces
Also check only remaining tour steps for unfinished actions.
* Fix tour resumption after completed split steps
* fix(sidebar): keep discovered worktrees hidden when adding a project
Adding a project no longer switches it to show worktrees Orca didn't create
(Conductor workspaces and other tools' worktrees). They stay behind the
sidebar's "Hiding N discovered worktrees" line, the same as every other
way a project is added.
* fix(sidebar): open a picked linked worktree instead of revealing its siblings
When the folder added as a project is itself a linked worktree, its main
checkout is hidden. Open the picked worktree instead of switching the whole
project to show worktrees Orca didn't create.
* fix(repos): register clone and create paths with symlinks resolved
Git reports checkout paths with symlinks resolved. Clone and create saved the
typed path, so a project cloned under a symlinked folder (e.g. /tmp on macOS)
did not recognise its own checkout and hid it as a discovered worktree. Resolve
the existing part of the destination before registering, as adding an existing
folder already does.
* fix(repos): keep finding projects saved under a symlinked clone or create path
Projects cloned or created before paths were resolved keep the typed
spelling. Match both spellings so retrying the same clone or create reuses
the saved project instead of failing on its non-empty folder.
* fix(repos): keep Windows clone and create paths as typed
Windows Git reports the typed spelling, and resolving would turn mapped
drives into UNC paths. Runtime clone/create tests now use resolved temp
roots, matching what registration saves.
* fix(repos): register Git's checkout path for clone and create
Replace the parent-symlink resolution with the path Git reports after clone
or git init, as adding an existing folder already does. This also covers a
symlink at the target folder itself and WSL paths, leaves plain folders and
Windows spellings unchanged, and matches saved projects by both the typed and
the resolved spelling.
* fix(sidebar): keep opening projects whose own checkout isn't recognised
Projects saved through a symlinked path by older builds or paired hosts don't
recognise their own checkout. Keep main's behaviour for that case: show the
project so the add still opens it.
* fix(repos): match resolved paths when importing a folder of repos
Clone and create now save Git's resolved checkout path, so a nested import
through a symlinked folder must also match that spelling instead of
registering a duplicate project.
* fix(repos): find saved projects through a symlink before the clone target exists
Resolve a missing clone target through its existing ancestors, reusing the
worktree-create alias resolver, and read the lookup keys inside the clone
lock. Queued clones through a symlinked folder reuse the first clone, and a
different repository at a saved project whose folder is gone is refused
before cloning, as on main.
* fix(repos): match a folder import's resolved path only to local projects
The resolved spelling names this machine's folder, so a remote (SSH) project
at the same path string must not be treated as the import.
* fix(repos): limit a desktop folder import's resolved-path match to this machine
Runtime-owned and SSH projects can share the path string; only projects on
this machine may match the import's resolved folder.
* fix(repos): read a nested import row's connection through the host helper
* fix(repos): match only this machine's projects when creating a local project
* perf(agent-hooks): start 5 processes per Claude hook event instead of 17
The managed Claude hook runs for every PreToolUse and PostToolUse. On macOS
each event started 17 processes; on Linux 17 (dash) or 19 (bash).
- Agent identity: Linux reads /proc/<pid>/stat and boot_id with `read`
builtins. macOS skips `uname` when OSTYPE is darwin and runs only
`exec /bin/ps`, without `sed` or `printf` subshells. The identity stays per
event: no shell builtin can tell a reused PID from the process that had it.
- Metadata header: packed once per pane into hook-metadata/pane-<id> beside
the endpoint file, and reused only while all six inputs match exactly.
- Payload: the capture subshell execs /bin/cat, curl reads the body from a
here-document, and the PreToolUse reply subshell execs curl.
Other agents keep their scripts byte for byte. Against a fake hook server,
the old and new scripts give the same server records, stdout, spool records
and time limits; the raw JSON body gains one trailing newline from the
here-document, which JSON parsing ignores.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(agent-hooks): keep the hook payload pipe off the exec path and prune metadata files
- Only the reply subshell that execs curl reads the body from a
here-document. The print-then-post path of Claude-compatible CLIs uses the
printf pipe again, so its body stays byte for byte and needs no TMPDIR.
- The spool drain removes hook-metadata files older than
AGENT_HOOK_SPOOL_MAX_AGE_MS, in main and in the WSL/remote guest.
- The Linux identity reads /proc/<pid>/stat to EOF, so a command name with
a newline keeps its start time.
- Comments are one line each, and the string-index stdin test is deleted;
the runtime stdin tests in the same file cover every generated script.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(agent-hooks): run the refresh locale test on the raw JSON exec-curl path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(agent-hooks): keep the Claude hook body piped to curl
The here-document added a trailing newline to the raw JSON body and,
under macOS /bin/sh (bash 3.2), wrote every payload to a temp file.
Pipe the body again so the hook server gets the same bytes as before.
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
* 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
* fix(contextual-tours): keep the Split tip until the user splits or closes it
The Split a terminal pane tip was saved as seen the first time it painted,
so any dialog, page change or restart ended it for good and the next tip
never appeared. A step that waits for an action is now done only when the
split succeeds (the saved split record) or the user closes the tour; the
tour resumes at its first unfinished step and keeps its session slot while
paused.
* fix(contextual-tours): a resumed tip never takes focus, at any step
* fix(contextual-tours): keep the pause across an activation that never painted
* fix(contextual-tours): a forced tour can't take a paused Split tip's place
* fix(contextual-tours): type the focus hook's tour ids
* fix(contextual-tours): remember a resumed tour in the store, and stop watching for a sidebar tip while the sidebar is closed
The overlay unmounts between activations, so its pause memory never
survived; the activation itself now says it resumes a tour already
started this session.
* fix(contextual-tours): keep the agent-sessions interaction counted only before a first split
* fix(contextual-tours): a tip that waits for a split never takes keyboard focus
It shows over the terminal the user types into and comes back each
session until they split, so taking focus (first display, after a
restart, or on the next tip after a keyboard split) would send their
keystrokes to its dismiss button. Replaces the in-memory resumed flag.
* fix(contextual-tours): keep focus in the callout when the user navigates inside it
* fix(contextual-tours): let other pages' tips show while the Split tip waits for a split
The Split tip now sits outside the one-tour-per-session limit while it is unfinished: it
neither blocks another page's tips nor is blocked by them, and it resumes afterwards.
* fix(contextual-tours): open the sidebar for a paused Split tip only if it started this session
* fix(contextual-tours): decide the session limit inside the tour effect, as main read its inputs
* fix(ai-vault): list managed Antigravity chats in Agent Session History
Orca's managed Antigravity chat sets GEMINI_HOME under the app's data
directory, so its transcripts land in antigravity-chat/antigravity-acp/brain,
which the history scanner never walked. Scan that root, take each session's
cwd from the server's conversations/<id>.meta so the row shows in its
workspace, and treat rows no chat owns as transcript references, since agy
cannot open the server's conversations.
* fix(ai-vault): scan managed Antigravity chats only for reference-aware clients
* feat(native-chat): let users change or turn off the idle stop for chat agents
The idle sweep stopped every chat's agent after a hard-coded 30 minutes,
which broke peer messaging, Claude Remote Control and background
subagents. Settings > Chat > Behavior now picks the window, including
Never, and the sweep reads it every tick so a change applies without a
restart. Never only keeps agents running: a chat handle with no agent
still retires on the default window.
* test(native-chat): type the childless sweep fixture's journal parameter
* feat(native-chat): add a setting to keep the scroll position when sending
Own sends from a pane bring the latest into view and follow the reply.
A new Chat > Behavior setting, "Scroll to latest when sending" (on by
default), turns that off: a reader who scrolled up stays in place, one
at the end keeps following the reply, and Jump to latest still works.
The gate sits in the one reveal every send path reports to, so the
explicit Jump to latest button and find navigation are unaffected.
Fixes#38153
* fix(native-chat): keep following a reader at the end when reveal on send is off
A reader can sit at the end without following (a rail jump that clamps at
the end, a short nudge up). The setting's gate skipped their reveal, so
the sent message and its reply grew below the viewport. The list now
decides: off skips only readers who stopped away from the end, judged by
where they last scrolled so the send's own echo doesn't count.
* refactor(native-chat): read the scroll-on-send setting through one helper
Also drops the redundant 'scroll' search keyword (the title already
matches) and the settings switch call-shape test.
* fix(native-chat): decide the send reveal from where the reader was at the press
The last-scroll distance stayed small after output grew past a reader who
had nudged up, so a later send still jumped them with the setting off.
The list now reads live geometry, and a structured message, which reveals
only once the host admits it, captures that answer at the press, before
its own echo moves the end.
* fix(native-chat): read the reader before Resume waits for the host
Resume reveals only after the host lifts the pause, by which time the
drain may already have added rows below the reader.
---------
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
* 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
* Give unconfirmed chat messages explicit recovery actions
* Resolve receipt settlement code quality findings
* Complete recovery copy localization and callback types
* Align send lifecycle contracts with explicit recovery actions
* Include the unconfirmed opener in the restart fixture type
* fix(chat): preserve recovery ownership across lifecycle boundaries
* Preserve send ownership across context replacement and recovery
* Separate history ingestion from live send settlement
* Preserve original send truth and reconcile acquired history
* Use summary-shaped history responses in acquisition coverage
* Preserve queued image recovery for released readers
* Prove independent late receipt recovery across reopen
* Preserve queued image sources in bounded catch-up projection
* Keep queued input and explicit chat retries in their original domains
* Preserve reader lifetime across main session interfaces
* Fix static checks after main integration
* Migrate retained recovery Stop contracts to current lifecycle
* test: use typed access for journal population counters
* fix: consolidate history page bounds type imports
* test: exercise legacy snapshot reuse through selected handoff
* Fix attachment draft typing and document test boundary casts
* Repair current journal integration types and contract fixtures
* Keep uncertain send recovery in queue reorder reopen contract
* Repair mobile contract boundaries and exact queue lookup
* Align input finalization contracts with current Stop ordering
* Keep recovery copies independent of queued message barriers
* Reconcile Stop and replay contracts with current lifecycle
* Update recovery tests for current module and draft APIs
* Align Stop recovery contracts with independent queue policy
* Expose independent recoveries to current queue controls
* Cover sending-only queue Resume visibility
* Adapt recovery contracts to shared queue projection
* Use current history and failure-word contracts in recovery tests
* test: retain released reader source contracts through queue settlement
* Keep uncertain sends in ordinary history and preserve saved queue choices
* test: prove mobile draft leaf subscription isolation
* Use typed operation instrumentation in mobile recovery test
* Align lifecycle test boundary typing with static rules
* Repair test module typing and retained runtime copy catalog
* Remove unused chat delivery notice translations
* test(chat): retain legacy handback without uncertainty notice
* fix(chat): omit saved uncertainty card captions
* test: bind released readers to exact queue wire and proof
* Replace archived reader evaluator with exact recorded contracts
* Mark queued edit test hook import as type-only
* Isolate queued card tests from native inline composer imports
* Complete structured mobile resolution in queued edit test
* Align mobile attachment cleanup lifetime test with send outcomes
* fix: restore journal prototype delegation methods
* Keep uncertain sends as ordinary messages in memory
* Release notes admission after uncertain opening completes
* fix: end opening selection operations at uncertain completion
* fix: derive selection admission from live requests and repair integration tests
* test: consolidate send imports and use a supported locale
* Fix CI test types and synchronize retired delivery catalogs
* Type exported test fixture mocks through the public Vitest API
* test: align selection and journal verification contracts
* Reconcile acquired history before journal projection
* Preserve saved invocation facts during history catch-up
* Repair journal recovery consumers and CI contracts
* Keep failed legacy import displays serializable and bounded
* Preserve journal owner boundaries in CI import cleanup
* Fix typed test fixtures for session recovery contracts
* fix: align history and recovery contract types
* test: verify logical rewind across released chats
* Bound retained queue and status reads
* Bound Stop and delivery reads to relevant journal inputs
* Bound subscriber catch-up and stopped-history reads
* test: align journal read fixtures and operation counts
* Bound automatic chat reads to current input evidence
* fix: align journal reader contracts and test fixtures
* test: type historical dispatch rejection fixtures
* fix: restore merged session projection and fixture types
* fix: preserve resumed queues across logical fork rewind
* Preserve queue pause chronology across logical rewinds
Keep original Stop and Resume coordinates while retaining matching warm failure evidence in the journal owner. Keep historical fixture authoring separate from current production writes.
* End historical fixture authoring before current queue actions
* Keep answer operations separate from retained messages
* Fix resting chat attention context
* Fix attention regression fixture provenance
* Validate retained RPC test frame reads
* Fix retained attention and RPC contract fixtures
* Keep send observations on canonical delivery evidence
* feat(editor): add a default Markdown view setting with a switcher right-click menu
Markdown files can now open in Source instead of Rich Editor. The choice
lives in Settings > General > Editor and in a right-click menu on the
editor's view switcher. Changing it keeps already-open tabs on their
current view; the right-clicked tab follows the new default.
Closes#38102
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(editor): switch the right-clicked tab through the normal view toggle
Picking a default from the switcher menu now goes through the same
handler as clicking a segment, so a tab showing Changes or a plugin
editor leaves it for the chosen Markdown view.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(terminal): a paired-server file link opens in the workspace it was clicked in
Clicking a server terminal link to a file another workspace holds switched to
that workspace: the client asked the host for the holding workspace
(crossWorkspace), and the editor loader moved any absolute-path tab -
including one already holding a grant - to that workspace. Anyone who can
open a tab can already run anything on the host, so the holding workspace
guards nothing. On hosts that save granted files, the link now opens through
a grant in the clicked workspace, and restored tabs re-grant in place. Hosts
that can't (older hosts, their own SSH workspaces) and folders keep opening in
the holding workspace.
* fix(runtime): a desktop client reads and saves a granted file as large as a workspace one
Hosts advertise files.resolve-terminal-path.in-place-files.v1, give desktop
clients a 2 MB grant budget (phones keep 512 KB), and report a grant's size,
so the clicked workspace opens a file another workspace holds in place and
falls back to the holding workspace only where a grant can't serve it.
* fix(terminal): open in place only what a grant can read and save
Review: a grant save must fit one request frame and grants serve no bytes
editors, so the 2 MB budget would open files that can't be saved. Hosts now
report a grant's size and binary content instead, the client opens in place
only text within 512 KB, and only the SSH-workspace refusal moves a restored
tab; other host errors stay retryable.
* docs(terminal): describe the in-place files probe
* fix(terminal): ask the holder first and keep downloads, HTML and missing paths unchanged
Review: the holder answers first, as before, so missing paths, folders, this
computer's files, downloads and HTML previews resolve exactly as they did; only
an existing text file another workspace holds asks again for a grant here.
In-place opens are capped at 256 KB so edits stay within the grant's save limit.
* test(editor): mark the placement test's store stub as a sound cast
* fix(automations): accept Pi model and thinking extra arguments
* fix(automations): keep Pi provider pins and refuse unpinned inline keys
* fix(automations): match Pi value options to its argument parser
* fix(automations): refuse Pi model overrides beside unscoped inline keys
* test(automations): cover Pi's last-provider-wins key pin
* fix(automations): refuse any Pi custom Command text with --api-key
* fix(automations): drop the Pi inline-key pin guard
Pi already sends an unpinned inline key to the chosen model's provider and warns;
the user typed both the key and the model, so Orca does not refuse it.
* Add Ultracode to Claude chat effort
* Correct Ultracode test type annotations
* Keep Claude workflow effort observations consistent
* Make effort picker test follow async option contract
* Keep effort coverage at its owning behavior layer
* Exercise workflow readback with recorded native settings
* Preserve configured workflow during effort reapplication
* fix: respect manual workspace order around primary checkouts
* test: consolidate manual primary-order coverage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: name twin-reorder cases after the dragged linked worktree
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: read worktree ID from mobile workspace row
* test: exercise primary checkout drops in reorder cases
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>