Commit Graph
14957 Commits
Author SHA1 Message Date
Jinwoo Hong 93ed192025 The window's layout stream reconnects after a drop; a retried quit still sends resume records (dark, layout-owner build only) (#30380)
* chore(layout): the drift check's ignore comment names every main-only kind (dark, layout-owner build only)

* fix(layout): a quit stage retried after a failed one still sends the resume records (dark, layout-owner build only)

* feat(layout): the window's local layout stream reopens after a loss, and its snapshot redraws every workspace (dark, layout-owner build only)
2026-10-18 10:25:37 -07:00
Neil 447c4a0fb2 refactor(ipc): import worktree, watcher and runtime-environment helpers from their owning modules (#30375)
Removes the re-export lines in worktree-logic, worktree-base-directory-poller, filesystem-watcher and
runtime-environment-transport-routing. Test mocks that supplied a re-exported name now mock the
module that defines it, so they still reach the code under test.
2026-10-18 09:39:14 -07:00
Neil 9905da80cc refactor(runtime): import runtime helpers from their owning modules, not re-export shims (#30373)
Removes the re-export lines in 22 src/main/runtime modules (rpc schemas, skill surface, worker
identity, terminal viewport, teardown, git, e2ee crypto and more); importers and test mocks name
the real modules.
2026-10-18 09:28:51 -07:00
Neil b1adb89157 refactor: import renderer runtime, shared remote-runtime and orcad helpers from their owning modules (#30370)
Removes the re-export lines in runtime-rpc-result (hasRuntimeRpcErrorCode), sync-runtime-graph,
sync-key, the terminal orphan-recovery modules, orcad-idle-exit, remote-runtime-subscription-transport,
two orcad modules and the ssh-connection test harness; importers and test mocks name the real modules.
2026-10-18 09:14:07 -07:00
Neil e1b2d58273 refactor(ipc): import ipc helpers from their owning modules, not re-export shims (#30369)
Deletes local-agent-install-dir-detection, notification-burst-cooldown, terminal-git-credential-guard
and tui-agent-detection-commands (pure re-export modules) and the re-export lines in seven more
ipc modules; importers and test mocks name the real modules.
2026-10-18 08:40:12 -07:00
Neil 1938bd055a refactor(ipc): group SSH and runtime-environment IPC handlers into ipc/ssh/ and ipc/runtime-environments/ (#30362)
git mv plus import, vi.mock and path-literal rewrites; e2e route regexes and the Windows host lane
filter follow the moved handlers.
2026-10-18 08:11:52 -07:00
Neil 658953dc23 refactor(ssh): group system-ssh transport, ssh config and remote exec into ssh/{system-transport,config,remote-exec}/ (#30355)
git mv plus import, vi.mock and path-literal rewrites; one e2e route regex follows the moved
dynamic-forward process.
2026-10-18 07:26:10 -07:00
Neil d7aea6dc28 refactor(managed-server): move host state (state locks, Windows host ops, machine homes) into src/main/managed-server/host-state/ (#30347)
orcad-state-*, orcad-windows-host-* and orcad-machine-* leave src/main/ssh. git mv plus import and
path-literal rewrites, including the Windows host lane's test path in its workflow and PowerShell
runner.
2026-10-18 06:39:56 -07:00
Neil 506aa03195 refactor(managed-server): move the managed server's lifecycle into src/main/managed-server/lifecycle/ (#30343)
orcad-managed-*, orcad-runtime-*, orcad-stdio-bridge-*, orcad-decommission-* and orcad-rollback-*
leave src/main/ssh. git mv plus import and path-literal rewrites; two e2e route regexes learn the
new folder. orcad-runtime-maintenance stays for now because open #29834 edits it.
2026-10-18 06:01:46 -07:00
Neil d38299290d refactor(managed-server): move the managed server's install and deploy code into src/main/managed-server/install/ (#30335)
orcad-remote-*, remote-install-*, remote-node-runtime-store-*, remote-versioned-install and
remote-deploy-timing leave src/main/ssh. git mv plus import and path-literal rewrites; one e2e route
regex learns the new folder. orcad-remote-deploy and orcad-remote-node-runtime-report stay for now
because open PRs #29834 and #29829 edit them.
2026-10-18 05:20:19 -07:00
Neil 50c06d572a refactor(ssh): move port forwarding into ssh/port-forwarding/ and hostile-host harnesses into ssh/hostile-host-test-support/ (#30277)
git mv plus import, path-literal and workflow path-filter rewrites only.
2026-10-18 04:35:04 -07:00
Neil aa07d5891a fix(mobile): break the transport and terminal-document import cycles, and gate cycles after mobile's install (#30290)
* fix(mobile): break the transport and terminal-document import cycles and gate them after mobile's install

client-context re-exported the host-client hooks, which import client-context back: the re-export
barrel is gone and importers (and their test mocks) name host-client-hooks directly. In the terminal
document, the cell-metric getters move to a leaf cell-metrics module and select-mode entry/exit to
selection-mode, so fit, transform, overlay and range no longer import each other. pr.yml lints imports
before mobile's install, when mobile's tsconfig can't load, so Mobile verify now runs the same import
rules over mobile after its install with zero warnings allowed.

* fix(mobile): the browser-pane render harness imports useHostClient from host-client-hooks

Its route source is a template string, so no typecheck saw the removed client-context re-export; the mobile web bundle check did.

* fix(ci): the e2e typecheck ratchet counts the same with or without mobile's install

Specs reach mobile/src/transport, whose expo-crypto and async-storage imports resolve only after mobile's install and then load React Native's globals (numeric timers, a required NODE_ENV), adding errors in unrelated specs. An empty stub pins both, so the static job reads 232 either way.
2026-10-18 04:00:24 -07:00
Neil c82cf2b35d fix(mobile): a session resumed from the phone's history shows its conversation before the first new turn (#10923) (#30283) 2026-10-18 04:00:18 -07:00
Neil 0627cd2bd6 refactor(managed-server): move orcad activation into src/main/managed-server/activation/ (#30320)
First slice of the desktop side of managed orcad leaving src/main/ssh. git mv plus import and
path-literal rewrites; host-lane workflow filters and the cross-host prefix list gain the new folder.
2026-10-18 03:59:34 -07:00
Neil db17b33ef9 ci: ratchet the legacy relay fence (importers of ssh/legacy-relay/ and COMPAT(legacy-relay-bridge) seams) (#30317)
Both lists may only shrink, so the 2027-01-15 retirement edits a known set of files.
2026-10-18 03:41:49 -07:00
Neil 2d1ec53533 refactor(ssh): fence the legacy relay in ssh/legacy-relay/ and drop the relay name from live deploy primitives (#30292)
Moves legacy-relay-bridge/ plus the relay-only census and endpoint files into ssh/legacy-relay/,
so the 2027-01-15 retirement deletes one folder. Live install, exec and framing modules that only
carried the relay name become remote-*. git mv plus import, path-literal, routing and workflow
path-filter rewrites only; no remote file name or path changes.
2026-10-18 03:17:41 -07:00
Neil 85d634cc58 fix(settings,status-bar): show access revoked / update required for paired servers (#30280)
* fix(settings): show one coherent status for servers that revoked this computer

* fix(settings): drop the redundant warning icon on revoked server rows

* fix(status-bar): show access revoked / update required for paired servers

A server that revoked this computer's pairing (or refused it as incompatible)
read as a plain "Disconnected" row with a futile Connect action, and the
aggregate segment stayed idle grey. Rows now take the execution-host registry's
blocked verdict: "Access revoked" with a Re-pair… action opening the existing
RuntimeRepairDialog, or "Update required" with the compat detail. A blocked
host turns the aggregate indicator destructive instead of hiding as idle.
2026-10-18 03:13:08 -07:00
Jinwoo Hong fc24ac3715 Window saves stop carrying tab and pane layout; main keeps its own (dark, layout-owner build only) (#30282)
* fix(layout): an SSH pane's terminal binds in its own session partition (dark, layout-owner build only)

Main keeps its own layout over a window save, so a binding only a save carries is lost. A window
or runtime spawn of an SSH pane bound in the local partition; it now binds where the pane's layout
lives.

(cherry picked from commit beb2275b45)

* test(layout): the SSH binding test uses the shared spawn commit dependencies

(cherry picked from commit 672b641897)

* fix(layout): main moves a tab between a local and an SSH workspace itself (dark, layout-owner build only)

moveTabToWorkspace across two partitions was refused as other_partition and left to the window's
save. Main now reads both partitions, moves the tabs as within one, and writes both in one durable
mutation.

(cherry picked from commit ee27a0bb07)

* chore(layout): one binding write for the partition choice; shipped builds keep their exact replaced-binding read

* fix(layout): window saves keep main's layout and give it only the window's view and facts (dark, layout-owner build only)

windowViewSaveForMain/windowViewPatchForMain replace windowSaveForMain: main's own layout joined
with the window's view, facts and carried fields, written only into the records that change. A
paired server's partition passes through. A visited workspace main holds keeps its terminal row
(D1). The P10 pending case is on.

(cherry picked from commit 0c2fc15974)

* fix(layout): the save divergence detector becomes a report-only drift check behind its log (dark, layout-owner build only)

It no longer wraps the write: it compares the window's raw save with main's layout model, and
only when ORCA_LAYOUT_SAVE_DIVERGENCE_LOG is set.

(cherry picked from commit 6bc1e5556f)

* fix(layout): tab reconcile and terminal reconnect stop writing tab structure (dark, layout-owner build only)

Main's frames draw the tab bar and rows: reconcile still returns its counts but writes nothing,
and reconnect still advertises restored terminals but leaves the rows to main.

(cherry picked from commit ef8eb625ca)

* fix(layout): a layout command main cannot apply is a logged refusal, not the window's own change (dark, layout-owner build only)

other_partition, a thrown call, and host_not_owned for a workspace that is not a paired server's
are refused and logged: a window save no longer carries the change, so drawing it would last only
until the next frame. A twin main may route to a paired server keeps today's path, as does the
first terminal's host_not_owned fallback.

(cherry picked from commit 2c513b2d10)

* fix(layout): the window's refusal code type keeps main's host refusals

(cherry picked from commit 36d46bdcc2)

* fix(layout): the quit checkpoint records only the quit capture's resume records in main (dark, layout-owner build only)

Main keeps its own resume records over a window save, so the quit capture's changes, which reach
main as async commands, could miss the quit. The capture now sends only what it changed with the
synchronous stage, and main writes them through the record-only sleep command before staging; a
wake main recorded that the window had not seen stays.

(cherry picked from commit 2a0f433c34)

* test(layout): the quit capture test builds a typed resume record

(cherry picked from commit d92d1246ee)

* chore(layout): one layout write per save handler

* chore(layout): shipped builds keep their exact quit capture

* fix(layout): the drift check compares structure only, not records main writes itself (dark, layout-owner build only)

Pane bindings and resume records, default-tab marks, closed-tab records and terminal row owners
are main's own writes; a save that has not caught up with them asks main for nothing, so they are
no longer reported.

(cherry picked from commit 93e8b2627c)

* test(layout): relaunch first-terminal cases, and the side-by-side resume case moves its tab the way the window does

(cherry picked from commit ab381332b1)

* test(layout): the relaunch case also checks a reopen that cleared read-only

(cherry picked from commit bbf3d040c8)

* docs(layout): the drift check names the record kinds it ignores

* revert(layout): drop the SSH binding partition change; SSH terminal starts are refused before any binding is saved

getProvider refuses every non-local host, so neither spawn path reaches persistPtyBinding for an
SSH pane, with the switch on or off.

* test: run A2's two real-SQLite session tests in the Node runtime project
2026-10-18 02:56:38 -07:00
Neil 10505696a2 ci: ratchet tests/ type errors so a broken spec import can't land unnoticed (#30286)
tests/ is typechecked by nothing in CI, so the Windows CLI matrix spec imported a helper that never existed (#30231). Per-file error counts under tests/ (tsc -p config/tsconfig.e2e.json) may now only go down.
2026-10-18 02:35:04 -07:00
Neil 019417bd86 refactor(ssh): import the system-ssh and ssh -G modules directly, not through re-export shims (#30255)
Deletes ssh-system-fallback.ts and the re-export lines in ssh-config-parser.ts, ssh-connection.ts,
system-ssh-file-binary-transfer.ts and ssh-remote-powershell.ts; importers name the real modules.
SshConnection tests mock each real module, keeping the parser stub that holds ~/.ssh/config out.
2026-10-18 02:34:30 -07:00
Jinwoo Hong 383513b8bb SSH pane terminals and local-to-SSH tab moves reach main directly (dark, layout-owner build only) (#30281)
* fix(layout): an SSH pane's terminal binds in its own session partition (dark, layout-owner build only)

Main keeps its own layout over a window save, so a binding only a save carries is lost. A window
or runtime spawn of an SSH pane bound in the local partition; it now binds where the pane's layout
lives.

(cherry picked from commit beb2275b45)

* test(layout): the SSH binding test uses the shared spawn commit dependencies

(cherry picked from commit 672b641897)

* fix(layout): main moves a tab between a local and an SSH workspace itself (dark, layout-owner build only)

moveTabToWorkspace across two partitions was refused as other_partition and left to the window's
save. Main now reads both partitions, moves the tabs as within one, and writes both in one durable
mutation.

(cherry picked from commit ee27a0bb07)

* chore(layout): one binding write for the partition choice; shipped builds keep their exact replaced-binding read

* revert(layout): drop the SSH binding partition change; SSH terminal starts are refused before any binding is saved

getProvider refuses every non-local host, so neither spawn path reaches persistPtyBinding for an
SSH pane, with the switch on or off.
2026-10-18 02:25:45 -07:00
Neil 3501ea935d fix(daemon): OMP's prompt-bubble markers no longer trip the dead-app repair check (#10923) (#30285) 2026-10-18 02:18:59 -07:00
Neil ddf4e6bdf2 fix(terminal): avoid duplicate snapshot replays after reveal (#30205)
Retain reveal sequence coverage until a parsed snapshot covers it, preventing a duplicate text-only replay from clearing newer terminal images. Keep conservative fallback recovery for unknown episodes, missing metadata and different terminal processes.

Verified against current main: 406 tests, full application typecheck, changed-code quality and four fresh hidden rendered restore checks pass. No xterm patches or dependency changes.
2026-10-18 02:04:28 -07:00
Neil 0249174cb9 refactor(runtime): import mobile-cloud-relay and browser-host helpers from their owning modules (#30279)
Removes the re-export lines in relay-region-preference, relay-session-broker,
browser-host-page-placement and browser-host-page-reconciliation-plan (no barrels).
2026-10-18 01:58:25 -07:00
Neil c30753c739 fix(runtime): show "Re-pair required" for revoked servers and re-pair in place (#30271)
* fix(runtime): show Re-pair required for revoked servers and re-pair in place

A server that revokes this computer's pairing token was labeled "Update
required" because auth refusals and protocol mismatches shared one blocked
state. Carry the blocked reason locally, label revoked hosts "Re-pair
required", and add a Re-pair action (sidebar host menu + Settings server
row) that verifies a new pairing link reaches the same server before
replacing the saved pairing.

* fix(sidebar): stop host header menu clicks from toggling or dragging the row

* fix(sidebar): vertically center host header label and menu button
2026-10-18 01:55:08 -07:00
Neil acc235187f refactor(runtime): move runtime/browser-host-* into runtime/browser-host/ (#30275)
git mv plus import and path-literal rewrites only.
2026-10-18 01:42:31 -07:00
Jinwoo Hong 4005884fe5 Main routes a project registered on two machines to the same owner the window saves to (dark, layout-owner build only) (#30196)
* refactor: move the contested-workspace primary-host rule to src/shared (move only)

* fix(layout-owner): main routes a twin repo's workspace to the same primary host the window saves to

* fix(layout-owner): route a twin repo's single-host worktree to the host that holds it; hydrate twins the same way

* fix(layout-owner): twin-repo routing counts only runtime owners from the catalog, matching the window; one table checks both sides

* fix: drop the duplicate layout-owner switch import after merging main

* fix: type the twin-routing fixture and partition set
2026-10-18 01:41:22 -07:00
Neil 677d127e97 fix(terminal): an app's own OSC 133 zone close no longer ends the agent's turn (#10923) (#30273)
OMP ends every user bubble with OSC 133 B C D;0 to close its own prompt zone.
Orca read that D as the shell's command finishing, retired the pane's hook
authority mid-turn and deleted its status row, so the phone's chat view lost the
provider session it reads the transcript by. A D;0 directly after B C is now an
app's zone close, not a command exit.
2026-10-18 01:36:42 -07:00
Neil ecb1d6859c refactor: compatibility folders name their entry modules instead of an index barrel (#30269)
Deletes remote-layout-snapshot/index.ts and workspace-layout/old-client/index.ts. The compat-boundary
check now lists each folder's entry modules, so deleting the folder plus its listed importers'
import lines still removes the path.
2026-10-18 01:36:12 -07:00
Neil 2c12c1edf1 refactor(runtime): move runtime/relay to runtime/mobile-cloud-relay (#30274)
The folder is the cloud relay that reaches phones; under its old name it read as the legacy SSH
relay. git mv plus import and path-literal rewrites only.
2026-10-18 01:35:40 -07:00
Neil 5229ef804e test: tighten the round-2 parity, serve and watcher tests (#30267)
Parity test: one string-skip helper, no infinite loop on an unterminated block comment, no internal shorthand. Serve test: orcadServeArgs takes a bindHost instead of the test splicing argv, typed readiness, and stderr back in the daemon failure. Watcher test: a sentinel at both watched levels.
2026-10-18 01:30:22 -07:00
Neil 8721b9c755 refactor(orcad): import orcad helpers from their owning modules, not re-export shims (#30265)
Deletes orcad-runtime-lifecycle.ts and the re-export blocks in orcad-managed-tunnel,
orcad-local-build-hash, orcad-remote-launch, orcad-remote-node-runtime, orcad-update-plan,
relay-protocol and shared/orcad-migration-manifest; importers and test mocks name the real modules.
2026-10-18 01:29:57 -07:00
Neil a261091cd6 refactor: drop the runtimeWorktreeIdsEqual alias and name the WSL hook relay gate for what it gates (#30264)
Importers call worktreeIdsEqual from shared/worktree/id directly (the alias was a renamed
re-export). isRemoteAgentHooksEnabled becomes isWslAgentHookRelayEnabled; the env var and its
parsing are unchanged. ws-transport inlines its one-line HTTP server factory, and a duplicated
acquisition-id doc comment goes.
2026-10-18 01:27:32 -07:00
Brennan BensonandOrca Worker 407bf039c1 Session History: find every agent's older sessions in Workspace and Project views (#29977)
* fix(session-history): find every agent's older sessions in Workspace and Project views

Session History kept only the newest sessions across every agent, then filtered
by workspace; only Claude, Pi and CodeBuddy got their older in-scope sessions
back. Every agent now declares how its cwd is found without a full parse, and
the scan selects in-scope sessions before the recency cap: Codex and other
header agents by their opening record, SQLite stores by their directory column,
the rest by their cached parse. The scan and the cached-list cut share one
scope rule.

* fix(session-history): keep discovery under the file length limit

* fix(session-history): type the scope walk's file list

* Keep session history scope complete before applying the display cap

* test: align session history scope fixtures

* perf(session-history): settle known out-of-scope transcripts without a per-file read

A scoped scan walks every transcript, and each one cost an await, a parse-cache
database lookup and, for Codex, two head reads every scan. Remember each file
version's settled cwd (from its opening records or its parse), drop settled
out-of-scope files synchronously before the async walk, and read Codex's
roughly 20 KB first record in one 64 KB read.

* fix(session-history): let the parse cache decide scope before transcript heads

The settled-cwd prefilter let a transcript-only verdict reject files whose
current parse (hot or cold) says otherwise: a Cursor chat whose meta.json
appeared later, or a Codex session whose parsed latest cwd moved after its
row left memory. Restore parse-cache-first selection; keep Codex's single
64 KB first read.

---------

Co-authored-by: Orca Worker <orca-worker@localhost>
2026-10-18 01:19:14 -07:00
Brennan Benson 6fd2172b3f feat(runtime): remove an agent's downloaded runtime only once nothing on the host can still run it (#29139)
* feat(runtime): remove an agent's downloaded runtime only once nothing on the host can still run it

managedRuntime.remove {agent} (host-admin, capability managed-runtime.remove.v1)
deletes the agent's releases inside the launch gate. Before anything is deleted the
gate aborts starts under way (chat starts and conversation copies), stops the
agent's loaded chats on this host, and proves every retained child gone: failed
chat starts and sign-in children whose close was never proven. Every close settles
before the gate releases; if any owner stays unproven, Remove fails and keeps the
files. Stopping chats by agent is now one generic host helper that sign-in shares.
Install refuses while a removal runs, Remove refuses while an install runs, and a
removal cannot be cancelled.

* fix(runtime): status says whether a copy is there to remove, damaged copies included

canRemove is set whenever Orca's copy is present, whole or damaged, so Settings offers Remove for a
damaged copy too. The failed-start retain is dropped: the launch gate already holds every child it
admitted until it exits.
2026-10-18 01:15:11 -07:00
Neil e770ec3c44 test(runtime): compare macOS tmpdir paths by realpath in create-intent and clone tests (#30268) 2026-10-18 01:15:07 -07:00
Neil 06fbf8f450 refactor(terminal): drop remote-pty checks isRemoteExecutionHostPtyId already covers (#30256)
Since #30232 it accepts null and covers both remote: and app SSH ids, so the extra isRemoteRuntimePtyId / parseAppSshPtyId / null guards never change the result.
2026-10-18 01:13:19 -07:00
Jinwoo Hong 9bd47de3cf feat(sidebar): after a restart, the host clears sort tiers nothing backs any more (dark) (#30259)
* feat(sidebar): sort stamps reconcile stored tiers at startup against live hook rows and terminals (dark)

* test(sidebar): a restart clears an unbacked local tier and keeps an SSH host's

* fix(sidebar): run the sort tier reconcile once hook rows and PTYs settle, seeding hydrated rows

* fix(sidebar): clear a stored tier only on proof its terminals died; a rest seed adds no clear

* chore(sidebar): merge origin/main; locality helper moved to shared
2026-10-18 01:09:06 -07:00
Neil 58ce3f5eb4 refactor(git): the common-dir check uses areWorktreePathsEqual (#30263)
Its private POSIX copy predates areWorktreePathsEqual's POSIX guard and WSL UNC fold, which now give the same answers; the one difference is macOS treating /tmp and /private/tmp as one directory, which they are. Also reuse looksLikePosixAbsolutePath in the frozen comparison key.
2026-10-18 01:04:34 -07:00
Neil 7121917a66 fix(ssh): two overlapping update checks never both try a host the first one just failed on (#30253)
failedBefore read the recorded failure before the host lock, so a check waiting behind one that failed still tried the update and noted a stale reason. Rename retryRecordedFailure to failedThisLaunch and read both inside the lock. Also share withDetail and drop a test that could not fail.
2026-10-18 01:02:14 -07:00
Jinjing 2d0fa9368f Scope tab-group shortcuts and pane actions to the focused split (#30258)
Every split pane's tab strip stays mounted, so focusing a pane used to add or remove its action buttons and reflow the tabs. Quick-command shortcuts also fired from hidden or unfocused groups.

- Keep the Pane Actions and quick-command buttons mounted in every strip. Unfocused strips dim instead of disappearing, so focus no longer reflows the tabs.
- Hide the button labels by strip width with container queries, so narrow split groups stay icon-only.
- Only the focused, visible group registers quick-command keyboard and Electron shortcut listeners. An open menu closes when its group loses focus.
- Add "Close split pane" to the tab context menus, shown only when the group is one of several splits.
- Stop Radix from restoring focus to a stale group when the pane actions menu closes.
2026-10-18 00:54:58 -07:00
Neil a2946f0a65 chore(worktree): composeWorktreeId plus a ratchet on hand-built worktree ids (#30238)
Worktree ids built as `${repo.id}::${path}` by hand are how one worktree got two
spellings (#30150). New code composes them through src/shared/worktree/id.ts; the
ratchet counts the remaining hand-built ids per file (18) and may only go down. Six
byte-identical `${repo.id}::${repo.path}` sites move to getRepoMainWorktreeId.
2026-10-18 00:51:41 -07:00
Neil 8f86ccf764 fix(ssh): refuse a migration request too large for the host's sealed frame before sending it (#30249)
A manifest under the 768 KiB validation cap can still overflow the host's 1 MiB inbound
frame once sealed (base64 adds a third), more so when a commit carries its blob list. The
host answers such a frame by closing the socket, so the move failed with a lost answer.
The catalog client now measures the request against REMOTE_RUNTIME_MAX_INBOUND_REQUEST_JSON_BYTES
and refuses it with the existing 'too large' guidance, unsent.
2026-10-18 00:50:59 -07:00
Brennan Benson 29a43a73ed feat(antigravity): sign Antigravity chats in with the server's own Google sign-in (#28650)
* feat(antigravity): sign this host's Antigravity chats in with the server's own Google sign-in

Start spawns the Antigravity ACP server exactly as a chat start would (pinned
runtime, private temp, owner-only chat folder), behind the launch gate that
first stops this host's running Antigravity chats, and asks it to authenticate
with oauth-personal. A host without a pinned server build refuses Start, as it
refuses chats. The server's sign-in line now yields its link (validated as
Google's sign-in page back to a loopback port here) instead of ending the
connection signed out. Link long-polls the flow's state (25 s, early on change),
Cancel ends it, a new Start replaces it, and it expires after 300 s. All run on
the execution host behind accounts.antigravity-chat-sign-in.v1 and need
accounts-admin. List reports chatSignIn {saved, signingIn}; saved is a stat of
the server's own token file, which Orca never reads.

* Retain unclosed sign-in children and detach ended polls

* Narrow sign-in regression launch fields

* Keep fake sign-in fixtures independent of host support

* fix(antigravity): chat sign-in never installs the server and keeps its flow on the shared revisioned state

Sign-in resolves the server exactly as a chat start does and fails with the
not-installed reason when no copy is found, instead of downloading one. Its
flow state is a RevisionedState, the same publish-and-wait primitive the
runtime installer uses; replacement, close proof and the Link wire are unchanged.

* fix(antigravity): the chat sign-in status names the running sign-in, so a client that comes back can follow and cancel it

chatSignIn gains an optional flowId while a sign-in runs. Before, a sign-in nobody watched held the
chats' fence for up to 5 minutes and no client could see or cancel it.

* feat(antigravity): clients follow this host's chat sign-in by revision, as they follow an install

* fix(antigravity): name the sign-in state apart from the sign-in function so the module parses

* fix(antigravity): chat sign-in status is pushed to subscribers, failures read as plain sentences

accounts.antigravityChatSignInSubscribe (no params) sends the full sign-in
status as a snapshot on subscribe, then one frame per state revision, and
closes with the transport. It replaces the accounts.antigravityChatSignInStatus
long-poll, its long-wait lane and the bounded revision wait, as the install
status already did.

A failed sign-in now tells the person what happened in plain words (no
subscription, account not eligible, not approved, not installed, or a
generic retry) and logs the raw error instead of showing it.

Stopping the running chats before a sign-in waits for every close to settle
before it reports, so the fence never lifts while a close is still running.

* feat(antigravity): finish a chat sign-in from the address pasted by hand

When the browser runs on another computer than the host (SSH or a paired remote host), Google's last page points at a port on the host that the browser cannot reach, so the sign-in never finished. accounts.antigravityChatSignInComplete takes that pasted address, checks it is Google's answer to this flow's own link (same loopback origin and path, one matching state, one code or error, no userinfo or fragment, a Google issuer if any), and sends it once to the server's listener on the host with a single direct GET. The flow shows a new verifying phase while the server finishes, and refuses a second paste.

* fix(antigravity): Cancel answers once the sign-in has unwound, so a chat sent right after it is not refused

* fix(antigravity): the sign-in reads its launch sources through the shared helper, keeping the session create support within its line limit

Main's file already sits at the limit, and the runtime method only forwarded to the helper.

* fix(antigravity): a rejected pasted sign-in address says what is wrong with it

Every bad address used to get one sentence. It now gets the specific one:
too long, not a complete address, not this sign-in's, not exactly one
Google answer, or not from Google. The checks themselves are unchanged.

* fix(antigravity): chat sign-in follows the server's answers and belongs to the client that started it

The host's chat sign-in status was a check that the server's sign-in file
existed, which says nothing about whether the sign-in still works. The
link came only from one printed line, a new Start from any device
silently replaced a running sign-in, and a second link replaced the first.

- The server's BROWSER is now a one-line helper run by Orca's own
  executable in Node mode, which prints the link on error output; it is
  checked before every server start, and the printed line is still read,
  on standard output as well as error output. No browser opens on the
  host, Windows included.
- A sign-in belongs to the client that started it. Others see it in
  progress without its link and cannot start, cancel or complete it; it
  ends on its own after five minutes.
- After Google answers, a session on the same server must start before
  the sign-in reads as signed in.
- The host's status is the server's latest answer: signed in when a chat
  session or the sign-in's session starts, signed out when a chat hits
  the sign-in prompt or is refused for sign-in, and unknown until then.
  Nothing is read from the sign-in file and nothing is saved.
- A second, different sign-in link fails the sign-in.

* test(antigravity): the launch parity record shows the sign-in link helper as the server's browser

* fix(antigravity): a sign-in owns its work until it has unwound, and reads only whole, valid sign-in lines

Problems in the previous round: a sign-in could read as finished while its
server or pasted-address request still ran, a server refusing a sign-in
after a chat started left the host shown as signed in, the checking
session stayed saved in the server's own store, and a broken sign-in line
could count as the server asking to sign in.

- The browser helper is POSIX only, with Node mode set inside the BROWSER
  command; Antigravity chats are not offered on Windows.
- Sign-in lines are read by source: standard output carries the printed
  line, error output the printed line and the helper's. Only a whole,
  valid link is an answer; a malformed one on error output is dropped, and
  on standard output it ends the server. Standard output goes through the
  protocol's own line reader, including a last unterminated line, and
  error output keeps a whole link while its diagnostic tail stays small.
- Any request the server refuses for sign-in marks the host signed out.
- A sign-in is the host's one operation from Start until its work has
  unwound; a Start before then is refused, and Cancel or expiry also stops
  a pasted address on its way to the server.
- A different second link fails the sign-in at any point, including while
  it is being checked.
- The checking session's saved conversation is removed once the server is
  proven gone, only when its metadata names the sign-in's own folder.
- A pasted address is checked for length before it is trimmed.

* Preserve ACP auth answer ordering and sign-in cleanup

* Fix ACP settlement lint and await sign-in cleanup in fixtures

* test: update Antigravity browser launch snapshots
2026-10-18 00:46:43 -07:00
Neil 06618fd572 fix(ssh): a connection never redials a host the user disconnected before its teardown runs (#30245)
The Disconnect is recorded synchronously but the teardown that disposes the connection waits
behind the target's lifecycle; until then a drop's backoff, a wake retry or reconnect() could dial
the host again. SshConnection now consults the same per-host record the connection manager does.
2026-10-18 00:44:13 -07:00
Brennan Benson fc925c3e9b fix(native-chat): Claude, Pi and ACP chats are Working only while the agent holds the send (#30134)
* fix(native-chat): Claude, Pi and ACP chats are Working only while the agent holds the send

Each adapter reports the sends it still holds (Claude's dispatch waiters, Pi's sends until
settlement, ACP's unsettled prompt and steers). A late settlement's write runs inside the
per-send handover window, so a send reads held until its row lands, and a failed write
reads as doubt at once. Removes the idle-release API and its callers.

* Fix interruption reporting from held send ownership

* Simplify ACP reading control cleanup registration

* Preserve provider child identity when reattaching

* Replay original attach in recovery overlap regression
2026-10-18 00:40:10 -07:00
Neil e958614303 fix(orcad): SSH host management on a server without the desktop app refuses with an accurate message (D3) (#30242) 2026-10-18 00:37:51 -07:00
Neil 1e4d65ea51 ci: path-literal check scans live gate references; historical gate commands move to currentCommand (#30252)
Gate evidence prose and evidence runs record what ran then, so the check reads only each gate's
commands and test files (baseline 53 -> 14). Four evidence-pinned historical commands that named
deleted tests are removed from their gates' commands and their runs point at the successor via
currentCommand, the manifest's existing mechanism. One live command drops a deleted updater test.
The managed-SSH catch-all route is renamed remote-sources and its test joins the route contracts.
2026-10-18 00:35:33 -07:00
Neil ed3ee7e08a refactor: name the vm transcript and mobile pending-write caps for what they count (#30251)
Both cap UTF-16 string length for local display and memory, never wire bytes, so _BYTES misled readers into treating them as consumer byte budgets.
2026-10-18 00:35:30 -07:00
Neil dcfbec0377 refactor(execution-host): one isLocalExecutionHost in shared (#30241)
Replaces the agent-hooks copy, a private wrapper and five inline parseExecutionHostId(x)?.kind === 'local' checks.
2026-10-18 00:34:36 -07:00