* fix(startup): pin Windows appData and userData before anything resolves them
A Windows session without a loaded profile (e.g. orca serve over SSH) can fail the
roaming AppData known-folder lookup. Electron 43 then falls through to Chromium's
userData provider and crashes natively. Resolve appData first (falling back to
APPDATA, then USERPROFILE\AppData\Roaming), and set userData explicitly so
Electron's provider never runs.
* test(startup): remove the AppData fixture through the retrying helper
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* test(ssh): prove connect-time conversion to managed orcad on real Linux and Windows hosts, and the downgrade view
* fix(e2e): read the SSH host's session partition, provision the convert cell's account, and keep rollout file overrides out of packaged builds
* test(e2e): report the full relay state when the convert poll times out
* test(e2e): require the relay to list no terminals before the converting connect
* test(e2e): require no running-terminal lease before the converting connect
* test(e2e): report the host's terminal leases when the converting connect keeps the relay
* test(e2e): end the relay era with no relay shell left to respawn
* test(e2e): settle before the converting connect and name the tabs a blocking shell belongs to
* test(e2e): use the exited relay tab as the session tab, since any mounted tab starts a shell
* test(e2e): carry an editor tab through the conversion instead of a terminal tab
* test(e2e): log the conversion census inputs before the converting connect
* fix(orcad): log which state blocked a refused conversion
* test(e2e): log both session partitions before the converting connect
* fix(orcad): a source partition's copy of focus on another host no longer blocks conversion
* fix(ssh): an ssh2 forward on port 0 reports the port it bound, so managed tunnels pair
* test(e2e): give the conversion its full budget again
* test(e2e): report the migration journal phase when the conversion stalls
* test(e2e): report the connect's own result and main's state when the conversion stalls
* fix(ssh): a converted host's managed state reaches the renderer instead of staying on 'converting'
* test(e2e): print a failed server call's response
* test(e2e): give server calls the budget a fresh server's first inventory needs
* test(e2e): read the converted worktree's tabs with a scoped session.tabs.list
* test(e2e): log the converted worktree's tabs instead of asserting them, pending the server-side fix
* test(e2e): prove retirement by the dropped source rows; the journal compacts away after it
* test(e2e): drop the conversion diagnostics now the cell passes
* test(e2e): fail a hung disconnect or connect with main's state instead of the whole budget
* test(e2e): convert an upgraded relay-era profile's host on its first connect, on Docker and Windows
* test(e2e): seed the relay-era target the way addTarget registers it
* fix(ssh): a stale ssh2 forward drops a late connection instead of crashing main on 'Not connected'
* fix(orcad): the active-slot readiness probe reads Windows hosts through the host script
* ci(ssh-windows): let only the convert cell's account open the SSH local forward its managed server needs
* test(e2e): match server paths in their JSON-escaped form, for Windows backslashes
---------
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
Co-authored-by: m4air <m4air@Mac.localdomain>
Ports PR #10521 onto current main: agent catalog, managed hook service,
agent-status listener, session resume, AI Vault parser, per-pane daemon
isolation, and Source Control AI support.
Co-authored-by: Neil <neil@stably.ai>
Add Ruby task/configuration filenames to the existing generated language associations.
Co-authored-by: ggbdpq <ggbdpq@gmail.com>
Co-authored-by: Neil <neil@stably.ai>
Move the existing initial CPU observation and histogram enable inside the existing try/finally so their failures clear the sampler's owned heartbeat, preserving successful operation order and original errors.
Verified selection plans previously validated each selected filename with a scan of all discovered files. One per-call Set now handles membership checks. Exact source/discovery checks, nonempty selection, fallback to all tests, shard balancing and manifests remain intact.
Iterate the existing live visited Set in FIFO discovery order instead of maintaining a second shifted queue; both actual callers own untouched esbuild JSON metadata.
* fix(ci): run mobile typechecks without concurrent dependency refresh
* test(ci): check effective Linux E2E package list
* test(ci): preserve the mobile production compiler barrier
---------
Co-authored-by: Orca Integration Recovery <orca-validation@invalid.example>
* Let measured cache producers keep stores without downloading them
* Check that restore-only callers do not publish a producer path
* Enable the measured producer mode and record hosted comparisons
* refactor(ai-vault): delete the unused session-scanner worker thread
Production always scans through the forked session-scanner service process;
the worker thread was reachable only under NODE_ENV=test or the
undocumented ORCA_AI_VAULT_SERVICE_PROCESS=0 switch, and nothing fell back
to it on service failure. Remove the thread (spawn, client, protocol, entry,
tests), its build entry, knip and plain-node-guard listings, and the
backend switch, so session-scanner-background always routes to the service.
- Move the scan options type to the service protocol as
AiVaultServiceScanOptions.
- Tests now mock session-scanner-service-spawn, the seam production calls.
- Repoint the hot-path listing reliability gate from the worker-client test
to the service-client test, which covers the same bounded-queue,
cancellation, and fault-restart properties for the real executor.
STA-9122
* test(ai-vault): cover the service's Claude-vs-OMP subagent lister choice
Runs the real service entry and subagent reader, replacing only the two
per-agent listers, so a swapped lister choice fails.
STA-9122
* fix(opencode): read the binder's session store on the foreign SQLite reader worker (STA-9122)
Before: the OpenCode session binder listed new sessions from opencode.db with
node:sqlite on the main thread every 60 s (and on SessionStart kicks), so a
large or contended store could stall the app the same way Cursor's did.
After: the read is a pure openCodeBinderSessions reader in
foreign-sqlite-readers/readers/, run only on the worker. The binder's
correlation, pane snapshot and process sweep stay where they were.
- The binder round awaits listSessions and re-checks its generation right
after, so a stop() during the read discards the round before it touches the
unbound map or the watermark.
- The client's in-flight dedupe key now includes the cursor, so a stale round
from before a restart cannot hand its rows to the restarted round.
- Idle teardown is per reader. The binder lane keeps its thread for 120 s,
longer than its 60 s poll, so the thread is not respawned every round.
- A timeout, crash, malformed reply or unstartable worker resolves to [] (no
sessions), the value the old read already returned on failure.
- An absent store still reads as [] without a log line, and a permission or
corrupt-file failure still logs (kept from #24577, now in the reader: it
stats the path and throws anything but ENOENT/ENOTDIR to the client's log).
- The binder lane inherits #24572's limits from the shared lane: no respawn
until a timed-out worker has exited, 2 consecutive deaths, a queue cap of
8. Its timeout stays 60 s, matching its poll.
- dispatch switches on the destructured kind, so a new kind without a case
still fails to compile.
orcad: the hook server runs there too, so orcad now ships
foreign-sqlite-reader-entry.js beside orcad.js (ORCAD_ARTIFACTS, built as an
orcad child). build-orcad runs a smoke check that starts the built worker
under the build's Node and under the pinned runtime, and does a real binder
read on a fixture DB, a Cursor read of a missing file and an OpenCode history
list. The OpenCode history scanner uses the same entry and was bundled into
orcad without it, so on orcad it always failed closed; it can now run.
Tests: reader (cursor, same-ms ids, OpenCode 2 rows, missing then created,
corrupt, inaccessible directory), retirement gate for the binder lane, dispatch
routing, client lane (rows, failure -> [], dedupe per cursor, own thread, idle
teardown default and override), binder loop with an async listSessions
(failure -> [], stop during the read), orcad path resolution through orcad's
host adapters, artifact list, and the smoke check against good, missing and
non-reading entries.
* test(opencode): cover the binder read deadline with fake timers and name the failure test accurately (STA-9122)
* refactor(sqlite): rename the OpenCode SQLite worker entry to foreign-sqlite-reader (STA-9122)
The worker thread that reads OpenCode's database off the main thread is about
to read other apps' databases too, so its entry is renamed to what it is:
src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts, built as
out/main/foreign-sqlite-reader-entry.js.
Why now: #24572 fixed the Cursor focus freeze with a second, dedicated
worker. Rather than grow one worker per foreign app, the next commit moves
Cursor onto this entry and deletes that worker. This commit is the rename
only; #24572's cursor-desktop-profile-worker-entry lines stay until then.
It moves out of ai-vault/ into a new foreign-sqlite-readers/ module because
it will no longer be session-scanner code; the module will own the readers,
their dispatch, protocol and main-process client.
The entry still routes only OpenCode kinds in this commit. The OpenCode
dispatch, protocol and process entry stay in ai-vault/ and stay OpenCode-only,
because the SSH/WSL relay reader bundles them (build-relay.mjs).
Every reference is updated: electron.vite.config.ts input key, knip entry,
the plain-node entry guard and its test, the asarUnpack list (the scanner
service still spawns this entry under ELECTRON_RUN_AS_NODE), and the
electron-builder test that reads the filename. The filename and the
beside-or-one-up (Rollup chunks) lookup now live in
foreign-sqlite-reader-entry-path.ts, which the OpenCode spawn reuses, plus an
Electron-main resolver that uses the packaged app.asar path.
* fix(cursor): move the desktop-login read from its dedicated worker onto the foreign SQLite reader (STA-9122)
#24572 fixed the Cursor focus freeze (#24360) with a dedicated worker
(rate-limits/cursor-desktop-profile-worker*.ts). Orca already runs OpenCode's
database reads on a worker, and more foreign-app SQLite reads are coming, so
keeping one worker per app means one entry, build input, asarUnpack line, knip
entry and guard line each. This keeps one pattern instead: Cursor's
state.vscdb read runs on the shared foreign SQLite reader entry, and the
dedicated worker, its entry and its config lines are deleted.
What moves:
- The read itself is a pure cursorProfile reader in
foreign-sqlite-readers/readers/ (was rate-limits/cursor-desktop-state-db.ts),
run only on the worker. A separate dispatch owns the new kinds and refuses
an unknown kind. The entry routes OpenCode kinds to the untouched OpenCode
dispatch, so the relay's OpenCode reader stays byte-identical.
- ForeignSqliteReaderClient gives each reader its own WorkerThreadRequestQueue
lane (own lazily started, idle-torn-down thread; one shared factory) with
in-flight dedupe per database path. Any failure resolves to the reader's
existing failure value and never falls back to the main thread.
Kept from #24572, so every reader gets them:
- Await worker retirement before respawning. Worker.terminate() cannot
interrupt a native SQLite call (e.g. a WAL-index rebuild), so the old
thread lives on until that call returns; respawning at once stacked a new
thread on the same work for every timed-out read (#24572 measured three
live workers). This belongs in the shared host, which fire-and-forgot
terminate(): LazyWorkerThreadHost now takes awaitRetirement and refuses to
spawn until the terminated worker settles, and the queue fails calls closed
meanwhile. Opt-in, because pure-JS clients (session scanner abort, port
scan) respawn right after an abort. A rejected terminate() also ends
retirement, so it cannot latch the reader off (raised in #24572's review).
- 10 s Cursor timeout, 2 consecutive deaths, a queue cap of 8.
- #24572's worker tests, rewritten against the shared client: responsive
caller plus coalesced probes, unavailable worker without path leaks,
stalled-worker recovery, no respawn before retirement, dispose settles.
Tests: reader, dispatch, client (timeout, 10 s default, crash, malformed,
unavailable without a main-thread read, dedupe, queue cap, own thread per
reader), queue retirement (stalled and rejected terminate), import boundary,
and an event-loop test reading a ~50 MB WAL with no -shm on a real worker.
* test(sqlite): walk the reader import boundary with the shared source-tree scan (STA-9122)
* fix(sqlite): key reader dedupe on a caller-supplied key, not the path alone (STA-9122)
* Keep large Markdown previews responsive
* Fix large preview review navigation and Find budgets
* Initialize preview scroll caches once and check viewport visibility
* Restore large previews after loaded rows are measured
* Refresh loaded Markdown rows after viewport changes
* Keep Markdown revisions visible and reuse bounded search text
* ci(release): publish after a skipped orcad template
#24872 skips orcad-template for tags that predate it, but a skipped ancestor
skips every job that keeps the implicit success(), so publish-release and the
post-release jobs never ran for v1.4.219.
* test: brace-free filter in the orcad downstream contract
* ci: reuse pnpm verification records in Alpine builders
* ci: qualify consumers of the verification restore action
* ci: match Linux verification cache archive paths
* ci: defer headless dependency installation until graph analysis is needed
* docs: align headless CI rollout with platform and cache policy
* test: isolate headless detector output from the parent CI step
* test(ci): list the serve mode-switch e2e job in the release-cut permissions matrix
* test(ci): expect the orcad Windows host cells in the SSH Windows hosts workflow
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Orca downloads a newer agent-state-rules.json from a fixed GitHub release (stable or next channel), validates it like the bundled rules, and applies it without a restart; a local override wins over the download, which wins over the bundled rules. A hand-started workflow from main is the only publisher; merging publishes nothing.
* test(serve): prove D7 and the profile lock across a real Electron/orcad serve switch
* ci(e2e): install ripgrep for the serve mode-switch job's window-manager wait
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(serve): run orca serve on the local orcad slot behind ORCA_SERVE_RUNTIME=orcad (T6-11)
* fix(serve): keep orcad selection app-side and wait out Windows temp cleanup
* refactor(orcad): move the data-root privacy check out of the instance lock
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* Let scheduled CI warmers wait and measure WebRTC startup
* Measure a smaller daemon shutdown fixture image
* Counterbalance WebRTC startup and verify retained fixture files
* Record CI fixture measurements and remove temporary pilots
* Clarify fixture build dependency cleanup evidence
* Make coalesced snapshot fixture delivery deterministic
* test: type the PTY write delay observer