* test: remove 37 low-value cases and 3 suites
* test: delete ten more renderer wiring and copy suites
* test: drop deleted suite from its contract entry point
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(files): open host files outside workspaces for any client with terminal access
Paired clients that can open terminals on a host can already read and write
anything its user can, so the per-terminal provenance gate on files outside
workspaces protected nothing. The host now grants any existing file outside
its workspaces; older hosts get a clear update message instead of a refusal.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(files): refuse SSH, device and WSL-home paths instead of misreporting them
Co-Authored-By: Claude <noreply@anthropic.com>
* perf(files): size grant digests to the file and skip status checks for local fallbacks
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(files): read procfs files whose stat reports size 0
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(ssh): move enabled SSH automations to the host's Orca server
Connecting an SSH host moves its saved state to the host's managed Orca
server. An enabled SSH automation refused that move on every Connect
("automations (1), automation runs (4)"), leaving the host unconnectable;
Move anyway connected it but stranded the automation on the desktop, where
it no longer ran.
An enabled automation whose runs have all finished now moves with its run
history. The manifest still carries it disabled, which every server version
accepts; once the move commits the desktop disables its retained copy and
turns the server's copy back on through automation.update, re-sending its
start time so the next run is the next future occurrence. A server that
can't is noted in Settings; an unreachable one is retried on the next
Connect. While a move fences the host, the desktop scheduler, Run now and
the launch re-check write nothing for its automations, so a tick can no
longer break the fenced export; releasing the fence resumes them. A run
still in flight keeps blocking and the refusal now says to wait for it.
Fixes#29083
* test(ssh): mock the server automation enabler in the delta-move handler test
* test(e2e): keep the Move anyway specs refusing now that enabled automations move
The inline Move anyway spec seeded an enabled automation to force a
refusal, which this branch now moves instead. It seeds one pinned to an
earlier registration of the host, which still stays behind. The relay
bridge spec's Move anyway lookup also matched the refusal toast's
button since #34041; it now takes the pane's own.
* Source control actions start chats and terminals on their saved model
A "start an agent" action's model lived only in free-text CLI arguments, which a native chat
never reads, so AI Fix opened a chat on the default model. Each action now saves a structured
model and effort that both routes apply: chat create options, or the agent's own flags in a
terminal (winning over the same flag in CLI arguments). Desktop, dialog, fix-checks and mobile
launches carry it; Settings rows get Model/Effort selects and the CLI arguments field says it is
terminal-only.
Tracked in STA-11102.
* Name the model in the repository override note
* Type the dialog's model hand-off; keep Agent in English in Japanese copy
* fix: preserve action chat model choices through launch
* Preserve action selection ownership across chat launches
* Keep terminal host contract fixtures aligned with preflight
* fix: wait for action Settings agent inventory
* fix: consolidate direct agent routing imports
* fix: use standard action option labels
* fix: align action launch contracts with shared types
* fix: sync action option localization metadata
* test: provide action Settings inventory in mounted fixtures
* Keep action options row height stable while loading
* Let each Source Control action choose its chat permission mode
An action's saved chat choice may now carry a permission mode, with or without a model;
"Same as new chats" saves nothing. A model is replaced only when the action names one,
so a permission-only choice keeps the chat's remembered model and options.
* fix(native-chat): leave older hosts their own permission mode and keep action options readable
- An action's saved permission mode is sent only to hosts that advertise
agentSession.create.options-mode.v1. Older hosts get no mode, in create
options or a later setOption, so the chat starts on that host's new-chat
default, as a phone launch to such a host already does. Hosts from
1.4.225 to 1.4.227 refused a mode their tables lacked (OpenCode, Grok,
OMP), leaving the action unable to start.
- Settings action rows give Model and Permissions full rows in the options
column so saved values are readable; the loading placeholder reserves the
same rows.
- Remove two unused locale keys; fix two stale comments.
- Tests: the older-host create carries no permission mode; a permission
mode picked alone keeps the remembered model on an acquired create.
* fix(settings): reserve one options row while loading an action with nothing saved
Terminal and permissions-only rows no longer shrink when loading ends; a chat
agent with a model list may grow by its Model row once known.
* fix(native-chat): keep the create options mode a checked literal type
* fix(settings): share verified action option fields
* fix(settings): keep action selectors on standard typography
* Keep the launch files under their length limits after the main merge
The structured route imports its result types where they are defined, and the two older-host
action-launch tests share one setup helper.
* One action settings section for chat and terminal launches
A Source Control action's Model, model options and Permissions now apply whether it opens a
chat or a terminal; terminals receive them as the agent's own flags, and a repository's own
CLI arguments keep the flags it sets. Extra CLI arguments stay terminal-only.
* fix(source-control-ai): one terminal projection for saved action choices
Ask in a terminal now states its permission instead of leaving it to the
user's own config: Claude and Grok pass --permission-mode default, Codex
passes -a on-request -s read-only -c approvals_reviewer="user" (the
interactive CLI has no untrusted policy, so a read-only sandbox is what
asks before edits). Agents whose CLI has no flag for a mode show the
existing "Applies to chats only" hint.
The strict launch-preferences projection now requires the launch agent at
every caller, composes model ids through the resolver's own step, carries
a mode only where the agent's terminal has a flag for it, and the local
string wire keeps booleans as 'true'/'false', so Cursor Thinking/Fast reach
the terminal and an OpenCode permission-only choice is not refused.
The argument parser knows flag arity, so removing a boolean permission
flag keeps other options' values, following positionals and '--'.
Pre-admission and executor share one terminal admission check on the
options the terminal will receive. Customize with Save launches the recipe
as it will resolve once saved; legacy partial repository overrides are
edited as the complete recipe they resolve to. Empty Extra CLI arguments
start collapsed.
* fix(source-control-ai): an edited repository action saves complete
Every Settings edit of a repository action (agent, model, permission,
prompt or arguments) now starts from the complete recipe the action
resolves to, whether its stored override is owned or a legacy partial.
The resolved agent selection is kept (never an agent only detected to run
a default), an explicit null args clear stays null, and empty args stay
empty instead of being dropped. Clearing the last preference therefore
means the action agent's own defaults rather than re-inheriting Global.
The action text draft is lossless: unset or cleared prompt and args stay
so until the user types, and the inputs show them as empty, so saving a
prompt no longer writes empty args that suppress the agent's default
flags. Untouched sibling actions are not rewritten by the edit.
* fix(settings): style the Extra CLI arguments toggle through Button's own variant and size
CI's changed-code quality check refuses restyle classes on Button and
CollapsibleContent. Use the ghost variant at size xs with a margin, and
put the content spacing on a plain inner wrapper.
* fix: keep saved action and restart launch recipes consistent
* fix: describe inherited arguments and chat-only permissions accurately
* test: check repository action settings fixture type
* test: map saved action options into terminal compiler inputs
* fix: retain saved action controls during agent detection
* fix(i18n): retire obsolete Portuguese action labels
* test: align folder launch fallback mock with outcome export
* fix: carry resolved connector launch intent and mode together
* test: pin shared action launch branches to recorded agent output
* test: preserve saved source control choices through detection and migration
* test: align launch fixtures with integrated result contract
* test: retain recipe and restart contracts after main integration
* Unify Source Control action permission settings
* Keep native Ask copy with its owning change
* Preserve action drafts and old-host permission intent
* Consume rejected Source Control action saves
* Follow the moved Settings persistence fixture
* Keep permission integration contracts in the cross-version test project
* Include the action permission inheritance label in English catalogs
* Align launch contracts with shared permission recipes
* Keep Source Control action controls within their Settings columns
* Use primitive variants for compact action settings controls
* Show action arguments only for terminal defaults and widen recipe rows
* Apply terminal-only action arguments visibility to repository overrides
* Align action permission control with model controls
* Use shared settings label for action permissions
* Hide action model controls until argument migration ships
top costs ~263 ms of CPU per sample, so the memory panel only refreshed
footprints every 10 s. The new orca-process-footprint helper reads
phys_footprint for every same-user process in ~3 ms, so footprints now
refresh on the panel's 2 s poll. top stays as the fallback when the helper
is missing or fails.
Co-authored-by: m4air <m4air@Mac.localdomain>
The packaged agent-browser binary resolves its version-matched skills from the
nearest skills/ directory above it (Resources/). Only the binary shipped, so
`agent-browser skills get core` answered "Skill not found" and `skills list`
"No skills found". Ship node_modules/agent-browser/skills/agent-browser and
skill-data beside it on mac, linux and win, and cover it with a test that stages
the host's extraResources slice and runs the real binary.
Refs #17705
Co-authored-by: zerone0x <zerone0x@users.noreply.github.com>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
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.
PR close/reopen/merge confirmation titles were built from a fragment
template ("{{value0}} PR #{{value1}}?"), so locales could not reorder the
verb, and merge method labels came from English-only shared constants.
Add whole-sentence title keys per action and merge method plus translated
merge method labels in a renderer copy module, and route every PR surface
(item dialog, PR page, Tasks MergeCell, right-sidebar HostedReviewActions)
through it. Drop the English labels from the shared merge-method
presentation and remove the dead fragment keys from all locales.
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
* 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>
JSON.parse silently keeps the last value of a repeated key, so the
catalog verifier could not see duplicates. Scan en.json and every target
catalog with ts.parseJsonText before parsing and fail with file:line and
the dotted key for each duplicate.
Fixes#27153
Co-authored-by: outof-place <contact@outofplace.space>
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.
cmd /c strips the first and last quote of a line that starts with a quote
unless exactly one quoted, paren-free executable path is present. A spaced
.cmd launcher plus any quoted argument (or a Program Files (x86) launcher)
was cut at its first space and the spawn silently failed. Prefix the batch
invocation with `@` so the line never starts with a quote, in both the
waiting and detached start /B forms.
Add a real cmd.exe round trip in the Windows CI lane.
Co-authored-by: Neil <neil@stably.ai>
* 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>
lint:ast-grep and check-flaky-test-pattern-ratchet each parsed the whole tree.
ast-grep-gates.mjs scans once; the lint gate re-runs ast-grep only on files with
warning-or-error findings (ast-grep's own report and exit code), and the flaky
ratchet counts test-* matches from the shared scan.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
The main bootstrap banner was prepended to index.js in generateBundle,
after Rolldown had already emitted index.js.map, so every main-process
crash trace decoded ~200 lines off. Emit it via Rolldown's output.postBanner
instead, which shifts the source map natively.
Co-authored-by: outof-place <contact@outofplace.space>
- Plan unit selection starts after setup (overlaps lint) instead of last.
- Localization extraction starts with the typecheck; test-file-runners is background.
- run-ratchets.mjs runs ratchets in a pool (19s serial -> 8s locally).
- pnpm lint uses CI's single-parse check-import-boundaries.mjs.
- ORCA_UNIT_FULL_SHARD_COUNT accepts 2-10 (default stays 5).
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
SwiftPM 6.4 (Xcode 27) defaults to the swiftbuild build system, which writes
products to an xcodebuild-style layout instead of .build/<triple>/release, so
the lipo step in build-computer-macos.mjs finds no inputs. Pass
--build-system native to both per-triple builds.
Fixes#21145
V8 stores a script source as UTF-16 when any character is above U+00FF, so a
single em dash in a hot chunk doubled that chunk's resident source. Emit ASCII
(escaped) output for main, preload, renderer and worker bundles, escape the
CJK sentence marks in the prose URL regex source, and fail the renderer
boot-graph check if a boot chunk regresses to two-byte.
Co-authored-by: m4air <m4air@Mac.localdomain>
A killed Vitest left its node-runtime worker running the rest of the file
(still alive after 150s). Exit on 'disconnect' with process.exit captured
before Vitest replaces it with a throwing guard.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* perf(dev): size the dev server's Rolldown runtime for many parallel instances
~93% of idle electron-vite RSS is Rolldown's native mimalloc arenas. The dev
wrapper now gives electron-vite MIMALLOC_PURGE_DELAY=0 and 4 Rolldown/Rayon
threads; a serve-only renderer plugin strips exactly those keys before
Electron spawns, so dev Orca's terminals never inherit them.
* fix(dev): add the runtime-env plugin only when the dev wrapper set its keys
Keeps createDevServeConfig returning the renderer config unchanged when there
is no port and nothing to strip, as electron-vite-output-contract pins.
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Tests leak os.tmpdir() fixtures broadly (8.6k dirs from repeated prefixes on
one shared dev host; orca-runtime-rpc alone 2,729). run-vitest.mjs now points
TMPDIR/TEMP/TMP at a marked per-run dir, removes it after Vitest exits
(including on SIGINT/SIGTERM), and sweeps marked dirs whose launcher died.
On POSIX a root longer than 50 chars (macOS /var/folders) falls back to /tmp
so Unix socket paths stay under sun_path limits.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Rolldown defaults to 1.5x physical cores Tokio workers plus a Rayon pool per
logical CPU (24+24 here). Capping both at 8 on >8-core hosts cuts electron-vite
build CPU 24% with byte-identical output. pnpm dev no longer blocks on a stale
pairing web build; it stages into out/.web-next and swaps on success.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(computer-use): send correct named keys and hotkey letters on Linux
press_key passed the keysym for named keys (Return, Tab, arrows, Escape)
to AT-SPI as PRESSRELEASE, which expects a hardware keycode, so a
different key was pressed. Synthesize with SYM instead.
hotkey forwarded upper-case letters such as CmdOrCtrl+A to xdotool,
which reads them as shifted keysyms and sends Ctrl+Shift+A. Lower-case
single letters in key combinations.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(computer-use): drop the unreachable lone-key hotkey case
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Each custom oxlint JS rule now checks the file text first and returns no
visitors when it cannot report, so oxlint skips the AST transfer to JS.
app-store-performance only resolves scopes for tracked hook names.
anti-slop rules are wrapped with per-rule text prefilters. react-doctor
rules are off for folders without React (the old cloud/** ignore never
matched: config/ globs need a leading **/).
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
set_value looked up node.is_editable_text before attempt() ran. GI bindings
from at-spi2-core < 2.53 (e.g. Ubuntu 24.04) do not expose that function, so
the AttributeError escaped and every set-value failed. Probe with
get_editable_text_iface, which has been bound since 2.9.2 and checks the same
interface.
Closes#10569
Co-authored-by: bbingz <zzb@gxsmjx.com>
* test: remove low-value inventories, passthroughs and redundant cases
* style: format test suites after pruning redundant cases
* test: remove obsolete workflow and flaky-test references
* test: prune deleted builder test from Windows shim allowlist
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>