* 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
* feat(orcad): deploy, activate and roll back orcad on Windows SSH hosts (W3)
* test(orcad): exhaustive op switch in the Windows lifecycle fake
* test(ssh): narrow the Windows host-cell descriptor by lane before building a relay cell
---------
Co-authored-by: m4air <m4air@Mac.localdomain>