Commit Graph
17556 Commits
Author SHA1 Message Date
Neil c8b6d38bd4 fix(ci): keep mobile localization out of desktop-only test installs (#35576)
Load the Hermes plural-rules polyfill from the phone app entry instead of
mobile-i18n, and transform mobile-i18n and its catalog loader without the
Expo tsconfig in root vitest.
2026-10-28 19:06:34 -07:00
OrcaWinandOrcaWin 7802d16fda test: remove 17 low-value cases and seven suites (#35394)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 19:04:19 -07:00
Jinjing 366eaffa99 Prioritize direct URL navigation over history suggestions 2026-10-28 18:56:15 -07:00
e1b7248f0a feat(wsl): re-key the profile of UNC Windows-drive projects converting to drive paths (D1c-4b) (#33128)
* feat(wsl): re-key the profile of UNC Windows-drive projects converting to drive paths (D1c-4b)

* fix(wsl): keep the conversion's field table out of the main layout-writer census

* fix(wsl): merge the drive-keyed rows startup wrote for a UNC drive project instead of refusing

WSL Git lists a UNC /mnt/c project's folders under their drive paths, so startup discovery writes a
bare C:\-keyed worktree row (and its identity alias) beside the saved UNC one. The re-key then
landed both on one key and every conversion was refused as wsl_drive_unc_key_collision.

Before the re-key, a drive-keyed row holding only discovery bookkeeping is dropped with its alias
and identity row, so the saved row (instance id, name, links) takes the key. Any other two keys
that meet merge when one is empty or both match; only differing user data refuses, and the error
names the key.

* fix(wsl): treat a chosen workspace status as user data, so the conversion never drops it as a discovery row

Discovery writes only the default status. A drive-keyed row with any other status now counts
as the user's, so the conversion refuses with the key instead of dropping it.

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

* fix(wsl): read /mnt/<letter> with the same case rule as the UNC path folding

Only a lowercase /mnt is drvfs, with the drive letter in either case, as
foldWslUncPathCaseInsensitiveParts already says; /MNT is an ordinary Linux folder.

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

* fix(wsl): a refused duplicate spelling no longer blocks the drive folder's one converted project as an overlap

* test(wsl): a project nested under a refused duplicate's folder still converts

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 18:51:54 -07:00
Kelvin Amoaba f5c84eae58 fix(mobile): the first Back while dictating stops it and keeps what was said (#35477) 2026-10-29 01:44:01 +00:00
Kelvin AmoabaandNico Hu 18c4e6bc47 feat(mobile): give chat code, tables, quotes and diagrams a clearer layout (#34456)
Code blocks get a header with the language and copy button, syntax
colours from the file reader's highlighter, a line-number column and
horizontal scrolling. Short tables fill the message width, cells get more
room, quotes sit on a panel, bullets are dots, and Mermaid diagrams use
the app's borders and type.

Co-authored-by: Nico Hu <haoyu.hu@lexmount.com>
2026-10-29 01:36:56 +00:00
Kelvin Amoaba f640517132 feat(mobile): show chat images that live on the paired desktop (#34462)
* feat(mobile): show chat images that live on the paired desktop

* fix(mobile): read every image type desktop chat shows

* refactor(runtime): share the bounded preview read and chat-image type check

* test: keep the chat-image tests typed and off importActual
2026-10-29 01:27:57 +00:00
Neil 0978e3e049 fix(runtime): quarantining a partly corrupt device registry no longer revokes every device (#35539)
A load that drops an unreadable row quarantines the file at the first
save. The save then re-read the now-missing file, took the empty list
as an admin deleting it, and dropped every valid device. The writer now
records its own quarantine and writes the save as is until a write
lands; a file someone else deleted still revokes everything.
2026-10-28 18:27:12 -07:00
Neil 3a68805eee fix(wsl): Settings CLI status, CLI repair, interop health and link checks never boot a stopped distro (E9) (#35412)
* fix(wsl): Settings CLI status, startup CLI repair, interop health and link checks never boot a stopped distro (E9)

- cli:getWslInstallStatus: opening Settings takes a settled running read and shows a refreshable
  "not running" status instead of starting the distro; the refresh button passes wakeWslDistro.
- Startup CLI repair re-reads each listed distro (settled) right before its repair spawns and
  defers it otherwise, so a distro stopping mid fan-out is not restarted.
- Interop health: stop-triggered checks no longer trust the stop event's list; every check takes a
  settled read, and again before the root repair.
- shell:pathsExist (chat link and terminal hover existence) refuses a stopped distro's UNC path
  instead of statting it; callers already retry an unverifiable answer.

* docs(wsl): note the missing-kernel availability probe as the known E9 exception

* fix(wsl): shell:pathsExist refuses only the stopped distro's path, not the whole batch

One UNC path in a stopped distro no longer fails the host paths checked with it; the renderer
treats that path alone as unverifiable and retries it.
2026-10-28 18:24:26 -07:00
NeilandClaude c14c99bb49 feat(wsl-host): a paired phone reaches the desktop's WSL host and never starts its distro (E6) (#33911)
* feat(wsl-host): a paired phone reaches the desktop's WSL host and never starts its distro (E6)

Behind ORCA_INTERNAL_WSL_HOSTS and the Experimental switch. The desktop relay
lists its WSL hosts to phones. Every relayed call (resolve, call, watchChanges,
status.get) passes a never-start check, and a WSL host serves a phone only
while it already runs.

- WslHostPhoneGate holds the phone's view. The call check reuses E9's
  focusReachability, so with no bridge in this process it refuses without a
  running-list read. A host shows as "stopped" only on a confirmed stop
  (liveness's distro-stopped, or a running list read by the check); anything
  else gets a neutral "isn't available" message. Hosts are hidden from phones
  while the Experimental switch is off or a Remove is pending.
- The relay host list sends optional `stoppedOnDesktop` only for a confirmed
  stop. The phone badges those rows "Start on computer"; older peers ignore
  the field.
- The paired-server rows producer carries WSL hosts like any server, so the
  main-computed sidebar feed a phone reads has their rows.
- The paired-phone e2e drives a WSL host project end to end and asserts a
  stopped distro is never started.

* fix(wsl-host): keep the phone's no-start check off non-WSL servers, and a stale stop off a ready host

- status.get runs the no-start check only for a WSL host, through a
  check-only helper. SSH-managed and paired servers reach the status owner
  exactly as on main: no reconnect, no redeploy, and the manual-disconnect,
  coalescing and repair handling stay in place. The preparation option is
  stripped before the probe.
- WslHostPhoneGate drops a 'stopped' read when a ready status arrived while it
  ran (a per-host ready generation), and clears a recorded stop when a check
  finds the host answering.
- A phone asking about a host that is switched off or being removed gets copy
  that says so, not "open one of its projects".

* test(wsl-host): the real no-start helper leaves SSH-managed and paired servers untouched

* fix(wsl-host): tie a phone's confirmed WSL stop to that host's status, and label a host not connected

- A stop a phone's check confirmed is stored with that host's own status
  object and holds only while that status is current. Another host's change no
  longer clears it. Any status of its own (ready, a disable's closed, a failed
  Remove's closed) does. A read never records a stop over a ready status, so a
  read shared with one begun before ready can't. Removed hosts drop their
  entry. The generation map and status listener are gone.
- The relay sends optional `unavailableOnDesktop` for a WSL host this desktop
  isn't connected to and doesn't know is stopped. New phones badge it "Open on
  computer"; older ones still show Connecting.
- The relay list reads the WSL host records once per poll (reachAll).

* refactor(wsl-host): one records read per phone check; note the gate's status identity compare

* test(wsl-host): read the phone's host flags as booleans in the paired-phone e2e

toMatchObject({ stoppedOnDesktop: undefined }) requires the key to be
present, and the desktop omits an unset flag, so the ready poll could never
match. The poll now compares relay plus both flags read as booleans.

* test(wsl-host): expect the neutral refusal once main's fake drops a stopped distro's bridge as closed

Main's fake connector (#34573) now publishes 'closed' when a stopped distro's
bridge drops, not liveness's 'distro-stopped'. So the phone's check reads the
stop under a ready status and doesn't claim it. The phone gets the neutral
copy and unavailableOnDesktop; the confirmed-stop copy stays unit-tested.

* test(wsl-host): the paired-phone e2e expects the confirmed stop again, and checks nothing booted the distro

Main's fake now publishes 'distro-stopped' when it drops a stopped distro's
bridge (#34624), as liveness does, so the phone gets "isn't running" and
stoppedOnDesktop. The spec also checks distros.json still reads 'stopped' at
the end: the fake boots a distro by rewriting it.

* test(wsl-host): the startup reconcile suite stubs the phone gate built beside the service

The reconcile still runs before the connector exists; the suite only lacked the new
setWslHostPhoneGate export on its service-instance mock.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 18:23:02 -07:00
Neil dcbfc42c1d fix(wsl): anchor the guest kill's stop read and re-check before each Codex heal batch (E9) (#35448)
* fix(wsl): anchor the guest kill's stop read after the guest ran; re-check before each heal batch

A 'stopped' answer skips the guest kill as proof the group ended, so it must come from a probe
started after the guest reported its group. The Codex index heal re-checks the distro right before
each batch spawns its guest codex, closing the window during the inter-batch delay.

* fix(wsl): the Codex heal also stops on an explicit may-have-stopped note

A hook-relay or watcher exit notes the distro may have stopped before any running list sees it;
shouldStop now hears those notes too, not only the running-list diff.
2026-10-28 18:21:21 -07:00
NeilandClaude 5433c70e70 feat(wsl): fetch and cache a remote WSL hosts policy (kill switch, remote half 1/2) (#35528)
* feat(wsl): fetch and cache a remote WSL hosts policy for the kill switch

Adds the client half of a remote switch that can turn WSL hosts off: a
small versioned policy file, downloaded from a fixed release-asset URL per
channel, validated, bounded, and cached in userData with a monotonic
revision. Nothing reads it yet; wiring into the gate follows.

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

* refactor(wsl): expose the cached WSL hosts policy as allow, block or missing

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 18:19:45 -07:00
Neil be78042ab3 refactor(shared): colocate native chat turn row attribution (#35425) 2026-10-28 18:19:15 -07:00
OrcaWinandOrcaWin 5ed3c8c072 feat(mobile): localize shared components, pull requests and diff review (#35532)
Moves ~600 strings in the shared components (modals, drawers, host cards, dictation,
accounts), the pull request sidebar and diff review to the translation API, with all
ten translations.

- Invalid account snapshots are detected by error type, not by matching English text
- Credit expiry wording uses separate keys for one and several credits instead of
  plural rules, which would pick the wrong sentence in Japanese or Russian
- The PR chip memo recomputes on a language change

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 18:17:58 -07:00
Neil 8c3551bde3 fix(wsl): background Git, GitHub and GitLab reads never start a stopped distro; explicit opens may (E9) (#35410)
* fix(wsl): keep background git and GitHub reads from booting a stopped distro

Git history, diff and status-follower reads, GitHub issue/work-item/check
polls, chat link existence checks, the composer's create-base prefetch,
the worktree-root fan-out and the Settings/Automations orca.yaml previews
now refuse or skip a stopped WSL distro instead of starting it (E9).

* fix(wsl): explicit opens may start a stopped distro; more polls gated (E9)

Folds the parallel G1-G6 work into this branch and splits background
reads from user acts:

- An explicit open runs as a user act for its distro and may boot it:
  showing a diff tab or its Retry, showing Commits or its Refresh,
  opening the checks panel or entering its tab, checks Refresh, a check
  action, and linking or creating a PR. Main takes a wakeWslDistro flag
  on git:diff, git:branchDiff, git:commitDiff, git:history and
  gh:prChecks and runs those reads under runAsWslUserAct.
- Polls, timers, refreshes after Git actions, prefetches and fan-outs
  stay background and are refused while the distro is stopped.
- Also gated: the hosted-review card poll for every provider, the GitLab
  checks-panel poll (background flag), and the composer's open-time
  orca.yaml check (Create re-checks in the foreground).
- Pollers keep the data they already show on a refusal: the issue on a
  card, the checks list, an open diff and loaded submodule children, and
  stop logging it.

* docs(wsl): note that a hosted-review poll's stopped-distro refusal is still logged (E9)

* fix(wsl): Settings re-asks orca.yaml once a stopped distro runs; drop link-check gating (E9)

- Link existence checks (shell:pathsExist / pathExists) are no longer
  gated here: answering "missing" cached chat and terminal links as
  absent and toasted "File not found" on markdown link clicks. The
  pathsExist refusal lives in its own PR, which throws instead.
- Settings no longer sits on "checking" forever: a repo whose distro
  refused the background check is re-asked on window focus, on
  visibility, and after 10 s, until it answers. An unverifiable distro is
  now marked (wsl-distro-unverifiable) and treated as unread too, instead
  of being stored as "no orca.yaml".
- The sidebar issue poll and the Tasks list and count refuse with "Open a
  terminal in it to start it", since their Retry is itself a background
  read; the checks panel keeps "Retry", whose Refresh is a user act.

* fix(wsl): Tasks Refresh, interactive review refresh and manual PR lookups may start a stopped distro (E9)

- Tasks: a Refresh, Retry or search, or Tasks opened on a single repo,
  passes wakeWslDistro through gh:listWorkItems and gh:countWorkItems
  (IPC only; the RPC twins and web routes drop it). A multi-repo open
  stays background. Their refusal says "Retry" again; only the sidebar
  issue poll says "Open a terminal".
- hostedReview:forBranch wakes for an interactive request (the checks
  panel's manual Refresh), so GitLab, Bitbucket, Azure DevOps and Gitea
  reviews with nothing cached can load.
- gh:prForBranch, the renderer's fallback when refreshPRNow is missing,
  is gated like the other card polls; a manual lookup wakes, matching
  refreshPRNow's manual-only rule. The fallback call moves into its own
  module, built from the refresh candidate.

* fix(wsl): only an explicit Refresh starts a stopped distro for review status (E9)

hostedReview:forBranch woke on admissionTier 'interactive', but the
visible-review scheduler sends 'interactive' for the selected card on a
timer, so that poll restarted a stopped distro every interval. The wake
is now an explicit wakeWslDistro flag (desktop IPC only). The card
refresh helper sets it, since every caller follows a user act (the
checks panel's manual Refresh, or a review created, linked or edited),
and the manual Refresh also wakes its pre-refresh git status.
admissionTier is back to priority only.

* fix(wsl): an explicit review Refresh never joins a refused poll (E9)

fetchHostedReviewForBranch let a forced card Refresh join an in-flight
forced scheduler poll, since the join only compared force. On a stopped
WSL distro that poll is refused, so the click got the refusal. The
in-flight entry now records the wake, and a waking request joins only a
waking flight; a poll may still join an explicit Refresh.
2026-10-28 18:16:49 -07:00
Neil 8b9d2770df test(wsl): measure lane restarts over one held socket (#35526)
Each terminal read in the restart measurement opened a fresh connection,
which on WSL spawns a new wsl.exe bridge, so first-output time counted
bridge spawns the app never pays. Hold one shared control connection per
restart, as the app does.
2026-10-28 18:14:37 -07:00
Neil 5616230ecd feat(wsl): bridge fish panes report their folder (OSC 7) at every prompt (#35517)
The bridge fish launch's -C now also defines a fish_prompt hook that
sends the same percent-encoded OSC 7 as bash and zsh, only inside WSL,
after the user's config.fish.
2026-10-28 18:10:58 -07:00
OrcaWinandOrcaWin fe7d4c9445 fix(extensions): bound split native-host header copies (#35359)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 18:10:30 -07:00
Neil 0654de9f6d fix(cli): orca worktree rm reports the delete's outcome, not its acceptance (#35459)
The host answers a worktree delete as soon as it accepts it and lets Git
delete the checkout in the background. Clients that show a "removing"
marker ask it to wait for Git, but the CLI could not, so it printed
`removed: true` before anything was deleted, and a delete Git then refused
(for example a checkout with submodules) failed only in the host's log.
Scripts saw success, and every retry repeated the same silent failure.

`worktree.rm` takes an optional `waitForBackgroundRemoval` flag, and the CLI
sets it, so the command exits with Git's real result or error. It waits as
long as the desktop and web clients do and, if it stops waiting first, says
the delete may still be running and how to check. A reply sent on
acceptance now says `removed: false` alongside `removing: true`, so callers
that still get the early answer are not told the checkout is gone. Older
hosts ignore the flag, and the CLI then says the delete is still running.

Fixes #35135
2026-10-28 18:09:24 -07:00
Neil 459da96fff fix(worktrees): refuse a submodule checkout before stopping its terminals (#35458)
Git refuses `git worktree remove` without --force for any checkout with
submodules, even when nothing is dirty. Orca's dirty check passed such a
clean checkout, so the delete was accepted, its terminals were stopped, and
Git's refusal arrived later in the background, where the CLI and
automation never saw it.

The dirty check now applies Git's own test (submodule repositories under
the worktree's admin directory, or a gitlink checked out with its .git),
which the native Windows path already used, and refuses a clean checkout
that fails it with a message that keeps Git's wording, so every app
version still offers Force Delete with the submodule warning. The same
test now decides when a dirty refusal names submodules. Force is not
applied automatically: it would also delete submodule commits, branches
and stashes that were never pushed.

Refs #35135
2026-10-28 18:09:01 -07:00
OrcaWinandOrcaWin 8e0c153b70 fix(browser): track native frame ports during cleanup (#35346)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 18:07:51 -07:00
Neil 1ffea48dbc test(e2e): release the early-typing rc only once the keys reach the tty (#35522)
The rc was released right after Enter, so on Linux CI the keys' trip to the host
sometimes outlasted the rc's 50 ms poll and they landed after the prompt. Wait for
the tty's echo of the typed line first, which appears only if the bytes reached
the PTY while the rc still waited, and restore the check that they came before
the first prompt.
2026-10-28 18:07:32 -07:00
Neil b117789286 test(runtime): fix the stale orchestration context timestamp before the sync reads the clock (#35516)
The mock built completed_at when the projection called it, after the
projection captured now. With 1 ms or more between the two, the
"stale" row was within the freshness window and the test failed under
load.
2026-10-28 18:05:44 -07:00
OrcaWinandOrcaWin ccd0829e6f feat(mobile): localize app screens, settings, pairing and host lists (#35498)
Moves ~600 strings in the root screens, settings, pairing, onboarding, accounts,
agent history, diagnostics, connection status, home and host workspace lists to the
translation API, with all ten translations.

- Connection verdicts carry an explicit `dialing` flag instead of matching the
  "…" ending of an English label
- Update-failure copy and connection-path accessibility labels are built from data,
  not by editing translated text
- Workspace status names stay the host's labels, as on desktop; transport errors
  stay English
- The stale-key check keeps a plural family while any of its forms is referenced

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 18:03:37 -07:00
Neil a33b40f0d6 fix(orcad): harden the startup qualification marker (execPath, node-pty load failure) (#35513)
* fix(orcad): harden the startup qualification marker (execPath, node-pty load failure)

- The key includes process.execPath, so a slot re-pointed at another Node build re-qualifies.
- A node-pty load failure in orcad (degraded local PTY routing) discards the slot's marker, so
  the next launch re-probes node-pty and reports the cause; reported through a small listener so
  the shared provider stays free of orcad imports.
- Tests: a schema-1 marker never matches; a Windows slot is never qualified by a matching marker.

* fix(orcad): discard the startup marker only after an in-flight record lands

A node-pty failure right after readiness could unlink the marker before the confirm's write
renamed it into place, recreating it. The discard now waits for the last marker write first.
2026-10-28 18:02:47 -07:00
Neil 9babef2866 fix(wsl): background preflight and agent detection never boot a stopped WSL distro (E9) (#35411)
* fix(wsl): background preflight and agent detection never boot a stopped WSL distro (E9)

Integration checks (git/gh/glab --version and auth status) and agent detection ran inside the
focused workspace's WSL distro on every mount, poll and status-bar render, and wsl.exe starts a
stopped distro. They now take a settled running read first and refuse (WSL_DISTRO_STOPPED or
WSL_DISTRO_UNVERIFIABLE) when it is not running. Window focus/visibility, retry buttons, agent
refresh buttons, a runtime choice in Settings and first-run onboarding pass wakeWslDistro, which
runs the check as a user act on that distro only. Running distros behave exactly as before.

* fix(wsl): a focus wakes only a focused WSL workspace's distro; end-to-end preflight gate test

A focus with a native workspace active sends no wake. Ports the real running-list preflight case
from #35395 and adds user-act scoping cases.

* test(wsl): model the running gate in the preflight RPC suite and cover a stopped distro

Windows CI runs the real gate, so the WSL detection case must state that the distro runs.

* fix(wsl): an agent refresh click never joins a background refresh it would be refused with

Store the wake flag with each in-flight refresh, as preflight.ts does, so a status-bar or Agents
refresh click during a mount refresh reaches main as a user act. Note why the RPC project branch
stays ungated.

* fix(wsl): a refused background check waits for the distro, and an agent picker wakes it

A preflight or agent detection refused for a stopped WSL distro was final: once the distro came
up, nothing re-ran it, so the tab-bar + menu offered no WSL agents (real-WSL golden). Now a refusal
is deferred until the distro is next confirmed running (deferUntilWslDistroRunning), and main tells
renderers to re-ask. Opening an agent-launch picker (tab-bar +, composer, continuation dialog,
source-control action dialog) whose list was refused retries it as a wake, never joining a
background probe.

* fix(wsl): an open agent picker wakes a refused list once, and never retries real failures

The picker wake fired whenever the list read 'failed', so a woken probe that failed again
(pending -> failed) re-fired it: an endless wsl.exe loop while the picker stayed open, and repeated
probes for native failures too. It now fires at most once per open per target, and only when the
last probe was an E9 refusal (distro not running/unverifiable), matched by the gate's message.

* fix(wsl): forget agent-inventory refusals when the inventory or its project contexts are cleared
2026-10-28 18:01:42 -07:00
3a51382df5 feat(wsl): scope and path map for converting UNC Windows-drive projects (D1c-4a) (#33108)
* feat(wsl): offer Git for Windows in a Windows-drive WSL project's settings

Project settings show a Git row for a WSL-runtime project on a Windows drive (WSL
hosts on). "Use Git for Windows" checks the project, shows any blocker in plain words,
optionally sets core.autocrlf in the repo, and saves the returned runtime through the
normal project update. Once converted the row says where Git and terminals run.
Switching the distro keeps Git for Windows instead of silently dropping it.

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

* fix(wsl): offer the Git choice only for a Git repo, not a folder

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

* feat(wsl): scope and path map for converting UNC Windows-drive projects (D1c-4a)

The mover refuses a project kept as a distro's UNC path into a Windows drive
(\\wsl.localhost\<d>\mnt\c\x). D1c converts it in place to C:\x. This adds the pure
part: which local repos and folder workspaces qualify (every stored path on the drive;
not remote; not already a C:\ project here), the UNC → drive path map, and the
worktree id each converted worktree gets (same repo id, drive path). Reuses the mover's
list of a repo's stored paths. Nothing calls it yet.

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

* fix(wsl): say Windows denied access when adding a WSL path it refuses, not that it isn't a repo

* fix(wsl): name a refused WSL path only with WSL hosts on

The new message replaced "Not a valid git repository", which the renderer
matches to offer adding the folder as a non-git project. With the WSL hosts
gate closed the add fails with the usual text again.

(cherry picked from commit a5a70dad7743f679fd764c3e17a3e27b71c9f28b)

* fix(wsl): convert one UNC spelling per drive folder, and only folders the distro mounts from that Windows drive

- Two UNC spellings of one drive path (\\wsl$ vs \\wsl.localhost, \mnt\C vs \mnt\c) would
  both convert into two projects. Each accepted conversion now claims its drive path, so the
  next spelling is refused as a duplicate. Folder workspaces get the same duplicate check.
- Any /mnt/<letter> read as a Windows drive. The scope now takes the distro's Windows-drive
  mounts (drvfs/9p from its mountinfo, parsed as the WSL-host drive guard does) and converts a
  path only when its mount is that same whole drive. A folder workspace has one path, so that
  check is its mixed-location check too.

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

* fix(wsl): match the distro's drive mount point case-sensitively, so a real /mnt/C directory never converts onto C:

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 18:00:29 -07:00
Neil 134226ae5e fix(runtime): never hand a parent the token of a delegated child the save dropped (#35510)
upsertDelegatedMobileDevices returned every planned entry, including a child whose row was
removed on disk and so dropped by the merged save; the parent would pass that dead token to the
phone. It now returns only entries still in the written registry.
2026-10-28 17:58:31 -07:00
OrcaWinandOrcaWin 43cf7b4b24 fix(browser): release native messaging startup queue on close (#35344)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:56:07 -07:00
OrcaWinandOrcaWin 1775410850 perf(renderer): reuse folder connection inference across store writes (#34800)
* perf: cache folder workspace connection inference

* fix: preserve folder resolver fallback for partial catalogs

* test(renderer): trim folder connection cache test to one direct warm-read check

Drop the zustand store wrapper and duplicate 1,000-repo case, and use a neutral fixture path.

* test(renderer): drop folder connection read-count test

The invalidation and tri-state test guards observable behavior; the getter
read counter only pinned the cache implementation.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-29 00:55:53 +00:00
OrcaWinandOrcaWin 601bf63c62 Preserve concurrent PR comment changes when thread resolution fails (#35315)
* fix(github): preserve concurrent changes on thread rollback

* test(github): assert reaction publication before rollback

* fix: restore thread resolution on newly posted replies

* test(github): trim thread rollback tests to behavior guards

Drop duplicate false/throw variants, the cleared-cache and paired-source
cases, and the helper case already covered by the remaining lib tests.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:55:26 -07:00
Jinjing 33d57df894 test(preflight): align enabled agent detection mock 2026-10-28 17:51:53 -07:00
Jinjing 5af784a77e fix(preflight): ship worker and preserve CLI liveness 2026-10-28 17:51:53 -07:00
Jinjing 0eb18d9775 fix(preflight): isolate directory enumeration 2026-10-28 17:51:53 -07:00
Jinjing 0710886dc5 fix(preflight): preserve network path detection 2026-10-28 17:51:53 -07:00
Jinjing 7c364fa757 fix(preflight): preserve path detection compatibility 2026-10-28 17:51:53 -07:00
Chen f54448bfb7 Limit literal PATH probes to agent detection 2026-10-28 17:51:53 -07:00
Chen b2fb4d1d38 Preserve extensionless PATH command detection 2026-10-28 17:51:53 -07:00
Pr1p a40db68ed5 fix(preflight): address review on the batched PATH lookup
- Deduplicate candidates per command: 'tool' and 'tool.CMD' may resolve to
  the same on-disk file and both must still be found.
- Probe known candidate names directly when readdir is denied (EACCES/EPERM):
  an execute-only directory cannot be listed, but stat on known names works,
  which is what the per-candidate lookup did.
- Skip the install-dir fallback's PATH re-scan: the batch already proved the
  missed commands absent on the PATH it searched, and that PATH is a superset
  of the fallback's (merged persisted PATH on Windows, the same filtered PATH
  on a WSL host), so the fallback scans install directories only.
2026-10-28 17:51:53 -07:00
Pr1p 6af1ef000a perf(preflight): read each PATH directory once during agent detection
findCommandsOnLocalPath() replaces one isCommandOnPath() call per agent
command: it reads each absolute PATH directory once with readdir and matches
command names and PATHEXT permutations in memory, then verifies only the
hits through isExecutableFile. Symlink, directory, permission,
case-insensitivity and absolute-only PATH semantics match the per-candidate
lookup. On the machine in the issue this replaces about 24,000 stat() calls
per detection run with about 38 directory reads.

Fixes #34636
2026-10-28 17:51:53 -07:00
OrcaWinandOrcaWin 769d382f24 fix(editor): restore Mermaid reading position after rendering (#35031)
* fix(editor): restore diagram scroll after async rendering

* fix(editor): retain pending diagram scroll while hidden

* fix(editor): key Mermaid restore on rendered source and cancel it on user scroll

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:51:35 -07:00
OrcaWinandOrcaWin 78279250d0 Keep Markdown completions available when a sibling pane changes files (#34975)
* Keep Markdown completion catalogs owned by surviving panes

* Assign completion test editor ref in a layout effect

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:50:04 -07:00
OrcaWinandOrcaWin 8600995271 fix(editor): preserve folds and horizontal scroll across tab switches (#34810)
* fix(editor): preserve folds and horizontal scroll across tabs

* refactor(editor): keep reading state cache with its lifecycle

* test(editor): give stale-cache model its URI

* refactor(editor): keep editor view state cache beside diff view state

Move editorViewStateCache into scroll-cache.ts, clear it in the shared model
lifetime fixture, drop the e2e evidence spec and the duplicate LRU test.

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:48:32 -07:00
OrcaWinandOrcaWin ed7fe7d5dc Combine exact PR fields and stack summary queries (#35295)
* Read sidebar PR and stack metadata in one GraphQL query

* Preserve direct PR error recovery without duplicate GraphQL reads

* Keep combined sidebar queries out of merge preflight

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:46:20 -07:00
OrcaWinandOrcaWin 4c42c4448b Combine PR participants and viewed-file queries (#34842)
* perf(github): combine PR detail context reads

* perf(github): avoid redundant file retry after context failure

* Isolate viewed-state failures and preserve cached PR metadata

* Start participant recovery independently of cached metadata

* Give cached metadata and PR context independent semaphore permits

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:46:16 -07:00
OrcaWinandOrcaWin a516ba9a03 perf(github): reuse repository merge metadata reads (#34848)
* perf(github): reuse repository merge metadata reads

* Preserve capability reuse across worktree directories

* Use required braces for capability writer cleanup

* Isolate capability configuration and cancellation lifetimes

* Keep capability fixtures independent of ambient configuration

* fix(github): isolate fallback configuration directories

* Keep successful merge metadata through competing read failures

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:46:11 -07:00
OrcaWinandOrcaWin 127487f931 perf(github): load PR conversations without duplicate REST requests (#34747)
* perf(github): avoid redundant REST reads for PR conversations

* fix(github): retain valid inline comments beside missing numeric IDs

* fix(github): preserve comment quota errors during REST recovery

* fix(github): order review summaries by submission time

* fix(github): keep forced PR conversation refreshes out of in-flight sharing

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:46:07 -07:00
e6a27089e6 feat(wsl): offer Git for Windows in a Windows-drive WSL project's settings (D1c-3) (#33097)
* feat(wsl): offer Git for Windows in a Windows-drive WSL project's settings

Project settings show a Git row for a WSL-runtime project on a Windows drive (WSL
hosts on). "Use Git for Windows" checks the project, shows any blocker in plain words,
optionally sets core.autocrlf in the repo, and saves the returned runtime through the
normal project update. Once converted the row says where Git and terminals run.
Switching the distro keeps Git for Windows instead of silently dropping it.

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

* fix(wsl): offer the Git choice only for a Git repo, not a folder

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:44:41 -07:00
OrcaWinandOrcaWin d57e55472c perf(editor): skip full-text reads for ignored Monaco content events (#34920)
Subscribe to onDidChangeModelContent directly instead of the
@monaco-editor/react onChange prop, which calls editor.getValue() before
Orca's ownership and programmatic-sync checks run. Programmatic echoes
(external reloads, shared-record commits, read-only live tail) no longer
materialize the full model text only to discard it.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:43:51 -07:00
OrcaWinandOrcaWin b510cd1f77 perf(browser): reuse tab resolution within extension enumeration (#35327)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 17:42:58 -07:00