Commit Graph
1549 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin 86a75e99c6 perf(bench): measure startup memory and cold SSH latency (#33912)
* perf(bench): separate historical startup loading evidence

* fix(bench): retry owned root identity before teardown

* fix(bench): format survivor identities explicitly

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 15:29:32 -07:00
ad2156c358 test: remove 140 low-value cases and 49 suites (#34062)
* test: remove 140 low-value cases and redundant browser probes

* fix: remove unused upstream chat menu import

* test: pin the host-split layout fixture branch

---------

Co-authored-by: Orca Test Audit <test-audit@stably.ai>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 15:16:27 -07:00
a93e31a933 perf(renderer): keep modal blur with independent source regions (#33799)
* perf(renderer): drop full-window overlay blurs and the idle usage-chip pulse

A full-window backdrop-filter is re-blurred on every frame while anything
beneath it animates, which held ~370 MB of extra GPU render-pass textures and
swapchain buffers while a dialog, sheet, palette or onboarding was open. The
2px scrim blur is barely visible under the black scrim, so keep the dim only
(5 points darker to keep the background as recessive) and drop the panel blur
that sits under a 96%-opaque background. The status-bar usage chip also pulsed
forever before its first fetch (unfocused windows never poll); show it static
until a fetch is actually running.

* perf(renderer): preserve modal blur with independent source regions

* fix(renderer): preserve modal blur recovery and Space coverage

* fix(ci): remove stale context-menu import after main merge

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 14:40:39 -07:00
Brennan Benson 9ae33a96f9 fix(native-chat): keep damaged chats readable without granting agent actions (#31931)
* fix(native-chat): validate saved next-fence floors before use

* WIP: separate saved conversation observations from runtime proof

* Consolidate duplicate imports for WIP compiler checkpoint

* Preserve saved conversation observations with strict runtime authority

* Consolidate session admission and catalog imports

* fix: align conversation observation contracts and fixtures

* test: update conversation observation and writer fixtures

* test: use checked host fixtures for structured workers

* fix(native-chat): bound conversation projection work per request

* test(native-chat): consolidate scale fixture imports

* test(native-chat): use checked scale fixture types

* test(native-chat): bound unreadable inventory traversal

* Test native CLI admission and durable reference reads

* test: bound cold conversation name subscription work

* test: distinguish native receipt probes from terminal identity

* test: retain exact mutation refusal recovery identity

* fix: explain agent conversation preparation refusals

* test: adapt remaining conversation readers and document CLI timeout

* fix: register preparation refusal English message

* test: align conversation fixtures with checked read APIs

* test(native-chat): use checked conversation in Codex fixture
2026-10-26 13:16:41 -07:00
Neil ec42b433ca fix(ssh): make Move anyway the next step when saved items refuse a host's move (#34041)
* fix(ssh): show Move anyway on a host card whose move saved state refuses

A host whose move to its Orca server was refused over saved state (an
enabled SSH automation and its runs, stale workspace details, unsupported
saved tabs) stayed in error on every Connect. Move anyway, which connects
it and leaves those items on this computer, was only in the card's
overflow menu, so the host looked stuck. The card now offers Move anyway
next to its refusal, as it already does for Recover server.

Refs #29083.

* fix(ssh): make Move anyway the next step when saved items refuse a host's move

When a host's move to its Orca server is refused only over saved items
that Move anyway can leave on this computer (#29083's enabled
automation and its runs, for example), every surface now leads with it:
- the host card says which items can't move and that Move anyway
  connects the host and keeps them here, with Move anyway as its
  primary button;
- the refusal toast says the same and offers Move anyway, opening SSH
  Hosts where the move is confirmed;
- the terminal pane's Move anyway is primary too;
- the host picker and connect toast read the same line.

Refs #29083.
2026-10-26 13:01:30 -07:00
Jinwoo Hong fa3bd28995 Let Resource Manager End stop orphaned terminals that main is attached to (#34040) 2026-10-26 15:29:06 -04:00
Neil b67429c03f fix(ssh): lead an SSH connect failure with what to do about it (#33990)
* fix(ssh): say why SSH failed when Connect never reaches the host

When the SSH session itself could not open (key rejected, port refused,
host not answering, host key not trusted), Connect on a host Orca had not
set up yet said "Orca couldn't start its server on this host" and offered
a plain SSH terminal that could not work either. Errors from opening the
SSH session are now marked where they are dialed, and a setup that fails
on one ends the connect with SSH's own reason. A held move keeps its
status. The connect-failure toast also drops Electron's IPC prefix.

* fix(ssh): lead an SSH connect failure with what to do about it

#33928 shows SSH's own reason when Connect never reaches the host. Raw
reasons like "connect ECONNREFUSED 10.0.0.1:22" or "Timed out while
waiting for SSH authentication" still leave users guessing. A failure
from opening the SSH session is now published with a next step for the
kinds users can act on (host key mismatch, rejected sign-in, refused
port, unknown host name, no route, timeout), and SSH's words follow in
parentheses. The connect-failure toast reads the same published text.
2026-10-26 12:16:04 -07:00
Neil ae55694d27 fix(ssh): show Move anyway on a host card whose move saved state refuses (#33961)
A host whose move to its Orca server was refused over saved state (an
enabled SSH automation and its runs, stale workspace details, unsupported
saved tabs) stayed in error on every Connect. Move anyway, which connects
it and leaves those items on this computer, was only in the card's
overflow menu, so the host looked stuck. The card now offers Move anyway
next to its refusal, as it already does for Recover server.

Refs #29083.
2026-10-26 12:02:02 -07:00
Brennan Benson 532f6a0e00 Ask before Codex workspace edits and apply permissions to fresh turns (#31299)
* Apply Codex Ask permissions at each fresh turn

* fix: admit fresh Codex input with current host permissions

* fix(native-chat): finish cancelled Codex input under its owner

* fix(native-chat): preserve mobile type boundary for input finalization

* test(native-chat): bound input finalization work at scale

* Fix cancellation result fences and exercise host proofs

* Fix input finalization type contracts

* Remove obsolete Portuguese permission description

* Preserve proven Stop outcomes during input finalization

* Preserve input handover proofs with session-ending Stop

* Preserve pending input recovery before lifecycle cancellation

* Assert one recovery card across overlapping close requests

* Preserve unwritten inputs across shared-agent Close preparation

* Narrow cancelled dispatch to its rejected outcome

* Import Codex app-server types from their colocated modules

* Use standard Ask policy for fresh Codex chat input

* Deliver applied Codex permission reports to the host

* Cover applied reports with pending settlement waiters at scale

* Fix settlement waiter timer portability on mobile

* Keep pre-send exit failures with their original input result
2026-10-26 10:50:00 -07:00
Brennan Benson c20971dbd1 fix(native-chat): send launch prompts and worker tasks through the retrying start (#33832)
* Make opening launch prompts own the retrying chat start

* test: observe launch inventory through surface publication

* fix: keep blank chat launch prompts unsent

* fix: bound launch seed filtering and update CLI replay fixture

* fix: preserve encoded launch selections after filtering
2026-10-26 10:45:40 -07:00
1d0d3f5e94 fix(ssh): expand %d, ${NAME} and other tokens in ssh -G IdentityFile paths (#33981)
* fix(ssh): expand %d and other tokens in ssh -G IdentityFile paths

OpenSSH prints IdentityFile values from `ssh -G` with their percent
tokens unexpanded (it expands them only at connect time), so a config
line like `IdentityFile %d/keys/work.pem` reached Orca as a literal
relative path. The key was silently skipped and the connection fell
back to a password prompt even though plain `ssh <alias>` worked.

Expand the tokens OpenSSH supports for IdentityFile that can be derived
locally or from the ssh -G output (%%, %d, %u, %i, %l, %L, %h, %n, %p,
%r). Paths with tokens that need OpenSSH internals (%C, %j, %k) are left
unchanged. A configured, non-default identity file that does not exist
is now named in the auth error instead of being skipped silently.

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

* test(ssh): reproduce #33849 end to end and keep tests off the real ~/.ssh

Adds a Docker e2e: a host from ~/.ssh/config whose IdentityFile uses %r
and %p connects with that key. It fails on v1.4.241 and passes with
the token expansion. Drops a unit assertion that read the real
~/.ssh/id_xmss.

* fix(ssh): expand ${NAME} in ssh -G IdentityFile paths too

ssh -G also prints IdentityFile's ${NAME} environment references
unexpanded, so a key at ${KEYS}/work.pem fell back to a password prompt
in the same way as #33849's %d. Expand the braced form first, and keep
the raw path when the variable is unset, as OpenSSH refuses it.

---------

Co-authored-by: william <wanglv93@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 08:51:31 -07:00
Neil c1d3031bcd test(e2e): wait for the catalog failure past a slow conversion (#33960)
"reconnect restores the managed host name after its conversion catalog
fails" started page.waitForEvent('console') before the reconnect that
converts the host. Its 30 s clock ran through the conversion, so on a
loaded machine or a slow host the test timed out even though the catalog
failure was logged. It failed this way on unmodified main locally. With
the Docker host frozen for 35 s during the reconnect it fails every time
before this change and passes after it. The test now collects console
messages and polls once the host is managed. It also drops a log line
the app no longer prints.
2026-10-26 07:52:20 -07:00
Neil 899d2aad96 fix(ssh): say why SSH failed when Connect never reaches the host (#33928)
When the SSH session itself could not open (key rejected, port refused,
host not answering, host key not trusted), Connect on a host Orca had not
set up yet said "Orca couldn't start its server on this host" and offered
a plain SSH terminal that could not work either. Errors from opening the
SSH session are now marked where they are dialed, and a setup that fails
on one ends the connect with SSH's own reason. A held move keeps its
status. The connect-failure toast also drops Electron's IPC prefix.
2026-10-26 06:51:39 -07:00
NeilandClaude f5b2cc5a79 fix(native-chat): say why Claude refused to start a chat, including Full access as root (#33812)
* fix(native-chat): say why Claude refused to start a chat, including Full access as root

Claude Code exits before initialize when Full access (--dangerously-skip-permissions)
meets a root uid, which is common on SSH hosts. Orca reported only that Claude
stopped before it finished starting, and retried four times. Classify that refusal
as fullAccessAsRoot with a next step, and show the CLI's own startup words behind
Details on the failure row and on the unsent message.

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

* fix(native-chat): keep message Details to start failures; cover the exit path

Route the exit-error module and delivery notices to the managed e2e, explain its
timeout, and drop the exec non-null assertion. Match the zh Full access label.

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

* test(native-chat): type the refused fixture so the web typecheck passes

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 05:00:45 -07:00
NeilandBen Grynhaus d1f04e6042 fix(terminal): a pane moved to a new tab stays moved on paired servers (#33027)
* test(e2e): a pane moved to a new tab on a paired server workspace stays moved

* fix(terminal): keep a pane moved to a new tab on paired runtimes

Moving a split pane to a new tab in a paired-runtime worktree changed only
the window store. The host never learned about the move, so the next host
snapshot rebuilt the old tab and the pane snapped back.

Add a session.tabs.movePaneToNewTab RPC that commits the move in the host
session through planTerminalLeafMove and republishes the session tabs.
For a mirrored host tab, the renderer applies the move first under the
mirrored id the host snapshot will use, then asks the host to commit it.
An older host or a refused move falls back to the old local-only move.

Fixes #32939

* fix(terminal): commit a host pane move through the existing leaf-move writer

The layout-writer ratchet allows no new main-process layout writers. The
headless host now hands the move to commitLeafMoveAndRekey, the same
commit a local window uses, and keeps only the window check, validation,
rehydrate and notify.

* fix(terminal): gate the host pane move on a host capability

An older host keeps today's window-only move under a local tab id instead of
a mirrored one it never confirms. Adds a terminal.list check to the e2e.

* test: drop type assertions from the pane-move tests

* fix(terminal): the host keeps a moved pane's place, focus and live terminal

After the host commits the move, the window gives it the drop position and
focus through the existing tab move and activate calls; a refusal redraws the
host's tabs. The host moves the live PTY's surface with its pane and checks the
target tab id. The move lives in its own runtime module.

* fix(terminal): hold a moved pane's drop order until the host has it

The host's snapshot of the commit goes out before its reply and appends the
tab, so the window records the drawn order as a reorder intent at the drop and
sends that order, and the focus read then, once the host answers.

* fix(terminal): route the moved tab's reorder to its owning host

The follow-up names the worktree's host instead of reading the active-server
setting (focus-read ratchet); the e2e narrows host rows to terminal tabs.

* fix(terminal): the host places a moved pane's tab in the move itself; a refusal reverts

The move carries the drop's group and index (optional; an older host appends)
and the host places and selects the tab before its one publish, replacing the
follow-up reorder and the drop-time order hold. A refused move closes the tab
this window drew without stopping its terminal and redraws the host's tabs even
when unchanged. E2e covers a same-group drop and a refusal; host unit tests cover
same-group and cross-group placement.

* fix(terminal): a refused pane move keeps its pane records; drop index in host order

The revert hands the pane's status and launch records back to the source tab
before closing the drawn tab. The host turns a projected client's drop index
into its raw order with translateProjectedSessionTabMove, as session.tabs.move does.

* fix(terminal): only an unknown drop group appends a moved pane's tab

The host catches only target_group_not_found and invalid_tab_order from the index
translation and rethrows anything else.

* fix(terminal): settle a pane move by what the host holds when its reply is lost

A lost reply is not a refusal: the window asks the host whether it holds the
pane in the new tab before undoing anything, and waits for the next snapshot
when it cannot ask. A move the host committed but this window could not draw
takes the host's tabs.

* fix(terminal): a lost transport on a pane move is unknown, not a refusal

runtimeEnvironments.call answers a dropped or overloaded transport with an error
envelope; those codes (the shared recoverable set) now ask the host instead of
undoing a move it may have committed.

* test(e2e): pane-move spec waits on real signals, not delays

The source tab is created on the server and split once its shell is listed, so
the split no longer races a desktop-seeded tab's first spawn (the CI failure).
The stay check follows output from the moved pane; the refusal check waits for
the drawn tab to appear and go.

* test(e2e): read the refused move's tab counts without Reflect (anti-slop)

* fix(terminal): a moved pane's tab joins the order the user had, not a rebuilt one

The host inserts the new tab into the group order captured before the commit,
appending without a drop position, so editors and pages keep their places. The
shared group-move fallback is no longer used here.

* fix(terminal): a moved pane's groups hold the host's current tabs, in the user's order

Placement takes membership from the rebuild after the commit and only the order
from before it, so a tab opened while the commit was pending stays (after the
user's tabs) and no stale id is written.

* fix(terminal): a moved pane's placement keeps a reorder made while it committed

The order is read after the commit, from the host's current tabs, not before it.

* fix(terminal): a moved pane keeps the lone group the user merged into

A rebuild names a single group with the default id; placement keeps the user's
id for it, so the drop position still applies after a split was merged back.

* fix: import error classification from its new shared/remote-runtime path

* fix(terminal): a pane or divider drag survives focus moving inside the window

The drag's window blur listener was registered in the capture phase, so it also
heard every element blur. A terminal attach or host snapshot that moved focus
between panes mid-gesture ended the drag; in the paired pane-move e2e on CI it
cancelled the drag before the drop. Only the window losing focus ends it now.

* test: drive the focus-change drag test through a real pane manager, without casts

* fix(terminal): a headless host moves a pane with its live terminal and never empties its source

The host names the PTY it holds for the pane, so a session copy an SSH respawn
left with an old id no longer refuses the move as a mismatch. A move that would
leave its source tab with no pane (a sibling closed meanwhile) is refused, since
no headless cleanup retires the emptied tab and it would publish as a phantom.
The e2e fences its stays-moved check on a later server rename instead of
sampling on a timer.

---------

Co-authored-by: Ben Grynhaus <ben.grynhaus@wiz.io>
2026-10-26 02:01:08 -07:00
Neil e6da9ca339 fix(terminal): answer queries in output a paused paired view discards (#33783)
* fix(terminal): answer queries in ACK-pending output a paused paired view discards

Refs #32944

* fix(terminal): capture yielded-query ownership at ingestion and cap reply age

Refs #32944

* fix(terminal): settle yielded queries by their own end seq across split frames

Refs #32944

* test: use a fixed timestamp in the yielded-query responder test

* test(cross-version-wire): stub yielded-query runtime methods on the host runtime

Refs #32944
2026-10-26 01:56:42 -07:00
Brennan Benson c0714b9ce0 Fix Codex goal Stop and selected model settings (#33631)
* Fix Codex goal Stop and selected model settings

* Preserve settings evidence and captured Stop outcomes

* Preserve refused goal pauses and bound Stop retry diagnostics

* Use checked settings state in goal contract tests

* Narrow captured Stop child and type its timing fixture

* Coordinate Stop timing fixture with deferred phases

* Fix typed mobile warning icon assertion

* Align Stop tests with reconciled controls and owned shutdown

* Check integration attach parameters without a type cast

* Match restart offer close calls to optional observer contract
2026-10-26 01:01:19 -07:00
Jinjing e4b1e4d22b Revert "fix(native-chat): preserve Claude approval choices across model chang…" (#33823)
This reverts commit 4833b736f7.
2026-10-26 00:44:45 -07:00
OrcaWinandOrcaWin cc3ca668d8 test: remove low-value predicates, inventories and helper echoes (#33778)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 22:57:11 -07:00
Neil 4843f85f2a refactor(renderer): group agent-status records and reducers (#33665)
* refactor(renderer): group agent-status records and reducers

* refactor(renderer): consolidate concrete type owner imports
2026-10-25 22:20:14 -07:00
OrcaWinandOrcaWin 852dfcd282 test: remove redundant browser and transport coverage (#33757)
* test: remove redundant browser and transport coverage

* test: retire deleted suites from reliability manifest

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 20:46:39 -07:00
Neil ddcedee37c fix(remote): a desktop no longer serves other runtimes its tabs on its servers' files (#33424) (#33752)
* fix(remote): a desktop ignores its own workspaces echoed back by a server it serves (#33424)

When two desktops pair to each other, each server republishes the tabs it
mirrors from its own servers. Desktop A then received B's mirror of A's own
workspace under the real workspace id and grafted it onto its local copy as
B-hosted tabs, so opening those files asked B (selector_not_found) and closing
them closed B's tabs.

A session-tabs frame from a paired server no longer writes a workspace this
app lists as its own (a stamped local or direct SSH row) unless that server
also lists a copy. Other servers' workspaces stay open to every runtime.

* fix(remote): retire echoes already taken and replay frames a twin's late row releases

An echo fenced out of this app's own workspace now applies as that server's
tombstone, so rows it left before the fence (restored sessions, or frames that
arrived before this app's own row listed) are retired without closing anything.
A held frame replays once the server's own copy of the workspace lists, so a
same-id twin that publishes before its row loads still mirrors. The e2e waits
on a later frame from the same stream instead of a fixed delay.

* fix(remote): serve a desktop's tabs on its servers' files only to its phone, not to other runtimes

Redesign of the #33424 fix at the source. A desktop publishes every editor tab in
its window, including ones on files of its paired servers; its phone uses those
through the desktop's relay. Served to another runtime, such a tab routes the file
to the desktop, and in a pairing cycle it is that runtime's own workspace coming
back as the desktop's tab: file reads fail with selector_not_found and closing it
closes the desktop's real tab.

Publishers now stamp those rows with hostRuntimeEnvironmentId (window, layout-owner
main projection and the windowless projection alike). projectSessionTabsForClient
strips the stamp for every caller and drops the stamped rows for runtime-scope
callers, keeping groups, layout and the active tab consistent. Phones and local
callers see what they saw before. The receiver-side fence is removed.

* refactor(remote): keep the file-host stamp helper outside the old-client boundary; test an all-server snapshot
2026-10-25 20:28:07 -07:00
OrcaWinandOrcaWin f01a97201b test: remove wrapper replays and test fixture inventories (#33745)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 20:09:25 -07:00
OrcaWinandOrcaWin 1ff73e808d feat(claude): navigate and track subagent views from sidebar (#33322)
* feat(claude): open subagent views from sidebar rows

* test(claude): type mod session events for CI lint

* test(claude): preserve sidebar preference types

* fix(claude): localize subagent navigation notices

* fix(claude): refresh managed mods asynchronously

* fix(claude): track the viewed agent and honor parent selection

* test(rpc): include Claude view observations in terminal manifest

* fix(claude): preserve bindings and isolate optional view setup

* fix(claude): scope subagent mods and avoid redundant shortcut input

* fix(claude): reconcile navigation setup outside PTY spawns

* fix(i18n): include Claude navigation search terms in runtime catalog

* fix(claude): keep terminal spawns independent of navigation setup

* test(claude): use fixed clocks for navigation coverage

* test(claude): isolate navigation cleanup from startup fixtures

* fix(claude): clean cached shell configs without probing

* docs(claude): describe cached config cleanup limitation

* fix(i18n): preserve navigation search localization after rebase

* feat(claude): enable sidebar subagent navigation by default

* test(claude): update WSL fixtures for automatic navigation

* docs(claude): remove subagent navigation readme

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 18:53:42 -07:00
Brennan Benson 4833b736f7 fix(native-chat): preserve Claude approval choices across model changes (#30914)
* fix(native-chat): a Claude chat saved as Approve for me keeps it when Orca can't read its model list

A chat's auto mode dropped to Ask whenever the saved model list was missing
or couldn't name the chat's model (another account home, first start in a
folder, an unlisted model id), so a resumed chat launched asking for approval.
Auto now drops to Ask only when the list shows the model without it; Claude
itself starts a model that can't run auto in its default mode.

Tracked in STA-10953.

* fix(native-chat): a model list from a CLI older than auto mode still reads as Ask

A CLI that marks no model with auto support predates the auto value (2.1.71)
and would refuse --permission-mode auto, so its listing is evidence, not a gap.

Tracked in STA-10953.

* docs(chat): correct auto support reporting version

* test(chat): type saved launch option cases

* Honor requested chat permissions across model changes

* Match outgrown child fixture to journal null contract

* fix(native-chat): preserve admitted input and current mail choices

* perf(native-chat): derive wake debt and held sends once per retirement decision

The retirement check derived wake debt (a child-work projection and a scan
for the newest turn) before asking whether open work had already decided
the outcome, and its admitted-input fallback rebuilt the provider's held-send
set once per unanswered submission, O(S x W) per decision.

Open work is now read first and wake debt only where it picks the outcome or
the refusal reason. Current work gains one batch query that reads the held
set and the handover set once, sharing the single holds rule with the
per-send reader. Outcomes and refusal reasons are unchanged.

Adds N/10N operation-count contracts on the real Claude host rig: two
retirement checks per ordinary send, each one pass over history, with a
control that the second sees a sign-out reported between them; no wake debt
mid-turn; one held-set read per refusal in a queued model-change burst.

* Keep active Claude input on its turn choices

* Fix chat admission type imports and cover turn-scan costs

* Preserve root lifecycle delivery under journal pressure

* test: construct Codex mail fixture with its source

* test: expect root retention metadata in Claude turn timing

* test: cover captured Claude full-ID Auto launch

* test(native-chat): explain queued-send test timeout

* test: supply explicit mailbox working policy
2026-10-25 17:53:19 -07:00
c0a51bcd88 fix(ssh): don't refuse a host's move over a pane that saved no terminal history (#33681)
* fix(ssh): don't refuse a host's move over a pane that saved no terminal history

A pane with an empty inline buffer, a deleted snapshot, or a zero-byte
snapshot has no history to lose, but the move's projection filed it
under "saved terminal history Orca could not read" and refused the whole
host. Tell absent snapshots apart from unreadable ones and move the
former without history; unreadable history still blocks.

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

* fix(ssh): keep looking in the fallback root when a scrollback snapshot is empty

A zero-byte snapshot in the primary root returned 'absent' without checking
the fallback root, so a pane whose history lived there moved without it.
Also check ENOENT inline rather than importing a window staging helper.

* test(e2e): seed unreadable relay scrollback as an over-limit snapshot

A missing snapshot file now means the pane saved no history, so the
leave-behind spec needs history that exists but cannot be read.

---------

Co-authored-by: Younghwan Chae <chyohw97@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:27:13 -07:00
Jinjing d37c04c82c Fix notification bell layout (#33683)
* Fix notification bell layout and isolate Vite tsconfig resolution

* Move Vite tsconfig fix out of notification bell PR
2026-10-25 16:45:52 -07:00
Brennan Benson 3aec926fe5 Chat renames are saved as the chat's name, so Session History shows them after the tab closes (#31602)
* Chat renames are saved as the chat's name, so Session History shows them after the tab closes

Renaming a native chat tab only changed that window's tab. Session History, phones and other windows read the host's saved name, so the rename vanished from History once the tab closed or Orca restarted.

A rename now goes to the host that owns the chat (agentSession.rename) and is saved as the chat's one name, the field History, tabs, sidebars and phones already read. The record remembers that the user chose it, so automatic naming never replaces it. A window's pre-upgrade tab rename is uploaded once and only fills a name Orca chose. Hosts without the new capability keep the old tab-only rename. Every native agent's History row now shows the chat's name once it has one.

* Keep saved chat names consistent across readers and reconnects

* Carry qualified chat names into cached readers

* Reuse the history recorder context across platforms

* Use recorded chat ownership for legacy name transfer

* Transfer legacy chat names only from known catalog ownership

* Correct recorder path matching and History subscription order

* Require complete evidence for bridged parity exclusions

* Preserve sparse array lengths in complete recording comparisons

* Initialize History observation before loading workspace context

* Integrate measured History recordings and scoped parity evidence

* fix chat naming retries and certify both replay modes

* fix ambiguous chat rename labels after navigation

* preserve chat rename intent across tab updates

* type dashboard snapshot fixtures without assertions

* fix: align chat name observation with store contracts

* test: update chat name consumer fixtures

* test: distinguish sender naming metadata from status

* Preserve saved Activity chat names across tab focus

* Clarify Activity tab projection identity

* Remove package-manager lockfile churn from main merge

* fix(runtime): validate tab property edits before saving chat names

* fix: refresh History ownership after conversation clear

* fix: commit History request identity before refresh effects

* Fix History scan scope typing and integration test placement

* test: cover saved chat name reader contracts

* test: make chat naming fixtures deterministic
2026-10-25 16:20:29 -07:00
Brennan Benson 23798eff7c Let chats follow the agent permission setting (#32334)
* feat(agents): store each agent's permission itself instead of typing flags into Arguments

Terminals and new chats read one stored choice per agent (Use the agent's own
settings, Ask for approval, Accept edits, Approve for me, Full access). Orca adds
the flag at launch; Arguments hold only the user's own text. A one-time move
lifts Orca's flags out of saved Arguments. Older clients still see and write
the flag as part of Arguments; the host translates.

* fix(agents): say the all-agents switch resets agents set separately; keep primitives unstyled

* test(agents): the one-time move returns every launch-profile field

* Fix permission carrier ownership and surface-specific defaults

* Preserve uncertain permission operands and name the option inventory

* Check env entries without indexing typed agent maps

* Combine Chat permission capability imports

* Use folder execution-host platform for permission environment

* Preserve launch map replacement and acknowledge permission saves

* Keep permission feedback fallbacks statically discoverable

* Provide preload platform to Agents settings render tests

* Preserve Gemini approval arguments under Full access

* fix(settings): retain complete environment edits through save outcomes

* fix(settings): narrow local failure scope and preserve host messages

* fix(settings): retire argument drafts after acknowledged saves

* fix(settings): keep Goose environment editable after reset

* fix(settings): show resolved arguments for legacy hosts

* Preserve pending environment resets and bound launch settings work

* Use agent permission choices for new chats

* Let Claude resolve chat permissions from its own settings

* Keep optional settings fallback in repository metadata reads

* Consolidate permission report imports

* Update permission choice contracts for own settings

* Read repository visibility defaults through the raw settings fixtures

* Match existing translated Agents settings labels

* Update readback and legacy host test expectations

* Align Chat behavior tests with host permission capability

* Fix permission compatibility and host-owned descriptions

* Prepare whole Environment edits and retire unchanged drafts

* Handle null explicitly in permission report decoder

* Keep Environment settings transitions in an acyclic module

* Update raw settings reader test fixtures

* Place test fixture safety notes on assertion starts

* test: pin permission settings work and recovery contracts

* test: type permission settings work fixtures

* test: cover migrated permission inputs and captured CLI grammar

* Publish permission reports and reuse host capability state

* Combine mobile option state React imports

* Honor mobile status feed capability for permission reports

* test: preserve typed permissions in WSL Claude restarts

* Correct permission report child and fixture type contracts

* Delegate older-host chats to explicitly selected own settings

* Avoid rebuilding live ACP option catalogs

* test(chat): place cross-boundary permission contracts in integration project

* Preserve existing chat capability gates and complete report test fixtures

* fix(chat): preserve newer Claude startup permission reports

* test(chat): clarify startup report fixture provenance

* Show reported permission modes in chat menus

* Keep reported permissions available after chat mode picks

* Remove obsolete guard from concrete permission selection

* Report the installed approval policy for ACP chat menus

* test: keep accepted mobile mutation fixture on current fence

* test: cover installed ACP approval report for own chats

* test: align capability scaling contract with concrete permission menus

* Ship required permission help in English runtime catalog

* Adapt permission persistence test to shared menu
2026-10-25 16:00:15 -07:00
Jinwoo Hong 47ed6e1154 fix(orchestration): wake an agent for new mail even while it still holds an unacknowledged batch (#33639)
Fixes STA-11980
Fixes STA-11631
Supersedes #29006
2026-10-25 18:38:34 -04:00
Jinwoo Hong 28de913868 test(connectors): drive a connector conversation end to end on a headless serve host (#33613)
Adds an end-to-end test that boots an isolated headless serve host and drives the orca connector CLI against a scripted Claude. Runs in the existing PR e2e job only when connector code changes.
2026-10-25 18:07:30 -04:00
Neil 47d1b31027 refactor(mobile): group native chat send and stream state (#33640)
* refactor(mobile): group native chat send and stream state

* refactor(mobile): use concrete type namespaces in send fixtures
2026-10-25 14:59:51 -07:00
Brennan Benson 883b768bc7 A chat never starts writing a conversation a terminal is still writing, and restored panes respect open chats (#30930)
* fix(native-chat): one ownership index with link roles, and a chat refuses to start while a terminal writes its conversation

Each chat link now carries its role (head or earlier) and key; Session History names
the chat continuing a conversation first, duplicate adoption checks only head links in
both the pre-commit check and the store transaction, and terminal resumes stay refused
exactly as before. The terminal-writer check now also runs inside acquireOwner before
the spawn, refusing with the typed pre-spawn reason conversationOpenInTerminal.

* fix(native-chat): hold a terminal start Orca issues until its terminal reports it

An in-memory registry of managed terminal starts per conversation, registered in the
same step as the resume admission (terminal.send with a resume command, createTerminal
with a command), bound to the PTY execution that runs it, and ended only when that
terminal's hooks report the conversation or the execution is gone. A chat's agent
start refuses while an entry may hold its conversation.

* fix(terminal): an automatic pane restore never resumes a conversation an open chat continues

Resume recipes built from a pane's saved facts (cold restore, deferred and late reattach,
sleeping wake, host mobile materialization) carry resumeOrigin 'saved'. The execution host
decides before any command is issued: while an open chat continues the conversation, or a
chat may be writing it, the pane starts its plain shell with the started-fresh notice and
its saved claim is forgotten; with unreadable records only a saved restore is refused and
its record kept. An admitted resume registers its managed start in the same step, so the
chat's agent start refuses until the terminal reports it or exits. Clearing the last saved
record now reaches disk.

* Fix saved terminal resume ownership and effective launch results

* Preserve conversation case and clear refused cold restore identity

* fix: publish effective terminal launch results on attachment

* fix: preserve terminal launch callback and candidate ownership

* fix: keep existing terminal attachments observational

* fix: consolidate terminal launch imports

* test: document snapshot runtime fixture boundary

* fix: preserve terminal launch identity types

* fix: accept reattach payload policy sessions

* fix: preserve terminal result validation contracts

* refactor: separate terminal create contract

* test: document partial terminal runtime fixtures

* test: align sleeping resume store fixture

* Fix terminal create type contracts

* fix: return the terminal main started to its waiting view

* fix: register reattached terminals before publishing their handles

* Check unavailable-resume test fixture types

* Complete sidebar resume test store fixture

* test: bound saved resume ownership and refusal work

* Settle refused saved resume claims from actual launch results

* Fix saved resume test type contracts

* test(e2e): capture exact terminal parking diagnostics

* test: verify parked terminal with fresh host inventory

* Consolidate agent session imports in remote terminal transport

* Clarify terminal conversation refusal guidance

* Admit note-only saved conversations without hiding live writers

* Retain terminal writer proofs through final admission
2026-10-25 14:39:05 -07:00
NeilandMohith S 92fd257bd9 fix(projects): refuse project setup on a paired server's SSH host with a clear reason (#33284)
* Refuse unsupported SSH project setup before local API dispatch

* fix(projects): keep the desktop's SSH refusal copy and drop a re-export

The desktop's own project-setup IPC is not an Orca server, so it keeps
saying the SSH connection is not connected; the renderer now refuses SSH
setup before reaching it. Callers import the shared refusal message
directly instead of through the controller. Adds a headless paired e2e
that sets up a project on the server's SSH host from a web client.

Refs #33124

* fix(projects): give the server refusal only for a paired server's SSH host

A desktop's own SSH host keeps its 'not connected' copy; the server
refusal shows on a web client, or for a target only a paired server lists.

Refs #33124

* test(e2e): read the added SSH target from the RPC result

* test(e2e): pass a typed SSH execution host id

* test(e2e): give the paired SSH project-setup timeout bump its reason

---------

Co-authored-by: Mohith S <smohith58@gmail.com>
2026-10-25 13:15:44 -07:00
Jinwoo Hong 2f25699094 fix(orchestration): let a new check --wait start while an old one is still waiting (#33013)
Fixes #30895
2026-10-25 15:00:51 -04:00
OrcaWinandOrcaWin 2a28fc7d4e [comment audit] Finish launcher and configuration comment review (#33513)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 04:20:32 -07:00
OrcaWinandOrcaWin 7d6603aa17 [comment audit] Complete repository-wide comment cleanup (#33249)
* [comment audit] Align legacy failure-read counts with cached display

* [comment audit] Condense shared provider lifecycle and browser recovery comments [skip ci]

* [comment audit] Condense shared generation, path and preview comments [skip ci]

* [comment audit] Condense host, file and Git contract rationale [skip ci]

* [comment audit] Tighten Git lifecycle and provider contract comments [skip ci]

* [comment audit] Clarify shared host authority and launch isolation [skip ci]

* [comment audit] simplify local access mobile and native chat contracts [skip ci]

* [comment audit] simplify native chat presentation and state contracts [skip ci]

* [comment audit] simplify native runtime and provider contracts [skip ci]

* [comment audit] simplify migration and orchestration contracts [skip ci]

* [comment audit] simplify plugin trust and process capture rationale [skip ci]

* [comment audit] simplify terminal delivery and remote compatibility rationale [skip ci]

* [comment audit] clarify remote recovery and launch wire rationale [skip ci]

* [comment audit] shorten shared RPC compatibility and runtime evidence comments [skip ci]

* [comment audit] simplify secure storage shell startup and sidebar rationale [skip ci]

* [comment audit] clarify sidebar, skill and SSH invariants [skip ci]

* [comment audit] condense structured chat delivery and timing rationale [skip ci]

* [comment audit] condense terminal replay and telemetry invariants [skip ci]

* [comment audit] clarify launch permission and terminal delivery rationale [skip ci]

* [comment audit] clarify workspace ownership and layout contracts [skip ci]

* [comment audit] wait for fitted and painted SSH terminal links

* [comment audit] clarify layout persistence and session ownership [skip ci]

* [comment audit] clarify host routing and workspace lifecycle contracts [skip ci]

* [comment audit] clarify startup persistence and app lifetime comments [skip ci]

* [comment audit] clarify recovery and activity boundaries [skip ci]

* [comment audit] condense activity and artifact invariants [skip ci]

* [comment audit] condense automation authority contracts [skip ci]

* [comment audit] simplify automation scheduling and history contracts [skip ci]

* [comment audit] clarify browser chrome and annotation lifecycles [skip ci]

* [comment audit] clarify browser routing and retained guest ownership [skip ci]

* [comment audit] clarify browser recovery and document ownership comments [skip ci]

* [comment audit] restore hosted runners required by native IME fixtures

* [comment audit] shorten preview, palette and dashboard invariants [skip ci]

* [comment audit] clarify terminal preview, dashboard and retention comments [skip ci]

* [comment audit] clarify diff-note recovery and editor lifecycle comments [skip ci]

* [comment audit] shorten rich-text and combined-diff ownership comments [skip ci]

* [comment audit] shorten autosave, draft recovery and model ownership comments [skip ci]

* [comment audit] shorten save-queue, notebook and Markdown constraints [skip ci]

* [comment audit] shorten Monaco, PDF and rich Markdown safeguards [skip ci]

* [comment audit] clarify rich Markdown source and selection safeguards [skip ci]

* [comment audit] clarify editor loading and emulator stream lifetimes [skip ci]

* [comment audit] trim emulator and feature tour narration [skip ci]

* [comment audit] clarify floating workspace and GitHub cache ownership [skip ci]

* [comment audit] trim provider controls and Linear filter explanations [skip ci]

* [comment audit] clarify pairing and chat resume lifetimes [skip ci]

* [comment audit] clarify chat delivery and transcript lifetimes [skip ci]

* [comment audit] clarify session options and host-owned status [skip ci]

* [comment audit] clarify draft durability and live-status precedence [skip ci]

* [comment audit] Trim chat send and model ownership explanations [skip ci]

* [comment audit] Shorten transcript ownership and send recovery comments [skip ci]

* [comment audit] Simplify native chat composer and transcript hook comments [skip ci]

* [comment audit] Shorten native chat scroll and structured session explanations [skip ci]

* [comment audit] Trim workspace picker and onboarding commentary [skip ci]

* [comment audit] Simplify pet rendering, review cache and quick open comments [skip ci]

* [comment audit] Trim sidebar and session history explanations [skip ci]

* [comment audit] Condense session resume and review checks comments [skip ci]

* [comment audit] Shorten checks state and file explorer refresh comments [skip ci]

* [comment audit] Trim plugin bridge and source-control action rationale [skip ci]

* [comment audit] Trim source-control listing and review rationale [skip ci]

* [comment audit] Shorten sidebar lifecycle and explorer safeguards [skip ci]

* [comment audit] Condense Settings account and appearance rationale [skip ci]

* [comment audit] Trim pairing and repository Settings explanations [skip ci]

* [comment audit] Condense Settings search SSH and terminal safeguards [skip ci]

* [comment audit] Shorten Settings voice and provider ownership comments [skip ci]

* [comment audit] Condense Settings draft persistence and host-state rationale [skip ci]

* [comment audit] Trim Settings hooks and sidebar setup rationale [skip ci]

* [comment audit] Condense sidebar deletion and board-filter safeguards [skip ci]

* [comment audit] Condense worktree cards, host ownership and Markdown contracts [skip ci]

* [comment audit] Condense sidebar drag, folder and filtering contracts [skip ci]

* [comment audit] Condense sidebar parity, sleep and host ownership contracts [skip ci]

* [comment audit] Prune focus-read baseline after comment cleanup

* [comment audit] Clarify sidebar visibility, board drops and agent evidence [skip ci]

* [comment audit] Tighten sidebar listing, drag and reveal contracts [skip ci]

* [comment audit] Clarify viewport geometry and skill update safeguards [skip ci]

* [comment audit] Tighten skill inventory, usage and host status comments [skip ci]

* [comment audit] Clarify usage ownership and resource kill safeguards [skip ci]

* [comment audit] Tighten tab selection, rename and search contracts [skip ci]

* [comment audit] Tighten tab-strip geometry and drag ownership comments [skip ci]

* [comment audit] Tighten Tasks recovery, pagination and mutation comments [skip ci]

* [comment audit] Tighten provider loading and terminal recovery comments [skip ci]

* [comment audit] Tighten completion, cadence and PTY ownership comments [skip ci]

* [comment audit] Clarify terminal restore and parked-pane boundaries [skip ci]

* [comment audit] Tighten PTY startup and replay explanations [skip ci]

* [comment audit] Clarify PTY identity and delivery ownership [skip ci]

* [comment audit] Shorten remote reconnect and input replay rationale [skip ci]

* [comment audit] Condense terminal parking clipboard and file link comments [skip ci]

* [comment audit] Clarify IME ownership and trim trace history [skip ci]

* [comment audit] Shorten pane recovery and parked watcher explanations [skip ci]

* [comment audit] Condense snapshot replay and visibility recovery rationale [skip ci]

* [comment audit] Shorten terminal parking and keyboard ownership rationale [skip ci]

* [comment audit] Trim renderer lifecycle and menu rationale [skip ci]

* [comment audit] Condense workspace cleanup ownership and settlement notes [skip ci]

* [comment audit] Clarify renderer hook evidence and source ownership [skip ci]

* [comment audit] Tighten IPC ownership and reconnect explanations [skip ci]

* [comment audit] Trim renderer focus, paste and attention comments [skip ci]

* [comment audit] Shorten scroll, locale and agent lifecycle comments [skip ci]

* [comment audit] Trim agent launch, resume and ownership commentary [skip ci]

* [comment audit] Shorten account, browser and editor comments [skip ci]

* [comment audit] Clarify host-mirror waits, previews and input ownership [skip ci]

* [comment audit] Condense launch recovery and editor tokenization comments [skip ci]

* [comment audit] Condense workspace selection and terminal pane rationale [skip ci]

* [comment audit] Condense terminal fitting and rendering recovery comments [skip ci]

* [comment audit] Condense terminal input and host routing explanations [skip ci]

* [comment audit] Condense ownership and sleeping-session recovery rationale [skip ci]

* [comment audit] Condense structured launch and terminal link explanations [skip ci]

* [comment audit] Condense terminal ownership and workspace file routing rationale [skip ci]

* [comment audit] Condense session persistence and workspace activation rationale [skip ci]

* [comment audit] Condense workspace routing and browser ownership rationale [skip ci]

* [comment audit] Condense mirror recovery and layout authority rationale [skip ci]

* [comment audit] Condense runtime transport and file safety rationale [skip ci]

* [comment audit] Condense runtime graph and structured session rationale [skip ci]

* [comment audit] Condense browser creation and remote tab recovery rationale [skip ci]

* [comment audit] Condense snapshot authority and publisher recovery rationale [skip ci]

* [comment audit] Condense frame, startup and provider cache rationale [skip ci]

* [comment audit] Condense host twin and agent lifecycle rationale [skip ci]

* [comment audit] Condense browser authority and editor cleanup rationale [skip ci]

* [comment audit] Condense editor buffer identity and review cache rationale [skip ci]

* [comment audit] Condense provider lifetime and repository ownership rationale [skip ci]

* [comment audit] Condense reconnect, hydration and terminal retirement rationale [skip ci]

* [comment audit] Condense recovery, reconciliation and persistence rationale [skip ci]

* [comment audit] Condense cleanup ownership and listing admission rationale [skip ci]

* [comment audit] Condense teardown ordering and terminal ownership rationale [skip ci]

* [comment audit] Condense recovery ledger and web host-boundary rationale [skip ci]

* [comment audit] Condense web reconnect and credential lifecycle rationale [skip ci]

* [comment audit] Condense cloud rollout and assignment safety rationale [skip ci]

* [comment audit] Condense relay session and database recovery rationale [skip ci]

* [comment audit] Condense relay placement and protocol compatibility rationale [skip ci]

* [comment audit] Condense build and packaging constraints [skip ci]

* [comment audit] Condense CI gates and validation isolation rationale [skip ci]

* [comment audit] Condense catalog identity and browser validation rationale [skip ci]

* [comment audit] Condense mobile browser and frame-budget rationale [skip ci]

* [comment audit] Shorten mobile route and browser test explanations [skip ci]

* [comment audit] Condense editor and session seam test rationale [skip ci]

* [comment audit] Trim session and terminal closure history [skip ci]

* [comment audit] Shorten terminal browser and census explanations [skip ci]

* [comment audit] Preserve root-only E2E diagnostic baseline

* [comment audit] Condense mobile seam and HTML preview test rationale [skip ci]

* [comment audit] Condense preview instrumentation and render harness rationale [skip ci]

* [comment audit] Condense bundle contracts and native-build constraints [skip ci]

* [comment audit] Shorten native packaging and CI routing rationale [skip ci]

* [comment audit] Condense release tooling and benchmark constraints [skip ci]

* [comment audit] Condense packaging and platform gate rationale [skip ci]

* [comment audit] Shorten mobile route and history rationale [skip ci]

* [comment audit] Condense mobile browser and component rationale [skip ci]

* [comment audit] Shorten drawer and workspace-form rationale [skip ci]

* [comment audit] Trim mobile review and editor-document explanations [skip ci]

* [comment audit] Condense editor lifecycle and Markdown explanations [skip ci]

* [comment audit] Trim mobile file, diagnostics and dictation commentary [skip ci]

* [comment audit] Simplify mobile host-list and workspace-view explanations [skip ci]

* [comment audit] Clarify mobile shell lifetime and bridge delivery constraints [skip ci]

* [comment audit] Condense bridge stream, native request and audio rationale [skip ci]

* [comment audit] Reduce bridge schema and page-client commentary [skip ci]

* [comment audit] Tighten mobile page bridge contracts [skip ci]

* [comment audit] Clarify mobile cache and session constraints [skip ci]

* [comment audit] Condense mobile route and lifecycle rationale [skip ci]

* [comment audit] Tighten mobile shell hook timing rationale [skip ci]

* [comment audit] Clarify route handoff and notification compatibility [skip ci]

* [comment audit] Clarify push registration and dictation cleanup constraints [skip ci]

* [comment audit] Condense keyboard geometry and native media ownership rationale [skip ci]

* [comment audit] Tighten mobile chat scroll and composer concurrency rationale [skip ci]

* [comment audit] Condense mobile reply compatibility and upload ownership rationale [skip ci]

* [comment audit] Condense optimistic echo and scroll ownership rationale [skip ci]

* [comment audit] Tighten stream replay and queued session ownership rationale [skip ci]

* [comment audit] Condense mobile composer and reply-schema constraints [skip ci]

* [comment audit] Clarify mobile transcript recovery and session ownership [skip ci]

* [comment audit] Clarify mobile queue and source-control compatibility [skip ci]

* [comment audit] Condense storage and task launch constraints [skip ci]

* [comment audit] Clarify task schemas and terminal document ownership [skip ci]

* [comment audit] Tighten terminal input and viewport rationale [skip ci]

* [comment audit] Shorten terminal and RPC recorder contracts [skip ci]

* [comment audit] Condense recorder engine and connection contracts [skip ci]

* [comment audit] Shorten host credential and relay recovery comments [skip ci]

* [comment audit] Tighten pairing recovery and bundle transport rationale [skip ci]

* [comment audit] Clarify RPC delivery and workspace catalog boundaries [skip ci]

* [comment audit] Condense catalog and relay entry contracts [skip ci]

* [comment audit] Shorten shutdown and SSH relay delivery contracts [skip ci]

* [comment audit] Condense WSL relay and E2E regression rationale [skip ci]

* [comment audit] Shorten cross-version harness and renderer fixture explanations [skip ci]

* [comment audit] Condense paired-host and E2E lifecycle rationale [skip ci]

* [comment audit] Shorten layout oracle and regression explanations [skip ci]

* [comment audit] Condense paired recovery and ownership regression contracts [skip ci]

* [comment audit] Shorten restart, sidebar and SSH lifecycle contracts [skip ci]

* [comment audit] Condense terminal rendering and IME regression rationale [skip ci]

* [comment audit] Shorten terminal recovery and benchmark contracts [skip ci]

* [comment audit] Condense tooling and Windows lifecycle proof rationale [skip ci]

* [comment audit] Condense workflow routing and release rationale [skip ci]

* [comment audit] Condense mobile security and installer contracts [skip ci]

* [comment audit] Shorten native rationale and stylesheet workarounds [skip ci]

* [comment audit] Shorten Windows visibility probe rationale [skip ci]

* [comment audit] Condense embedded release and signing rationale [skip ci]

* [comment audit] Retain current main test behavior in final reconciliation [skip ci]

* [comment audit] Complete final comment review across current source inventory

* [comment audit] Handle consolidated audit reports before final CI

* [comment audit] Preserve credential storage census detail [skip ci]

* [comment audit] Scale broad changed E2E selections with verified timing shards

* [comment audit] Align E2E assertions with browser close and settled session metadata

* [comment audit] Match existing E2Es to current resource and windowing contracts

* [comment audit] Observe the shared server outage notice in reconnect coverage

* [comment audit] Make existing renderer probes measure settled tab and PTY work

* [comment audit] Align palette E2E selector with task search

* [comment audit] Refresh remaining palette search selectors

* [comment audit] Keep selector correction within selected audit specs

* [comment audit] Await emoji fixture settings inside renderer evaluation

* [comment audit] Cancel fixture fit retries between terminal tests

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-25 04:05:46 -07:00
Neil 0b28553093 feat(ssh): show saved port forwards that couldn't start, with why, and let you remove them (#33450)
* feat(ssh): list saved port forwards that couldn't start, with why, and let you remove them (#32484)

A saved forward whose local port is taken, or that keeps failing, stayed
saved but invisible, retried in the background with no way to remove it.
The port-forward lists now show each saved forward that isn't open, with
the last start error, and Remove deletes it by its mapping.

* fix(ssh): a forward whose ssh exits after starting backs off like a failed start

* fix(ssh): re-register the new forward channels, close a forward a restore reopened before removing it, and update IPC fixtures

* fix(ssh): a flapping forward keeps its backoff streak until it stays up

* fix(ssh): translate the saved-forward row, say Stopped for a forward that died, toast a failed remove, and reset backoff on manual edits

* fix(ssh): keep saved forwards listed and removable while the host is offline; label the remove button; test the healthy-uptime reset

* fix(ssh): mirror saved forwards from main with a stale-read guard, including hosts that never connect

* fix(ssh): scroll the offline ports panel when saved forwards overflow it

* test(e2e): give the saved-forward restart case's timeout its reason
2026-10-25 02:37:30 -07:00
Jinjing 245e5d83fd Reduce tab preview tooltip delay to 500 ms (#33447)
* Reduce tab preview tooltip delay to 500 ms

* Reduce tab hover card test delay expectations
2026-10-25 00:44:53 -07:00
Neil e1ee51dec4 fix(ssh): saved port forwards come back after a restart that reconnects through the host's Orca server (#32484) (#33388)
* test(e2e): a saved SSH forward on a managed host comes back after a restart (#32484)

* test(e2e): a restart that reaches the host only through its server's tunnel restores saved forwards (#32484)

* fix(ssh): restore saved port forwards whenever a host's server is up, not only after an SSH connect (#32484)

A host whose managed server the app reaches at startup through its tunnel
publishes its served status from the tunnel path, which never ran the
forward restore. The served status itself now triggers the restore, from
any publisher, and a host kept on the legacy relay bridge restores too.

* test(ssh): type the restore spy's target argument

* fix(ssh): user forward edits keep unrestored saved forwards; restore once the tunnel is up

Add, edit and remove now merge with saved forwards that aren't live, so a
restart that restored nothing no longer lets one re-added forward erase
the rest. A call that brings up the managed server's tunnel restores too,
so a failed update check or redeploy can't skip it, and a restore runs once
per transport instead of on every status note.

* fix(ssh): a forward that failed to bind is retried on the same transport

* fix(ssh): restore again when a restored forward closed; a reused local port replaces its old mapping

* fix(ssh): user forward edits and restores share one per-host queue

A restore that ran mid-edit could reopen the mapping the edit was
replacing and save both. Every add, edit, remove and restore for a host now
runs in order through the same queue.

* fix(ssh): pace forward restores and back off a forward that keeps failing

Each runtime call triggers a restore over the managed tunnel, and with
system SSH every attempt is a new login. Restores on the same transport
now run at most once per 30 s, a forward that keeps failing waits longer
each time, and teardown forgets both. A tunnel with no status yet counts
only outside a connect; a remove re-checks its forward inside the queue;
drop a circular listener test and the plain restart e2e case.

* fix(ssh): a start a teardown cancelled records no backoff

* fix(ssh): a reconnected transport retries failed forwards at once
2026-10-25 00:32:24 -07:00
NeilandMaple e13e5e8b7d fix(orchestration): submit mail pointers to Cursor CLI instead of leaving them in the composer (#33347)
Orchestration mailbox pointers now get their delayed Enter for Cursor too (the Cursor no-Enter skip from #3156 left mail delivered but never acted on). Verified with real cursor-agent. Fixes #19760. Supersedes #19761.

Co-authored-by: Maple <54388301+zleo-ai@users.noreply.github.com>
2026-10-25 00:07:42 -07:00
Neil a6d4a4fea5 fix(windows): respawn a ConPTY pane that started without keyboard input (#33423)
* fix(windows): respawn a ConPTY pane that started without an input reader

Bundled ConPTY occasionally starts a pane whose console host never reads
its input pipe: the shell prints its banner and prompt, but every keystroke
and the typed launch command are dropped. Such a pane is identifiable from
its first output, because a healthy one always queries DA1 before relaying
anything else. The daemon now waits for that first output, respawns once
when it is missing, and replays the buffered startup output so no byte is
lost. The table stress probe now waits for node-pty's own readiness rather
than typed input.

* fix(windows): bound the ConPTY startup check and never re-run a command

- Respawn only when no command rode in the shell's argv; otherwise keep the
  pane and say on screen that it cannot take input.
- Accept the pane unverified after 5s of silence instead of stalling the spawn.
- Distrust the check after two misses with no pane ever announcing, so a
  changed ConPTY build cannot respawn every pane.
- Kill a discarded pane through its job before closing the pseudoconsole.
- Report a cancel during the wait as an attach cancel, not a spawn failure.
- Assert on real Windows ConPTY that a fresh pane announces its input reader.

* fix(windows): respawn only Orca's own shell argv and close an unready pane now

- Treat user shell args like an argv startup command: never respawn, show
  the notice instead, so a command such as pwsh -Command never runs twice.
- Close a discarded pane's pseudoconsole directly; node-pty defers kill()
  until first output, which a silent pane never produces. Kill the shell by
  pid when no job owns it.
- Reconcile a master node-pty retired during the startup wait.
- Drop the test-only respawn counter; the count rides in the daemon log.

* fix(windows): tear a discarded unready pane down through node-pty's agent

node-pty defers kill() until first output, so closing only the native
pseudoconsole left the input pipe and output worker of a silent discarded
pane alive until daemon exit. The agent's kill closes all three.

* fix(windows): discard startup panes by handle only; account for the mock prelude

A pid-addressed kill could hit a recycled pid when the shell exited during
startup; the job and the agent's native kill both act on handles. Lifecycle
assertions now expect the replayed DA1 query when the suite runs on Windows.

* test(e2e): give the mocked Windows pane its ConPTY prelude
2026-10-24 23:59:37 -07:00
Neil fef00e4461 feat(dev): give each worktree its own pnpm dev profile and ports (#33416)
Linked worktrees now get a per-worktree userData profile under
orca-dev-wt/<hash>, a deterministic collision-checked renderer port
(15200+) and CDP port (9333+), so parallel `pnpm dev` runs no longer hit
the single-instance lock. The main checkout keeps the shared orca-dev
profile; --shared-profile / --worktree-profile / ORCA_DEV_PROFILE override.

The runner prints `ORCA_DEV_INSTANCE {json}` on stdout and mirrors it to
out/dev-instance.json so agents can attach over CDP. orca-dev.mjs and the
terminal wrappers follow the profile the worktree's dev app used.

Adds profile seeding (pnpm dev:seed-profile, pnpm dev --seed-profile,
pnpm dev:fresh --seed-from): an allowlisted slim copy of projects,
workspaces, settings, SSH targets, and the account session, written as
orca-data.json for Orca's own import; the source is only read.

Storage reclaim removes per-worktree profiles once their worktree is gone
and no app, runtime, or daemon still uses them. dev-fresh-profile.sh is
replaced by a cross-platform dev-fresh-profile.mjs.
2026-10-24 23:08:52 -07:00
NeilandClaude Opus 5.5 8e9f86b119 feat(managed-server): Update and Update anyway for a managed SSH server, keeping its running terminals (#33397)
* feat(managed-server): offer Update and Update anyway on a managed SSH server's row

A managed SSH server only updated on connect, and every connect deferred while
a terminal ran there. Its row now offers Update when this desktop bundles a
newer build than the Orca that runs the host. When running terminals defer it,
Update anyway restarts the server past them; the terminal daemon carries them
across the restart.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(managed-server): Update anyway passes only counted live terminals and keeps Update's version admission

Update anyway now sends the incumbent build it confirmed over; under the host
fence it is refused if another desktop activated a build since, keeps the
newer-host downgrade refusal, and never passes an uncounted terminal census.
The offer also covers hosts activated before the Orca version was recorded,
for the build this desktop already deferred there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(managed-server): Update anyway also confirms a menu Update the row does not advertise

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(managed-server): the row shows one confirmation at a time

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci(e2e): route managed-server update sources to the Update anyway Docker spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 22:49:18 -07:00
Neil 95df4c74ed refactor: group Parcel watcher process ownership (#33401) 2026-10-24 22:14:52 -07:00
Neil 4fa91acb4f fix(repos): drop a paired server's old workspace rows when it relists them under new project ids (#33396)
* fix(repos): drop a repo's worktree rows when its host's catalog no longer lists it

A paired server that relists its checkouts under new repo ids (a project
copied into another profile, then that profile switched to) left the
desktop showing the old rows beside the new ones, the old under Unknown.
Every catalog fetch now drops the rows of the repo registrations it
removed, scoped to the dropped host.

Refs STA-12076

* fix(repos): purge a dropped repo's workspaces like a vanished checkout

Clears selection, tabs and per-workspace state of the dropped rows through
the same bulk purge an authoritative scan uses, flushing delayed editor
text first; the three catalog fetch paths share one finalize step.

* fix(repos): drop rows only, never a registration added after the request

Review: purging tabs and selection could race repo add/remove and lose
state. Keep the change to rows, and fence it to registrations the store
held when the catalog request went out.

* test(e2e): drop the fixed settle wait from the repo id change repro
2026-10-24 21:51:22 -07:00
OrcaWinandOrcaWin fdcf887bf0 chore(lint): fix suppressed lint violations instead of ignoring them (#33294)
* chore(lint): remove disable directives that suppress nothing

Each was reported unused by the oxlint config that owns its rule (root,
casting, react-doctor, anti-slop, native-plugins), including 17 file-level
react-doctor blanket disables whose rule no longer fires. An unused
react-hooks disable was masking a react/purity finding in
useAgentBucketCounts (compiler rules skip functions with hook
suppressions); suppress that one explicitly where the code explains it.

* test(tab-bar): use typed tab/file fixtures instead of @ts-expect-error partials

* chore(lint): fix misc suppressed lint violations instead of disabling

- consistent-type-imports: the "vi.importActual requires inline import()"
  rationale was wrong; use typed vi.mock(import(...), importOriginal) or a
  type-only namespace import.
- no-control-regex: source-control commit/push failure summaries, shell PATH
  hydration, and ipynb ANSI parsing reuse the shared ansi-escape-sequences
  stripper and control-character pattern instead of private copies.
- no-explicit-any / no-useless-spread / no-this-alias: typed `this` in
  bridge test mocks, drop blanket file-level disables, drop a this-alias.

* refactor(main): replace avoidable type assertions with checked narrowing

17 production cast suppressions in main/wsl-guest removed: untrusted IPC
and RPC payloads (Jira issue update, WSL guest plugin install, handshake
type) now narrow through isRecord/type guards and build typed results;
redundant casts dropped; hand-rolled object checks and errno casts use the
existing isRecord / hasErrorCode helpers.

* refactor(renderer,mobile): replace avoidable type assertions with checked types

13 production cast suppressions removed: RPC failures read through the
`ok` discriminant instead of casting to RpcFailure; react-native-web host
refs narrowed with instanceof HTMLElement; redundant reply/diff casts
become checked annotations; the TUI agent param uses z.custom(isTuiAgent)
like its sibling schemas; the agent-status slice cast that hid missing
actions is gone so the creator's return type checks the whole slice.

* chore(lint): drop dead tiptap wrapper; scope anti-slop mocking rule to test support

- safe-react-node-view-renderer patched handleSelectionUpdate, which
  @tiptap/react 3.31.3 no longer has, so it always returned early. Use the
  stock ReactNodeViewRenderer.
- The anti-slop test override only matched *.test.{ts,tsx}, forcing
  file-level no-module-mocking disables in test harnesses and fixtures.
  Match *-test-harness, *-test-fixture(s), .test-fixture and *.test.mjs,
  then drop those disables and the now-redundant per-file exemptions.

* test: replace repeated cast suppressions with typed fixtures (main/shared/e2e)

Net -119 cast directives. Typed fixtures replace recurring casts:
unusedSshConnection/unusedOrcadHostTransport placeholders, a typed
readPersistedState harness read (exposed a test treating optional
httpProxyUrl as always set), real Response objects in fetch spies, an
updater main-window fixture, a CDP webContents adapter, one shared
releaseModuleExport for cross-version tests, and requireOverlayDir in
place of `as string` on possibly-undefined overlay paths.

* fix(runtime): validate loaded device rows and host scope instead of casting

Two cast suppressions claimed checks that did not happen:
- device-registry-file-read: "normalizeLoadedDeviceRow re-validates every
  field" was false; deviceId, token, name and timestamps were never
  checked. Rows without an identity are now dropped and the file is set
  aside through the existing corrupt-file path (registry reads as
  doubtful, so no revocation verdicts); a non-string token is stripped
  so the row stays listed but cannot authenticate.
- client-ui: "only optionality differs" was false; any string reached
  persisted workspaceHostScope. Narrow it with isWorkspaceHostScope and
  ignore unknown scopes (wire schema unchanged for mixed versions). The
  remaining cast now states what it actually covers.

* test(runtime,ipc): drop redundant cast suppressions; typed runtime store fixture

-98 cast directives across runtime/ipc tests: 61 casts that typecheck
without the assertion; a typed vi.fn for scoped invalidation; a
partialRuntimeStore fixture in place of `store as never` for
OrcaRuntimeService; typed worker terminal/authority builders in the
incarnation-fallback suite (the old stub lacked runtimeId, ptyId,
worktreeId and launchTokenHash) plus removal of stacked duplicate
directives there.

* chore(lint): typed vi.mock imports and explicit listener snapshot in shared-bucket tests

Remaining files from the misc-rule pass that overlapped other buckets:
codex-accounts mocks use the typed vi.mock(import(...)) form instead of
a consistent-type-imports disable; the daemon late-exit fixture copies
its listener set with Array.from instead of a no-useless-spread disable.

* refactor(github,mobile): narrow routing settings type; drop remaining avoidable casts

- work-item-routing cast a one-field object to AppState['settings'] under
  a claim that readers only consume activeRuntimeEnvironmentId. Return the
  existing RuntimeFocusSettings pick instead and narrow the cache-key
  chain's parameters, so the compiler enforces that claim.
- mobile file preview reads refusals through the RpcResponse `ok`
  discriminant rather than a cast.
- terminal document host-notify accepts `unknown` errors, removing the
  message-bridge cast.
- native chat readability drops a redundant repo-list cast.

* test(renderer): replace repeated cast suppressions with typed fixtures

-140 cast directives (and ~150 unsuppressed casts of the same shapes):
- mockPanePtyArgs owns the connectPanePty fixture casts, so a wrong
  argument order or fixture is now a type error; drop binding casts for
  members PanePtyBinding already declares.
- Seed AppState tab rows with the typed makeTerminalTab; this exposed a
  split direction 'row' that is not a TerminalPaneSplitDirection.
- Partial GlobalSettings use getDefaultSettings overrides; Jira-only
  stores use createTestStore; runtime environment rows/statuses come from
  a typed paired-runtime-environment fixture.

* chore(lint): drop no-module-mocking disable now covered by the test-fixture glob

* test(e2e): fix all 221 grandfathered e2e type errors; baseline to zero

The e2e typecheck baseline grandfathered 221 errors in 119 files. About a
third were tests drifted from the current API, several of which would
fail or mislead at runtime:
- terminal-shortcuts called a nonexistent xterm buffer method;
- the daemon-lifecycle fake lacked terminateOwnedTree, hidden by importing
  its type from a module that does not export it;
- arguments in the wrong position (listProcesses(hostId, opts), a dropped
  pty.write inputKind, an extra toWebTerminalSurfaceTabId argument);
- removed enum values ('drawer', 'idle', 'editor',
  'session-insecure-origin') and a launch_source the telemetry schema
  rejects;
- missing required fields (turnScope, childWorkOpen, providerIdentity,
  reviewLookupOutcome, runtimeServiceAccount behind an `as RelayConfig`);
- dead reads (tab.customTitle, bucket.targets, changedPixels).
Also lifts variables that narrowed to `never` after poll-callback
assignment, and adds a typed xterm render-dimensions accessor. Includes
the cross-version suites' shared releaseModuleExport adoption.

* chore(typecheck): gate the now-clean e2e typecheck in local lint

The e2e baseline is empty, so the ratchet now rejects any tests/ type
error. CI already runs it via run-ratchets; add it to pnpm lint's
explicit ratchet list and replace the stale 'not yet clean' note.

* test(mobile): typecheck every mobile test; baseline 105 files -> 0

mobile/tests-typecheck-baseline.txt grandfathered 105 test files (531
errors) whose types CI never checked. Contract changes had landed without
these tests following, and type pins in them silently checked nothing.

- Root cause: salvagedOptional (src/shared/zod-salvage.ts) cast away
  zod's optional marker, so every reply type built on it claimed
  salvaged fields were always present. Return a real ZodOptional;
  runtime is unchanged (the outer optional short-circuits undefined).
- Production now takes the port it uses: RpcOperationSender instead of
  RpcClient for send-only callers, a narrow fetch signature, and only the
  request fields push-receive reads.
- findAllByHostType/findByHostType replace `'Text' as never` lookups;
  stubRpcClient gives tests a typed RpcClient.
- Real test bugs: settings-host-client-lifecycle "relay" hosts were
  direct hosts (relayHostId no longer exists); two toEqualTypeOf pins
  could never hold; a recovery hook ran with an undefined scope key;
  a create-PR test cast to a never-imported type; "no URL" assertions
  passed on null; plus stale required props, args and enum values.

* test(e2e): parse workerStart result instead of casting it

* test(runtime): typed partial runtime stores with production-shaped fixture data

Route every partial store passed to OrcaRuntimeService through
partialRuntimeStore with typed row builders, removing 60 cast directives
that hid fixture data production never produces:
- paired-client-navigation-test-harness keyed setWorktreeMeta writes by
  `[object Object]` (it took an id where the store takes a target), so
  reads never saw them;
- invalid worktree lineage origin/capture and incomplete workspace lineage;
- getWorkspaceSession returning null where the store returns the default
  session; getGitHubCache returning undefined;
- orcad migration states missing migrationId/manifest/receipt, with a
  toEqual pinned to that incomplete shape;
- partial repos, metadata, folders, project groups and notification rows.

* refactor(renderer): resolve suppressed React hook lint instead of disabling it

109 of 187 react-hooks/react-doctor suppressions fixed:
- ~95 exhaustive-deps disables only hid stable refs and setters passed
  through controller objects; list them (identity never changes, so
  nothing re-runs), plus a few real stale closures (tabId/worktreeId).
- Effects keyed on one value that read the latest props now use
  useEffectEvent (WebConnect, skill freshness, Bitbucket dialog seeding,
  Landing preflight, automation catalog, structured-session recovery,
  file explorer).
- The conditional layout-owner hook is selected once at module load from
  the build constant instead of a rules-of-hooks disable that also hid
  the whole controller from compiler and react-doctor rules.
- A hook disable was masking a react/purity Date.now() in the palette's
  recent-tabs memo; sample it when the snapshot is captured.
- Three identical debounced-search effects share
  useTaskSearchDebouncedApply; layout snapshot merge helpers move out to
  stay under max-lines.
Remaining suppressions are mount-once resources, invalidation epochs,
deliberately keyed fields, and test harnesses that mock the dispatcher.

* chore(ratchet): exempt test harnesses and fixtures from the focus-read ratchet

The ratchet skipped *.test-fixture.ts but scanned *-test-harness,
*-test-fixture(s) and *.test-support files. Those seed settings with
getDefaultSettings (which the ratchet discovers as a focus reader) and
never route host work, so 17 baseline entries were false positives, and
replacing a test's `settings: {...} as never` with typed defaults tripped
it. Match the repo's test-support names and prune (which also drops one
stale entry), and rename the frame-ordering harness to *-test-harness like
its siblings. A blanket "-harness" match would also exempt
e2e-terminal-pty-harness, which production imports, so the names stay
explicit.

* test: merge duplicate shared/constants imports

* revert(file-explorer): restore original tree load effects pending SSH e2e investigation

* test(runtime): drop RuntimeStore cast now that the fixture is typed

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-24 19:37:19 -07:00
Neil db8fc6d0cc refactor: group agent-session conversation and message identity (#33324) 2026-10-24 18:43:40 -07:00
Neil 874a251cb4 test(e2e): click a terminal link only after the terminal refits to its pane (#33328) 2026-10-24 18:19:07 -07:00
Jinjing 870038cfc6 Test title-only fallback for unavailable AI Vault search (#33234) 2026-10-24 18:10:06 -07:00