Commit Graph
14981 Commits
Author SHA1 Message Date
8c3775f8d6 fix(shortcuts): Cmd+C no longer pastes on remapped Latin keyboard layouts (#29587)
* fix(shortcuts): Cmd+C no longer pastes on remapped Latin keyboard layouts

On macOS the main-process paste intercept matched `code === 'KeyV'` OR
`key === 'v'`, so on Turkish F (where the C letter sits on the physical
KeyV) Cmd+C was routed to ui:appMenuPaste. Trust the produced key when it
is a Latin letter or digit and only fall back to the physical code for
non-Latin layouts (Cyrillic etc.), matching the shared keybinding matcher.

Fixes #29574

Claude-Session: https://claude.ai/code/session_01TYbS9P1pnW4WRN7bGpuNaW

* test(shortcuts): cover Dvorak, Korean and IME composition for the macOS paste intercept

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

* refactor(shortcuts): match the macOS paste intercept by produced key token, in its own module

The produced key token wins on every Latin layout, punctuation included (BEPO puts . on KeyV); non-Latin and IME keys fall back to the physical key.

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

---------

Co-authored-by: İzzetEmre <emreizzet@hotmail.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:13:55 -04:00
Jinwoo Hong bad74e1b7c test(sidebar): the desktop window and a phone reading the feed draw the same list (dark) (#30426)
* test(sidebar): the desktop window and a feed reader draw the same list (dark)

* fix(sidebar): a feed reader lists a paired server's folders and nested workspaces as the window does (dark)

* fix(sidebar): the paired-server shadow compares the lineage the server's check keeps (dark)

* fix(sidebar): paired-server rows carry the unread flag Smart Done reads (dark)
2026-10-18 18:01:45 -04:00
Brennan Benson 4298ba998d Mark completed Codex reviews Done when Stop is absent (#28860)
* Settle Codex review turns from their session completion

* Preserve interruption relay metadata when settling Codex reviews

* Keep the Codex turn id across status writers and settle through the existing host verdict path

The turn id that matches a rollout turn end was dropped by every lead writer
that did not pass it, so a failed turn after a child update never settled.
Drop the synthetic Stop label: the unlabelled poll update already carries the
host's main-agent verdict, including a failure, to current desktops. A remote
desktop now takes the host's settled verdict for a late hook, and a rollout
settle retires hook-only children like Stop does.

* Retire Codex children through the poll and start a fresh turn on any non-compaction session start

A rollout-settled turn deleted the child roster, so the local reconcile
re-seeded the child from the last row as running and the pane stayed Working.
Clear it instead, only from the poll (a child hook settling the root must not
drop that live child), and let a remote desktop clear its roster when the host
reports a done turn with no children. A resumed or forked session no longer
inherits the previous turn id. Also drops accidental pnpm-lock churn.

* Replay a Codex rollout turn end as the root Stop it stands in for

Codex fires no Stop for internal subagents such as /review, so the rollout's
task_complete was settling the main agent through a second path that every
other status writer (local and remote reconcile, child hooks, polls) had to
learn about. The transcript poll now replays that end as an ordinary root Stop
through hook normalization, and a root hook for an already ended turn is
classified as that Stop. A failed end carries its failure outcome and is
published unlabelled like a cancellation, since desktops derive a labelled
Stop's outcome as success. The separate settle path, the remote host-verdict
adoption and the child-hook rollout reads are gone.

* Keep an ended Codex turn retired across compaction, and keep WSL polls alive

A compaction SessionStart queued before the next prompt carried the previous,
already ended turn id, so the poll replayed its Stop: a Done flash and a
second "finished" notification. A compaction now keeps the turn only while
it is still running and its rollout end is unrecorded. The WSL guest
rescheduled its transcript poll with the update instead of the stored row,
so the poll stopped after its first update and a later turn end never
replayed there. A Stop also clears the child roster instead of deleting it,
so a reconcile cannot re-seed retired children from the previous row.

* Restate an ended Codex turn's hook in provider dispatch

Keeps the shared hook normalizer within its size limit after main's merge;
the Codex dispatch returns the event it normalized, which the envelope uses
for the published name and prompt classification.

* Type the rollout record helper in the Codex turn-end test

* Accept Codex's turn_complete name and keep only replayed Stops labelled

The rollout reader also records turn_complete, the name the existing
interruption reader already accepts. A poll row that is not a replay no
longer restates the last hook's event name, so only a replayed Stop can
carry the Stop label.

* Drop a delayed Codex hook for an ended turn the lead has moved past

A late root hook for an older finished turn was restated as Stop and marked
the newer running turn Done; passing it through would instead rewind the
lead's turn id so the poll replays the old end.
2026-10-18 14:49:21 -07:00
Jinwoo HongandClaude d3026df586 feat(sidebar): Smart Done means finished and unread (dark) (#30425)
* feat(sidebar): Smart Done means finished and unread (dark)

Owner decision Q1: with ORCA_SIDEBAR_INPUTS=main, a Done row holds its tier only
while the workspace unread flag is set, so opening the workspace or sending the
next prompt ends it. Reuses the existing flag; no new state or timer.

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

* test(sidebar): reading a workspace drops its Done row in the live list

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-18 17:39:48 -04:00
Neil 3dbb804f3e fix(macos): the TCC prompt watcher's log stream dies with Orca, and old orphans are reclaimed (#30148)
* fix(macos): the TCC prompt watcher's log stream dies with Orca

log stream only writes when its predicate matches (about never), so it never
gets SIGPIPE when Orca dies without running stop() (crash, SIGKILL, e2e
teardown, force-quit dev builds) and lived on under launchd. One dev machine had
126 orphans holding 566 MB and ~40% CPU. A /bin/sh wrapper now holds a
never-written stdin pipe from Orca and kills log stream on EOF.

* fix(macos): reclaim TCC log streams that older builds orphaned

The wrapper stops new leaks, but users upgrading still have every log stream an
earlier crash or force-quit left under launchd. Ten seconds after launch, once
per process, Orca terminates launchd-parented processes running exactly the
watcher's old command line. A live watcher's log stream is parented by its
wrapper, so it never matches.

* test(macos): document the fake log stream cast

* fix(macos): arm log stream wrapper trap before fork; verify orphan executable

* fix(macos): re-read orphan identity before SIGTERM; disable inherited errexit in wrapper
2026-10-18 14:25:39 -07:00
Jinwoo Hong eaa1ee131d A CLI-started terminal shows once in its workspace, and a pane close main has no pane for closes in the window (dark, layout-owner build only) (#30391)
* fix(layout): a workspace only main held shows main's tab on the window's first visit (dark, layout-owner build only)

* fix(layout): a live terminal no pane shows goes through main, which names the tab it holds; a pane close main has no pane for closes here (dark, layout-owner build only)

* test: no type assertions in the CLI-first tests

* refactor: the switch-off build keeps today's live-terminal mint as it was

* review: frame sync under the line limit; the first-visit test names exactly main's tabs

* fix(layout): adopt takes the recorded pane only while it is unbound

* fix(layout): a refused live-terminal adoption is declined, not counted as shown
2026-10-18 16:25:49 -04:00
Kelvin Amoaba b0a7d2eb48 fix(mobile): keep typed commit messages, restore failed shortcut removals, name icon buttons (#30142) 2026-10-18 20:05:28 +00:00
Kelvin Amoaba cf7423c8f4 feat(mobile): redesign the chat composer with file attachments and inline skills (#30359)
* refactor(native-chat): move the slash picker builder and upload chunking to shared

Mobile builds the same skill and command list as desktop.

* feat(mobile): redesign the chat composer with file attachments and inline skills

* fix(mobile): the composer field owns its input style

The page's font-size census cannot follow a style passed in as a prop.
2026-10-18 20:03:26 +00:00
Jinwoo HongandClaude 91b696b6cf refactor(sidebar): main keeps sleeping retention only, no order of its own (dark) (#30404)
* refactor(sidebar): the stamp-sorted window list runs no settle, latch or saved order (dark)

With ORCA_SIDEBAR_INPUTS=main the window's sort hook is a pure read of the
rows' stamps: no settled-epoch store listener, no Smart latch, no saved Smart
order writes, no class telemetry over the old attention map. Switch off: the
existing hook, unchanged.

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

* test(sidebar): stamp sort hook reads no live sources; stronger switch-on tests

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

* test(sidebar): clear the order-save mock between tests

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

* wip: main keeps sleeping retention only

* fix(sidebar): stamp sort reads a shared empty-sources constant, not a renderer layout literal

The layout-writer ratchet counts layout field keys written in the renderer;
the empty sources object now lives beside SmartSortSources in shared code.

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

* refactor(sidebar): main keeps sleeping retention only; no order of its own (dark)

Clients sort by the owning host's stamps, so main's temporal owner loses its
settle window, Smart latch, create grace and catalog-listing classifier, and
the shadow check stops comparing order. Retention, its clock and its shadow
comparison stay.

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

* fix(sidebar): every retention listing shares one sequence; publish after the first

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

* test(sidebar): the first listing bumps the retention revision

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-18 15:51:52 -04:00
Jinwoo HongandClaude 63f0cb9570 refactor(sidebar): the stamp-sorted window list runs no settle, latch or saved order (dark) (#30401)
* refactor(sidebar): the stamp-sorted window list runs no settle, latch or saved order (dark)

With ORCA_SIDEBAR_INPUTS=main the window's sort hook is a pure read of the
rows' stamps: no settled-epoch store listener, no Smart latch, no saved Smart
order writes, no class telemetry over the old attention map. Switch off: the
existing hook, unchanged.

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

* test(sidebar): stamp sort hook reads no live sources; stronger switch-on tests

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

* test(sidebar): clear the order-save mock between tests

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

* fix(sidebar): stamp sort reads a shared empty-sources constant, not a renderer layout literal

The layout-writer ratchet counts layout field keys written in the renderer;
the empty sources object now lives beside SmartSortSources in shared code.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-18 15:31:39 -04:00
Brennan BensonandOrca Worker c7942252b5 test(e2e): align title-strip drops with pane selection rules (#29903)
* fix(terminal): a file dropped on a pane makes that pane active

Dropping a file on an inactive pane's title strip pasted the path but left the
other pane selected, because the drop only focused the terminal. Activate the
pane instead (which also focuses it). Tracked in STA-9893.

* test(e2e): give the title-strip drop the source owner real drags carry

* test(e2e): preserve pane selection when checking title-strip drops

---------

Co-authored-by: Orca Worker <orca-worker@localhost>
2026-10-18 12:11:36 -07:00
Kelvin Amoaba df460b8338 fix(native-chat): move a chat visual's Open and Share buttons above it (#30356) 2026-10-18 19:08:48 +00:00
Kelvin Amoaba 9189e0fbe1 feat(native-chat): pan and zoom chat image previews like mermaid diagrams (#30154) 2026-10-18 19:07:36 +00:00
Jinwoo HongandClaude 3af9c22cc9 fix(cleanup): count visits as last activity once terminals stop stamping Recent (dark) (#30397)
* fix(cleanup): count visits as last activity once terminals stop stamping Recent (dark)

With ORCA_SIDEBAR_INPUTS=main, terminal start and exit no longer write
lastActivityAt, so a workspace used only through plain shells could look idle
to workspace cleanup and old in the jump palette. Both now read the later of
the Recent stamp and the last visit. Switch off: unchanged.

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

* fix(cleanup): stamp the workspace you leave; space table reads visits too (dark)

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

* fix(cleanup): every reveal stamps the workspace you leave, host-aware (dark)

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-18 15:01:08 -04:00
Kelvin Amoaba d378f49f17 fix(mobile): show a renamed terminal tab's name on the phone (#30163) 2026-10-18 18:46:53 +00:00
Kelvin Amoaba e43f3e7e04 feat(opencode): open OpenCode 2 in the chat view and list 2.x models before the first message (#28424) 2026-10-18 18:42:23 +00:00
Brennan Benson b6325ef951 style: format the resume and transcript files main left unformatted (#30137)
Two merged changes left lines past the formatter's 100-column width in
structured-session-create-support.ts, structured-agent-session-create-adoption.ts
and transcript-opencode-sqlite-query.ts. Any branch that merges main gets them
reformatted by the pre-commit hook, which pushes two of them past the 300-line
limit and fails CI. Format them, and keep them under the limit by moving the
bounded row readers and the resume adopt payload into the modules that own them.
No behavior change.
2026-10-18 11:17:20 -07:00
Jinwoo HongandClaude 3a2f162911 feat(sidebar): sort Recent and Smart by the owning host's stamps, hold order under the pointer (dark) (#30284)
* 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

* feat(sidebar): sort Recent and Smart by host stamps behind the sidebar-inputs switch

With ORCA_SIDEBAR_INPUTS=main, the window, main and the phone order Recent by
lastActivityAt and Smart by smartTier then smartAt (Needs you, Done, Working,
then the rest by Recent). The window holds its displayed order while the
pointer is over the list or a drag runs. Switch off: today's sort path.

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

* chore: restore files the merge commit's formatter rewrote

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

* fix(sidebar): stamp-order review fixes behind the sidebar-inputs switch

The window writes no Recent stamps with the switch on (terminal start and
exit, unread marks, comment edits), the hover hold covers only Recent and
Smart and ends with a drag, main follows only explicit metadata saves, and
the phone picks its sort from the unfiltered rows.

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

* test(sidebar): folder writers and a Manual drag under the stamp switch

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

* test(sidebar): name the stamp type in the ps summaries test

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-18 14:16:34 -04:00
Jinjing a8d7151b49 Require a full hover delay before each tab preview (#30388)
* Require a full hover delay before each tab preview

Tab previews opened almost immediately after a previous preview had been shown, so sweeping across the tab strip caused a flurry of popups. Raise the tab tooltip delay to 800 ms and drop the warm-start chain: the shared open-state context, the 300 ms skip delay, and the slide animation that carried position between cards. Every tab now waits its full dwell time, and keyboard focus still shows the preview immediately.

* Test that tab hover cards wait a full dwell on every hover

The tab hover card no longer slides instantly between neighboring tabs. Each hover now waits for the full delay before showing a preview. The e2e test still expected instant sliding, so it was rewritten to match.

- Remove the frame-recording helpers and the slide and reversal assertions.
- Check that no card appears before the dwell, and that the card appears after it.
- Check that leaving a tab cancels a pending preview, and that time spent on other tabs does not count toward the dwell.
- Check that re-entering the same tab requires a fresh dwell.
2026-10-18 11:14:08 -07:00
Jinwoo Hong bde20afb1d Only the tabs the window just changed wait for main's answer; the window-wide layout hold goes (dark, layout-owner build only) (#30384)
* 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)

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

* feat(layout): frames keep each tab the window drew, closed or moved as drawn until main answers; the global frame hold goes (dark, layout-owner build only)

A refused draw-first terminal create is closed (its terminal stopped) at the refusal. The
activation create no longer draws main's tab itself while the stream is down: the reopened
stream's snapshot does.

* fix(layout): a tab move or drag-out the frame already drew is not placed again by the window (dark, layout-owner build only)

Also holds the group sizes the window drew until main saves them.

* test(layout): with frames flowing, a pin promotes a preview tab once and tab-change bookkeeping runs once (dark, layout-owner build only)

Also states that the held-tab overlay builds frame slices only.

* test(layout): read the rename's title without a cast

* chore(layout): the drift check's header lists the same ignored records as its inline comment
2026-10-18 14:13:15 -04:00
OrcaWinandOrca Worker 26554234df fix(rate-limits): run the Antigravity usage probe with agy's auto-update off (#30387)
A due update check makes agy start --bg-updater, whose own console child opens
a visible window on Windows and takes focus, so stepping away from Orca for
15+ minutes and coming back flashed a terminal (#27390). Set
AGY_CLI_DISABLE_AUTO_UPDATE=true on both probes; a background quota read should
not update the user's CLI anyway. Only 'true' is honoured (agy 1.4.2).

Co-authored-by: Orca Worker <orca-worker@localhost>
2026-10-18 11:08:47 -07:00
Brennan Benson ff294f0294 fix(mobile): put the session tabs in the top bar on a landscape phone (#29070)
* fix(mobile): put the session tabs in the top bar on a landscape phone

A sideways phone is about 390pt tall and the session header spent two rows
on it. On a landscape phone the tab strip now shares the top bar with the
back button, title and panel icons. Portrait and tablet layouts are unchanged.

* fix(mobile): give session tabs side borders and a filled active tab

In the landscape top bar the tabs sat between the title and the panel
icons with nothing marking where one tab ended. Each tab now has a 1pt
border on its sides, running the full height of the bar, and the active
tab gets the raised fill, as the desktop tab strip draws them. The same
strip is used in portrait, so both orientations match.

* fix(mobile): reset tab strip measurements on view attachment

* style(mobile): format tab strip ref dependencies

* fix(mobile): keep two header rows in landscape windows too narrow for top-bar tabs

A short, narrow window (a ~390x350 web window) is wider than tall, so it
counted as a landscape phone and moved the tabs into a top bar that has no
width left for them. Top-bar tabs now also need at least 568pt of width,
the narrowest landscape phone.

* fix(mobile): give the landscape top-bar tab strip a fixed left edge so scrolled tabs never read as part of the title

* fix(mobile): 12pt between the session title and the landscape tab strip
2026-10-18 10:52:10 -07:00
Brennan Benson 37a9eaaf41 feat(settings): remove a downloaded agent runtime from its Settings row (#29140)
* feat(settings): remove a downloaded agent runtime from its Settings row

When the host offers managed-runtime.remove.v1 and an Orca-installed copy is
there with nothing running, the Settings install row shows a trash button
("Remove downloaded runtime") that asks first: "Remove {agent} from this
host? Running {agent} chats stop. Chat history is kept." While the host removes
it the row says "Removing…"; a refused removal shows the host's reason and keeps
the button. Chats never show it.

* fix(settings): offer Remove for a damaged copy too, and say which host the downloaded runtime leaves

The row offers Remove whenever the host says Orca's copy is there (canRemove), damaged included;
an older host without it keeps today's rule. The confirmation now reads "Remove the downloaded
{agent} runtime from {host}? Running {agent} chats there stop. Chat history is kept.", naming the
paired host, or this computer.

* fix(settings): Remove follows the host's canRemove alone

* fix(settings): the Remove dialog says the sign-in is kept too

* fix(settings): show the downloaded runtime's install state as the provider's status line

The Antigravity row in Settings > Chat > Providers drew its install state as a
bordered box nested inside the row. It now reads like the other rows: one grey
status line under the name, with its actions as inline links joined by ' · '
(Installed · Remove, Not installed · Install · size, a thin progress bar with
Cancel while downloading, Reinstall · Remove for a damaged copy, Try again
after a failure). A healthy install no longer offers Reinstall. The Remove
confirmation now says running chats stop and their history is kept.

* fix(settings): make Antigravity's first Install a primary button beside the switch

Not installed now shows a high-contrast Install button at the row's right end in
Settings > Chat > Providers and Settings > AI Provider Accounts > Antigravity; the
status line keeps the sentences (Not installed · 112 MB download.). Every other
action stays a link in the line.
2026-10-18 10:40:20 -07:00
Brennan Benson 051708702c fix(jcode): let jcode's own client start its per-pane server (#30257)
Orca started jcode's background server itself as a terminal opened, ahead of
the jcode client. On daemon-backed terminals that launch had no PATH and
silently failed; where it did start, the server ran jcode's tools and hooks
outside the shell's environment, without the client's launch flags, and
outside jcode's own startup lock. jcode's client already waits for its server
to signal ready, so it is now the only thing that starts it.
2026-10-18 10:30:00 -07:00
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