* feat(layout): main drops the layout of workspaces the catalog no longer validates (dark, layout-owner build only)
* rename the paired-host check so the switch-off bundle keeps its names
* a repo id two hosts register skips the listing purge
* Save-divergence detector: skip empty workspaces, see dropped tab-bar entries and kept pane trees (dark, layout-owner build only)
- A workspace key that names nothing (or only places a stored closed-tab record) is no longer
reported as "workspace added/removed" or "terminal row owner changed".
- A save that drops a terminal tab's tab-bar entry while keeping its row is reported, read from
the stored session before the Loader rebuilds the entry.
- A pane tree main keeps over the window's (windowSaveForMain) is reported, so a window-side
pane repair shows up.
* Detector: keep reporting empty-row flips, cover every overridden pane tree and one-sided closed tabs (dark, layout-owner build only)
* Detector: a save with no pane tree for a tab main keeps one for is reported too (dark, layout-owner build only)
* Detector: a closed tab record moved to another worktree in one save is reported (dark, layout-owner build only)
A user's Disconnect of an SSH host is now recorded for the session, and background
dials (a managed server's tunnel and status checks, census, host-resume recovery,
pane and automation restores) refuse it until an explicit Connect. Disconnecting a
managed host from Settings also stops its server's status checks, and the status
bar's Disconnect of a managed server also disconnects the SSH host it runs on, so
both surfaces read the same verdict.
Fixes#30086Fixes#30085
* refactor(pty): one spawn step stamps a terminal's pane identity for both spawn lanes
The window spawn controller and the host runtime's caller each wrote
ORCA_PANE_KEY/ORCA_TAB_ID/ORCA_WORKTREE_ID and jcode's runtime dir, in
different layers, so per-pane env behavior drifted (the jcode daemon
pre-warm exists only on the window lane). stampPtySpawnPaneEnv now writes
them in both controllers from the spawn's own tab/leaf/worktree ids;
buildTerminalWorkspaceEnv no longer stamps them. No behavior change: a
TEMPORARY prewarmsJcodeOnDaemonHost input keeps host daemon spawns from
pre-warming until its own PR.
* test(runtime): read a fake spawn's pane env without type assertions
* test(pty): host serializer-settlement spawns name their pane by tab and leaf, as the runtime does
* fix(pty): preserve caller runtime directory after managed preparation fails
* feat(sidebar): main keeps a registry of workspace creations in progress, checked against the window in dev and test
* fix(sidebar): open the runtime creation entry after the create's own repo resolve
* refactor(sidebar): one creation handle opened after the create's repo lookup; move create startup resolution to its own module
* feat(sidebar): put the creation registry behind the ORCA_SIDEBAR_INPUTS dark build switch
* test(sidebar): cover the creation registry with the switch off and the gated creation id
* feat(sidebar): main keeps one live set of paired-server rows, checked against the window in dev and test
* fix(sidebar): settle review findings; main also publishes paired-server host facts
* fix(ssh): a host that needs a password waits for the user at launch instead of prompting
Restores the persisted 'last sign-in needed a typed credential' flag that
the relay removal (#27214) stopped writing, and at launch marks those hosts
as awaiting sign-in so background reconnects (startup restore, managed-server
status checks and tunnels) refuse without dialing instead of opening the
password dialog. The user's own Connect lifts it and prompts. The terminal
toast shows the refusal as an SSH state, not a bug to report.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(ssh): give the raw-connected fixture the cache query; annotate the harness-shaped registration
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(terminal): keep the sign-in branch out of the toast component
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(ssh): link a folder workspace the server kept from an earlier move instead of conflicting (#27285)
* fix(ssh): resolve a server folder's host before linking it, and read folder lease owners
* fix(ssh): name a linked folder workspace in the connect's left-behind warning
* feat(native-chat): image messages wait in the queue like text
A message with images now queues behind the running turn and the cards
ahead of it, instead of skipping the queue. Cards show an image icon and
count, an image-only card names its image, and editing a card's text keeps
its images. The host publishes no card holding an image to a client that
has not advertised agent-session.queued-image-cards.v1, since released
clients edit by copying a card's text and deleting the card.
* test(native-chat): an image follow-up queues like text
* fix(native-chat): project queued images before phone frame limits
* fix(native-chat): preserve image sends from older clients
* Clarify direct text recovery at send admission
* fix(native-chat): expose queued image names to keyboard users
* fix(ssh): re-check a macOS host's ended launch-session warning so another desktop's restart can clear it
The ended verdict was cached for the whole SSH session, so when another desktop restarted the server under a live session, this desktop kept the warning. It now expires like every other verdict: a live re-probe clears the note, and an unanswered one keeps the proven verdict.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): only a live probe clears a proven launch-session end, and a failed recheck republishes it
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): a failed launch-session recheck restores the warning only for the same live connection
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(native-chat): retire acknowledged send echoes after catch-up
* test: follow phone lint rules in reconnect regression
* test: format reconnect message expectation
* Keep current chat requests independent of loaded history
* Read current chat requests in bounded cursor pieces
* Bound desktop catch-up after independent request support
* Fix current request subscription static checks
* Match generated request schema import ordering
* fix(native-chat): correct current request type boundaries
* Accept readonly client capability fixtures
* Exercise current request reads in wire compatibility inventory
* Align current request fixtures with provider commit and RPC surface
* test(native-chat): include current request browser capability
* Keep the mobile chat session hook within its line budget
* Format mobile current request readers
* fix(native-chat): reopen once for a current-request version whose read keeps failing
A deterministic read failure reopened the subscription, whose first frame re-read the same version and reset the backoff, so the pane resubscribed every 750 ms forever.
* test(native-chat): type the current-request snapshot fixture
* test(native-chat): wait for the hydrated open before driving the subscription
* feat(layout): report window saves that still change main's layout (dark)
In a layout-owner build, each window session save (session:set, session:patch, the shutdown
checkpoint) is projected to main's published layout before and after it is written. Any workspace
whose layout the save changed is logged, and appended to ORCA_LAYOUT_SAVE_DIVERGENCE_LOG when set,
so evidence runs can show which tab changes still reach main only through the save.
* feat(layout): name the fields a diverging save changed
* fix(layout): the save check diffs main's whole layout model and never fails the save
Review: a failed log write could reject a save that already landed; and the published layout omits
editor views, pane records (sleeping agents, incarnations, titles), closed-tab tombstones and the
workspace records, all of which a later save trim would drop.
* fix(layout): the save check covers record-only workspaces and row owners, and counts rebinding last
* fix(layout): the save check counts first binds as rebinds and keeps the count past the cut
* fix(ssh): allow a host's orca CLI to control Orca by default, and stop resetting saved choices
An absent allowRemoteCliControl now means on; only an explicit false turns the
desktop browser bridge and relay-era orchestration commands off. Removes the
one-time reset of saved true values, the consent stamp writes and the reset
notice, which would have silently turned off hosts upgraded from stable.
* fix(ssh): keep the CLI control choice when adding a host from the sidebar
* fix(ssh): read an older client's omitted CLI control switch as off over RPC
* fix(ssh): check the managed fence before routing settings in browser bridge candidates
* fix(native-chat): retire acknowledged send echoes after catch-up
* test: follow phone lint rules in reconnect regression
* test: format reconnect message expectation
* Keep current chat requests independent of loaded history
* Read current chat requests in bounded cursor pieces
* Fix current request subscription static checks
* Match generated request schema import ordering
* fix(native-chat): correct current request type boundaries
* Exercise current request reads in wire compatibility inventory
* Align current request fixtures with provider commit and RPC surface
* test(native-chat): include current request browser capability
* Keep the mobile chat session hook within its line budget
* Format mobile current request readers
* fix(native-chat): reopen once for a current-request version whose read keeps failing
A deterministic read failure reopened the subscription, whose first frame re-read the same version and reset the backoff, so the pane resubscribed every 750 ms forever.
* test(native-chat): type the current-request snapshot fixture
* test(native-chat): wait for the hydrated open before driving the subscription
* fix(projects): refuse a folder-to-Git type change that would hide folder workspaces (STA-10638)
A folder project's extra workspaces exist only as metadata rows that the folder listing shows. Changing the project to Git switches it to `git worktree list`, so those workspaces drop out of the next refresh and their saved tabs are purged as if they had been deleted. Only the automatic upgrade checked for this; `orca project setup-update --kind git`, repo updates and clone-into-folder did not.
The check now lives in the one repo write every type change goes through, so any caller gets the same refusal and nothing is written. The automatic upgrade and both clone paths use the same check and keep the project as a folder project.
* test(repos): give the repo handler store mock the metadata read the clone path now uses
* fix(projects): a manual folder-to-Git change proves the folder is the Git root first (STA-10638)
Only the automatic upgrade checked that a folder project's path is the top of a Git repository and recorded Git's spelling of that root. A manual change (orca project setup-update --kind git, repo updates, clone into a folder project) flipped the type without either, so a project inside another repo became a broken Git project, and a project whose path Git spells differently lost its main workspace's id and tabs on the next refresh. All of them now run the same proof and write the proven root with the type change. SSH projects keep the unverified change because their Git runs on a host this process can't probe.
* Revalidate folder-to-Git conversion targets after Git proof
* Explain when a project changes during its Git check
* Fix clone conversion for replaced folder project
* test(runtime): create real Git root for clone upgrade fixture
* test: normalize runtime clone root stamp expectation
* test: check clone registration identity without unknown access
* chore: restore main's pnpm-lock.yaml that the main merge reverted
A Pi or OMP agent started from the window inside WSL, with the terminal
daemon on, could start before the distro's hook relay was up. It then
reported no working/idle status for that session. Host starts and
local-provider starts already waited (#21721); the window's daemon path
was the one left out.
The shared host-env step now always runs the wait on the daemon spawns
it builds, so the lane input that skipped it for window starts is gone.
The wait is a no-op for anything but an explicit Pi/OMP launch in WSL.
* Window pane trees drawn from main's layout frames (dark, build switch off by default)
Co-Authored-By: Claude <noreply@anthropic.com>
* Review fixes: paired-server saves keep their trees, last-pane guards count pending closes, draw main's answer when no frame is coming, redraw main's tree after a zoom
Co-Authored-By: Claude <noreply@anthropic.com>
* Delta review: a closed stream's frozen cache never redraws pane trees; the frame reconciler never closes a tab's last pane
Co-Authored-By: Claude <noreply@anthropic.com>
* Second delta review: draw the activation tab only when no frame showed it; a stream not yet open counts as coming; a redraw re-queues only its tab's workspace
Co-Authored-By: Claude <noreply@anthropic.com>
* Independent review: a late record of a split main asked for restores it only if main took it back; a closed stream never redraws pane trees
Co-Authored-By: Claude <noreply@anthropic.com>
* Delta review: deny a late record only for a split main wrote and did not take back itself; pane_closed only where the tab is; a reply before the stream opens waits for its first frame or end
Co-Authored-By: Claude <noreply@anthropic.com>
* Re-review: replies wait only once the window opened its stream; a record that lands while main takes its split back waits for the outcome
Co-Authored-By: Claude <noreply@anthropic.com>
* A record waits only while main is taking its split back
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(layout): main keeps the pane of a split it asked for
Drops the timed withdraw and the window's late record of a main-asked split: main writes the pane and keeps it, a refused write fails the split, and a tab's first mount leaves queued main-asked splits to their request so the startup command still runs.
* refactor(layout): drop the start-without-pane option no caller uses
* refactor(layout): drop an always-false check in the queued main-split filter
* test(layout): main-asked splits into an unmounted tab, with the stream down, and with no start
* test(layout): type-safe withdraw stub
* fix(layout): equalize draws itself when no frame is coming
* refactor(layout): name the frame-tree pane moves for their role
* refactor(layout): frames' pane trees reach the store through the frame store patch
---------
Co-authored-by: Claude <noreply@anthropic.com>
optionalAskTimeout computed exactly what cappedWait does (an undefined timeout stays undefined;
anything else clamps to 0..ORCHESTRATION_ASK_MAX_TIMEOUT_MS), so the ask call uses cappedWait.
Three functions used only inside their own file lose their export, and the per-host switch's
doc names the orchestration commands it has gated since #29571.
Co-authored-by: Claude <noreply@anthropic.com>
* Run automated workspace setup in a dedicated tab
* Preserve native-chat setup route coverage after placement retirement
* Preserve Setup tab design and independent review evidence
* Classify activation test fixtures consistently for routing checks
* Sync runtime English catalog after removing setup preferences
* Update listener savings model after retiring setup action
* fix(wsl-cli): keep the WSL CLI status check from timing out on a cold or slow-profile distro (#29497)
* fix(wsl-cli): run install/remove without the login PATH; a PATH-check timeout reports PATH unknown
* fix(projects): refuse a folder-to-Git type change that would hide folder workspaces (STA-10638)
A folder project's extra workspaces exist only as metadata rows that the folder listing shows. Changing the project to Git switches it to `git worktree list`, so those workspaces drop out of the next refresh and their saved tabs are purged as if they had been deleted. Only the automatic upgrade checked for this; `orca project setup-update --kind git`, repo updates and clone-into-folder did not.
The check now lives in the one repo write every type change goes through, so any caller gets the same refusal and nothing is written. The automatic upgrade and both clone paths use the same check and keep the project as a folder project.
* test(repos): give the repo handler store mock the metadata read the clone path now uses
* test(pty): pin where the two spawn lanes build a daemon spawn's host env differently
Characterization on main's code before the host-env step merges: which failed env builds sweep
per-PTY state (minted ids only, both lanes), the empty-id split, the host-only WSL Pi/OMP guest
readiness wait, and that a host create operation still waits on a managed Codex login.
* refactor(pty): one host-env step for both terminal spawn lanes
The window (pty:spawn) and host (runtime controller) lanes each carried a copy of Codex resume,
Codex home selection, the managed-auth wait, backfill recovery and the daemon host-env build.
Both now call resolvePtySpawnHostEnv. Lane differences are explicit inputs: two TEMPORARY ones
(the host-only WSL Pi/OMP guest readiness wait; the host skipping host env for an empty id) and
three that mean the same in both lanes. The resume step's launchEnv was never read and is gone.
* test(pty): pin that both lanes hand Codex resume prep the request's CODEX_HOME
orca serve (#29209) skips resume prep for a launch whose env names a client-sent CODEX_HOME.
* test(pty): type the new lane-pin requests instead of asserting them
* test: pin selected Codex home on terminal restart
* test(launch): pin what a paired agent session spawns today
Characterization on main's code before createAgentSession moves onto the
host planner: plain launch, short/long/multi-line prompts on macOS, a
stdin-prompt agent starting clean, Windows PowerShell and cmd quoting, and
the identity-required refusal when no launch can be built.
* refactor(runtime): plan paired agent sessions with the host planner
terminal.createAgentSession built its own launch command beside the planner
every other host launch uses, and the two had drifted. It now hands the
request to createTerminal as a startupAgent, so one planner builds it.
The planner gains a draft delivery input, and one TEMPORARY input
(startupPromptCarry: 'force-line') keeps what createAgentSession did: the
prompt always rides the typed line, and an agent that reads its prompt
after start launches clean. The later change that delivers uncarried
prompts after start removes it. A launch that can't be built still refuses
with agent_session_identity_required.
* test(accounts): pin that the selected account wins over Settings agent env
A paired agent session now layers the host-selected account env the way
every other host launch does.
* fix(runtime): report prompt carry truthfully on the planner's direct path
Review round 1: a stdin-prompt agent's text never rides its launch line, a
draft comment that overstated the carry rule, the error class's name, and
formatting the cherry-picked commit skipped.
* docs(runtime): scope the account-order and draft comments accurately
Review round 2.
* test(launch): drop paired-session parity rows that pin nothing new
The no-prompt and short-prompt rows plan the same with or without
force-line, and the Windows cmd row repeats the OpenCode-model Windows
row's createAgentSession runtime and cmd quoting. The long-prompt,
aider, PowerShell, refusal and account-env pins keep the coverage.
* docs(runtime): label the draft's carry-rule exemption temporary
Skipping the typed-line carry rule for drafts is createAgentSession
parity, not design: a draft on the line has the same hazards as a
submitted prompt. The one prompt/draft delivery policy removes it with
force-line.
* fix(runtime): keep main's error name for an unbuildable agent launch
Overriding the name made every other planner caller's stringified
error read 'AgentLaunchUnbuildableError: ...' instead of main's
'Error: ...', which renderer code that strips an 'Error:' prefix
would show raw. createAgentSession matches by instanceof, so the
override bought nothing.
* fix(agents): a resumed agent's chat is readable on the phone before its first new turn (#10923)
* fix(agents): skip a dropped Codex resume and keep the seeded identity across restart
* fix(agents): seed resume identity before the spawn's first await and keep it through terminal evidence
* fix(agents): seed after the spawn commits, and name the session on host-built resumes
* fix(terminal): tell panes their daemon died at once and say when typed input was lost
* fix(terminal): use the info toast the terminal suites already stub
A symlink to a directory was listed as a file on SSH and managed hosts, so
projects behind a linked path could not be reached. Follow links when
classifying entries; broken links and loops stay files.
Co-authored-by: Gideon <jjin6573@naver.com>
* fix(projects): adding a project through a symlink alias reuses the existing project
On a managed host, adding repo-link (-> repo) created a second project for the
same checkout while re-adding repo was deduped. Compare the real path, resolved
on the host that owns the files, so an alias finds the tracked project; distinct
checkouts keep distinct real paths and stay separate. Local folder workspaces
get the same check.
* test: run fixture git through process-host
* fix(ssh): keep a host connected for its bridged relay terminals when another desktop already moved their project (STA-10604)
Desktop 2's move onto the server desktop 1 already runs refused to link a
project its own relay-era terminal still runs in, and the connect then failed
outright: this version has no relay to fall back to. The decision now keeps
that host connected and unmoved, starts the legacy relay bridge, and the old
tab reattaches its shell through it. The SSH host card names the terminals and
how to clear them; the next connect after they exit links the project.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): release a bridged ssh: row pane's claim on detach too
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): admit the bridged mark in the renderer, and remount bridged tabs even when the connect reply lands first
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): keep the unverifiable line for a bridged host whose terminal can't be confirmed
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ssh): keep the linked-project terminal guidance neutral; only the live bridged line reassures
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat(wsl-mover): the ledgered desktop rewrite stage that finishes a committed move (D1b-7b)
* fix(wsl-mover): a move finishes its rewrite only once every store exists (D1b-7b)
* fix(wsl-mover): chats never move per decision C, the journal enforces registry completeness, stores time out (D1b-7b)
* fix(agent-hooks): bound retained agent exits
Proven exits were only forgotten by a successor claim, so closed tabs and
retired panes kept theirs forever and every save rewrote them. Drop an exit
when its tab closes, its pane retires or its PTY is really torn down (not a
reconnectable disconnect), and prune exits older than the hydrate window
at save.
* fix(agent-hooks): closing a moved pane's former tab keeps its exit
* fix(agent-hooks): keep an aged exit while its retained resume row remains
* fix(agent-hooks): launch-authority retirement keeps a proven exit
* ci: remove Windows build and persistence test overhead
* ci: collect unit phase diagnostics during PR checks
* test(ci): seed hook reuse fixture from the canonical prebuild
The hook reuse regression first built into a missing private --output, so it
always reached Cargo (74s warm on Windows). Build through the default output
instead, which reuses a warm canonical prebuild, then copy its executable and
fingerprint into the private fixture root.
* fix(lint): clear inherited max-lines and broad object tab parameter after main merge
Combine the duplicate shared/execution-host imports in runtime-host-services
(301 -> 300 lines) and type the overlap test's tab mapper with the
RuntimeMobileSessionClientTab owner type instead of object.
* fix(ci): align inherited runtime and workflow contracts
* test: establish changed runtime probe signatures deterministically
* test: await asynchronous daemon profile cleanup
* test: shut down owned daemons before deleting profiles
* test: clean up oracle daemons during final app close
* test: recognize verified Linux zombie exit during daemon teardown
* fix: preserve folder SSH ownership when project groups conflict
* fix(accounts): open the browser for a WSL account sign-in
A WSL Add account / Sign in again ran the provider CLI inside the distro,
where stock distros have no opener, so no browser opened. Claude's link is
now caught by the same BROWSER stand-in Copy link uses, Codex's by the link
it already prints, and the desktop opens it after validation.
* fix(accounts): never open a cancelled WSL sign-in's link; wait the full login window
Addresses review: watch the login's cancel signal before opening, give auto-open
the whole login window to receive Claude's link, log the refused host, and cover
cancel-before-delivery and service wiring in tests.
* feat(layout): add the dark layout.apply channel and route pane splits through main behind ORCA_LAYOUT_OWNER
A build made with ORCA_LAYOUT_OWNER=main registers layout.apply: main applies the
window's layout command to the stored partition through the shared applyLayoutCommand,
minting new ids. A user split then waits for main's answer and mounts the pane id main
minted. Every other build substitutes 'window', so neither branch is compiled in.
* fix(layout): write only the records a layout.apply command touched
A load-then-save rewrite also normalizes records the command never touched. The command's
effect is now the diff between the save before and after it, written onto the stored
partition record by record. A split whose main reply says a paired server holds the tab
splits as today.
* fix(layout): write a load-supplied record whole and check that patched partitions reload to the command's result
* feat(layout): close, rename and equalize panes through main behind ORCA_LAYOUT_OWNER
In a layout-owner build the window's pane close, title change and equalize go through
layout.apply and the window shows main's answer. A window pane close keeps the legacy
close's rules: the tab's last pane is refused, a pane restarted since main read the close is
left alone, every partition holding the tab closes it, and the tab's remote session id follows
the remaining pane. The rules sit behind a command field only layout.apply sets.
* fix(layout): close the tab when a racing pane close leaves the window one pane
* fix(layout): leave an unmounted tab alone when main refuses its last pane
* feat(layout): move panes and save divider ratios through main behind ORCA_LAYOUT_OWNER
Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125
* test(layout): a taken pane drop whose pane closed does nothing
Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125
* test(layout): pin the window's pane move to main's saved tree, and the drops main cannot take
Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125
* fix(layout): close a user's pane even if its terminal restarted, as today
Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125
* test(layout): pin the restarted-pane close directly, not through a made-up profile state
Claude-Session: 10569c9a-a0a1-4fc9-8469-0edfb7aed125
* fix(layout): leave a split to today's path only when the workspace's row names a paired server
The split switch point asked which host to route to with a helper that falls back to the focused
server, so a focused server could claim a workspace whose row names no owner. Use the same owner
test the tab mirror uses.
* test(layout): type the split owner mock without a cast
* test(layout): type the layout-owner command mocks with the real signature
* test(layout): type the gesture command mock with the real signature
* fix(layout): close the dark path's gaps: unmounted split panes, refused or failed splits and moves, ratios during a move, release guard
- A pane main saved but the window could not mount (source pane or manager gone during the await)
is closed again in main, so it does not come back on restart.
- A split main refuses because its copy lacks the workspace, tab or pane, or a failed call, splits
as today; a refused or failed move moves as today.
- Divider ratios committed while a move is in flight wait for the window's move, then go to main.
- The orcad bundle gets the ORCA_LAYOUT_OWNER define when the switch is on.
- Packaging and the orcad template refuse ORCA_LAYOUT_OWNER=main and any output a dark build marked.
- workspace-layout-record-patch.ts: no non-null assertions; plain comment for the map depth.
* test(layout): count a split pane as mounted from the split mock's own results
* fix(layout): act as today whenever main lacks the target or the call throws, not just for splits
- sendPaneCommandToLayoutOwner runs asToday for workspace/tab/pane_not_found and a thrown call, so
close, rename and equalize fall back like split and move; a handler that throws no longer runs the
fallback too.
- A close main refuses as its last pane, while this window still has others, closes as today.
- A move whose local step throws still releases held divider ratios.
- Drop the orcad output marker: nothing read it; the template build refuses the switch itself.
* test(layout): plain names for the last-pane fallback test and the marker comment
* docs(layout): say plainly what an indeterminate write can leave behind
* fix(layout): finish the main merge with this branch's versions of the layout-owner files
* test(build): copy the layout-owner build guard into the compiler-cache checkout fixture
* feat(layout): send tab rename, color and pin through main behind the layout-owner build switch
In an ORCA_LAYOUT_OWNER=main build, the tab bar's rename, color and pin ask main's layout.apply
first; the window then runs today's action. When main lacks the tab or the call fails the
window acts as today; a paired server's workspace keeps today's path. Pinning a tab now also
ends its preview in main's copy, as the tab bar's pin does. Other builds compile the switch out.
* fix(layout): leave a pinned tab's preview mark to the window until main opens files
Changing the shared pin command would change what a paired client's pin does in every build.
* fix(layout): write a folded legacy row in its loaded form when a layout.apply command touches its claim
A legacy terminal row the load folds into a tab-bar tab stays stored as is. Closing the tab it
repeats, or giving it a tab-bar entry by moving it, let the next load resolve the claim the other
way: the row came back or took the other tab's terminal. Such a command now writes the row as
the load had it; every other record still stays as stored.
* feat(layout): accept tab moves, group splits and group sizes on layout.apply
Group sizes have no tab, so they go to the workspace's routed partition.
* refactor(layout): move the window's layout.apply sender out of the terminal pane folder
Tab groups send through it too; it now also acts as today when main lacks the group.
* feat(layout): reorder, move and split tab groups, and save group sizes, through main behind ORCA_LAYOUT_OWNER
A tab drop and Move Tab to Split wait for main's answer and then show main's placement, with main's
new group id; group divider sizes are drawn while dragging and saved by main when the drag ends.
Closing an empty group needs no command: main never holds an empty group.
* docs(layout): wrap the layout-owner sender's doc comment
* fix(layout): review fixes for tab moves through main
- Read a folded row's terminals with the loader's own claim rule, so rows sharing only an SSH
session are covered too, and drop the row's remote session entry with it.
- The record-patch test allows a folded row only in its loaded form.
- A tab drag ends at once; main's answer shows the move after.
- A lone group main moved whole is placed so only when this window's group is lone too.
* refactor(layout): adopt only a folded row's pane layout beside its row
A row's remote session entry is carried through load and save unchanged, so adopting it from the
load changed nothing (the earlier commit's message overstated it).
* feat(layout): record a window's terminal tab close through layout.apply
closeTabs can now record each terminal tab it closes, or does not find, as closed for the given
reason (pruned as a partition's records are), so a start that commits later is refused, as today's
close records it. layout.apply takes one tab's close with the window's reason: main forces it in
every holder partition, marks a user close's launches, stops no terminal (the window already did,
sparing any another tab shares), and leaves a workspace it lacks to today's close. A sibling the
load supplied that the close only renumbered is no longer written.
* feat(layout): send the window's terminal tab close to main behind ORCA_LAYOUT_OWNER
The window still closes the tab and stops its terminals itself; main records the close through
layout.apply instead of the close intent, which stays for paired servers and when main lacks the
workspace.
* fix(layout): review fixes for the tab close through main
- The window's close sends through a store-free sender, so the store no longer imports itself.
- Main marks a user close's launches by the terminal's own id.
- A recorded close prunes the whole partition's close records, as today, not one workspace's.
* feat(layout): move a window's dragged-out pane into a new tab through layout.apply behind ORCA_LAYOUT_OWNER
* refactor(layout): keep the topology commit under its line limit
* fix(layout): review fixes for the window's pane drag-out through main
* refactor(layout): re-key a moved pane from the move alone
* feat(space): open disk usage in a separate window
* perf(space): move local disk scan off Electron main thread
* fix(space): satisfy full PR quality gates
* test(runtime-environments): pin connect, remove, call readiness, hint and phone relay per host kind
* refactor(runtime-environments): dispatch on one exhaustive host-kind classifier
* test: avoid type assertions in host-kind characterization fakes
* refactor(runtime-environments): keep service-owned connect/remove in one module; tighten characterization tests
* style: break, not bare return, in host service ops switches
* fix(ssh): an opted-in desktop serves its browser to a managed SSH host's orca CLI again
* fix(ssh): scope bridged pages through the renderer, render them as desktop pages, and route the e2e
* fix(ssh): bridge refuses file URLs and clipboard reads, revokes on disconnect, closes desktop tabs
* fix(ssh): judge bridged paste chords as the page sees them; accept long workspace ids
* fix(ssh): bridged clipboard denial follows popups; revoked commands never leave the browser queue
* fix(ssh): refuse option-like host values bound for agent-browser argv; report undeliverable results
* fix(ssh): bound bridged error results and fall back when the host refuses one
* fix(ssh): bridge only routed host tabs, and bound bridged page scripts by a deadline and revocation
* fix(ssh): cap waiting bridged commands below the desktop socket's result capacity
* fix(ssh): bridge revokes on routing changes, checks each page's route at run time, and cancels host-driven downloads
* fix(ssh): name the bridge registry's owner type
* fix(ssh): bridge refuses pages showing a local document, and never starts a command past orcad's deadline
* fix(ssh): bridged commands may leave Chromium error pages, and stop starting before orcad's deadline
* fix(ssh): ask for a fresh opt-in to host CLI control saved before it drove the desktop browser
* test(ssh): type the bridge registry deadline test
* fix(ssh): finish the macOS launch-session warning's gaps (#29382)
Check it on automatic restores, once per SSH connection; create the data root
before recording; inherit a session only from this root's verified daemon; and
let only a verified restart clear the warning.
* fix(ssh): recheck the launch session per reconnect generation, after the restore update
* fix(ssh): reapply a known ended session to a replaced status; leave an unreadable daemon's attribution unknown
* fix(ssh): expire live launch-session verdicts, and drop an answer outlived by its connection or server
* [CI] Keep transport-only tests outside the app store graph
* [CI] Advance the updater install clock in failure tests
* [CI] Avoid descriptor formatting in replay clip counts
* [CI] Advance native-chat test observation clocks
* [CI] Restore observation timers after failed test setup
* [CI] Clean up final headless daemons during public close
* [CI] Keep serializer test oracle out of production smoke triggers
* [CI] Keep three unit fixtures out of production smoke triggers
* [CI] Bound frozen-clock close callbacks in tests
* [CI] Avoid the app-store graph in feedback dialog tests
* [CI] Keep hidden popup fixture compositor frames active
* test(ci): reuse mobile runtime fixture for pairing listeners
* test: restore native chat clocks before rig cleanup