* refactor(ipc): worktree handlers are local or runtime only
* refactor(runtime): explain the route witness on removal listing
* test(runtime): pin the SSH create refusal and drop the deleted branch's reliability gap
* test(runtime): drop a needless cast in the SSH create refusal test
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* refactor(layout): add the pane start, exit, first-surface and rename rules
Pure rules in the shared layout model, with no caller yet:
- startPane leaves a bound pane, or one whose start is in flight, alone;
- a process exit retires its pane on code 0, keeps today's keep cases as
exited, and only unbinds on an unproven exit or attach absence;
- a per-pane last outcome, cleared by startPane and restartPane;
- createTerminalTab/openAgentSessionTab `initial: restore | activation`;
- editor tabs and their file records follow a renamed file.
* fix(layout): keep a newborn pane's exit whatever its code, as today
* fix(layout): keep a split by today's facts and report renamed tab ids
registerRuntimeTerminalTab, hasRegisteredRuntimeTerminalTab,
focusRuntimeTerminalSurface and the mounted-tab maps now live in
runtime/mounted-terminal-tab-registry.ts. The runtime graph subscribes to
registry changes and still schedules a graph sync on mount, unmount and an
explicit leaf focus, exactly as before. No behaviour change.
The legacy Mermaid dark theme drops color from flowcharts and uses light Gantt surfaces. Dark previews now use the `base` theme with palette values read from the app's CSS tokens. Chart tokens can resolve to oklch(), which Mermaid does not accept, so colors are converted to hex through a canvas. Tests cover Gantt label contrast and distinct pie colors.
* fix(native-chat): a closed chat tab stays closed while the host is still closing it
Closing a chat tab removes it from the window at once. A tab-list frame the
host publishes before it has handled the close (a working chat's status
update, for one) still listed the chat, and the window appended it back at
the end of the strip until the host's own removal arrived.
The window now leaves out a chat whose close it has not heard back on, using
the in-flight close record it already keeps, and re-reads the host's tab list
once the close settles so a chat the host kept comes back.
* fix(native-chat): hide a closing chat tab through the existing close intent
Record a close intent for agent-session:<id> under the chat's host when a chat
tab close begins, so a host frame sent before the host handles the close cannot
re-add the chat at the end of the strip. The intent lifts when a host frame
stops listing the chat, or by its TTL. Only a failed host close clears it and
re-reads that worktree at the version already applied, so the chat the host
kept comes back.
Replaces the close-owner gate and the re-read after every close.
* fix(native-chat): end a chat close intent even when no host frame follows
Re-read the closed chat's worktree after every settled close, not only after a
failure, so a close the host had nothing new to publish for still ends its
intent; otherwise the same chat reopened within the intent's 20 s limit stayed
hidden. Skip the intent for floating-panel chats, whose frames are never
applied. Share one one-worktree local refresh with the Session History reopen
path. Reset close intents between tests in the reopened-tab e2e file, whose
harness tears the host down before a close's follow-up re-read lands.
* fix(native-chat): re-read after a successful chat close only for paired servers
This machine's host emits its removal frame before the close answers, and the
window applies it, so a local chat re-reads only when the close fails. A paired
server's frames travel apart from its answer, so, as for its terminal closes,
every close is followed by a read, and that read no longer joins a tab-list
request that began before the close. Floating-panel chats record no intent and
get no read.
* fix(native-chat): pin a chat close intent to the pairing the close began under
Record and clear the intent with one owner captured at close start, as paired
terminal closes do, so re-pairing a server mid-close cannot miss the clear, and
pass that pairing to the paired re-read.
* fix(native-chat): a new chat's effort pill keeps its first-frame value before the agent starts
A chat with no model pick runs the catalog's default model at that model's
default effort. The at-rest options answer now says so for every agent, not
only those whose live child reports the model's default, so the effort pill
no longer blanks and then jumps when the agent starts.
* fix(native-chat): read a chat's at-rest options for the folder it runs in
The at-rest options read asked the model catalog with no workspace, so it
always named the account's default model and effort, even in a repo whose
own agent config could pick another. The new chat's first frame, read for
that repo, names nothing there. The at-rest read now asks for the session's
own folder, so both frames agree on the model and the effort.
* fix(native-chat): scope the at-rest options read only for clients that take no model
A client that needs a model in every options answer (mobile today, older
desktops) refuses an answer naming none, and loses that read's commands with
it. Only a client advertising the optional-model capability gets the answer
for the chat's own folder; any other keeps today's account-default answer.
* test: run the at-rest workspace-scope RPC test in the Node SQLite project
* test: build catalog listings so the fixtures compile before and after main drops the tier map
* fix(native-chat): one at-rest rule — the chat's folder decides its default for every client
The folder-scoped catalog read now decides the default for every client. Where
it names one, the answer names that model and its effort. Where it names none,
a client that takes a model-less answer gets none, and one that needs a model
gets the account default model with no effort: exactly what it got before.
The reader is now required, and the first frame and the at-rest read share one
rule for which locations name a local folder.
* fix(native-chat): keep test callers of the host's options read untouched
Only in-process callers omit the reader at the host's entry, and they read
as the RPC gate treats an in-process caller. The shared read itself still
requires one. This leaves main's newer test call sites unconflicted.
* refactor: one native-local location check for Claude, Codex and the at-rest folder read
Nothing in production feeds the SSH PTY output intake: its only data and exit
entry points were called from tests, and the SSH PTY provider that would have
fed it is gone. Delete the intake, its source-obligation ledger, model
admission, projection publication and source-ack plumbing, and strip the
projection ids and source-credit bookkeeping they threaded through the local
renderer delivery path (accept, pending, flush, payload, accounting, exit,
session). Local terminal delivery is unchanged.
Because the intake also installed the runtime's remote source-range hooks,
this desktop host now answers a terminal.subscribe that asks for
ackOutputSourceRanges the way every orcad host already does: without the
capability, so the client uses the byte-window ACK. No source ranges were
ever attached to local output.
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(mobile): verified https pairing links; custom scheme carries no secret
The desktop's copy-link now emits https://www.onorca.dev/pair#<code>, with the
code only in the fragment. Orca Mobile claims that link as a verified app link
and refuses any pairing code delivered through orca://, which any app can claim;
orca://pair alone opens the scanner with an explanation. In-app QR scan and
paste still accept the custom scheme, so older desktops and phones keep pairing.
The confirm screen shows the desktop address and host key fingerprint before
pairing. config/verified-links/ holds the apple-app-site-association,
assetlinks.json and fallback page to deploy on www.onorca.dev, with a test that
keeps them, mobile/app.config.js and the link builder in agreement.
Part of #17397.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(mobile): refuse pairing codes nested in or normalized out of unverified links
The router unwraps expo-development-client ?url= links and normalizes dot
segments after +native-intent runs, so an orca:// wrapper could still deliver a
code to the confirm screen. Refuse any unverified link carrying code= at any
encoding depth, and match pairing routes on decoded, dot-free segments.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(mobile): escape the apostrophe in the refused-link notice
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(mobile): decode escapes byte by byte before refusing nested pairing codes
An invalid UTF-8 escape made the whole escape run fail to decode, hiding an
adjacent encoded &code= that the router still decodes leniently.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(mobile): decode nested pairing links to any depth before refusing codes
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(mobile): ignore URL-stripped whitespace when refusing nested pairing codes
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(mobile): decide pairing-link refusal on the router's own parse
Stop re-implementing URL decoding. The guard now runs expo-router's own
extractExpoPathFromURL and parseUrlUsingCustomBase, the functions its linking
applies after +native-intent, and refuses any link from which the router would
read a `code` param or reach a pairing route with a payload. A link the router
cannot parse is refused. Release builds refuse expo-development-client
wrappers outright. A property-style test walks wrapping depths, encoding
layers, stripped control characters, case and unicode, and asserts that the
guard never passes on a link from which the router would read a code.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(mobile): match pairing routes on the top-level segment only
A host link with a segment named pair was sent to the scanner.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(mobile): pin line-terminator fragment links as refused
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
* refactor(main): agent detection, automations, AI vault and ephemeral VM drop SSH provider arms
* refactor(skills): refuse SSH skill destinations at the branch and delete the relay skill services
* test(preflight): clear the local-detection mock before the SSH refusal cases
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* refactor(pty): delete the SSH PTY provider and its registry slot
Nothing in production registers an SSH PTY provider, so the registry's SSH
map was always empty: every SSH lookup answered undefined or threw the
'No PTY provider for connection' error. Delete the provider stack, its
consumer-session and source-recovery contracts, the registry maps and the
getSshProvider dependency, keeping each caller's existing result for an
absent provider. The registry now dispatches only 'local'; any other host
throws PtyHostNotDispatchableError, which keeps the renderer-matched
message for SSH ids and is never read as a gone or exited PTY.
* test(pty): keep the no-provider SSH routing cases in local-only form
* test: reword a comment naming the deleted SSH PTY provider
* test: drop an import the rebase left unused
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(daemon): keep the host's own record of refused legacy restores
* feat(daemon): the host keeps its own record of old-client restores it refuses
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(runtime): device-key authentication and per-installation key migration (host)
* fix(runtime): corrupt registry is never a revocation verdict; keyed sockets dispatch without a token; forks keep their Relay binding
* fix(runtime): keep an unparseable device registry aside; an unlisted key is never 'revoked' while it exists
* fix(runtime): a set-aside corrupt registry keeps verdicts doubtful even when the registry file is missing
* test(runtime): registerDeviceKey reaches the bound socket through the dispatcher for runtime and mobile rows
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* refactor(daemon): keep the gate's host share in its own module
* test(daemon): pin that an observing desktop's restores count against serve's budget
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* refactor(terminal): panes have two transports, local or remote runtime
* fix(terminal): keep local-only startup gates off unconverted SSH panes
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Fold the streaming dispatcher, the unary invocation helper and two
single-importer helpers into dispatcher.ts so request/response and
streaming-unary share one unary path. No behaviour change.
Co-authored-by: m4air <m4air@Mac.localdomain>
* refactor(runtime): paired sockets authenticate to a device principal
* chore: format and comment touch-ups
* test(mobile): give the launch-authority socket fixture its principal
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(daemon): cap terminals per execution host
* fix(daemon): never let a ledger cleanup throw into a spawn
* fix(daemon): recreate the host terminal ledger dir after a /tmp cleaner
* test(daemon): drop a default-parameter case from the ledger dir test
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(serve): let the owner resume paused automatic restores
The terminal daemon now answers automaticWorkStatus and
resumeAutomaticWork. Resume clears a recorded same-boot crash pause or
a pressure pause, writes the cleared state durably, and wakes restores
that were waiting. The runtime exposes runtime.automaticWork.status and
runtime.automaticWork.resume (host-admin; advertised as
runtime.automatic-work.v1), the CLI adds 'orca serve restore resume',
and a sleeping pane paused by its host offers 'Resume automatic
restores'. A daemon that predates the requests reports no gate.
* fix(serve): a stale daemon cannot resume, and an old one says so
Resume now re-reads endpoint ownership right before it runs, so a
daemon replaced by a successor cannot rewrite the successor's run
marker. A gate-bearing daemon from before resume existed is reported as
'terminal host predates resume' instead of 'no gate'; the CLI says to
run the command again after the terminal host restarts, and a sleeping
pane still resumes when the user asks for it.
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
The terminal gate's relay lister always resolved to null in production (no SSH PTY
provider is ever registered), so its relay and previous-relay branches, the legacy
relay route/router/routing, the previous-relay census and the once-connected
re-check could never run. The gate now takes only the host census; census-only
verdicts are pinned by a characterization test written before the change.
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude <noreply@anthropic.com>
On macOS a second Electron main aborts inside _RegisterApplication
before any Orca JavaScript can apply the one-Orca-per-profile rule, so
supervisors and agents retrying 'orca serve' loop on SIGABRT (#14541).
The CLI now checks the profile before it execs Electron serve. A runtime
that answers, or whose socket accepts, is live; one whose socket neither
accepts nor refuses, or that refuses this CLI's credentials, is
unverifiable; both refuse with exit code 3, the single-instance code
systemd units already key off. Only a definitive refusal (ENOENT or
ECONNREFUSED) lets it start. A fresh profile keeps the old synchronous
launch. A macOS startup abort is remembered per environment, so a later
separate 'orca serve' from the same launchd session refuses for 30
minutes with exit 78 instead of aborting again; --force overrides, and
a serve that reaches readiness clears it.
Adapted from #14768; the Launch Services diagnostic wording and the
exit code 3 contract come from #14542.
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: thiagomsoares <5190162+thiagomsoares@users.noreply.github.com>
* feat(terminal): declare restore intent and keep deferred panes sleeping
The visible pane's agent restore is sent as user-resume and hidden ones
as automatic-restore, to hosts that advertise terminal.spawn-intent.v1
(and always on the local spawn path). When the host keeps a restore
asleep, the pane shows 'Sleeping — click to resume' with the reason,
keeps a sleeping record so the session stays listed and resumable, and
resumes as the user's own when it is opened or clicked. A deferred pane
is not remounted, which would only be deferred again.
* refactor(shared): one restore spawn intent type
* fix(terminal): a deferred pane owns its session against wake sweeps
A deferred pane has no PTY, so the activation and mobile wake sweeps
read its unfinished record as unowned and could launch the session in
a new tab while the pane still held a resume. The sweep now treats a
deferred pane as the owner, the remembered record is a quit-style
record a sweep never discards, and a retry declines to resume a session
that is already live in another pane.
* fix(terminal): keep a deferred pane's claim through its sweep and retry
The wake sweep now leaves a deferred pane's record alone, since that
pane's own queued resume matches it and is not a duplicate. A retry
keeps the pane registered as the session's owner until its PTY binds,
and declines to resume when another tab already has the same session
queued.
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(updater): let supervised macOS serve installs stage Squirrel during install
Supervised `orca serve` keeps autoInstallOnAppQuit off, so electron-updater's
MacUpdater hands the download to Squirrel.Mac only inside quitAndInstall. The
updater, however, held the status at "downloading 100%" and gated quitAndInstall
on Squirrel having already staged the bundle. Neither could happen first, so
every macOS serve update stalled at macos_waiting_for_squirrel, remote installs
failed with remote_update_not_downloaded, and a local install request timed out
and quit without installing.
In supervised serve mode, report the download as installable and let the install
proceed to the handoff and native quitAndInstall. The install commits and arms
the exit watchdog when Squirrel signals it has staged the bundle; a staging
failure still recovers through the existing pre-commit error path.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(updater): hold destructive install prep until Squirrel stages the serve bundle
The supervised macOS install now calls electron-updater's quitAndInstall before
Squirrel has staged anything, and that staging completes asynchronously. Three
consequences needed handling:
- PTY cleanup and close-listener removal ran before staging, so a Squirrel
failure recovered the server with its in-process sessions already killed.
They now run when Squirrel reports the bundle staged, together with the
commit and exit watchdog.
- Any updater 'error' during staging (for example a background check) failed
the handoff while MacUpdater's pending listener would still quit and install.
While staging is awaited, only Squirrel's native error ends it.
- Nothing bounded a Squirrel that never answers. After two minutes the install
recovers through the existing pre-commit failure path and the server keeps
serving.
isMacStagingDeferredToInstall is now darwin-only, so Linux supervised installs
keep their immediate commit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(updater): report a slow Squirrel staging instead of abandoning the install
Recovering the install on the staging timeout reset Orca's state and failed the
supervisor handoff, but electron-updater's MacUpdater keeps its own completion
listener. A Squirrel that finished after the timeout still quit the app and
installed, now with a failed handoff, so the supervisor skipped the replacement
spawn.
The timeout now only reports a non-retryable error status and records the slow
staging; the handoff and in-flight install stay live so a late staging commits
and relaunches normally.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(updater): commit a staged serve install before its session cleanup
Squirrel's update-downloaded listeners run in registration order, and Orca's
runs before the one MacUpdater adds to quit the app. The staged-install commit
ran PTY cleanup first, so a throwing cleanup callback skipped the commit, the
exit watchdog, and MacUpdater's quit, leaving the install stuck in progress.
Commit and arm the watchdog first, then run cleanup under the same
post_commit_cleanup_failed handling performQuitAndInstall already uses.
The tests now register MacUpdater's persistent quit listener per unstaged
install, so a retried install is followed through completion.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(updater): pin the MacUpdater staging behavior supervised serve installs rely on
The supervised macOS serve install assumes electron-updater's MacUpdater starts
Squirrel staging only inside quitAndInstall when autoInstallOnAppQuit is off,
and quits the app once staged when autoRunAppAfterInstall is off. Every updater
suite mocks electron-updater, so run the installed MacUpdater methods directly;
an upgrade that changed either behavior now fails here instead of silently
restoring the deadlock.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(updater): adapt the serve staging tests to current main
Main's macOS quit-guard test predates the staging callbacks this change
adds, so it now passes them, and the new install test builds its window
without a type assertion.
Co-authored-by: jbamlee <dev.jbam@gmail.com>
---------
Co-authored-by: jbamlee <dev.jbam@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: m4air <m4air@Mac.localdomain>
The legacy remote-server help text promises that one manual update enables remote updates, even when the server reports its updater is unavailable. Replace the promise with accurate host-side update guidance in every supported locale and cover the fallback and specific help branches.
Refs #22261
Co-authored-by: Oliver Mee <102673257+oliver-mee@users.noreply.github.com>
* fix(serve): keep the isolated profile off the login keychain
The E2E/pairing runtime hands the app a fresh HOME, so there is no login
keychain for OSCrypt to read. On the serve path the secret-protection report
runs inline before readiness and probes safeStorage on the main thread, where
Chromium's keychain lookup creates the item and waits on an authorization
reply that never arrives, so `orca serve` never advertises (#25453).
The sidecar already launches with --use-mock-keychain for exactly this
profile; share that decision and give the foreground serve process the same
switches.
* test(serve): read spawn args without type assertions
Co-authored-by: Paolo <paovalletta@hotmail.it>
* fix(serve): only an isolated userData profile drops the keychain
The sidecar always runs on a fresh profile, so either E2E variable is
enough there. The foreground serve process opens the selected profile's
sealed secrets, and a HOME override alone still selects the user's real
profile, so it now needs ORCA_E2E_USER_DATA_DIR.
Co-authored-by: Paolo <paovalletta@hotmail.it>
---------
Co-authored-by: Paolo <paovalletta@hotmail.it>
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(sidebar): stop a removed folder workspace from leaving a blank row
A folder-project workspace exists only as its worktreeMeta row. When it is
deleted while a terminal is still bound, the renderer keeps the row until its
teardown runs, and a PTY reattach in that window stamps lastActivityAt through
worktrees:updateMeta. setWorktreeMeta then minted a default row with an empty
name, which the sidebar listed under the project name and which came back after
every delete. The metadata IPC now refuses to create a row for a folder
workspace instance that no longer exists.
Fixes#22712
Claude-Session: https://claude.ai/code/session_01XZXEdbC4RKp288k2gBzLUW
* fix(sidebar): also refuse runtime writes to a removed folder workspace
Move the existence check into a shared predicate that matches any same-id
folder owner, so an owner at a different path on another host cannot bypass
it, and apply it to the runtime's worktree.set path, where a resolution
snapshot taken before the removal still returns the workspace.
Claude-Session: https://claude.ai/code/session_01XZXEdbC4RKp288k2gBzLUW
* test: type the removed-folder-workspace fixture meta for the anti-slop lint
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(runtime): accept a declared spawn intent from paired clients
Paired clients can now say whether a terminal restore is the pane the
user is looking at (user-resume) or a hidden one (automatic-restore).
The host forwards the intent to its fork gate, advertises
terminal.spawn-intent.v1 so clients only send it to hosts that accept
it (terminal.ensureAgentSession params are strict), and reports a
deferred fork as terminal_spawn_deferred with its reason.
No client sends the field yet; that lands next with the sleeping-pane
handling.
* fix(daemon): a claimed agent resume cannot declare itself interactive
Interactive forks skip the gate, and paired clients can now declare
intent, so the host keeps inferring from the claim when a request
says interactive.
* fix(runtime): clients may only declare restore intents
A daemon kept running across an update still lets a declared
interactive request skip its gate, even for a claimed resume. The RPC
and local IPC now accept only user-resume and automatic-restore, and
the daemon request boundary turns a claimed interactive into an
automatic restore.
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
The pane listener subscribed to 'orca:wake-hibernated-agents-worktree' while the
dispatcher fires WAKE_HIBERNATED_AGENTS_WORKTREE_EVENT ('orca-wake-...'), so the
in-place wake never ran. Extract the listener and bind it to the shared constant;
the dispatcher test now drives the real listener instead of a stand-in.
Co-authored-by: m4air <m4air@Mac.localdomain>
orcad now checks its flags with the same validator Electron serve and the
CLI use, so contradictory pairing flags fail with the same message instead
of one silently winning. The CLI launcher drops its duplicate recipe check
(the CLI handler already ran the shared validator).
Removes the daemon-init and cli/runtime/index re-export barrels and the
parsePtySessionId / OrcadInstanceLockError re-exports; callers and mocks
import the defining modules.
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(cli): extract the serve supervisor's after-exit decision into a pure policy
* refactor(cli): type the exit signal without a child_process import
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(runtime): reuse cached worktree rows when the admin probe cannot answer
* test(runtime): wait for the fingerprint probe to settle instead of a fixed delay
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* feat(daemon): process-growth breaker that pauses automatic restores per host and names the agent
* fix(daemon): breaker trips only on sustained growth, pauses in memory, observes on desktop
* fix(daemon): sample fast only while a tree is rising or tripped
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
* fix(serve): report secrets unavailable instead of hanging on an unreachable macOS keychain
* fix(serve): classify keychain probe by exit code, skip under a mock keychain, ratchet direct safeStorage imports
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Nothing mints an SSH-bridge credential since the relay client was removed
(#27214), so the 'ssh-bridge' caller kind, its host binders, result filter,
the CLI bridge-mode policy and the ORCA_SSH_BRIDGE_CREDENTIAL env read could
never run. The allowRemoteCliControl target field stays for older peers.
Co-authored-by: m4air <m4air@Mac.localdomain>
Removes seven modules that only their own tests import, dead orcad exports
and protocol constants, spells orcad's configuration exit code once, reuses
the shared errorMessage helper, and drops links to the deleted
docs/reference folder.
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(daemon): observe-only fork gate for automatic terminal restores
* fix(daemon): keep a canceled fork charged until reaped; never strand a user resume
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
The relay client is gone, so the three relay-ladder cells and the
@orcad-cli-relay-kept matrix case could not run. Delete them, their
last helper (ssh-test-target-connection), a stale path filter and the
unused build:relay step; rename the runner to invoke-windows-host-cells.ps1.
Co-authored-by: m4air <m4air@Mac.localdomain>