Commit Graph
13408 Commits
Author SHA1 Message Date
Neil ab9532ecd8 feat(wsl): let an idle WSL distro stop once its server idle-exits (#33084)
* feat(wsl): let an idle WSL distro stop once its orcad idle-exits

The WSL host's holder kept the distro (and the WSL VM) running after Orca quit, even with
nothing running in it. orcad now leaves a release request in ~/.orca when a managed idle stop
retired its terminal daemon; the holder waits for that orcad to exit, claims the request and
ends, so WSL can stop the distro. Live terminals, working agents, enabled automations or a
returning client keep the distro held as before. A host whose distro is stopped at startup
reads as stopped instead of unreachable, and the real-WSL lane gains a phase that proves the
release and records memory.

* fix(wsl): key the holder release on the WSL-host launch marker; name the lane phase

The real-WSL lane showed orcad idle-stopping with its daemon retired while the distro stayed
up: the setsid'd orcad's environment is not guaranteed to carry WSL_DISTRO_NAME, so the
release request was never written. Use ORCA_WSL_ORCAD_HOST, which only WSL-host launches set.
Phase 3 now carries its phase name and path filter, and records what kept a distro running.

* test(wsl): dispose the idle-release lane's guest transports

Each guest command left its exec loop running, a wsl.exe client that kept the distro up after
the holder had already let go (the receipt showed no holder, no orcad, no request left).

* test(wsl): record which wsl.exe clients keep the idle-release lane's distro up

* test(wsl): satisfy the flaky-test ratchet; feed the new idle port in the release test

* test(wsl): snapshot guest processes after launch to find what holds the session

* test(wsl): locate the step that leaves the zombie holding the idle distro

* test(wsl): log the idle-release lane's guest commands with times to place the zombie

* test(wsl): follow the remote runtime client's move

* test(wsl): record when each leftover WSL session init started

* fix(wsl): keep the distro while the user still runs anything, and never trip on the request file

Review of #33084:
- The holder now checks, before claiming a release, that no process of the user runs outside
  the holder itself (session plumbing aside: systemd --user, (sd-pam), dbus-daemon). A detached
  tmux, nohup job or dev server keeps the distro; it fails toward holding.
- A new holder drops any request left from before it started, so an older orcad's request can
  never end a holder a client just asked for.
- orcad touches the request file only for WSL-host launches and never throws over it.
- The real-WSL lane proves a detached job keeps the holder and its request, and the distro
  stops once the job ends.

* fix(wsl): a running container keeps the distro, whoever owns its shim

Docker's containerd-shim processes run as root, so the user-only scan missed them and a
release would have stopped running containers. Any containerd-shim process now keeps the hold.

* fix(wsl): read each process status only up to Uid; document what keeps the hold

Delta review of #33084: dash reads a status file a byte at a time, so stop at Uid. Document
that a root default user never releases, that per-user agents hold it, and the hidepid
exception. The lane's pkill no longer matches the shell running it.
2026-10-27 01:28:40 -07:00
Neil 0ed5f4bb21 fix(orcad): materialize the app's agent-browser driver into the local slot (#34150)
* fix(orcad): materialize the app's agent-browser driver into the local slot

Replaces #34111's ORCA_AGENT_BROWSER_DRIVER hand-off, Windows profile copy and
claimed snapshot store. Packaging now references the app's own
resources/agent-browser-<target> from the orcad template manifest
(packagedBrowser, like packagedRipgrep), so the materialized slot carries it and
every local orcad launch finds it beside orcad-server.js. macOS signs the driver
before hashing; Windows reseals it after SignPath. The resolver now also tries
the musl driver name on Linux.

Refs #33846

* build(orcad): let a checkout keep template drivers with ORCAD_OMIT_AGENT_BROWSER=0
2026-10-27 01:28:20 -07:00
OrcaWinandOrcaWin 755bbfaa13 test: remove 53 low-value cases and eight suites (#34302)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 01:16:41 -07:00
OrcaWinandOrcaWin 4378e2fd3b perf(native-chat): load the chat host and agent adapters on first use (#34318)
Startup evaluated every structured-agent adapter (claude, codex, acp, pi)
even when no chat was opened. The host install already loaded the
registrations with a dynamic import, but structured-chat-cli-fork imported
the same module statically to read sessionHistory, which the lightweight
metadata already exposes.

- structured-chat-cli-fork reads structuredAgentRuntimeMetadata (the same
  objects, so behavior is unchanged).
- installOnJournal moves unchanged into structured-agent-session-host-assembly,
  which install() loads on first host install; the existing installing slot
  already single-flights and retries it.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 01:14:23 -07:00
Neil 3cf09081da refactor: group shared native chat scope cache (#34314) 2026-10-27 01:12:21 -07:00
NeilandSeiji Kohara c0f9df5bea fix(ssh): keep the IME confirmation Enter from submitting the port-forward dialog (#34315)
The SSH port-forward dialog renders its four fields as raw inputs inside a
form with a submit button. IMEs that redispatch an unmarked Enter after
compositionend therefore trigger implicit submission with the half-typed
value. The pre-revert ImeEnterGuardedForm covered this form; #25480 moved
the guard into shared fields but did not reach these raw inputs, and the
#28609 lint rule only inspects Enter handlers, which these fields lack.

Render the fields with ImeInput so the shared gesture tracker swallows the
confirmation and its redispatch while ordinary Enter still submits.

Co-authored-by: Seiji Kohara <sage.0118@gmail.com>
2026-10-27 01:03:19 -07:00
Neil 80c9278b89 fix(wsl): say why a silent WSL guest command failed (#34304)
* fix(wsl): say why a silent WSL guest command failed

A guest command that exits non-zero with empty stderr was reported as
"WSL <distro>: command failed". When wsl.exe itself fails it writes its
error to stdout, so the real cause was dropped. Report stderr, else
wsl.exe's own error, else the exit code, for the Claude account pointer,
OpenCode reader, WSL CLI install and WSL file operations.

Refs STA-12262 (#33917)

* refactor(wsl): share the wsl.exe host-failure exit check

* test(wsl): type the guest failure fixture instead of asserting it
2026-10-27 00:58:25 -07:00
OrcaWinandOrcaWin bbc35c1a98 test: remove 30 low-value cases and 11 suites (#34288)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-27 00:54:59 -07:00
Neil 16ea126b4e fix(repos): remove a paired-server project while its server is unreachable (#34079)
* fix(repos): let a project be removed while its paired server is unreachable

An unreachable server's repo.rm timeout aborted the whole removal. The error toast
now offers 'Remove from this desktop now', which purges this desktop's rows, records
a pending repo.rm (persisted UI state, optional), fences the server's catalog so it
cannot re-add the project, and replays the removal once the server is ready again.
Re-adds and replays for one server are serialized so neither undoes the other.

Fixes STA-9705

* fix(repos): replay owed removals whenever the server is ready, and lift the fence on refusal

Main publishes status only on change, so a record written or seeded after the ready
snapshot now replays at once. A refused replay refreshes the server's catalog, a
retired server drops its records, a user disconnect also offers local removal, and
the field is main-owned so paired clients cannot overwrite it.

* fix(repos): keep owed removals across disconnects and re-pairs; drop them only for forgotten servers

Also picks up records written during an in-flight replay, classifies the new UI field for
WSL moves, and fixes the test's projection shape.

* fix(repos): say 'disconnected' when the user disconnected the server, and test records surviving re-pair

* fix(repos): retry a replay when the server reconnects while it is still failing

* test(repos): narrow the toast action instead of asserting its type

* test(repos): run the toast action's removal directly instead of dispatching its handler
2026-10-27 00:51:44 -07:00
Neil e59e4eb550 fix(wsl): close a WSL host channel with stdin EOF before killing wsl.exe (#34307)
* fix(wsl): close a WSL command channel with stdin EOF before killing wsl.exe

Killing wsl.exe while its guest command still runs can leave the WSL session (an /init with a
wslhost.exe helper) behind, which keeps an idle distro running. A closed channel now ends stdin
first and kills wsl.exe only if the guest has not exited within 2 s.

* fix(wsl): kill WSL-host channels still in their close grace at app quit

Review of #34307: a guest command that ignores stdin EOF would otherwise keep its wsl.exe up
past Orca's exit for the rest of the grace. Quit teardown now kills every channel still in its
grace. The abort test runs on fake timers instead of waiting the grace in real time.
2026-10-27 00:50:37 -07:00
NeilandClaude 4c66f91c84 perf(native-chat): stop unrelated host status flips from rerendering every chat (#34300)
useStructuredAgentSessionOwnPermissionState subscribed to the whole
runtimeStatusByEnvironmentId map, so each status publication for any paired
host rerendered every mounted chat (including hidden ones). Select the
derived capability verdict for the chat's own host instead.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-27 00:34:28 -07:00
Neil 2c6dd27276 refactor: group shared native chat shell environment policy (#34301) 2026-10-27 00:30:13 -07:00
Kelvin Amoaba cbbaa2d763 fix(agents): stop reading "action required" in a Pi/OMP session name as a permission prompt (#34294) 2026-10-27 07:19:37 +00:00
Neil 1dec1ebc35 refactor(shared): group native chat visual contracts (#34296) 2026-10-27 00:03:29 -07:00
Kelvin Amoaba 30872835cd fix(browser): type text that starts with a dash literally instead of as an agent-browser option (#34289)
* fix(browser): type text starting with a dash literally instead of as an agent-browser flag

* fix(browser): keep fill scripts on eval --stdin and send well-formed batch text

* fix(browser): leave passthrough multi-command batch replies unwrapped

* fix(orcad): pass the wait process timeout through the run options

* refactor(browser): let caller stdin imply argv mode and share the batch decoder in tests

* test(orcad): decode batch commands in the provider selection fake
2026-10-27 07:01:46 +00:00
Brennan Benson a0e7fa0619 Keep Claude approval choices across model changes without freezing delivery (#34031)
* fix(native-chat): keep Claude approval choices across model changes without freezing delivery

A Claude chat saved as "Approve for me" could reopen asking for every approval,
because Orca read the folder's saved model list as launch policy, and a model
change could keep running in a weaker approval mode Claude opened with. The
first fix for this was reverted after it froze the app: restored history left
a turn reading as running, a send was refused against it, and delivery retried
the same send with nothing changed.

- The saved approval choice goes to Claude as-is; the menu offers every mode.
- Orca records the mode Claude actually opened in. A send that picks a new
  model reopens Claude first when that mode differs from the one requested,
  only when the chat owes no work; Orca mail notices never reopen it.
- A message sent while a Claude turn is running joins that turn on its current
  choices; new choices apply at the next new turn. Nothing is refused.
- History catch-up closes every turn it opens, in the thread it opened in.
- At startup, a turn reading as running under the new agent that the agent is
  not running is ended as interrupted.
- Delivery goes round again only after a step shows what it changed (a commit,
  a different child, a start it joined ending, or a wake); otherwise it waits
  for the next change instead of repeating the same step.

Tracked in STA-10953.

* fix(native-chat): preserve execution evidence at dispatch

* Fix delivery iteration ownership and progress contracts

* Correct journal fixture types in delivery regressions

* Separate Claude input choices from error correlation
2026-10-27 00:01:09 -07:00
Brennan Benson 1c4d4a03bc feat: drag to reorder queued messages on desktop and phone (#34026)
* feat: drag to reorder queued messages on desktop and phone

* fix: use the queue grip button padding from its primitive

* fix: preserve the queue grip touch width with hit slop

* test: carry queue animation mocks into the chat view harness

* test: complete the shared chat view harness registrations

* test: carry the queue move cross-version wire contract

* Scope queue move feedback to the issuing chat and preserve phone touch width

* Keep queue reorder presentation stable during measurement and pending moves

* Keep measured row handoff tokens constant size

* Avoid rebuilding queue arrival IDs on unchanged renders

* Fix mobile queue regression test fixture boundaries

* Share the queued message leading slot with its reorder grip

* Fix queue regression fixture quality findings

* Check queue icons within the leading slot

* Allow every unsettled queued message to reorder

* Supply stable scope in queued row test mock
2026-10-26 23:57:36 -07:00
Kelvin Amoaba b01dc62972 fix(browser): copy and cut from streamed browser pages to the local clipboard (#34290)
* fix(browser): copy and cut from streamed browser pages to the local clipboard

The streamed frame forwarded Ctrl/Cmd+C and X to the host page as a
keypress, so the host's Chromium copied into the host machine's
clipboard. The chord now runs copy or cut inside the page over the
existing browser.eval and writes the text to the viewer's clipboard. A
cut deletes the selection only after that write succeeds.

* test(browser): read streamed keyboard RPC calls through the typed helper
2026-10-27 06:53:41 +00:00
217f935597 fix(updater): skip IPC when the main window is destroyed (#11567)
The updater kept a reference to the main BrowserWindow after it closed, and
every status/nudge/install-abort send read `webContents` on it. Electron throws
"Object has been destroyed" from that getter, so the hourly background check
produced main-process unhandled rejections from the MacUpdater failure path.

Route all updater IPC through UpdaterState.sendToMainWindow, which drops the
send when the window or its webContents is destroyed. The renderer re-pulls
status via updater:getStatus on mount, so nothing is lost. Updater test window
mocks now come from the shared updaterMainWindow helper.

Fixes #11544

Co-authored-by: Brennan Benson <brennan@stably.ai>
Co-authored-by: Neil <neil@stably.ai>
2026-10-26 23:51:44 -07:00
Kelvin Amoaba 50f898fbc3 fix(agents): recognise OMP and Pi titles after Orca rebrands them (#34292) 2026-10-27 06:49:11 +00:00
Kelvin Amoabaandoutof-place 8655ce670f fix(browser): deliver agent clicks and keys to pages that loaded while their pane was hidden (#34291)
A page that loads while its browser pane is parked (display:none) never
paints, and Chromium drops input to a document before its first paint.
orca click/hover/keypress/mouse on such a page reported success after a
~5 s mouseMoved stall while the page got no press or key.

Before agent input reaches a webview guest, from the CDP proxy queue or
the bridge's direct pointer and key routes, ask the page whether it has
painted. If not, hold its paint with the existing capture paint hold
until a paint entry appears or a few frames pass, once per document.

Co-authored-by: outof-place <contact@outofplace.space>
2026-10-27 06:48:31 +00:00
OrcaWinandOrcaWin 136721fcb9 test: remove53 low-value cases and8 suites (#34264)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 23:45:26 -07:00
MeapriandNeil 47567c6ac7 fix(terminal): refuse non-finite mouse coordinates so scroll never sends NaN to the PTY (#23330)
xterm's touch inertia gesture events carry no clientX/clientY, so with a
TUI requesting wheel reports a flick sent `ESC[<65;NaN;NaNM` to the PTY
(#20983). NaN slipped past `col < 0 || col >= cols`; the patched range
check in MouseService._triggerMouseEvent is negated so it fails closed.
Regenerate the beta.304 bundle and lock hash.

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-26 23:36:01 -07:00
Neil b29ae01912 fix(automations): show why a hook-review-blocked automation fails, keep it running, and stop stuck-tab pile-up (#33638)
* fix(automations): pause a schedule whose agent is stuck on a hook review

Codex opens a blocking 'Hooks need review' dialog when a hook in hooks.json is
new or changed. Only a person can answer it, so every later scheduled run of
an automation hit the same dialog and failed. Pause the schedule on the first
such failure and say how to recover. Also re-enable Orca's own Codex hook on
SSH installs, matching local installs.

Refs #28252 #23289

* fix(automations): keep a hook-review-blocked schedule running and say why it fails

Replace the auto-pause with a visible, self-clearing failure: the run error
explains the Codex hook review, the automation and run pages show it above
saved output, and earlier tabs stuck on the same prompt close so only the
newest stays open to answer. Runs succeed again on their own once the hooks
are trusted or removed.

* fix(automations): only close hook-review tabs the run still owns and that are provably unused

- Cleanup resolves the pane through runOwnHandle, so a cold-restored pane holding a new process is left alone.
- Close only on definite 'unused' input history, matching headless run-terminal retention.
- Catch failures from the fire-and-forget cleanup call.
- Show the run page error notice only for dispatch_failed runs, and add the missing en catalog keys.
2026-10-26 23:21:28 -07:00
Kelvin Amoaba cd757f4b19 fix(browser): pass orca wait's timeout through to agent-browser (#34283)
Condition waits never forwarded --timeout, so agent-browser always stopped at its own 25s default and --timeout 60000 still failed at 25s. orcad's external Chromium run and Electron sidecar socket also capped waits at a fixed 90s. One builder now passes --timeout (explicit or the documented 25000 default) on the local and orcad paths, process kills sit 5s above it, and every forwarding hop waits max(60s, T+30s).
2026-10-27 06:17:21 +00:00
Neil 43eb0b969c fix(opencode): give OpenCode 2 a private server only when another data dir holds the service port (#33784)
* fix(opencode): run managed OpenCode 2 accounts on a private server

OpenCode 2's background service binds one fixed port per machine, so a
second managed account's service could never start. Launch managed
accounts with --standalone, which picks its own port.

Fixes #33780

* chore(opencode): tighten standalone rewrite comments

* fix(opencode): use a private OpenCode 2 server only when another data dir holds the service port

Users with one managed account keep the shared background service. Orca
adds --standalone only when a live upstream registration
($XDG_STATE_HOME/opencode/service.json) belongs to a different data dir,
plus a short in-process claim for launches that start together.

* fix(opencode): judge resumed accounts by their applied data dir and claim the port only for real launches

Daemon spawns consume the resume request before the private-server check runs, so
derive the launch's own data dir from the applied account env when present. Only
take the shared-port claim when the --standalone rewrite can apply.
2026-10-26 23:06:43 -07:00
Neil ec8f4dd8bd refactor: group repository source-control AI settings (#34278) 2026-10-26 23:05:39 -07:00
OrcaWinandOrcaWin 0fcc74ea2a test: remove 56 low-value cases and 5 suites (#34268)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 23:03:21 -07:00
Wooseong KimandNeil 845e4668e3 fix(orchestration): stop calling unobserved worker input "submitted" (#21453)
When a worker's turn start was not observed, the dispatch receipt claimed
the input was "written and submitted". A swallowed Enter leaves the prompt
in the composer, so say the text and Enter were written, keep the wait bound
and possible causes, and point at `terminal read` before resending.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 22:59:09 -07:00
OrcaWinandOrcaWin 84494ce394 test: remove 338 low-value cases and 28 suites (#34234)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 22:58:55 -07:00
Neil fa4d2e99db fix(wsl): reap the bash stdio relay's cats before it exits (#34260)
* fix(wsl): reap the bash stdio relay's cats before it exits

The relay killed the surviving cat and exited at once. WSL's per-session init never reaps
orphans, so that cat stayed a zombie, its session never ended, and the distro never stopped
even with nothing of Orca's left in it (seen on every real-WSL idle-release run). Wait for both
cats after the kill.

* test(wsl): prove the bash relay waits for the cat it kills
2026-10-26 22:54:27 -07:00
hwantageandNeil 483573f0b9 fix(browser): focus newly opened image tabs (#34127)
* fix(browser): focus newly opened image tabs

Focus the window before the webview so Command+W closes the new
image tab instead of the original tab after a plain image click.

Add tests for focus order, image loading, and close-shortcut forwarding.

Fixes #34114

* test(browser): verify image tab focus with native keyboard input

* refactor(ci): keep browser E2E routes within registry size limit

* fix(ci): enable background launch for native browser regression

* test(ci): include browser routes in isolated detector fixture

---------

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 22:52:40 -07:00
Neilandlorenzozanee bca89125ce fix(updater): apply the app proxy to electron-updater's session (#34276)
electron-updater sends checks and downloads through its own
"electron-updater" partition, so a proxy configured only in Orca settings
never reached update requests. Apply the same proxy policy (and request
guard) to that partition at updater setup and on settings changes, and
answer its proxy login challenges with the configured credentials.

Co-authored-by: lorenzozanee <195543813+lorenzozanee@users.noreply.github.com>
2026-10-26 22:52:25 -07:00
EvgeniiandNeil 8d72873b78 fix(i18n): resolve plugin-pack plurals with the pack's declared locale (#12505)
Plugin language packs register under synthetic plugin<hex> resource
languages, so i18next's plural resolver fell back to English rules and
Russian/Polish/etc. packs never selected their _few/_many forms. Map each
pack's resource language to its declared (Intl-supported) locale inside
the plural resolver, and fill missing plural categories from the key's
_other form so packs that only ship _one/_other stay in-language.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 22:42:57 -07:00
Ulises MillánandNeil 7815c07874 fix(session-history): close other row action menus when opening one (#31801)
Opening the "..." menu on one Session History row left another row's
menu open, because the row wrapper's pointerdown stopPropagation hides
the click from Radix's outside-dismiss. Each row now controls its menu
state and broadcasts the shared close-all-context-menus event when it
opens, so any other open row menu closes.

Fixes #31563

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-26 22:42:39 -07:00
Neil 6ae3fbc89b fix(browser): open target=_blank file links from a local page in an Orca tab (#34057) 2026-10-26 22:42:19 -07:00
hiro 1fdf89685e fix(i18n): use the product name "Finder" in Japanese reveal/open labels (#30081)
macOS Japanese UI shows Finder by its product name, not the katakana
transliteration. Update openInFinder and revealInFinder accordingly.
2026-10-26 22:31:19 -07:00
Neilandoutof-place d5070dedb8 fix(app-icon): restore the sharp bundle icon on the Dock for packaged Classic macOS builds (#34094)
Packaged Classic builds left the live Dock tile on the 256px icon.png set by
applyAppIcon. Once the queued AppKit custom-icon clear succeeds and no newer
icon request is pending, persistMacDockIcon now calls
app.dock.setIcon(nativeImage.createEmpty()); Electron passes that to AppKit as
nil, so the Dock draws the full-resolution bundle icns. A failed or timed-out
clear keeps the PNG, as before.

Fixes #27138

Co-authored-by: outof-place <contact@outofplace.space>
2026-10-26 22:30:59 -07:00
Kelvin Amoaba f719d0fb10 fix(mobile): open terminal urls and file paths with desktop's link detection (#33964)
* fix(mobile): open wrapped terminal urls and paths with desktop's link detection

Desktop's terminal URL and file-link detectors move to src/shared and the phone's
WebView document calls them, replacing its single-row copies. File taps carry every
reading of the tapped text so the phone opens the longest one the host finds, as
desktop does.

* fix(mobile): keep the unc host of osc 8 file links for the host to resolve

* fix(mobile): resolve terminal file-tap readings a few at a time

A tap inside a run of path rows yields hundreds of hard-wrap guesses; firing them all at once overflowed the page bridge's pending-request cap and the real path was never checked.

* refactor(terminal): share the osc 8 link classifier and trim file-tap plumbing

Desktop and the phone now read OSC 8 targets through one shared classifier. Terminal file taps carry only their candidate list, deduped by path, and desktop checks OSC overlap only for candidates it can resolve.

* refactor(terminal): keep shared link files under the line cap

The xterm buffer subset gets its own module, and the text-only OSC resolver goes now that the router uses findExactTerminalFileLink.
2026-10-27 05:30:05 +00:00
Kelvin Amoaba 9d2e441947 fix(mobile): compare branches and show diffs with desktop's base-ref and whitespace settings (#34038)
* fix(mobile): compare branches and show diffs with desktop's base-ref and whitespace settings

Base-ref resolution moves to src/shared and the host publishes the compare-against-upstream
and show-whitespace settings, so the phone's branch compare and diffs match desktop.

* fix(mobile): use the upstream compare policy on the review screen and rebuild diffs when whitespace changes

* fix(mobile): reread Source Control settings on Refresh and restart diffs loading under the old whitespace setting

* test(mobile): cover diffs dropped when desktop's whitespace setting arrives

* refactor(mobile): share one Source Control settings read per host across screens
2026-10-27 05:29:46 +00:00
Neil 6d43596fda fix(wsl): keep a user's GLIBC_TUNABLES and delegate the launch-env wrapper (#34248)
* fix(wsl): keep a user's GLIBC_TUNABLES and delegate the launch-env wrapper

The orcad launch now sets GLIBC_TUNABLES only when the launching shell has
none, so a value forwarded through WSLENV wins and the claim leaves it in
place. withOwnBuildLaunchEnv delegates to the transport instead of copying
its own properties, so a class-based transport keeps its methods.

* test(wsl): read the delegated transport through its type, not Reflect

withOwnBuildLaunchEnv now returns the transport's own type, so the test
calls the class method directly. The comment no longer claims #private
class fields survive delegation.
2026-10-26 22:26:11 -07:00
a7c9d19048 fix(file-explorer): offer permanent delete when moving to Trash fails (#33956)
Offer confirmed permanent deletion when moving an item to Trash fails.
Preserve authorization and workspace ownership checks, cancellation behavior,
text-snapshot undo, remote compatibility, and all supported translations.

Fixes #33944

Co-authored-by: nori <dosukoicrypto@gmail.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 22:25:01 -07:00
Neil 362104ca18 fix(wsl): background Git and the roots catalog never start a stopped WSL distro (E9) (#34231)
* fix(wsl): background Git and the roots catalog never start a stopped WSL distro

git status ran on the UNC project root 0.45 s after a terminate, next to the
explorer read; either boots the distro. Background Git (status, conflict
operation, upstream status, branch compare, the upstream-ref watch) now asks the
shared running gate first and refuses for a stopped distro, including host
paths whose Git runs through wsl.exe. The authorized-roots rebuild skips a
stopped distro's repo and leaves it dirty, and the detected-worktree scan fails
as unavailable, so rows are kept and the next scan after the distro runs lists it.

* fix(wsl): the active workspace's first status and a wake read's roots rebuild may start WSL

- Drive-path projects whose Git runs through WSL had no wake path: the active
  workspace's first git:status after it becomes active now passes
  wakeWslDistro, so Source Control starts the distro; later polls stay gated.
- A user act runs in an async scope naming its distro; gated work inside it
  (the authorized-roots rebuild an authorization miss triggers, the detected
  scan, the Git) may start that distro and no other. External worktrees on a
  stopped distro no longer fail a wake read with access denied.
- After a user act wakes a distro, background reads stop trusting the older
  'stopped' read and probe again.

* fix(wsl): explicit WSL launches refresh the running read; wake only on tab change; gate the home probe

- Any wsl.exe Git/CLI run (commit, push, fetch) or WSL terminal spawn for a
  distro last read as stopped records that it started, so background reads probe
  again instead of refusing for up to 60 s.
- The active editor tab wakes only when the active tab changes; effect re-runs
  driven by git status or overview views read without waking.
- The authorization roots' WSL home probe no longer runs wsl.exe in a stopped
  distro when the home is uncached.
- The settle window no longer imports the orcad liveness module (it pulled main
  code into the web typecheck); a test pins it to EXIT_SETTLE_MS.

* fix(wsl): deferred work and running-list listeners never inherit a user act

A user act's async scope could leak into work it triggers indirectly: a drain of
deferred tasks it caused, or listeners of a running-list probe started inside
it. Both now run outside the scope, so only the act's own work may start its
distro.

* fix(wsl): keep shared modules free of main-only gate imports

worktree-logic.ts and wsl-running-distro-cache.ts are also compiled by the web
project, which cannot see main-only modules (AsyncLocalStorage, wsl.exe).
getAllowedRoots now injects the gated home lookup into computeWorkspaceRootWithin,
and the background gate's own cache subscriptions run outside the user-act scope
instead of the cache knowing about it.
2026-10-26 22:23:07 -07:00
OrcaWinandOrcaWin a8f7afe84b test: remove 128 low-value cases and 22 suites (#34206)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 22:21:44 -07:00
Brennan Benson 2e181b1b78 Reuse chat history snapshots across readers (#34215)
* Reuse rendered chat history across readers

* test: cover current journal reads across source changes

* test: align journal assertions with current snapshot reuse
2026-10-26 22:19:15 -07:00
9dd44715ba fix(mobile): keep a renamed tab's name on mobile after the host restarts (#33743)
* fix(mobile): keep a renamed tab's name on mobile after the host restarts

After a restart, the reconnecting client restarts each saved tab's
terminal (restored-pane-materialize -> createRuntimeOwnedMobileSessionTerminal),
and the mobile row built from the new terminal carried no customTitle, so
the phone showed the terminal's own title although the saved session still
held the name. publishPtyBackedMobileSessionTerminal kept a name only from
an earlier mobile row, which a restart does not have.

Both builders now resolve the name through one helper: a value already on
the mobile row wins, including a cleared null; only a row with no value
falls back to the tab's saved name.

Fixes #33737

Co-Authored-By: Claude Code <noreply@anthropic.com>

* refactor(mobile): resolve a restarted tab's saved name through getPtyManualTitle

getPtyManualTitle already owns a terminal's manual name (the saved tab's,
else the live rename), so the row builders use it instead of a second
saved-session lookup. A cleared name reads as cleared from the saved
session, so the test now covers that instead of a row-only clear.

* fix(mobile): keep a row's cleared name instead of falling back to the saved one

A null customTitle on a row is a clear: paired desktops need it to drop a
cached name, and a desktop clear lands on the row before the debounced
session write. Only a row with no value falls back to getPtyManualTitle.

* test(mobile): pin that a row's cleared name survives a terminal restart

---------

Co-authored-by: clayphi <193966884+clayphi@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-27 05:18:58 +00:00
Neil bff2843fca refactor(shared): organize native chat ask input owners (#34251)
* refactor(shared): group native chat ask input owners

* refactor(shared): keep split ask type imports erased
2026-10-26 22:18:52 -07:00
Kelvin AmoabaandChris Stephens 619ee954c9 fix(browser): paste the local clipboard into streamed browser pages (#34269)
The streamed page's keydown handler forwarded Ctrl/Cmd+V to the host as a
keypress and cancelled the browser's paste event, so the host pasted its
own (usually empty) clipboard. Native paste chords now fall through, and
the frame's paste event inserts the clipboard text with
browser.keyboardInsertText on the pane's input queue, split into chunks
that fit the runtime socket frame.

Co-authored-by: Chris Stephens <nyldn@users.noreply.github.com>
2026-10-27 05:16:01 +00:00
Kelvin Amoaba e79388e3ab fix(agents): keep OMP session titles when a turn finishes (#34266)
Orca wrote a synthetic "OMP ready" / "OMP - action required" title over
the session title that OMP and Orca's titlebar extension already paint.
OMP's hooks are authoritative and its own rest title reads as idle, so
stop synthesizing terminal titles for OMP, as for OpenCode.

Linear: STA-11986
2026-10-27 05:15:58 +00:00
Kelvin AmoabaandFelipe 19c53e5248 fix(browser): let Grab page element pick and track elements inside open shadow roots (#34265)
* fix(browser): let Grab page element pick and track elements inside open shadow roots

Document hit-testing and marker lookups stop at a shadow host, so Grab only
ever picked the host. The overlay now descends through open shadow roots,
and both the overlay and the annotation viewport bridge find the marked
element and listen for scrolls inside them. Closed roots stay opaque.

Co-authored-by: Felipe <5784455+fbetancourtc@users.noreply.github.com>

* fix(browser): track slotted ancestors and stop re-walking shadow roots for a lost target

* fix(browser): walk shadow roots once per selection and count fixed shadow hosts

* fix(browser): restore grab pointer events if a page's shadowRoot throws; type the shadow fixtures

* fix(browser): keep composed-tree walks safe from page-named form controls

---------

Co-authored-by: Felipe <5784455+fbetancourtc@users.noreply.github.com>
2026-10-27 05:15:54 +00:00