Commit Graph
12 Commits
Author SHA1 Message Date
Neil 66501d1d37 fix(windows): keep agent hooks when an Orca registration names no install location (#35668)
The uninstaller's other-install check treated an Orca registration whose
InstallLocation reads empty as "none", so it would remove the agent hooks.
That registration could still be another install, so it now reports "unknown",
which keeps the hooks; every doubtful case leaves them in place.
2026-10-28 21:42:04 -07:00
Neil 4a24d5aacd fix(windows): remove Orca's agent hooks and PATH entry when uninstalling (#35588)
* fix(windows): remove Orca's agent hooks and PATH entry when uninstalling

On Windows most agents' managed hooks, and Claude's status line, call Orca's
.cmd scripts by bare path (to avoid starting PowerShell per event), and the
uninstaller removed neither those entries nor the `orca` command's user PATH
entry. Once %USERPROFILE%\.orca went, every agent failed a hook on each event.

A real uninstall (not an update) now runs the installed exe with
--orca-uninstall-remove-agent-hooks, mirroring the WSL holder release: no window,
lock or IPC, file edits only, a 30 s self-exit, and an exit code the uninstaller
ignores. It then drops $INSTDIR\resources\bin from the user PATH with native
registry calls, keeping every other entry and the value's type, and skipping the
edit if the read could have been truncated.

* fix(windows): keep agent hooks while another Orca install remains; skip PATH edits of unknown type

The hook scripts live in the shared ~/.orca\agent-hooks and reference nothing in
$INSTDIR (they call system curl/more and a copy of orca-agent-hook.exe there), so
they outlive an uninstall; the entries only break once that folder is removed.
The last Orca install for this user now takes them out: the uninstaller reads
the other per-user/per-machine registration (every channel shares one app GUID)
with native registry calls, and skips the removal if another install still has
the app or a read fails. PATH cleanup still runs, as it is per $INSTDIR.

PATH cleanup now writes only with a value type it actually read (REG_SZ or
REG_EXPAND_SZ); a failed open or query skips the write instead of assuming REG_SZ.

* fix(windows): install the app environment before the uninstall hook removers run

The uninstall mode skips the app's own preflight, so setAppEnvironment was
never called. Claude's remover then threw at getAppEnvironment() right after
writing settings.json: its agent-view keybinding stayed in every profile home
and its status-line marker stayed too. Install ElectronAppEnvironment right
after the AppData path, as main-process-preflight does. A new test runs every
agent's real remover in that mode with no environment preset; none warns, the
mode exits 0, and Claude's agent-view binding and status-line marker are gone.

* test(windows): register the uninstall preflight's host port and keep its real-remover test off real homes

The uninstall hook-removal preflight installs the app environment, so it joins
HOST_PORT_SOURCES. Its real-remover test now points HOME, USERPROFILE,
ORCA_USER_DATA_PATH, XDG_CONFIG_HOME, APPDATA, CODEX_HOME and CLAUDE_CONFIG_DIR
at the fixture: on Linux CI the Codex runtime home resolved from the runner's
XDG_CONFIG_HOME, which the real-agent-home write guard rejected.
2026-10-28 21:24:39 -07:00
NeilandClaude 284411d893 fix(wsl-host): uninstall and startup release WSL holders; a partial Remove keeps the host pending (#33843)
* fix(wsl-host): uninstall and startup release the WSL distro holders Orca left running

The detached wsl.exe holder outlives the app, so an uninstall left its distro,
orcad and shells running. The uninstaller now runs Orca with
--orca-uninstall-release-wsl-holders after killing the app and its daemon; it
ends only the holders this profile recorded, each verified by pid, start time
and command line, and keeps any it cannot verify.

At startup the WSL host service now releases holders whose distro is no longer
a host (a failed add or remove), and every holder while WSL hosts are off; a
closed gate releases them too.

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

* fix(wsl-host): a Remove that can't prove the server stopped keeps the host, pending

A partial Remove dropped the host anyway, leaving a server whose live
terminals block the next add's activation. Remove now drops the host only on a
proven stop; otherwise it records a pending stop on the WSL record, keeps the
host listed and says why (live or unverifiable). Remove again retries without
ever booting a stopped distro (it says to start it); Connect or Add on the same
distro keeps the host; a distro that is no longer registered finishes. Nothing
reconnects a pending host on its own.

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

* fix(wsl-host): E11 review — keep holders when records are unreadable; finish removals a stopped or renamed distro proves

- Startup keeps every holder when the WSL host records can't all be read
  (unverifiable), and no longer re-adopts a pending host's holder.
- Remove matches a renamed distro by GUID (isWslDistroRegistered), and a
  stopped distro finishes a pending Remove: the cold probe proves the stop.
- Only the user's Connect or Add withdraws a pending Remove; other connects
  are refused, and re-adding respects startIfStopped.
- Settings' Remove carries the kept result, so it warns instead of 'Removed'.
- A holder record without a start time is never killed on its command line
  alone, except the one this process just spawned.

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

* fix(wsl-host): E11 review 2 — a closed gate keeps live hosts' holders; stop a renamed distro by its current name

- With the gate closed, a launch releases only orphan holders (no host record,
  or a pending Remove), under the same keep rule as startup; a user with no
  holder records costs one folder check, nothing else.
- The keep rule re-reads host records per holder and keeps an Add in flight.
- Remove resolves the distro's current name from its GUID and stops it there.
- The uninstall command arms its exit timer first and exits 1 if setup throws;
  NSIS launches it only when a userData holder folder exists.

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

* fix(wsl-host): never boot a host whose Remove is pending at the next launch

Early wake built its host list from every record, so a host focused when its
Remove ended pending was booted at each launch, undoing the stop's proof. It
now skips pending records, and Remove forgets the host's early wake whatever
the outcome.

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

* fix(wsl-host): no wake for a pending host; the e2e fake stops an unbridged server like the real one

- mayWake skips a host whose Remove is pending, so a due automation can't
  boot it (focus already couldn't).
- The e2e fake connector read a host with no bridge as stopped. Since E9 a
  re-enable connects nothing, so Remove after off/on left the host's shells
  running. Like the real connector, it now reconnects the always-running fake
  distro to stop its server.
- Status bookkeeping moves to WslHostStatusBoard, and the pending-host connect
  rule to admitConnectToPendingHost, to keep the service under max-lines.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 20:17:53 -07:00
OrcaWinandOrcaWin 7d6603aa17 [comment audit] Complete repository-wide comment cleanup (#33249)
* [comment audit] Align legacy failure-read counts with cached display

* [comment audit] Condense shared provider lifecycle and browser recovery comments [skip ci]

* [comment audit] Condense shared generation, path and preview comments [skip ci]

* [comment audit] Condense host, file and Git contract rationale [skip ci]

* [comment audit] Tighten Git lifecycle and provider contract comments [skip ci]

* [comment audit] Clarify shared host authority and launch isolation [skip ci]

* [comment audit] simplify local access mobile and native chat contracts [skip ci]

* [comment audit] simplify native chat presentation and state contracts [skip ci]

* [comment audit] simplify native runtime and provider contracts [skip ci]

* [comment audit] simplify migration and orchestration contracts [skip ci]

* [comment audit] simplify plugin trust and process capture rationale [skip ci]

* [comment audit] simplify terminal delivery and remote compatibility rationale [skip ci]

* [comment audit] clarify remote recovery and launch wire rationale [skip ci]

* [comment audit] shorten shared RPC compatibility and runtime evidence comments [skip ci]

* [comment audit] simplify secure storage shell startup and sidebar rationale [skip ci]

* [comment audit] clarify sidebar, skill and SSH invariants [skip ci]

* [comment audit] condense structured chat delivery and timing rationale [skip ci]

* [comment audit] condense terminal replay and telemetry invariants [skip ci]

* [comment audit] clarify launch permission and terminal delivery rationale [skip ci]

* [comment audit] clarify workspace ownership and layout contracts [skip ci]

* [comment audit] wait for fitted and painted SSH terminal links

* [comment audit] clarify layout persistence and session ownership [skip ci]

* [comment audit] clarify host routing and workspace lifecycle contracts [skip ci]

* [comment audit] clarify startup persistence and app lifetime comments [skip ci]

* [comment audit] clarify recovery and activity boundaries [skip ci]

* [comment audit] condense activity and artifact invariants [skip ci]

* [comment audit] condense automation authority contracts [skip ci]

* [comment audit] simplify automation scheduling and history contracts [skip ci]

* [comment audit] clarify browser chrome and annotation lifecycles [skip ci]

* [comment audit] clarify browser routing and retained guest ownership [skip ci]

* [comment audit] clarify browser recovery and document ownership comments [skip ci]

* [comment audit] restore hosted runners required by native IME fixtures

* [comment audit] shorten preview, palette and dashboard invariants [skip ci]

* [comment audit] clarify terminal preview, dashboard and retention comments [skip ci]

* [comment audit] clarify diff-note recovery and editor lifecycle comments [skip ci]

* [comment audit] shorten rich-text and combined-diff ownership comments [skip ci]

* [comment audit] shorten autosave, draft recovery and model ownership comments [skip ci]

* [comment audit] shorten save-queue, notebook and Markdown constraints [skip ci]

* [comment audit] shorten Monaco, PDF and rich Markdown safeguards [skip ci]

* [comment audit] clarify rich Markdown source and selection safeguards [skip ci]

* [comment audit] clarify editor loading and emulator stream lifetimes [skip ci]

* [comment audit] trim emulator and feature tour narration [skip ci]

* [comment audit] clarify floating workspace and GitHub cache ownership [skip ci]

* [comment audit] trim provider controls and Linear filter explanations [skip ci]

* [comment audit] clarify pairing and chat resume lifetimes [skip ci]

* [comment audit] clarify chat delivery and transcript lifetimes [skip ci]

* [comment audit] clarify session options and host-owned status [skip ci]

* [comment audit] clarify draft durability and live-status precedence [skip ci]

* [comment audit] Trim chat send and model ownership explanations [skip ci]

* [comment audit] Shorten transcript ownership and send recovery comments [skip ci]

* [comment audit] Simplify native chat composer and transcript hook comments [skip ci]

* [comment audit] Shorten native chat scroll and structured session explanations [skip ci]

* [comment audit] Trim workspace picker and onboarding commentary [skip ci]

* [comment audit] Simplify pet rendering, review cache and quick open comments [skip ci]

* [comment audit] Trim sidebar and session history explanations [skip ci]

* [comment audit] Condense session resume and review checks comments [skip ci]

* [comment audit] Shorten checks state and file explorer refresh comments [skip ci]

* [comment audit] Trim plugin bridge and source-control action rationale [skip ci]

* [comment audit] Trim source-control listing and review rationale [skip ci]

* [comment audit] Shorten sidebar lifecycle and explorer safeguards [skip ci]

* [comment audit] Condense Settings account and appearance rationale [skip ci]

* [comment audit] Trim pairing and repository Settings explanations [skip ci]

* [comment audit] Condense Settings search SSH and terminal safeguards [skip ci]

* [comment audit] Shorten Settings voice and provider ownership comments [skip ci]

* [comment audit] Condense Settings draft persistence and host-state rationale [skip ci]

* [comment audit] Trim Settings hooks and sidebar setup rationale [skip ci]

* [comment audit] Condense sidebar deletion and board-filter safeguards [skip ci]

* [comment audit] Condense worktree cards, host ownership and Markdown contracts [skip ci]

* [comment audit] Condense sidebar drag, folder and filtering contracts [skip ci]

* [comment audit] Condense sidebar parity, sleep and host ownership contracts [skip ci]

* [comment audit] Prune focus-read baseline after comment cleanup

* [comment audit] Clarify sidebar visibility, board drops and agent evidence [skip ci]

* [comment audit] Tighten sidebar listing, drag and reveal contracts [skip ci]

* [comment audit] Clarify viewport geometry and skill update safeguards [skip ci]

* [comment audit] Tighten skill inventory, usage and host status comments [skip ci]

* [comment audit] Clarify usage ownership and resource kill safeguards [skip ci]

* [comment audit] Tighten tab selection, rename and search contracts [skip ci]

* [comment audit] Tighten tab-strip geometry and drag ownership comments [skip ci]

* [comment audit] Tighten Tasks recovery, pagination and mutation comments [skip ci]

* [comment audit] Tighten provider loading and terminal recovery comments [skip ci]

* [comment audit] Tighten completion, cadence and PTY ownership comments [skip ci]

* [comment audit] Clarify terminal restore and parked-pane boundaries [skip ci]

* [comment audit] Tighten PTY startup and replay explanations [skip ci]

* [comment audit] Clarify PTY identity and delivery ownership [skip ci]

* [comment audit] Shorten remote reconnect and input replay rationale [skip ci]

* [comment audit] Condense terminal parking clipboard and file link comments [skip ci]

* [comment audit] Clarify IME ownership and trim trace history [skip ci]

* [comment audit] Shorten pane recovery and parked watcher explanations [skip ci]

* [comment audit] Condense snapshot replay and visibility recovery rationale [skip ci]

* [comment audit] Shorten terminal parking and keyboard ownership rationale [skip ci]

* [comment audit] Trim renderer lifecycle and menu rationale [skip ci]

* [comment audit] Condense workspace cleanup ownership and settlement notes [skip ci]

* [comment audit] Clarify renderer hook evidence and source ownership [skip ci]

* [comment audit] Tighten IPC ownership and reconnect explanations [skip ci]

* [comment audit] Trim renderer focus, paste and attention comments [skip ci]

* [comment audit] Shorten scroll, locale and agent lifecycle comments [skip ci]

* [comment audit] Trim agent launch, resume and ownership commentary [skip ci]

* [comment audit] Shorten account, browser and editor comments [skip ci]

* [comment audit] Clarify host-mirror waits, previews and input ownership [skip ci]

* [comment audit] Condense launch recovery and editor tokenization comments [skip ci]

* [comment audit] Condense workspace selection and terminal pane rationale [skip ci]

* [comment audit] Condense terminal fitting and rendering recovery comments [skip ci]

* [comment audit] Condense terminal input and host routing explanations [skip ci]

* [comment audit] Condense ownership and sleeping-session recovery rationale [skip ci]

* [comment audit] Condense structured launch and terminal link explanations [skip ci]

* [comment audit] Condense terminal ownership and workspace file routing rationale [skip ci]

* [comment audit] Condense session persistence and workspace activation rationale [skip ci]

* [comment audit] Condense workspace routing and browser ownership rationale [skip ci]

* [comment audit] Condense mirror recovery and layout authority rationale [skip ci]

* [comment audit] Condense runtime transport and file safety rationale [skip ci]

* [comment audit] Condense runtime graph and structured session rationale [skip ci]

* [comment audit] Condense browser creation and remote tab recovery rationale [skip ci]

* [comment audit] Condense snapshot authority and publisher recovery rationale [skip ci]

* [comment audit] Condense frame, startup and provider cache rationale [skip ci]

* [comment audit] Condense host twin and agent lifecycle rationale [skip ci]

* [comment audit] Condense browser authority and editor cleanup rationale [skip ci]

* [comment audit] Condense editor buffer identity and review cache rationale [skip ci]

* [comment audit] Condense provider lifetime and repository ownership rationale [skip ci]

* [comment audit] Condense reconnect, hydration and terminal retirement rationale [skip ci]

* [comment audit] Condense recovery, reconciliation and persistence rationale [skip ci]

* [comment audit] Condense cleanup ownership and listing admission rationale [skip ci]

* [comment audit] Condense teardown ordering and terminal ownership rationale [skip ci]

* [comment audit] Condense recovery ledger and web host-boundary rationale [skip ci]

* [comment audit] Condense web reconnect and credential lifecycle rationale [skip ci]

* [comment audit] Condense cloud rollout and assignment safety rationale [skip ci]

* [comment audit] Condense relay session and database recovery rationale [skip ci]

* [comment audit] Condense relay placement and protocol compatibility rationale [skip ci]

* [comment audit] Condense build and packaging constraints [skip ci]

* [comment audit] Condense CI gates and validation isolation rationale [skip ci]

* [comment audit] Condense catalog identity and browser validation rationale [skip ci]

* [comment audit] Condense mobile browser and frame-budget rationale [skip ci]

* [comment audit] Shorten mobile route and browser test explanations [skip ci]

* [comment audit] Condense editor and session seam test rationale [skip ci]

* [comment audit] Trim session and terminal closure history [skip ci]

* [comment audit] Shorten terminal browser and census explanations [skip ci]

* [comment audit] Preserve root-only E2E diagnostic baseline

* [comment audit] Condense mobile seam and HTML preview test rationale [skip ci]

* [comment audit] Condense preview instrumentation and render harness rationale [skip ci]

* [comment audit] Condense bundle contracts and native-build constraints [skip ci]

* [comment audit] Shorten native packaging and CI routing rationale [skip ci]

* [comment audit] Condense release tooling and benchmark constraints [skip ci]

* [comment audit] Condense packaging and platform gate rationale [skip ci]

* [comment audit] Shorten mobile route and history rationale [skip ci]

* [comment audit] Condense mobile browser and component rationale [skip ci]

* [comment audit] Shorten drawer and workspace-form rationale [skip ci]

* [comment audit] Trim mobile review and editor-document explanations [skip ci]

* [comment audit] Condense editor lifecycle and Markdown explanations [skip ci]

* [comment audit] Trim mobile file, diagnostics and dictation commentary [skip ci]

* [comment audit] Simplify mobile host-list and workspace-view explanations [skip ci]

* [comment audit] Clarify mobile shell lifetime and bridge delivery constraints [skip ci]

* [comment audit] Condense bridge stream, native request and audio rationale [skip ci]

* [comment audit] Reduce bridge schema and page-client commentary [skip ci]

* [comment audit] Tighten mobile page bridge contracts [skip ci]

* [comment audit] Clarify mobile cache and session constraints [skip ci]

* [comment audit] Condense mobile route and lifecycle rationale [skip ci]

* [comment audit] Tighten mobile shell hook timing rationale [skip ci]

* [comment audit] Clarify route handoff and notification compatibility [skip ci]

* [comment audit] Clarify push registration and dictation cleanup constraints [skip ci]

* [comment audit] Condense keyboard geometry and native media ownership rationale [skip ci]

* [comment audit] Tighten mobile chat scroll and composer concurrency rationale [skip ci]

* [comment audit] Condense mobile reply compatibility and upload ownership rationale [skip ci]

* [comment audit] Condense optimistic echo and scroll ownership rationale [skip ci]

* [comment audit] Tighten stream replay and queued session ownership rationale [skip ci]

* [comment audit] Condense mobile composer and reply-schema constraints [skip ci]

* [comment audit] Clarify mobile transcript recovery and session ownership [skip ci]

* [comment audit] Clarify mobile queue and source-control compatibility [skip ci]

* [comment audit] Condense storage and task launch constraints [skip ci]

* [comment audit] Clarify task schemas and terminal document ownership [skip ci]

* [comment audit] Tighten terminal input and viewport rationale [skip ci]

* [comment audit] Shorten terminal and RPC recorder contracts [skip ci]

* [comment audit] Condense recorder engine and connection contracts [skip ci]

* [comment audit] Shorten host credential and relay recovery comments [skip ci]

* [comment audit] Tighten pairing recovery and bundle transport rationale [skip ci]

* [comment audit] Clarify RPC delivery and workspace catalog boundaries [skip ci]

* [comment audit] Condense catalog and relay entry contracts [skip ci]

* [comment audit] Shorten shutdown and SSH relay delivery contracts [skip ci]

* [comment audit] Condense WSL relay and E2E regression rationale [skip ci]

* [comment audit] Shorten cross-version harness and renderer fixture explanations [skip ci]

* [comment audit] Condense paired-host and E2E lifecycle rationale [skip ci]

* [comment audit] Shorten layout oracle and regression explanations [skip ci]

* [comment audit] Condense paired recovery and ownership regression contracts [skip ci]

* [comment audit] Shorten restart, sidebar and SSH lifecycle contracts [skip ci]

* [comment audit] Condense terminal rendering and IME regression rationale [skip ci]

* [comment audit] Shorten terminal recovery and benchmark contracts [skip ci]

* [comment audit] Condense tooling and Windows lifecycle proof rationale [skip ci]

* [comment audit] Condense workflow routing and release rationale [skip ci]

* [comment audit] Condense mobile security and installer contracts [skip ci]

* [comment audit] Shorten native rationale and stylesheet workarounds [skip ci]

* [comment audit] Shorten Windows visibility probe rationale [skip ci]

* [comment audit] Condense embedded release and signing rationale [skip ci]

* [comment audit] Retain current main test behavior in final reconciliation [skip ci]

* [comment audit] Complete final comment review across current source inventory

* [comment audit] Handle consolidated audit reports before final CI

* [comment audit] Preserve credential storage census detail [skip ci]

* [comment audit] Scale broad changed E2E selections with verified timing shards

* [comment audit] Align E2E assertions with browser close and settled session metadata

* [comment audit] Match existing E2Es to current resource and windowing contracts

* [comment audit] Observe the shared server outage notice in reconnect coverage

* [comment audit] Make existing renderer probes measure settled tab and PTY work

* [comment audit] Align palette E2E selector with task search

* [comment audit] Refresh remaining palette search selectors

* [comment audit] Keep selector correction within selected audit specs

* [comment audit] Await emoji fixture settings inside renderer evaluation

* [comment audit] Cancel fixture fit retries between terminal tests

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 04:05:46 -07:00
Neil 1912c90141 Extract subprocess handling into @orca/process-host (#26963)
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.
2026-10-09 18:32:28 -07:00
NeilandNeil 130b2ef425 feat(documents): open CSV and TSV files from the OS
Extend existing OS document associations and delivery to CSV/TSV, preserving restoration and authorization.

Co-authored-by: Neil <neil@stably.ai>
2026-10-03 00:51:13 -07:00
OrcaWinandm4air 4b6fe95943 fix(windows): preserve relocated terminals and native process scans (#22872)
* fix(windows): ship the process-table addon to the relocated daemon host

The Windows terminal daemon runs from a copy of the app under
%LOCALAPPDATA%\Orca\daemon-host\<version>. That copy took node-pty but not
@vscode/windows-process-tree, so the daemon's bare require of the addon found
nothing and every process-table read (foreground tracking, descendant sweeps)
fell back to a powershell.exe Get-CimInstance scan (#16905).

- Copy the addon's runtime files (package.json, lib/, the .node binary) into
  the host; the ~25MB of gyp intermediates beside them are filtered out.
- Treat a host missing those files as unmaterialized, so hosts built before
  this are rebuilt, and skip relocation if the install itself lacks them.
- Log the daemon's native/CIM capability at startup and warn once when the
  process table falls back to CIM.

Revives #19525 on current main.

* test(windows): locate update-survival loss before relaunch

* test(windows): preserve daemon tree before update-survival proof

* test(windows): distinguish Electron exit from launcher close timeout

* test(windows): verify process exit when inherited pipes delay close

* test(windows): trace installer process checks in isolated survival runs

* fix(windows): probe process-query capability before installer sweep

* fix(windows): match installer probe and process-check profile behavior

* fix(windows): use NSIS separators for the process-check include

* test(windows): dismiss session-search overlay in survival harness

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 14:31:07 -07:00
OrcaWinandOrca Worker fba90e017c fix(windows): copy the daemon host exe verbatim instead of renaming it (MDE T1036) (#17865)
* docs(windows): document the EDR signal surface

Six Microsoft Defender for Endpoint incidents fired against Orca 1.4.192 in
eight days on one enterprise Windows 11 / Intune tenant. All six were
behavioural process-tree scoring, not signature hits; two escalated to
multi-stage incidents mapped to ATT&CK Execution and Collection.

Add a reference doc mapping each attack-technique-shaped behaviour to the code
that produces it and to why it exists: the renamed daemon image (T1036), the
per-process PEB read, encoded policy-bypassed PowerShell (T1049), caret-escaped
cmd.exe lines, and computer-use screen capture plus runtime-compiled MSIL
(T1113). Records that signing is not the gate -- reputation is signer plus
hash-keyed prevalence -- and carries the two evidence gaps the report noted.

Adds an engineer checklist, deployment guidance for admins (AV path exclusions
do not suppress EDR behavioural alerts; an MDE alert suppression rule does), and
an explicit pre-deployment warning about computer use.

* docs(windows): correct the PowerShell flag inventory and admin paths

Review corrections to the EDR posture doc.

The "encoded, policy-bypassing PowerShell" list conflated three different
shapes and was incomplete. Split it into the three tiers an EDR actually scores
differently -- bypass plus encoding, encoding alone, and bypass alone -- and add
the sites it missed, including windows-mobile-firewall.ts, which encodes a
script and launches it elevated through Start-Process -Verb RunAs. system-fonts.ts
(-Command) and desktop-script-provider-bridge.ts (-File) were listed as encoded
and are not. Notes that a raw grep under-reports, because the hook sites reach
-EncodedCommand through wrapWindowsPowerShellEncodedCommand.

Attribute the in-payload Set-ExecutionPolicy move to #16576 rather than to
#16003's measurement, which keyed on -WindowStyle Hidden + -EncodedCommand, and
record that the launcher's own tradeoff is unverified on a real box.

Admin guidance was missing two ways a suppression rule pinned to one full path
misses real activity: the .staging-<hex> sibling that exists mid-update, which
is when the update-cluster incidents fire, and the userData fallback when
LOCALAPPDATA is unset.

Also: state the measurement conditions on the process-table timings, note that
Hermes has surface even though we have no telemetry for it, note that the
uninstaller names are electron-builder-generated and in no repo file, drop a
volatile line count, and mark the per-operation computer-use shape as being
addressed by an unmerged change. Drops the duplicated AGENTS.md section, keeping
the indexed bullet.

* docs(windows): reconcile the EDR posture doc with the shipped remediation

Three claims in this doc became false once the rest of the Windows EDR set
landed, and two told engineers the opposite of what the release does.

The process-table section still described one shared snapshot taken with
`Memory | CommandLine | CreationTime`, argued that splitting the cache per
field set "would restore exactly the fan-out it exists to prevent", and
concluded the shape was unfixable because "the information is only in the
PEB". The split shipped (identity opens no handle at all), `Memory` is
retired, and the command line now comes from the kernel through
`ProcessCommandLineInformation` -- `ReadProcessMemory` is absent from the
compiled addon and a ratchet asserts it against the import table. An engineer
reading the old text would have concluded both fixes were dead ends.

The PowerShell site inventories were stale in three of four lists: the port
scan went native, every `-ExecutionPolicy Bypass` + `-EncodedCommand` pair
was dropped as a measured no-op, and of the unencoded-bypass list only
`wsl-cli-scripts.ts` survives. Regenerated against the merged tree, including
the sites that reach the flag through `wrapWindowsPowerShellEncodedCommand`
and never spell it, which a raw `rg` misses.

Incident-evidence sections are left alone: they record what the tenant observed
on 1.4.192, not what the code does now.

* fix(windows): copy the daemon host exe verbatim instead of renaming it

Microsoft Defender for Endpoint flagged `orca-terminal-daemon.exe` as MITRE
T1036 (Masquerading): Orca copied its own `Orca.exe` into %LOCALAPPDATA% under a
different name, specifically so the NSIS updater's `taskkill /IM Orca.exe` could
not match, then ran it detached. Because that process is what every other flagged
action was attributed to, the name mismatch acted as a reputation multiplier on
unrelated findings.

The rename was never what made the daemon survive. In app-builder-lib 26.15.3 the
installer's FIND_PROCESS/KILL_PROCESS select processes whose image path is under
$INSTDIR; `taskkill /IM` is only the fallback for hosts where PowerShell is
missing or blocked. Survival is a property of the path, and
%LOCALAPPDATA%\Orca\daemon-host is outside $INSTDIR whatever the file is called.

Derive the host exe name from process.execPath so the copy is byte-for-byte,
name included — it keeps its Authenticode signature and carries no renamed-image
signal. On the no-PowerShell fallback the daemon is now killed with the app and
terminals cold-restore, which is the documented pre-relocation outcome the update
harness already asserts, not a regression.

The uninstall macro no longer needs a distinct name to find the daemon; it kills
the app's own image name (plus the legacy name, for hosts left by older builds).

Adds docs/reference/windows-daemon-host-relocation.md with the survival contract,
the rejected alternatives and their measured costs, and the invariants to keep.

* fix(windows): apply daemon-host relocation review corrections

Scope the uninstall taskkill to the current user with `/FI "USERNAME eq
%USERNAME%"` via cmd.exe, matching upstream's per-user KILL_PROCESS — without it
an elevated machine-wide uninstall reaches another logged-on user's session, so
the "no collateral" claim in the comment was overstated.

Comment the rmSync-before-publish: Windows refuses to delete a running image, so
a live daemon already hosted in this version's dir (same-version reinstall, or a
dev channel reusing a version) throws and materialization fails open.

Doc corrections:
- The fallback selector is the full per-user `taskkill /F /IM "<app>.exe" /FI
  "PID ne $pid" /FI "USERNAME eq %USERNAME%"`, not a bare `taskkill /IM`.
- The probe reads `Get-ExecutionPolicy -Scope Process`, not the effective policy,
  and GPO writes MachinePolicy/UserPolicy — so GPO-managed hosts take the primary
  path-scoped branch. Narrow the fallback triggers accordingly.
- Drop the Authenticode sentence: the old name was equally byte-identical and
  equally signed, so a filename has no bearing on signature validity.
- Name the new update-abort path: the daemon now matches FIND_PROCESS, so on the
  fallback branch an unkillable host reaches the retry loop's MessageBox /SD
  IDCANCEL and Quits, aborting a silent update.
- Correct the customCheckAppRunning rejection. It is ~6 lines, not a rewrite; it
  is wrong because forcing the PowerShell branch where PowerShell is absent makes
  FIND/KILL silently no-op and leaves the real app running with files in use.
- Bound the win honestly: OriginalFilename is empty on the shipped binary, so the
  strongest T1036 indicator never fired, and the residual copy-and-run-detached
  shape still maps to T1036.005.

Reconcile docs/reference/windows-edr-posture.md, which documents the rename as a
live finding and would otherwise contradict this change. Content-only edit:
markdown under docs/reference/ is not oxfmt-formatted as a matter of practice and
nothing in CI gates it, so the file is left consistent with its neighbours.

* fix(windows): expand USERNAME in NSIS instead of spawning cmd.exe

The uninstall macro routed both taskkills through `"$SYSDIR\cmd.exe" /C` purely
so `%USERNAME%` would expand — two extra interpreter spawns on the uninstall
path, in a change whose whole point is not adding scored behaviour, and the
exact `cmd.exe /c` shape the new AGENTS.md EDR bullet warns about. NSIS reads
the variable itself with ReadEnvStr, so the spawns buy nothing.

Verified on Windows 11 that the generated command line does what the filter is
there for: a copy of cmd.exe running as orca-nonexistent-probe.exe (pid 34244)
was terminated by `taskkill /F /IM "orca-nonexistent-probe.exe" /FI "USERNAME eq
<user>"` — SUCCESS, exit 0, process gone.

Guarded on an empty USERNAME because the degenerate case is silent: taskkill
rejects an empty filter value outright ("The search filter cannot be
recognized") and kills nothing, which would leave exactly the orphaned daemon
this macro exists to reap. `*` is rejected as a filter value too, so there is no
branchless spelling. With no USERNAME to scope by it kills unfiltered, as the
macro did before the filter was added. Stack stays balanced: three pushes, two
nsExec pops, three restores.

Also strike the last stale row in windows-edr-posture.md's remediation table.
"Copying our own image under a different name" read as outstanding work; it is
done by this change, so the row now points at the relocation doc. Same class of
staleness as the section reconciled in the previous commit, and git would not
have flagged it either.

* fix(windows): port the daemon-host uninstall sweep into the live NSIS include

The uninstall macro this branch rewrote lived in config/nsis/daemon-host-uninstall.nsh,
which main no longer includes: #17906 consolidated every Windows installer hook into
config/nsis/orca-installer-hooks.nsh because electron-builder accepts exactly one
`nsis.include`. Merged as-is, the rewritten macro would have been dead code while the
shipped uninstaller kept running main's stale sweep — `taskkill /F /IM
orca-terminal-daemon.exe`, which matches nothing now that the relocated host is a
verbatim Orca.exe copy. The RMDir that follows then cannot delete the running image, so
a live orphaned daemon and its ~224 MB tree would survive every uninstall.

Ported into the live include: the ${APP_EXECUTABLE_FILENAME} kill, the USERNAME filter
that keeps an elevated machine-wide uninstall out of another logged-on user's session,
and the register save/restore around both. The legacy orca-terminal-daemon.exe kill
stays so hosts left by older builds are still reaped.

The ratchet that was meant to catch exactly this pinned only the legacy image name,
which main's stale macro already satisfied, so it passed both ways. It now asserts the
app-exe kill and the USERNAME filter, against comment-stripped script — the prose above
the macro names both image names, so a toContain over the raw file proves nothing.

---------

Co-authored-by: Orca Worker <orca-worker@localhost>
2026-09-05 21:11:28 -07:00
Neil 4efc86a33c feat(app): open Markdown files from the OS in the floating workspace (#17906)
* feat(app): open Markdown files from the OS in the floating workspace

Registers Orca as a Markdown handler on macOS, Windows and Linux, and opens
an OS-handed .md/.markdown/.mdx file as a floating-workspace editor tab —
the one editor surface that needs no project. Works cold-start and when
Orca is already running.

Main buffers the paths and both pushes to a live renderer and answers a
pull on renderer mount, mirroring SkillShareDeepLinkState. The buffer is
only released once delivery is possible: the renderer's pull is what proves
its ui:openMarkdownFiles listener is attached, because a push into a window
whose renderer has not subscribed is dropped by Electron with no error. Both
the push and the pull restore an undelivered batch, and a renderer reload
clears the latch so the fresh renderer re-proves itself. Paths are stat'd and
proven to be files before authorizeExternalPath sees them.

Windows association is registered by hand in the NSIS include rather than
through electron-builder's `fileAssociations`: app-builder-lib emits
APP_ASSOCIATE, whose first line overwrites Software\Classes\.md's default
value with no backup — silently taking .md from whichever editor owns it,
for every existing user on their next update — and APP_UNASSOCIATE never
restores it. The hand-rolled registration is additive (ProgID +
OpenWithProgids + SupportedTypes) and leaves the user's default alone;
verified end to end on a real Windows 11 host.

Co-authored-by: Wooseong Kim <innocarpe@users.noreply.github.com>
Co-authored-by: Jaydev <java-jaydev@users.noreply.github.com>

Closes #10138

* fix(os-open): register the new listener in the IPC inventory, and guard a non-array payload

CI caught two things the local run did not.

useIpcEvents-lifecycle.test.ts is an inventory of every App-lifetime IPC
listener and the exact order they register in; ui.onOpenMarkdownFiles now
appears there, positioned after the workspace-shortcut bridge's last
listener, which is where it actually registers.

Chasing that failure surfaced a real gap: the pending-open payload crosses
the preload boundary, so a stale or mismatched preload can resolve with
something that is not an array, and reading .length off it threw inside the
promise chain instead of failing at the boundary. Array.isArray now gates it,
with a regression test.
2026-09-01 17:35:38 -07:00
OrcaWinandOrcaWin dde72f85de fix(windows): separate updater from orchestration migration (#11405)
* fix(windows): separate updater from orchestration migration

* fix(terminal): attest adopted reveal identity

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-07-29 15:23:06 -07:00
OrcaWinandOrcaWin 363e478909 fix(orchestration): preserve active workers across updates (#11271)
* fix(orchestration): preserve active workers across updates

* test(ssh): model absent legacy adoption

* test(orchestration): align compatibility contracts

* fix(windows): escape updater PowerShell booleans

* fix(windows): restore stock uninstall process check

* fix(orchestration): keep recovery off renderer startup barrier

* fix(orchestration): harden legacy recovery migration

* fix(orchestration): close recovery review gaps

* fix(orchestration): complete legacy worker cutover recovery

* fix(orchestration): preserve legacy workers across updates

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-07-29 11:31:35 -07:00
Jinwoo Hong c256a5a417 Windows terminal update-survival (single consolidated PR) (#7538) 2026-07-07 19:21:07 -04:00