Use one shared agent picker for creating workspaces, continuing conversations, and launching agents from Source Control and its settings.
Preserve saved agent choices, model and effort selection, custom arguments, keyboard navigation, and agent settings. Match the Create worktree menu to its field while keeping other menus compact, with stable model labels and responsive setup placement.
* fix(cli-runtime): preserve advisory inspection results on close failure
* fix(appimage): keep close errors from overriding verified inspection results
The AppImage identity and stable launcher readers closed their read-only
handle in an unguarded finally, so a close error replaced the verified
result and broke CLI status, startup crash capture and launcher upgrades.
Attempt the close once and discard its error, as the CLI runtime check does.
Also load the real closeSync in the node:fs mock factory instead of inside
the test body.
* test(cli-runtime): drop type assertions from close-failure fixtures
* fix(cli): keep inferred worktree creation in the caller project
* Fix caller checkout ranking and creation guidance
* Share caller-host containment preparation across CLI selections
* Correct Windows CLI fixture syntax and snapshot command
* Match worktree fixture output to typed execution hosts
* Regenerate bundled workspace placement guidance
* Refuse ambiguous workspace ownership and preserve launch replay
* Scope runtime filesystem mocks to their aggregate tests
* Preserve launch proof semantics under strict test diagnostics
* Keep launch proof imports within their compiler project boundary
* Consolidate journal cleanup test imports
* Adapt launch fixtures to the current host settings contract
* Keep the CLI error formatter under the file-size limit
Move the selector-ambiguity workspace-choice check into selector-ambiguity-recovery.ts, which already owns that error's recovery text. Behavior is unchanged.
* Expect main's concise orchestration output in the workspace-choice CLI tests
Orchestration commands now print the one-line failure on stderr and the workspace choices and next steps on stdout (or compact JSON plus the stderr line with --json), and print concise success fields.
---------
Co-authored-by: Orca QA <orca-qa@users.noreply.github.com>
At every startup, managed WSL CLI registration reconciliation ran a guest
command in every running distro it hadn't inspected recently, including the
user's own unrelated distros. That's EDR-noisy and touches environments Orca
never set up. It now repairs distros carrying Orca's own registration record,
and inspects only distros Orca deployed a WSL host into.
wsl.exe refuses any command for a distro that was unregistered, so Remove
failed and the distro stayed in wsl-cli-registrations.json for good. A
distro-not-found failure now drops every bookkeeping entry for it
(registration, inspection time, reconciliation) and reports not installed.
Fixes STA-12893
On a low-spec Windows machine the first in-app "install orca command"
failed with "Windows PATH command timed out after 5000ms" and a retry
succeeded: a cold PowerShell start plus the settings-change broadcast
outran 5 s. Raise the deadline to 15 s and retry once on timeout; the
write sets PATH to a fixed value, so repeating it is safe.
* fix(cli): never register the bundled launcher as a link to itself
orca serve registers the CLI at startup. On macOS the installer walks
PATH for an existing orca command, and Orca's own terminals put the
bundled Resources/bin first on PATH. The bundled launcher reads as a
managed Orca launcher, so it was picked as the command slot, moved
aside, and replaced with a symlink to itself. The app's CLI then broke
until reinstalled.
Skip the launcher when scanning PATH, and refuse any symlink install
whose command path is the launcher.
Fixes#33872
* fix(cli): compare the launcher by directory entry, not path spelling
The self-link guards compared path strings, so a PATH entry or
ORCA_CLI_INSTALL_PATH that reached Resources/bin through a symlinked or
differently cased directory still replaced the bundled launcher with a
link to itself. Compare entry and parent-directory identity instead.
Co-authored-by: Hotragn <103170876+Hotragn@users.noreply.github.com>
* fix(cli): keep differently named hard links to the launcher replaceable
* fix(cli): treat a case-variant name as the launcher only when it is an alias, not a second hard link
* refactor(cli): compare the launcher by inode via existing entry snapshots
Replace the speculative isSameDirectoryEntry helper with isSameEntry beside
readEntrySnapshot/hasSameIdentity, and drop the hard-link test that only
pinned the removed behavior.
Co-authored-by: Hotragn <103170876+Hotragn@users.noreply.github.com>
* Revert "refactor(cli): compare the launcher by inode via existing entry snapshots"
This reverts commit f02f8c2a2ba0263fd611170af7c3f76d22e48ea7.
* test(cli): fold the bundled-launcher cases into the macOS command-path suite
* refactor(cli): move the launcher entry check beside the entry snapshots
Reuse readEntrySnapshot/hasSameIdentity for the entries, keep the parent
identity check (a hard link in another dir such as /usr/local/bin must stay
replaceable, which is why f02f8c2a2ba was reverted), and drop the readdir
case-folding branch. Pin the cross-directory hard link instead of the
speculative sibling one.
Co-authored-by: Hotragn <103170876+Hotragn@users.noreply.github.com>
* fix(cli): keep a case-variant hard link beside the launcher replaceable
---------
Co-authored-by: Neil <neil@stably.ai>
* fix(linux): stop the serve `orca` dispatcher shadowing the screen reader, and remove it with the CLI
Headless `orca serve` writes ~/.local/bin/orca so Claude Team's bare `orca`
reaches Orca even when a login shell drops Orca's PATH entry. It exec'd the
launcher unconditionally, so it sat in front of GNOME's `orca` screen reader for
everyone, failed with "No such file or directory" once Orca was uninstalled, and
nothing ever removed it.
The dispatcher now answers for Orca's own children only (ORCA_CLI_BIN_DIR,
ORCA_PANE_KEY or ORCA_USER_DATA_PATH set). Anyone else gets the next `orca` on
PATH, skipping itself, with one hop so two dispatchers cannot loop; then this
app; then a clear message and exit 127 once the launcher is gone. Existing
dispatchers are rewritten on the next serve start. Removing the `orca` command
now also removes the dispatcher, and only if it carries Orca's marker.
* fix(linux): skip every Orca dispatcher on PATH instead of an env hop guard
The hop variable let a second dispatcher earlier on PATH send a screen-reader
user's `orca` to Orca, and leaked into the screen reader's environment so its
descendants' `orca` could land on Orca too. The PATH scan now skips any
candidate carrying the dispatcher marker (as well as itself), so dispatchers
cannot hand calls to each other, and the real target runs with nothing added to
its environment.
* test(linux): Orca's own children reach the screen reader once Orca is gone
* fix(linux): Orca's own children get "no longer installed", never the screen reader
With ORCA_CLI_BIN_DIR, ORCA_PANE_KEY or ORCA_USER_DATA_PATH set and the
launcher gone, the dispatcher now prints the message and exits 127 without
scanning PATH, so an agent's `orca …` can never start GNOME's talking screen
reader. The PATH scan also ignores relative entries, which depend on the
caller's folder. Tests cover each Orca variable, a PATH folder with spaces,
empty and relative entries, a symlink to the dispatcher, and an unreadable
candidate being run rather than skipped.
* 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.
* 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
* chore(lint): remove disable directives that suppress nothing
Each was reported unused by the oxlint config that owns its rule (root,
casting, react-doctor, anti-slop, native-plugins), including 17 file-level
react-doctor blanket disables whose rule no longer fires. An unused
react-hooks disable was masking a react/purity finding in
useAgentBucketCounts (compiler rules skip functions with hook
suppressions); suppress that one explicitly where the code explains it.
* test(tab-bar): use typed tab/file fixtures instead of @ts-expect-error partials
* chore(lint): fix misc suppressed lint violations instead of disabling
- consistent-type-imports: the "vi.importActual requires inline import()"
rationale was wrong; use typed vi.mock(import(...), importOriginal) or a
type-only namespace import.
- no-control-regex: source-control commit/push failure summaries, shell PATH
hydration, and ipynb ANSI parsing reuse the shared ansi-escape-sequences
stripper and control-character pattern instead of private copies.
- no-explicit-any / no-useless-spread / no-this-alias: typed `this` in
bridge test mocks, drop blanket file-level disables, drop a this-alias.
* refactor(main): replace avoidable type assertions with checked narrowing
17 production cast suppressions in main/wsl-guest removed: untrusted IPC
and RPC payloads (Jira issue update, WSL guest plugin install, handshake
type) now narrow through isRecord/type guards and build typed results;
redundant casts dropped; hand-rolled object checks and errno casts use the
existing isRecord / hasErrorCode helpers.
* refactor(renderer,mobile): replace avoidable type assertions with checked types
13 production cast suppressions removed: RPC failures read through the
`ok` discriminant instead of casting to RpcFailure; react-native-web host
refs narrowed with instanceof HTMLElement; redundant reply/diff casts
become checked annotations; the TUI agent param uses z.custom(isTuiAgent)
like its sibling schemas; the agent-status slice cast that hid missing
actions is gone so the creator's return type checks the whole slice.
* chore(lint): drop dead tiptap wrapper; scope anti-slop mocking rule to test support
- safe-react-node-view-renderer patched handleSelectionUpdate, which
@tiptap/react 3.31.3 no longer has, so it always returned early. Use the
stock ReactNodeViewRenderer.
- The anti-slop test override only matched *.test.{ts,tsx}, forcing
file-level no-module-mocking disables in test harnesses and fixtures.
Match *-test-harness, *-test-fixture(s), .test-fixture and *.test.mjs,
then drop those disables and the now-redundant per-file exemptions.
* test: replace repeated cast suppressions with typed fixtures (main/shared/e2e)
Net -119 cast directives. Typed fixtures replace recurring casts:
unusedSshConnection/unusedOrcadHostTransport placeholders, a typed
readPersistedState harness read (exposed a test treating optional
httpProxyUrl as always set), real Response objects in fetch spies, an
updater main-window fixture, a CDP webContents adapter, one shared
releaseModuleExport for cross-version tests, and requireOverlayDir in
place of `as string` on possibly-undefined overlay paths.
* fix(runtime): validate loaded device rows and host scope instead of casting
Two cast suppressions claimed checks that did not happen:
- device-registry-file-read: "normalizeLoadedDeviceRow re-validates every
field" was false; deviceId, token, name and timestamps were never
checked. Rows without an identity are now dropped and the file is set
aside through the existing corrupt-file path (registry reads as
doubtful, so no revocation verdicts); a non-string token is stripped
so the row stays listed but cannot authenticate.
- client-ui: "only optionality differs" was false; any string reached
persisted workspaceHostScope. Narrow it with isWorkspaceHostScope and
ignore unknown scopes (wire schema unchanged for mixed versions). The
remaining cast now states what it actually covers.
* test(runtime,ipc): drop redundant cast suppressions; typed runtime store fixture
-98 cast directives across runtime/ipc tests: 61 casts that typecheck
without the assertion; a typed vi.fn for scoped invalidation; a
partialRuntimeStore fixture in place of `store as never` for
OrcaRuntimeService; typed worker terminal/authority builders in the
incarnation-fallback suite (the old stub lacked runtimeId, ptyId,
worktreeId and launchTokenHash) plus removal of stacked duplicate
directives there.
* chore(lint): typed vi.mock imports and explicit listener snapshot in shared-bucket tests
Remaining files from the misc-rule pass that overlapped other buckets:
codex-accounts mocks use the typed vi.mock(import(...)) form instead of
a consistent-type-imports disable; the daemon late-exit fixture copies
its listener set with Array.from instead of a no-useless-spread disable.
* refactor(github,mobile): narrow routing settings type; drop remaining avoidable casts
- work-item-routing cast a one-field object to AppState['settings'] under
a claim that readers only consume activeRuntimeEnvironmentId. Return the
existing RuntimeFocusSettings pick instead and narrow the cache-key
chain's parameters, so the compiler enforces that claim.
- mobile file preview reads refusals through the RpcResponse `ok`
discriminant rather than a cast.
- terminal document host-notify accepts `unknown` errors, removing the
message-bridge cast.
- native chat readability drops a redundant repo-list cast.
* test(renderer): replace repeated cast suppressions with typed fixtures
-140 cast directives (and ~150 unsuppressed casts of the same shapes):
- mockPanePtyArgs owns the connectPanePty fixture casts, so a wrong
argument order or fixture is now a type error; drop binding casts for
members PanePtyBinding already declares.
- Seed AppState tab rows with the typed makeTerminalTab; this exposed a
split direction 'row' that is not a TerminalPaneSplitDirection.
- Partial GlobalSettings use getDefaultSettings overrides; Jira-only
stores use createTestStore; runtime environment rows/statuses come from
a typed paired-runtime-environment fixture.
* chore(lint): drop no-module-mocking disable now covered by the test-fixture glob
* test(e2e): fix all 221 grandfathered e2e type errors; baseline to zero
The e2e typecheck baseline grandfathered 221 errors in 119 files. About a
third were tests drifted from the current API, several of which would
fail or mislead at runtime:
- terminal-shortcuts called a nonexistent xterm buffer method;
- the daemon-lifecycle fake lacked terminateOwnedTree, hidden by importing
its type from a module that does not export it;
- arguments in the wrong position (listProcesses(hostId, opts), a dropped
pty.write inputKind, an extra toWebTerminalSurfaceTabId argument);
- removed enum values ('drawer', 'idle', 'editor',
'session-insecure-origin') and a launch_source the telemetry schema
rejects;
- missing required fields (turnScope, childWorkOpen, providerIdentity,
reviewLookupOutcome, runtimeServiceAccount behind an `as RelayConfig`);
- dead reads (tab.customTitle, bucket.targets, changedPixels).
Also lifts variables that narrowed to `never` after poll-callback
assignment, and adds a typed xterm render-dimensions accessor. Includes
the cross-version suites' shared releaseModuleExport adoption.
* chore(typecheck): gate the now-clean e2e typecheck in local lint
The e2e baseline is empty, so the ratchet now rejects any tests/ type
error. CI already runs it via run-ratchets; add it to pnpm lint's
explicit ratchet list and replace the stale 'not yet clean' note.
* test(mobile): typecheck every mobile test; baseline 105 files -> 0
mobile/tests-typecheck-baseline.txt grandfathered 105 test files (531
errors) whose types CI never checked. Contract changes had landed without
these tests following, and type pins in them silently checked nothing.
- Root cause: salvagedOptional (src/shared/zod-salvage.ts) cast away
zod's optional marker, so every reply type built on it claimed
salvaged fields were always present. Return a real ZodOptional;
runtime is unchanged (the outer optional short-circuits undefined).
- Production now takes the port it uses: RpcOperationSender instead of
RpcClient for send-only callers, a narrow fetch signature, and only the
request fields push-receive reads.
- findAllByHostType/findByHostType replace `'Text' as never` lookups;
stubRpcClient gives tests a typed RpcClient.
- Real test bugs: settings-host-client-lifecycle "relay" hosts were
direct hosts (relayHostId no longer exists); two toEqualTypeOf pins
could never hold; a recovery hook ran with an undefined scope key;
a create-PR test cast to a never-imported type; "no URL" assertions
passed on null; plus stale required props, args and enum values.
* test(e2e): parse workerStart result instead of casting it
* test(runtime): typed partial runtime stores with production-shaped fixture data
Route every partial store passed to OrcaRuntimeService through
partialRuntimeStore with typed row builders, removing 60 cast directives
that hid fixture data production never produces:
- paired-client-navigation-test-harness keyed setWorktreeMeta writes by
`[object Object]` (it took an id where the store takes a target), so
reads never saw them;
- invalid worktree lineage origin/capture and incomplete workspace lineage;
- getWorkspaceSession returning null where the store returns the default
session; getGitHubCache returning undefined;
- orcad migration states missing migrationId/manifest/receipt, with a
toEqual pinned to that incomplete shape;
- partial repos, metadata, folders, project groups and notification rows.
* refactor(renderer): resolve suppressed React hook lint instead of disabling it
109 of 187 react-hooks/react-doctor suppressions fixed:
- ~95 exhaustive-deps disables only hid stable refs and setters passed
through controller objects; list them (identity never changes, so
nothing re-runs), plus a few real stale closures (tabId/worktreeId).
- Effects keyed on one value that read the latest props now use
useEffectEvent (WebConnect, skill freshness, Bitbucket dialog seeding,
Landing preflight, automation catalog, structured-session recovery,
file explorer).
- The conditional layout-owner hook is selected once at module load from
the build constant instead of a rules-of-hooks disable that also hid
the whole controller from compiler and react-doctor rules.
- A hook disable was masking a react/purity Date.now() in the palette's
recent-tabs memo; sample it when the snapshot is captured.
- Three identical debounced-search effects share
useTaskSearchDebouncedApply; layout snapshot merge helpers move out to
stay under max-lines.
Remaining suppressions are mount-once resources, invalidation epochs,
deliberately keyed fields, and test harnesses that mock the dispatcher.
* chore(ratchet): exempt test harnesses and fixtures from the focus-read ratchet
The ratchet skipped *.test-fixture.ts but scanned *-test-harness,
*-test-fixture(s) and *.test-support files. Those seed settings with
getDefaultSettings (which the ratchet discovers as a focus reader) and
never route host work, so 17 baseline entries were false positives, and
replacing a test's `settings: {...} as never` with typed defaults tripped
it. Match the repo's test-support names and prune (which also drops one
stale entry), and rename the frame-ordering harness to *-test-harness like
its siblings. A blanket "-harness" match would also exempt
e2e-terminal-pty-harness, which production imports, so the names stay
explicit.
* test: merge duplicate shared/constants imports
* revert(file-explorer): restore original tree load effects pending SSH e2e investigation
* test(runtime): drop RuntimeStore cast now that the fixture is typed
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
findActivePathCommand now .catch(()=>null)s inspectSymlink so an execute-only foreign PATH `orca` is skipped instead of rethrowing EACCES; blocks the readFile EACCES at cli-installer.ts:551.
Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
Co-authored-by: Neil <neil@stably.ai>
Combine the completed comment cleanup from 319 stacked PRs into one change against `main`, so the full CI suite validates the combined result once. This replaces the previous audit stack; no additional audit work is included.
The change shortens redundant comments across 2,753 source and shell-snapshot files (25,235 net lines removed). Conflicts preserve current-main executable code. Runtime behavior, test assertions, directives, licenses, generated notices, SAFETY rationales, and compatibility markers are preserved. The audit tracker remains local, outside the repository.
Validation:
- Equivalent source/emitted AST and executable tokens across all 2,750 source files, with separate checks for embedded shell, SQL, JavaScript, CSS, and generated fixtures.
- Identical executable lines in the three shell snapshots; protected comments unchanged.
- Changed-code quality gate passed with no new findings.
- 358 tests passed, 2 skipped across 23 focused test files.
- `git diff --check` passed.
* refactor(shell): one shell-argument-quoting module for the duplicated quote copies
Each former copy now calls the canonical function with its exact spelling; a table test pins
byte-identical output for every copy over hostile inputs. Distinct spellings stay distinct
functions: '\'' vs '"'"', the two plain-word sets, and the cmd.exe doubled quote.
Co-Authored-By: Claude <noreply@anthropic.com>
* style: keep the quoting import at the top of two import-less files
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(wsl-cli): keep the WSL CLI status check from timing out on a cold or slow-profile distro (#29497)
* fix(wsl-cli): run install/remove without the login PATH; a PATH-check timeout reports PATH unknown
* fix(linux): unpack the AppImage copy in the background so the first daemon runs from it
A validated AppImage now extracts its generation in the background, at the
lowest CPU and I/O priority and under the registration lock, at a launch that
finds no copy for its file and when an update finishes downloading (into the
namespace and generation key the installed file will have). The copy is staged
without publishing the CLI launcher. A daemon about to be launched while this
launch is unpacking waits up to 8s for it, then runs from the copy instead of a
FUSE mount it would outlive. A full cache, noexec cache, untrusted download or
failure is logged and the launch keeps today's fallback.
* fix(linux): drop idle copies of earlier releases at launch
Staging never prunes, so a desktop that never registers the CLI would keep
every release's unpacked copy. At launch, once this release has its copy, idle
sibling generations in its namespace are pruned under the registration lock;
leases, residency and the installed CLI target still protect anything in use.
* fix(linux): leave serve's own first-start unpack and its progress in place
Serve already unpacks the copy itself with one deadline and progress on its
output (D3-D2), which the packaged shutdown oracle checks. Launch-time
pre-extraction now runs for the desktop only; serve still gets the
update-downloaded staging.
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(linux): a supervised AppImage serve restarts from a replaced AppImage
Swapping the AppImage file never reached a supervised serve: it runs the copy it unpacked, and
even a full service restart went back through the stable launcher to that same copy. The
extraction cache now records which AppImage each namespace came from. Before each start the
supervisor compares that file's identity with the build it runs; once a settled new file is
there and runs on this host, it execs the new AppImage with its own arguments (same pid), whose
serve unpacks the new build and re-points the stable launcher.
Fixes BUG-4 from the real-host Linux test run.
* fix(linux): try a replaced AppImage once, and let it past an old build's give-up
- A give-up recorded against the old build no longer stops the supervisor before it checks
for a replaced AppImage.
- The supervisor records the AppImage identity it is about to exec in the profile. If that
build dies before its own crash brake, later starts of the old build keep running it
instead of exec'ing the same broken file until systemd's start limit disables the service.
A supervisor running that build, a further replacement, or --force clears the record.
* test(cli): compare the namespace listing order-independently
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
On a validated AppImage the desktop's daemon launch first runs <generation>/resources/node-runtime/bin/node
on the generation's daemon-entry.js when the extracted copy for the file at $APPIMAGE is complete, carries
the bundled Node and the entry, and is the running release. It then falls back to the AppImage's own mount
and the current mount, logging every fallback. The copy rung records $APPIMAGE/<entry> like the own-mount
rung, so either daemon is adopted. Generation leases recognize the bundled Node. macOS, Windows, deb and
rpm never reach it.
Co-authored-by: m4air <m4air@Mac.localdomain>
A supervised serve started through the stable launcher runs from one extracted generation with
no $APPIMAGE. Its CLI registration then refused Orca's own ~/.local/bin/orca-ide (a link to
the stable launcher) as a non-Orca command, and pointed the bare `orca` dispatcher at the
generation's launcher, which a later update prunes. Both now resolve to the stable launcher.
Fixes BUG-8 from the real-host Linux test run.
Co-authored-by: m4air <m4air@Mac.localdomain>
Direct AppImage serve now unpacks its stable copy once, under one overall
deadline that also bounds the registration lock wait and both extraction
attempts, prints progress to stderr, and refuses fast when the private
cache is not writable, not executable, or too full.
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
* fix(linux): keep extracted AppImage copies that something still runs from
New builds extract into a namespace that pre-lease builds never prune.
Pruners now delete a generation only when no same-user process runs from
it and no lease names a live process (pid, start ticks, boot id).
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(linux): skip non-dumpable processes in the AppImage residency scan
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
* fix(wsl): stop booting stopped distros from background work
Any `wsl.exe -d` (or \\wsl.localhost access) boots a stopped distro: 1-2s of
VM boot, and on WSL < 3.0.1 its later idle-stop wipes the VM-wide WSLInterop
binfmt entry for every other running distro (microsoft/WSL#13885).
Add one gate (wsl-background-distro-gate.ts): background work checks
`wsl --list --running` (never boots), and stopped-distro work can be deferred
until the distro is next seen running (a confirmed running probe or a local
WSL terminal spawn).
- Startup CLI registration reconciliation: only running candidates; stopped
ones are deferred per distro and stay registry candidates for later starts.
- Fish history GC: keeps the tombstone (and its meta.json) while the distro is
stopped and finishes the cleanup once it runs; no admission slot is held.
- Codex/Claude/Kimi quota polls for WSL targets: skip while stopped (Codex
keeps its last value). User-driven resets still boot.
- Codex WSL auth drain before an update restart: skip stopped distros (no
live legacy pane there; the next launch prep drains anyway).
* fix(rate-limits): capture the Codex fetch generation before home resolution
The Codex home resolver is now async (it checks whether the WSL distro is
running), so a reset that lands during that await bumped the generation the
full-refresh cycle then read as its own, letting a stale result overwrite it.
Co-authored-by: Syed Zohaib Hussain <26768511+RoxasZohbi@users.noreply.github.com>
* fix(wsl): read an unconfirmed running-distro probe as stopped in the background gate
* test(wsl): pin the empty running list wsl.exe reports when no distro runs
---------
Co-authored-by: Syed Zohaib Hussain <26768511+RoxasZohbi@users.noreply.github.com>
Extract subprocess execution and process contracts into @orca/process-host with explicit public entry points, independent checks, and one Node 18 compatible CommonJS runtime. Migrate application consumers and integrate package builds, dependency selection, import enforcement, and runtime resource staging.
Preserve daemon startup ownership and profile isolation, and qualify development rebuild recovery and concurrent output publication. Remove unnecessary aliases, test forwarding exports, and a duplicate output scan.
Validation: full typechecks, changed-code quality, package and artifact checks, native Windows builds/types plus 306 runtime tests, and independent native reviews.
Matched full E2E controls on original main and unchanged reviewed head both pass all 17 applicable tests (nine skips). Earlier intermittent E2E failures are documented in the PR; no assertions were weakened. The final combined-tree audit preserves both branches with no import-boundary violations.
- Install store domain contexts with one generic symbol copy
- Share one import-source classifier and one copy-name deconflicter across local, SSH and runtime-upload imports
- Collapse kill.ts synthetic-exit and stop-failure repetition into helpers
- Use Promise.allSettled in SSH transport teardown
- Use the shared errorMessage() instead of inline copies
- Fold isLiveSshPtyLease into ssh-types and drop the duplicate predicate
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(orcad): provide execution host CLI in Unix managed terminals
* fix(orcad): keep the server starting when the CLI launcher cannot be written
---------
Co-authored-by: m4air <m4air@Mac.localdomain>