The manifest publisher is deprecated and ignored for catalog and Git installs:
catalog installs use the listing id, Git URL installs the URL owner, folders
'local' (or their still-declared publisher). Existing installs keep their key.
A format 2 manifest may omit publisher only with engines.orca >=1.4.246, so
older Orca reports 'requires Orca X' instead of failing to parse it. The v2
catalog documents an optional ownerId, which older Orca already strips.
* feat(mobile): give every text input the chat composer's look
Adds shared MessageBox, TextField and ComposerSendButton built from the
composer's own styles, and moves chat, form, search, Tasks, PR, review and
commit inputs onto them. The commit message becomes multi-line, every input
is 16pt (no page zoom on focus), and focus rings are gone. The terminal and
browser typing docks are unchanged.
* feat(mobile): rebuild the terminal dock around Keys and Message modes
Agent tabs open in Message mode, where you write in the chat composer and
Send types it into the terminal. Shell tabs open in Keys mode, where each
letter goes straight to the terminal through the live field. A pick made on
an agent tab lasts until the agent quits. The shell/agent rule is the one
keyboard dismissal already used, now shared.
The key row carries sticky ctrl, alt and shift (tap for the next key,
double tap to lock) and one arrow pad (tap a side, or hold and drag to
repeat through the existing held-key repeat). Paste, attachments, the
display width, the remaining keys and custom keys move to a ⋯ sheet. Return
in the composer adds a line; Send sends.
* fix(mobile): read arrow-pad taps from the pad and keep every key reachable from ⋯
A touch on a chevron made the icon the touch target, so the side was
measured against the icon's box and most taps read as left. The ⋯ sheet
now leaves out only the keys the current row shows, so agent tabs get Tab
and shell tabs get Shift+Tab and Enter back.
* fix(mobile): keep the last changed files clear of a growing commit box
The file list's bottom inset was a fixed 196 pt, so a commit message several lines long hid the last rows behind the commit bar. The inset now follows the bar's measured height.
* test(mobile): give the file list test its bottom inset
- Pin dialog and floating surfaces inside .plugin-security-chrome so a theme's --popover can't wash out trust text
- Limit auto-closing pairs and comment markers to 1-8 printable single-line characters (validate:plugin refuses; hosts drop the entry)
- Strip control, bidi and zero-width characters from plugin names, titles and listing text (validate:plugin refuses; hosts and the plugin list strip)
* fix(mobile): retain editor styling when switching color schemes
* test(mobile): fit theme-switch harness hooks under the file line cap
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(windows): start the WSL holder outside Orca's jobs so a crash doesn't take it down
* test(windows): prove the job closed with a non-breakaway control before checking the holder
* fix(mobile): keep table-cell and list-item line breaks on their own source line
Table cells and list items save line breaks as <br /> (and sibling P/DIV
blocks inside an item as breaks), and reopen attribute-free <br> tokens
as breaks, so Shift+Enter or Enter no longer splits a row or ends a list.
Typed '<br>' text gets only its '<' entity-escaped, raw text newlines
become spaces, and browser caret placeholder breaks are dropped (a cell
that holds only a placeholder saves empty; a cleared item keeps a <br />
so its marker still parses).
* fix(mobile): keep fenced code blocks inside Markdown list items
Indented fences under a list item (README steps such as
'1. Install:' followed by an indented bash fence) now read as a code
block inside the item and save back under the item's continuation
indent. Only items whose continuation holds a fence change; headings,
quotes, rules and tables after the fence end the item and read as
before. Top-level and list code blocks share one PRE writer, blank
separator lines are not indented, and a fence needs no blank line
beside it so tight items stay tight.
* fix(mobile): keep caret code blocks out of the paragraph they follow
Code block with a collapsed caret after text in its block ran native
insertHTML, which merged the PRE into that paragraph as prose. Prepend
a <br> only when content precedes the caret, so block-start, empty-line
and empty-document insertions stay as they were.
* fix(mobile): keep authored runs of trailing table-cell breaks
* fix(mobile): use template literal for list code-fence probe
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(mobile): preserve literal code through rich Markdown edits
* fix(mobile): preserve inline code containing backticks
* Preserve adjacent inline-code text when saving mobile Markdown
* Preserve quote paragraphs and blocks in mobile Markdown
* fix(mobile): preserve selected text when creating code blocks
* test(mobile): choose native history shortcut from browser host
* Preserve paragraph-owned mobile code blocks when saving
* Preserve code selected inside mobile headings after saving
* fix(mobile): keep code serialization space-normalized and trim review tests
- Inline code and code blocks keep turning browser-created NBSPs into spaces;
only the reader-side entity fix is needed for literal code.
- Inline code line breaks save as spaces so table rows and headings stay intact.
- Code blocks keep trimming trailing newlines left by placeholder <br>s.
- Heading- and paragraph-owned code blocks join adjacent inline code runs.
- Empty nested quotes reopen as a plain empty paragraph.
- Trim synthetic and behavior-locking tests.
* fix(mobile): keep quoted text literal when block reading would rewrite it
Quoted list continuations and lazy lines were restructured on save because the list reader drops them; reopen quote blocks only when they save the source or the same bytes as the literal paragraph.
* test(mobile): use template literal for saved code-block markdown
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* test: run the AI Vault title-input GC check on Node
The test asserts superseded maps are garbage collected. Under Bun, whose GC
scans the stack conservatively, it can keep one alive, which failed CI on an
unrelated PR. Route it to Node with the other V8 retention checks.
* test: run the other forced-GC checks on Node too
HostRemoveDialog and the happy-dom observer retention check force a
collection like the AI Vault check; under Bun's conservative GC they can
fail or pass falsely.
* fix(computer): leave Linux and Windows windows in the background for accessibility actions
Element clicks no longer restore and activate the target window when an
AT-SPI action or UIA Invoke/SelectionItem/Toggle pattern handles them; only
the pointer fallback activates. On Linux, type-text and paste-text insert
into the focused editable field through AT-SPI EditableText without needing
window focus, and fall back to key synthesis or the clipboard otherwise.
Refs #12412
* fix(computer): refuse pointer input after failed activation
* fix(computer): stop after unconfirmed text writes
* fix(computer): insert the full UTF-8 text on Linux
* test(computer): focus each Linux text-entry trial
* fix(computer): verify Linux text mutations before deletion
AT-SPI can acknowledge writes without changing text. Read back
mutation counts and caret state before reporting success.
* fix(computer): verify complete Linux text replacements
* fix(computer): decline unreadable Linux text selections
* feat(computer): drive macOS apps in the background by default
Clicks no longer activate and raise the target first. Pointer and key
input go to the target window's pid through a new BackgroundInputTransport:
mouse and scroll events carry the window id in field 51 and a window-local
location, keys run inside a focus-without-raise key-window scope, and
chords carry no Unicode string so menu key equivalents fire. Scroll and
drag now land (#27306); typed text no longer doubles in Electron (#17942).
The HID tap and focus fence stay for --restore-window only. Results
report action.delivery, the handshake reports supports.input.background,
and a missing private symbol or a popup click fails with
background_unavailable instead of falling back to the foreground.
* test(computer): read typed key strings back instead of diffing live-state events
* fix(computer): keep Unicode characters in one key event
* fix(computer): preserve active macOS key windows
Refuse key-window changes in the active app and surface failed
focus records, including cleanup after partially delivered input.
* fix(computer): guard macOS click routes before delivery
* fix(computer): let paste events read the clipboard
* fix(computer): classify clicks in the requested macOS window
* fix(computer): fence macOS scroll and drag recipients
Fixes#34312. Takes over naufaldi/orca#1 by @naufaldi, with the main.css part dropped because #34932 already covers it.
- SshTargetCard and the reasoning chevron now use the scoped `[[class~='group/x']:has(:focus-visible)_&]` shape. Tailwind's `group-has-*` compiles to a non-subject `:has()` whose subject is `*`, and that rule made Blink restyle whole subtrees on every mutation. This change is the entire measured win: 19.4 → 1.6 ms, 12.5 → 3.6 ms and 8.0 → 2.4 ms per mutation.
- rich-markdown-editor.css drops a redundant `:has()` on the TOC header, as defence in depth.
- Adds a guard, check-has-restyle-scope.mjs. It compiles the renderer's Tailwind CSS, adds plain stylesheets and the listed vendor stylesheets, and fails on any non-subject `:has()` whose subject has no class, id or attribute. Three pdf.js rules are baselined after being measured as harmless. It runs in lint, check:changed and PR CI in about 1.5 s.
Co-authored-by: Naufaldi <naufaldi.rafif@gmail.com>
* Support Windows native Antigravity account credentials
* Preserve Antigravity prompt arguments and sanitize Windows file failures
* Preserve Windows credential bytes and distinguish native read failures
* Import Buffer type in Windows security declarations
* Expose native credential bytes without a Node type dependency
* Let Windows agy launches keep shell ownership
* fix: declare Windows account messages and cover owner scope
* fix: resolve Windows account authority before snapshot projection
* fix: share Windows credential parsing with saved account reader
* test: type saved account identity lookup mock
* test: isolate native account fixture host detection
* test: reuse filesystem mock for container marker control
* test: preserve native credential contract failure diagnostics
* test: normalize private read expectation and cover Windows boundary
* fix(browser): every web link in Orca follows the open-links-in-Orca setting
* test(browser): pin where links from Orca UI open
* fix(browser): keep the link-routing escape modifier and owning workspace on UI links
Credential and star links stay in the system browser; shared markdown keeps its owner-aware routing.
* fix(browser): hover cards and review toasts open links in their own workspace
API-key and console pages stay in the system browser; non-web hrefs are ignored like the system bridge does.
* fix(browser): UI link wrappers pass the click so the escape modifier applies
Share to X stays in the system browser with the other account-action pages.
* fix(browser): folder workspace PR-check links open in the folder workspace
* test(browser): name UI link tests after the path they exercise
* chore(browser): keep the link-open ratchet's helpers private
* fix(browser): narrow the Linear project toast link before routing it
* fix(browser): UI links route with this desktop as their source owner
Links from Orca's own UI no longer read the Active Server setting; the opener routes by the host workspace.
* fix(browser): UI links open under the host workspace's own owner
A remote workspace's browser gets the original URL, not this desktop's localhost label.
* fix(native-chat): read browser route eligibility from its owner module
Importing it through workspace-browser-tab-open pulled the store into every link button and formed an import cycle.
* refactor: colocate Jira cache and project selection owners
* ci: refresh Jira refactor validation after main test fix
* ci: refresh Jira owner move after main validation fixes
* perf(diagnostics): split terminal echo latency into queueing, round-trip, parse and paint phases
The typing diagnostic started timing at its own capture handler and lumped the
PTY round trip, renderer output scheduling and xterm parse into one interval, so
a stalled renderer could not be told apart from a slow PTY or TUI. Exact samples
now also report trusted-event input queueing, onData to first output reaching
the output scheduler, scheduler queueing, and xterm parse, plus each sample's
overlap with long animation frames. The report shape only gains fields.
* test(bench): measure terminal echo phases under accumulated workspace-update pressure
Adds a typing bench scenario that types into one real PTY while the accumulated
store receives rank-only order publications (and optional status traffic), runs
the in-app phase diagnostic beside the PTY sidecar, and moves the shared bench
knobs and report writer into a module both specs use.
* perf(terminal): send a typed key to the PTY before publishing its activity stamp
xterm fires onUserInput before onData, and the first key after a pause wrote
lastTerminalInputAtByPaneKey synchronously there, so the key waited on every
store subscriber before it was sent. Publish the stamp in a microtask instead:
the same task still records it, after the key has been handed to the transport.
At 1,620 workspaces and 2,356 store listeners, input-to-dispatch for keys after
a pause fell from p50 1.2-1.5 ms to 0.5 ms.
* Improve typing latency diagnostic accuracy
* Flush queued long tasks in live typing latency reports
* test(e2e): on the real WSL lane, background work never starts the stopped distro (E9 guard)
The Windows real-WSL lane opens a project inside its own imported distro, terminates that distro,
and runs a window of background work elsewhere (focus/blur/reveal, workspace switches, a linked
issue/PR card, Settings panes, Tasks, account switches). Every child the main process starts is
logged; no wsl.exe may run anything in the distro (listings are fine), and `wsl --list --running`,
watched each second, must never show it, which also catches UNC touches. Opening a terminal in the
WSL workspace then starts it. A participation check fails the lane if the guard skipped.
* test(e2e): actually render each Settings pane in the WSL lane's E9 background window
openSettingsTarget alone only set the navigation target, so no pane mounted and none of its reads
(servers, accounts, agents, integrations, CLI status, the repo pane's orca.yaml check) ran. Open
Settings, wait for each pane's section to mount, then close it.
* test(e2e): harden the WSL lane's E9 guard per review
- process-host logs every spawn to ORCA_E2E_SPAWN_LOG when set, so the guard sees worker-thread
and inheriting-child spawns (e.g. the Codex rate-limit fetch), sync ones included.
- The spawn baseline is taken before `wsl --terminate`, and the running-list watcher starts right
after it, so work in the stopping window counts.
- A wsl.exe launch counts as starting the distro unless it names another or only lists/terminates.
- The watcher is async with a 5 s timeout and non-overlapping ticks; a failed read is retried and
fails the guard after three, never reads as "stopped". The recorder throws if it cannot hook,
and the spawn log must be non-empty. The doc names the watcher as the authoritative assertion.
* test(e2e): bound the terminate grace, keep the spawn log out of shipped runs, tolerate torn lines
- The watcher forgives running reads only within 3 s of `--terminate` and before its first
not-running read, which the rounds now await; any running read after it fails the guard.
- Main drops ORCA_E2E_SPAWN_LOG outside e2e mode (no ORCA_E2E_USER_DATA_DIR) before anything
spawns, so no daemon, PTY or agent inherits it; the log holds full argv, tests only.
- readSpawnLog skips a line torn by a concurrent append.
* test(e2e): no blocking wsl.exe in the WSL lane's E9 guard, and a timeline for failures
The first lane run was cancelled at the 30-minute job limit while the guard step had run 25
minutes: past three 5-minute test timeouts, which only a blocked worker survives. Every wsl.exe
call (setup, terminate, cleanup) is now async with a timeout, so a hung one fails the test. The
guard logs a timestamped timeline (each running-list read, terminate, rounds) for diagnosis, and
the job limit goes to 50 minutes for the three added runs.
* test(e2e): let the setup's own WSL terminal launch settle before the terminate; 10 s grace
The lane run failed with "Ubuntu was still listed 3000 ms after --terminate" in all three runs.
The timeline showed why: focusing the WSL workspace in setup is a user act that opens a WSL
terminal, and its launch (codex trust probe, PTY, hook relay) landed about a second after the
terminate and restarted the distro. Setup now waits for that terminal's PTY and for wsl.exe
launches to go quiet for 3 s before terminating. The grace is two running-list reads (10 s).
* test(e2e): interleave wsl.exe launches into the E9 guard's timeline
The lane saw the distro boot about two seconds after the terminate with nothing naming the
launcher; each running-list tick now also prints the wsl.exe launches logged since the last one.
* test(e2e): time and stack every logged spawn and main's WSL UNC touches
The E9 guard printed spawns at its poll time, up to a second late, and with
no caller. Each record now carries when it happened and the caller's stack,
and main's fs touches of \\wsl.localhost paths are logged too, so a boot
with no wsl.exe launch before it can still be attributed.
* test(e2e): keep spawn-log stacks and main's fs hooks strictly to e2e mode
process-host now writes the spawn log, and captures caller stacks, only when
ORCA_E2E_USER_DATA_DIR is set as well, so a stray log variable in a CLI or
daemon environment does nothing. The main-process fs/spawn hook refuses to
install outside an e2e-mode app, and a source scan pins that no shipped code
imports or installs it.
* test(e2e): guard a focused WSL workspace left idle through the stop
Device runs saw a stopped distro restart with its bridge workspace focused
and nothing touched: the stop's own fallout re-ran renderer reads as user
acts. The new case keeps that workspace focused with a folder expanded in
the Explorer and Source Control shown, terminates, and idles. Shared guard
helpers move to tests/e2e/helpers/wsl-boot-guard.ts.
* test(e2e): capture caller stacks deep enough to reach the IPC handler
* test(e2e): give the focused-idle guard's timeout bump its reason
* fix(windows): start the WSL holder with only a NUL handle to inherit
libuv starts every Windows child with bInheritHandles=TRUE and no handle
list, so a detached holder that outlives Orca kept any inheritable handle
Orca had open, such as a launcher's pipe or a DevTools socket. Start it
through CreateProcessW with PROC_THREAD_ATTRIBUTE_HANDLE_LIST naming one NUL
handle for its stdio. The build probes now check the newest export without
calling it, and the lane receipt labels ConPTY's own startup output.
* fix(windows): report isolated holder exits and kills the way libuv does
* test: clear inherited GIT_* env once per test file so real-Git suites cannot write into an outer repo
* test: clear only repo-locating Git env so the compat lane keeps GIT_EXEC_PATH
* fix(wsl): every local Git call follows its project's runtime unless it says why not (D1c-6)
* fix(wsl): rebuild Git routes on the store's own writes, never on a timer, and route a new worktree by its link
* fix(wsl): route WSL-made worktree links, aliased checkouts and sync Git; host Git only where marked; no wsl.exe storms
* fix(wsl): map WSL-made worktree links through each project distro's automount root
* fix(wsl): arm the missing-distro cache only with the Git router on, and feed it spawn failures
* fix(wsl): keep synchronous Git host-only, read the setup runner's path from the link, and keep the sync launch under the ratchet
* chore(wsl): move the sync Git runner's process-host import allowance with it
* fix(wsl): read only per-worktree git paths from the link, and only from a git dir that still exists
* fix(wsl): name which Git ran on stream and spawn spans too, so status shows its route
* test(wsl): setup runner lookups declare host Git; cover the link read with the router on and off
The hooks tests expected the setup runner's `rev-parse --git-path` call to
carry `wslDistro: 'Ubuntu'` for a WSL-runtime project. On main that field
never reached Git: main's gitExecFileSync options have no wslDistro and it
calls resolveCommand('git', args, cwd) with no distro override, so the
lookup ran host Git (WSL only when the cwd itself is a WSL path). The tests
pinned call arguments, not what ran. The sync runner now states that with
`hostGit: true` and resolves exactly as main did, so the tests assert that.
New worktree-runner-script-link tests cover the router-gated link read:
router on reads the link; router on with no usable link falls back to host
Git and converts its Linux path; router off makes main's host Git call and
never reads the link.
* test(git): read src/main once in the host-Git routing guard, so it holds under load
* test(wsl): pin the setup runner's sync Git spawn to main's exact launch on POSIX
The setup runner's path lookup now passes hostGit: true where it passed a
wslDistro that gitExecFileSync never read, so the binary, args, cwd and env
it spawns are unchanged. Update the call-shape assertions and pin the POSIX
execFileSync call itself.
(cherry picked from commit 6aae6d4d090e13b75c1d9ad2734f2f717dde7570)
* fix(wsl): await WSL Git admission in spawns only when there is one
With the Git router off admitWslGit returns null; awaiting it anyway added a
microtask to every spawn's admission path that main doesn't have.
(cherry picked from commit 883aaeb90bc23e89cafb039708a565ab3d72620e)
* fix(wsl): keep main's Git scheduling when the D1c Git router is off
The remote-identity sweep moved every user's probes to the background
admission tier, which only the router reads; it now keeps its tier unless the
router is on. Admission wrapping and the spawn stderr tail also step aside
without the router, so those calls run exactly as on main.
(cherry picked from commit 151a3091307c03078d0c0b98487bbe3bf467ec27)
* test(wsl): point the distro allowlist test at the sync runner's new home, as host Git
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 255e85fc93deba83addc4370f889c1b721180188)
* test(wsl): installing the Git router with the gate closed or off Windows leaves none installed
Co-Authored-By: Claude <noreply@anthropic.com>
* perf(wsl): skip the span-only Git resolution on every spawn while the Git router is off
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): read a distro's automount root only from a running list probed after its stop settled, so it never boots a terminated distro
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Boot the built orcad the way a WSL host launch does, open a repo and two
terminals, idle 90 s, and assert the whole process tree stays under
400 MB of RSS (about 251 MB today). It catches a new always-on worker or
a retained buffer between device runs of the 1 GB memory gate.
* fix(windows): keep Orca's std handles out of every spawned child
libuv spawns with bInheritHandles=TRUE, so an inheritable std handle reached
long-lived children such as the WSL holder and the daemon and held a
launcher's pipe open after Orca exited. Clear HANDLE_FLAG_INHERIT on the std
handles at the top of main startup; stdio 'inherit' still works because
libuv hands the child its own inheritable duplicate.
* test(windows): model Orca's Electron main, which keeps std handles inheritable
Plain Node clears its std handles' inherit flag at startup, so a Node child
never reproduced the leak. Electron main opts out of that, which is why Orca
leaks and why the control arm now runs Electron; a plain-Node arm pins the
difference.
* test(windows): say why the std-handle tests need longer timeouts
* feat(orcad): gate agent launches on accounts and cancel feature waits for departed callers
requires: may read the parsed params, so terminal.create and
session.tabs.createTerminal wait on accounts only when they start an
agent; plain shells stay ungated. createAgentSession, ensureAgentSession,
agentSession.create, agent.launch (unless it reuses a terminal),
git.generateCommitMessage and the worker-launching orchestration methods
also wait on accounts. The feature wait races the request signal and the
connection close and refuses without running the handler.
* feat(orcad): gate terminal.ensureAgentSession only for explicit launches
An attach to an existing session is restore latency and needs no fresh
account state; only kind 'explicit' may start an agent.
* test: reset orcad feature readiness after every unit test
A startOrcad test that fails partway left latches closed, so later tests
in the same worker could wait 10 s on a gated method.
Enable Vitest's persistent module cache outside CI under node_modules/.cache/orca-vitest-modules,
keyed by the existing CI module-cache policy hash (lockfile, tsconfig/package manifests, runner
scripts) plus the Node version. reclaim-space removes caches unused for 7 days.