Commit Graph
19647 Commits
Author SHA1 Message Date
Neil f46103acc9 fix(pairing): a registry save can no longer put back a device revoked while it was writing (#39192)
Device registry saves re-read the file, merge and rename. A save that read
the file just before another writer removed a device (an admin script, the
desktop, orcad) and renamed just after would write the revoked row back, and
its token would keep working. Saves now publish only if the file is still
exactly what they read (compare-and-swap via the staged write's last check),
and otherwise re-read and re-merge. A file caught half-written by a
non-atomic writer is re-read after a short wait instead of being treated as
corrupt and overwritten.
2026-11-06 16:59:56 -08:00
Brennan Benson ad4bb83fa1 Open the chat model picker without walking every worktree (#38660)
* fix(native-chat): list Claude and Codex models per account, not per folder

Opening the chat model picker rebuilt every worktree row to work out which
folder the read was for, because Claude and Codex model lists were keyed by
folder. Only the default model/effort depends on the project, so lists are now
keyed by account, WSL and the resolved CLI invocation and listed from the
account folder; the CLI is still resolved where the chat would launch. The
selected workspace is derived directly from its selector, and its own project
settings decide whether the account's default model and effort are shown.
The worktree projection and its cache are removed.

* test: merge duplicate node:os import

* fix(native-chat): list from Orca's probe folder, keep cwd-relative CLIs in their folder, one project-settings pass

- List Claude/Codex models from Orca's empty probe folder so a home folder's settings never read as another account's project settings.
- A command line naming files relative to the chat's folder lists there and is keyed to it.
- Read project settings once per binding for both the model and effort answers; per-model effort-only Claude settings keep the account model.
- A running chat's catalog withholds the account's configured choice where its project may pick its own.
- Bound the picker's workspace resolution so a stalled floating folder cannot hold it.

* fix(native-chat): catch quoted ./ arguments, list prewarm from Orca's probe folder, fake-timer the shared-listing test

* perf(native-chat): parse each project settings file once for both model and effort

* test: catalog e2e expectations list from Orca's probe folder; phone saturation keys per folder

* fix(native-chat): share a listing while any reader wants it; list custom command lines in the chat's folder; resolve a floating folder within the read's own wait

- A model listing shared by several folders keeps running while any reader still waits on it, queued or running, and stops (never starts) once the last one gives up.
- A Claude or Codex command line with user arguments or a relative command lists in the chat's folder; Claude reads only user settings there so project settings never narrow the account's list.
- A waiting read resolves a floating folder within its own deadline; a read that doesn't wait returns at once and starts the listing when the folder resolves.

* fix(native-chat): every reader of a shared model listing owns it until its own deadline; floating reads list their folder within their own budget

- Readers of the same request share one lookup that lives until the last reader's deadline, so later readers neither repeat CLI/settings setup nor lose the listing when an earlier one ends or is cancelled.
- A shared listing's requests carry no single reader's deadline: the provider timeout bounds them and the last reader leaving stops them.
- A floating picker read that doesn't wait starts its folder's listing under its own deadline and retirement, and says the listing is in progress so the picker follows with a waiting read.

* fix(native-chat): a shared model listing survives the chat that started it; unreadable workspaces list as the account

- Each reader of a shared lookup fences its own request, so one chat closing never ends another chat's listing; the lookup's budget is the latest deadline among readers still waiting, and its listeners are released when it ends.
- A picker for a workspace this host can't inspect (remote, WSL, ambiguous, stalled) lists as the account does from Orca's probe folder, never from wherever Orca itself runs.

* refactor(native-chat): readers of one model request share an ownerless setup and each own only their claim and the listing

- Same-request readers share one setup (folder, account, CLI scope and the folder's own default settings) that belongs to no reader: its budget is fixed when it starts, it ends with the service or the agent's retirement, and it is reused while it runs and while the listing it found runs.
- Each reader keeps its own claim, deadline and cancellation; a binding holds scope facts only and never cancels another reader's claim or a shared listing, so one chat closing never ends another chat's listing.
- A floating picker read that doesn't wait no longer asks to list the unresolved folder.

* fix(native-chat): shared catalog setups end on their budget or a workspace change, readers settle on cancel, and defaults and account seeding happen once

- A shared setup that runs out of its budget, or whose workspace or agent is retired, answers nothing at once and leaves the cache, so a reader with time left resolves afresh (a moved folder never reuses the old path).
- Cancelling a reader, or stopping the service, ends its wait at once.
- A folder's own default settings apply to its binding whenever they arrive; the account list is seeded once per shared setup, not per reader.
- A reader shares a setup only with readers whose own chat agrees on whether it may list.

* fix(native-chat): a settled catalog setup serves its whole listing, and a folder's default settings stay bounded and reach every reader

- A setup that has answered stays reusable while the listing it found runs, past its first reader's deadline, until it is ended or its agent retired, so later readers don't redo CLI and project-settings work.
- The setup's budget holds until the folder's default settings have answered too; settings that outlive it are read again while a reader still has time, and apply to the request's current binding whichever reader asked.

* refactor(native-chat): the catalog service owns each model refresh within one fixed budget; pickers only wait

A refresh (account, folder and CLI resolution, the folder's default settings,
admission and the listing) now belongs to the catalog service with one 30s
budget fixed before setup. Readers join it and wait only until their own
deadline or cancellation; none extends, shortens or ends it. Expiry withdraws
queued listings, stops the process and drops late answers. Defaults apply only
to the refresh's own binding, so a moved folder's late settings never describe
the new folder. A waiting read that used its whole budget is final.

Replaces per-reader claims, shared setups and reader-counted listing demand.

* fix(native-chat): retiring an agent or a chat's folder ends its catalog refresh at once, and a shared setup never rechecks the chat that started it

- Retiring an agent ends a refresh still stalled in setup, so a waiting picker
  answers at once instead of after the refresh's budget.
- A listing that runs in a chat's own folder stops, and its answer is dropped,
  when that folder's command context retires; listings shared across folders
  stay independent.
- Scope resolution uses only the passivity its readers had when they asked,
  so another chat's record going away mid-setup no longer turns it saved-only.
- A reader that stops waiting unsubscribes from the listing at once.

* fix(native-chat): one workspace's retirement no longer stops a catalog listing another workspace shares

A listing is keyed by the folder it lists in and the CLI invocation, so moving
one workspace never makes it describe the wrong folder; stopping it there
cancelled a listing another workspace on the same folder still needed. Agent
retirement and shutdown still stop listings at once.

* test(native-chat): a folder change keeps another workspace's shared catalog listing, and never answers the new folder with the old one's

* test(native-chat): a folder agent's listing survives another workspace on its folder moving

* test(native-chat): type the shared-setup harness's held stages without casts

* fix(native-chat): Claude and Codex pickers show the account's default in every folder

The picker no longer reads a repo's own model or effort settings for Claude and
Codex: they show the account's list and default everywhere, and the CLI still
applies the repo's settings at launch. OpenCode, OMP and Pi keep their project
checks. The model/effort split and the peek withholding go back to main's shapes.

* fix(native-chat): a Codex listing in the chat's folder never loads that folder's project config

A Codex command line that may name files in the chat's folder still lists there,
but now marks that folder and its parents untrusted for the listing, so a repo's
own model catalog can't replace the account's. The exported project-settings
check also answers no for Claude and Codex.

* fix(native-chat): Codex lists models only from Orca's probe folder

A Codex listing no longer starts in the chat's folder for custom or relative
command lines, so a repo's own config can never change the picker's list, as
other Codex hosts do. Chats still launch with the user's command line and folder.
Drops the untrusted-folder override.

* fix(native-chat): Codex listings never read project config above Orca's folder

With no project-root markers, Codex reads project config only from the listing's
own folder, so a trusted repo that contains Orca's profile can't supply the
account's model list.

* docs(native-chat): say what Codex listing isolation covers, and what managed config can still restore
2026-11-06 16:59:49 -08:00
NeilandAnddy Sahir Agudelo 5edd3346c0 feat(settings): add Antigravity IDE to the Open In Apps presets (#39237)
* feat(settings): add Antigravity IDE to the Open In Apps presets

Launch Google's Antigravity IDE through its bundled `antigravity-ide`
launcher (`agy` is the separate Antigravity CLI agent), and make the
setting searchable by "antigravity".

Supersedes #5636.

Co-authored-by: Anddy Sahir Agudelo <AnddyAgudelo@users.noreply.github.com>

* chore(i18n): add German Antigravity IDE entries for parity

---------

Co-authored-by: Anddy Sahir Agudelo <AnddyAgudelo@users.noreply.github.com>
2026-11-06 16:59:09 -08:00
Brennan Benson 5d1c2a8910 Honor agent defaults when setting up later (#38028)
Set up later saves the applicable visible Chat/Terminal and agent choices, preserves unvisited saved defaults and Blank, then opens the default agent through ordinary workspace activation in the captured workspace and host. First use and Help replay share the behavior, and failed saves remain retryable.

Independent reviews accepted the main-parent update. All 27 focused tests and final-head CI passed, including twelve unit shards, static/typecheck, changed E2E and packages. Real Claude/Codex Chat and Terminal, saved Blank and graceful-restart QA carries across the main merge. The final local changed-check prerequisite timed out in the resource queue before checks ran; this limitation is documented in the PR.
2026-11-06 16:53:48 -08:00
Brennan Benson 885ee1ee84 perf: avoid repeated publisher scans during workspace purge (#39232)
* perf: index workspace purge publishers by host

* test: construct host-qualified purge targets
2026-11-06 16:45:59 -08:00
NeilandJose Espana 1edd32de9a feat(runtime): cap unauthenticated WebSocket connections per source and record client source class (#39206)
The runtime WebSocket listener bounded connections only globally (256 TCP,
128 WebSocket), so one host holding unauthenticated sockets could take every
slot. Each source (one IPv4 address, or one IPv6 /64) may now hold at most 64
connections that have not authenticated; loopback is exempt, and a source
that already holds an authenticated socket is never refused.

Authenticated direct connections now record the class of their source
(loopback, private, tailnet, public) on the device row through the existing
deferred last-seen write, and the first authenticated public-source
connection persists allowPublicSources in userData. Nothing reads it yet.

Co-authored-by: Jose Espana <jose.espana@perseusoft.tech>
2026-11-06 16:43:54 -08:00
Jinjing 1f1eb76593 fix(i18n): translate recent desktop and mobile copy (#39233) 2026-11-06 16:33:34 -08:00
Brennan Benson 46575a257f Open fresh desktop profiles in a ~ folder workspace (#37898)
Fresh desktop profiles start in an ordinary folder workspace at the OS home directory, with the initial repo group named ~. Onboarding Continue saves the selected default agent and launches it in that workspace through the normal activation path. Existing profiles and user-renamed groups remain unchanged.

Independent reviews and prior real Claude/Codex QA are complete. Refreshed-head CI is green, including all unit shards, changed E2E, static/typecheck, packages, persistence and WSL. All 54 focused regression tests passed; three bounded local check timeouts are documented in the PR.
2026-11-06 16:29:36 -08:00
Neil 93589dc6f8 fix(shell): open linked scripts in the editor and reveal programs instead of launching them (#37930)
* fix(shell): show linked scripts in the editor and reveal programs instead of launching them

Markdown file links that would run code no longer go to the OS default
app. Main inspects the target (following symlinks, checking every name
in the chain plus the executable bit and the file header): readable
scripts open in an Orca editor tab, binaries and bundles are revealed in
the file manager, and everything else opens as before.

* fix(shell): reveal linked archives instead of unpacking them

Zip, tar, gzip, bzip2, xz, zstd, 7z, rar, cab and zip-based packages
(.war, .ear, .apk, .ipa, .xpi, .crx, .vsix, .nupkg) are revealed in the
file manager. Archive headers are also treated as binary content, so an
archive under a script name or an extensionless executable name is
revealed rather than shown as text.
2026-11-06 16:25:12 -08:00
NeilandMatheus Breguêz 42315bc039 docs: add a security policy pointing to private vulnerability reporting (#38926)
Adds .github/SECURITY.md so GitHub links reporters to the private
vulnerability reporting form, and points to it from CONTRIBUTING.md.

Replaces #25553, carried over with small wording changes.

Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>
2026-11-06 16:24:50 -08:00
AdolaniumandNeil b10f90c8f9 fix(files): restrict staged saves to their owner (#36343)
* fix(files): restrict staged saves to their owner

* fix(files): remove a temp restriction cannot keep

writeSecureFile publishes the file before it reports that owner-only permissions failed, and nothing else tracked it.

* fix(files): reject a staging directory whose mode does not stick

chmod can succeed on DrvFs without making the directory owner-only. Non-Windows setup now refuses unless the directory mode is 0700.

* fix(files): keep staged saves working where owner-only modes don't stick

Create the temp owner-only at creation (wx + 0o600) instead of through
writeSecureFile, and treat a staging folder whose mode or ACL cannot be
tightened as a one-time warning rather than a save failure, so network,
FAT and some WSL mounts keep saving.

---------

Co-authored-by: Neil <neil@stably.ai>
2026-11-06 16:24:28 -08:00
AdolaniumandNeil d2e4402623 fix(relay): authorize reserve routes before reading request bodies (#36346)
* fix(relay): bound internal reserve request bodies

* fix(relay): authorize before reading reserve bodies

Hono reads a chunked body inside the body limit before next(). A caller who fails the director check can no longer stall the refusal, and an oversized body from that caller is not reported as 413.

* test(relay): cover an unavailable demote body

The missing-route check only posted to /internal/reserve. Demote now gets the same oversized request and must stay 404.

---------

Co-authored-by: Neil <neil@stably.ai>
2026-11-06 16:24:06 -08:00
Neil bb5f37c916 feat(pairing): unscanned desktop pairing codes expire (QR 10 min, link 60 min) (#37957)
* feat(pairing): unscanned desktop pairing offers expire (QR 10 min, link 60 min)

Headless serve/orcad mint offers without a TTL, so they never expire.
Paired rows and rows without offerExpiresAt are unaffected.

* feat(pairing): refresh the mobile QR before it expires and show runtime link expiry

The QR re-mints a minute before expiry while visible; an unused runtime
link shows its expiry and, once expired, is replaced by a notice. Web
clients rejected while pairing now suggest asking for a new link.

* feat(mobile): say a refused pairing code expired or was replaced

A first pairing the desktop refuses (direct or Relay) now asks for a new
code instead of showing the raw transport error.

* refactor(pairing): replace type assertions in code-refusal detection and tests

* test(mobile): re-record pairing race golden for refused-code error

* fix(pairing): keep pairing codes valid across sleep and stale registry writers

- QR refresh rechecks the wall clock every 15 s and on window focus, so a
  computer waking from sleep never keeps showing an expired code.
- A registry save from a process with an older copy can no longer reset a
  paired row back to unscanned (which would let its offer expire).
- The QR caption says how long a copied code works.

* test(pairing): annotate the IPC handler stub cast
2026-11-06 16:23:44 -08:00
Neil a745884b17 fix(automations): store the approved setup hash and skip setup when a run's branch differs (#37979)
* fix(automations): store the approved setup hash and skip setup when a run's branch differs

Saving an automation with setup run records the hash of the content the user
approved; headless, chat and desktop-dispatched runs send it with the create,
so a branch whose setup differs skips setup (logged on the host). Writes that
set the decision without a hash (CLI --setup run) and older automations keep
today's behaviour.

* fix(automations): show on the run when setup was skipped because the branch differs

Runs record setupSkippedReason 'setup-changed' when the new workspace's
orca.yaml setup differs from the hash saved with the automation (headless,
chat and desktop-dispatched runs), and the run page says so with what to do.
The note survives the run's completion update.

* test(automations): pass run history to the setup-skipped run details test
2026-11-06 16:23:20 -08:00
Kelvin Amoaba 768df33d84 fix(dictation): handle cloud dictation's 10-minute cap, stalled uploads and bad API keys (#39114)
* fix(dictation): bound cloud uploads, stop at the 10-minute cap, check the OpenAI key on save

* refactor(dictation): share the OpenAI error reader
2026-11-07 00:22:24 +00:00
Kelvin Amoaba ea32ccb0ec fix(dictation): show Listening while the speech model loads, and link start toasts to Voice settings (#39136)
* fix(dictation): say Listening once the mic is recording, and translate start toasts with an Open Settings action

* refactor(dictation): derive the indicator label from the listening flag
2026-11-07 00:21:33 +00:00
Kelvin Amoaba a3a0e68380 fix(packaging): require macOS 13.4, the minimum the on-device speech engine runs on (#39135)
* fix(packaging): require macOS 13.4, which the bundled speech engine needs

* fix(updater): keep the macOS requirement title clear of the close button

* fix(packaging): check out the Darwin floor table for adhoc builds and raise the cask floor

* refactor(updater): reuse the parsed Darwin floor for the macOS requirement

* fix(updater): use a margin to keep the macOS requirement title clear of the close button

* fix(updater): say the macOS requirement comes from Electron and the speech engine
2026-11-07 00:18:50 +00:00
Kelvin Amoaba efc27ee8ee fix(terminal): finish a paste in its terminal when dictation or overlays move focus mid-paste (#39112)
* fix(terminal): finish a paste when focus moves to a non-input control mid-paste

External dictation tools and overlays can leave focus on a control outside the pane while the clipboard read is in flight, and the paste was thrown away as stale. Only cancel when another paste target (terminal, input, frame) took focus.

* fix(terminal): count Monaco and rich editors as paste targets

* test(e2e): a paste survives focus moving to a non-input control mid-read

* refactor(terminal): one focus rule for terminal and popout paste

* test(e2e): scope each focus-move script so later cases actually move focus
2026-11-07 00:18:12 +00:00
Kelvin Amoaba 58c739b75c fix(speech): add a dictation language setting that Whisper, SenseVoice and OpenAI use (#39102)
* fix(speech): send the dictation language to Whisper, SenseVoice and OpenAI

The voice language setting was stored but nothing read it, and its 'en' default never came from the user. Replace it with dictationLanguage (default auto), pass it to every engine that accepts one, and add a picker that says when the selected model ignores it.

* test(settings): add dictation language fixtures

* refactor(speech): keep each model's dictation languages on its catalog entry

Language support belongs to the model, not its engine type, so an English-only Whisper build can't be sent another language. Also reuse SettingsRow and cache Intl.DisplayNames.

* fix(speech): let SenseVoice users pick Cantonese

* test(speech): drop type assertions from the new language tests
2026-11-07 00:17:37 +00:00
Brennan BensonandWooseong Kim ef68fa9bb3 Shrink oversized pasted images to fit instead of failing with "Clipboard image is too large" (#39050)
* fix(clipboard): shrink re-encoded paste images to fit size limits instead of rejecting

Pasted images are re-encoded as PNG before saving, and the size cap was applied to
that output, so a retina screenshot or copied photo that grew during re-encoding
failed with "Clipboard image is too large". Downscale until it fits at every
re-encode site (desktop clipboard image, Windows copied files, renderer conversion).

Fixes #37855

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>

* fix(clipboard): keep image copies full size; only pastes shrink to fit

Copy image shares the PNG conversion with paste. Copies keep rejecting an
oversized PNG instead of silently copying a smaller image, and canvas
downscales use high smoothing quality.

* test(clipboard): match macOS paste tests to downscale-to-fit

Image mocks gain resize; the over-pixel-cap rejection case is removed since
those pastes now downscale (covered by the handler regression test).

* fix(clipboard): let pasted non-PNG images above the pixel cap downscale in the renderer

* test(clipboard): drop web paste test for the removed over-pixel-cap rejection

* fix(clipboard): let pasted PNGs above the pixel cap downscale instead of rejecting

* fix(clipboard): route web PNG pastes through the fit-to-limit converter

---------

Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
2026-11-06 16:11:45 -08:00
Brennan Benson d84abfb4f5 Offer terminal sign-in recovery in native agent chats (#39012)
* Offer terminal sign-in from native chats and retain refused worker tasks

* Handle sign-in terminal failures and complete failed-start cleanup callers

* Read retry task identity from its dispatch context

* Assert retained transcript identity through the bounded worker read

* Remove obsolete private structured retry teardown assertion

* Use real signed-out Pi and OMP error frames in regression coverage

* Route chat sign-in through explicit host terminal creation

* Keep paired agent launch owner explicit in the tightened terminal contract

* Keep focus baseline pruning limited to the removed reads

* Keep terminal login recovery available for unresolved model notices

* Keep the Grok diagnostic assertion scoped to its refused delivery

* Limit chat sign-in subscriptions to eligible failure rows

* Pass the execution host in terminal creation fixtures

* Scan Pi OAuth failures linearly and verify shared sign-in bounds

* Assert failure metadata and diagnostic routing without translated copy

* Bound diagnostic matcher steps at the Pi failure boundary

* Type the diagnostic matcher receiver explicitly

* Check sign-in button elements with a DOM type guard

* Recognize Pi credential failures and keep one recovery action

* Keep Pi sign-in diagnostics behind failure details

* Verify recovery action changes while refusal wording stays stable

* Use the recorded refusal sentence in the recovery fixture

* Type the recovery fixture as a submission rejection

* Make chat sign-in actions large primary controls

* Reuse primary action styles without duplicate notice subscriptions

* Keep translated primary chat actions within narrow notices
2026-11-06 16:06:14 -08:00
Jinwoo Hong 555bd481bc Let multi-repo folder workspaces parent and nest workspaces, including on other machines (#38904)
Multi-repo folder workspaces can parent workspaces on this machine and on paired servers, and their children nest under them in the sidebar and on the phone. Task parents are inferred at creation instead of on every lineage refresh.
2026-11-06 19:03:51 -05:00
Brennan Bensonandlydiassssz 548ba48c32 Upload images before publishing GitHub drafts (#38928)
* Upload GitHub images when pasted or dropped

Keep image bytes out of issue and review bodies by uploading from the owning composer and inserting hosted attachment URLs.

Co-authored-by: lydiassssz <60514233+lydiassssz@users.noreply.github.com>

* Preserve GitHub image intake across editor and thread states

* Keep image placeholder boundaries and ordinary HTML paste intact

* Match the native replace overload in the image projection fixture

* Use typed element queries in the image intake fixture

* Narrow textarea elements at the fixture boundary

* Show failed GitHub draft images as filename links

* Keep GitHub draft attachment links current across updates

* Supply the repository address in the attachment preview fixture

---------

Co-authored-by: lydiassssz <60514233+lydiassssz@users.noreply.github.com>
2026-11-06 16:03:20 -08:00
NeilandClaude a943631bd2 test(e2e): wait for the editor to see each pointer selection before Markdown Find takes focus (#39204)
ProseMirror reads a click's selection from the selectionchange event, which a
hidden Xvfb window delivers after Playwright's next step. The spec focused Find
right after clicking, so the editor still held an old selection when focus left,
and the Shift-click extended from the document start. Wait for that event after
the caret click and the range Shift-click; route Find sources to its specs.

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-06 16:00:54 -08:00
Jinjing a5da3ed41e Highlight already open structured agent panes (#39219) 2026-11-06 15:49:44 -08:00
Neil 2137a614d9 feat(browser): show when an SSH host is controlling Orca browser tabs, and let people stop it (#39212) 2026-11-06 15:49:24 -08:00
0b5a293fa2 feat(serve): add bind address option (#35095)
* feat(serve): add bind address option

* fix(serve): validate service bind address

* fix(serve): validate bind flag values

* fix(serve): reject scoped bind addresses

* docs(serve): document bind option paths

* docs(serve): note that --mobile-pairing needs an all-interfaces bind

* fix(serve): move bind address parsing to shared so the packaged CLI can load it

The packaged CLI ships out/cli and out/shared but not out/main/orcad, so
cli/runtime/serve-bind-flag.js failed the packaged runtime-import check
(and would fail to load) when it imported main/orcad/orcad-bind-address.
Move the module, unchanged, to src/shared and point orcad, Electron serve
and the CLI at it.

* test(serve): pin down the default listener and the --bind startup paths

- Extract the Electron serve listener pin into resolveServePinnedBindHost
  and test that serve without --bind stays unpinned (all interfaces, as
  before), an explicit --bind pins it from either argv form, and the orcad
  browser sidecar stays on loopback.
- Golden the orcad and Electron serve argv without --bind against the
  pre---bind output.
- Test that the CLI passes bind only when given and refuses --bind with
  --mobile-pairing before launching.
- Guard that serve-bind-flag and the shared serve validation load only CLI
  and shared modules, which is what the packaged CLI ships.

---------

Co-authored-by: lw <13579959+bertramlongwuyan@user.noreply.gitee.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: xuanchangfeng <210147232+xuanchangfeng@users.noreply.github.com>
2026-11-06 15:47:42 -08:00
c55459fa77 Remove allow-dyld-environment-variables from macOS entitlements (#37685)
Nothing in the repo reads DYLD_* variables, so the entitlement only weakens Hardened Runtime for the signed app and its inherited helpers. allow-jit stays because the terminal-host Node helper requires it.

Co-authored-by: Brijesh Vora <brijesh.vora@corelight.com>
Co-authored-by: Neil <neil@stably.ai>
2026-11-06 15:47:35 -08:00
Neil 490a5c05b8 fix(hooks): run a created worktree's setup once its own content is approved (#37978)
* fix(hooks): run a created worktree's setup once its own content is approved

Adds worktrees:runApprovedSetup (IPC) and worktree.runApprovedSetup (RPC,
capability worktree.run-approved-setup.v1). The host re-hashes the worktree's
setup and default-tab commands, runs them only on a match, and otherwise
reports the new content. After a create mismatch the host opens only the
command-less default tabs; approving in the trust prompt starts setup and the
command tabs. Clients whose host lacks the capability keep setup skipped.

* fix(hooks): review a created branch's different setup from the workspace, not instead of it

The trust prompt now says the workspace was created and its branch's setup
differs; approving runs it for that workspace without replacing the primary
checkout's approval (which made the next create prompt twice). Declining shows
a toast whose Review setup action reopens the prompt. Repo-wide trust returns
the content's hash so the host can run it.

* fix(worktrees): import approved setup from its path after the RPC methods move
2026-11-06 15:37:32 -08:00
Neil 9cb56ebc4c test(e2e): wait for the shell-ready deadline after a startup exec (#39203)
* test(e2e): wait for the shell-ready deadline after a startup exec

Since #30978 the terminal host no longer probes for a prompt when a profile
exec drops Orca's ready marker; it submits the startup command once at the
15 s shell-ready deadline. The oracle allowed only 8 s, so the headless serve
case failed unless the exec barrier happened to run long. Wait until that
deadline (measured from terminal creation) plus the recovery budget, and
route the spec from the shell-ready barrier and shell startup sources.

* ci(e2e): route the startup-exec oracle helper to its spec
2026-11-06 23:31:07 +00:00
Neil cf47e79147 test(e2e): isolate same-path editor models across two real hosts (#39208)
The spec forged an SSH owner for a local file and relied on the read
falling back to local transport. Since #31617 a tab reads only from its
captured owner, so the forged tab correctly shows 'Couldn't verify which
host owns this file'. Use a paired client that opens the same checkout
locally and on its runtime host instead, and route editor model identity
sources to the spec.
2026-11-06 23:25:30 +00:00
Neil 95a4d9b9af test(e2e): give each CSV preview its own link so the link opens a new tab (#39196)
A link whose page is already open now reuses that tab (#32907), so the paged
preview's click of the same URL never added the second tab the spec counted.
Also route CSV viewer sources to the CSV specs.
2026-11-06 23:24:35 +00:00
Neil 051bc5bc15 refactor(terminal): organize PTY connection lifecycle owners (#39188)
* refactor(terminal): organize PTY connection lifecycle owners

* refactor(terminal): consolidate imports from concrete owners

* test(e2e): assert durable pending automation acknowledgement
2026-11-06 15:23:27 -08:00
NeilandClaude d5d92649ac plugins: show the publisher when two plugins or themes share a name (#39205)
Co-authored-by: Claude <noreply@anthropic.com>
2026-11-06 15:15:26 -08:00
Brennan Benson e0005f5cbf Attach existing worktrees to folder workspaces from the CLI (#39018)
* feat(cli): attach existing worktrees to folder workspaces

worktree set accepts --parent-worktree folder:<id> (hosts advertise
worktree.set.folder-parent.v1), keeping each worktree to one parent in the
store. --parent-worktree active/current resolves to a folder workspace from
its terminal or enclosing directory, and worktree create without --repo under
a folder workspace lists the folder's Git repositories with a ready command.

* fix(cli): report folder parents and keep typed flags in folder repo choices

worktree show/set report a folder parent; the missing-repo error lists --repo
choices to add to the user's command and names the Attached worktrees panel.
Load and import repairs skip malformed rows and only touch imported worktrees,
an import keeps a worktree's existing parent, a twin-owned folder parent warns,
and folder ambiguity keeps its choices.

* fix(persistence): settle one parent per imported worktree before writing

An Orca server migration import now decides each touched worktree's parent
before any write: an explicit folder parent replaces an inferred worktree
parent, any other disagreement refuses the import. --parent-worktree active
in a folder terminal still lists the folder's repositories.

* fix(persistence): let a folder parent beat hydrate's inferred worktree parent

Load repair and import reconciliation share one rule: an inferred worktree parent loses
to a folder parent when the folder was chosen explicitly or the worktree parent carries
hydrate's orchestration stamp. Import tests now run payloads through the manifest parser
and cover a conflict that appears after staging.

* fix(cli): list folder repos when active resolves to the enclosing folder

worktree create without --repo used only the terminal's env to find the folder, so
--parent-worktree active run outside an Orca terminal fell back to the generic
missing-repo error. Use the parent create already resolved.
2026-11-06 15:13:57 -08:00
Neil c8ea52d37b test(e2e): drive the other-agents permission menu in agent-auto-permissions (#39202)
permission dropdown, and fresh profiles keep OpenCode on its own settings, so
the agents without Auto read Mixed after Full access -> Approve for me. Assert
that, track OpenCode in the stored-permission checks, and route the spec on
permission settings sources.
2026-11-06 23:08:29 +00:00
Brennan BensonandGuderlilian dbf56346e8 Keep phone chat menus above the keyboard (#38834)
Slash and mention suggestion menus in the phone chat composer stay reachable above the on-screen keyboard while typing.

Co-authored-by: Guderlilian <73724370+qq2144@users.noreply.github.com>
2026-11-06 15:05:05 -08:00
Neil f1ab15045f test(e2e): keep the descendant-kill stand-in's marker path out of argv (#39201)
Claude launches now get --plugin-dir prepended (subagent navigation, #33322),
so the stand-in read '--plugin-dir' as its marker path and the spec never saw
the detached child. Route the spec on descendant-kill and Claude launch-flag
sources.
2026-11-06 22:58:52 +00:00
Neil 71ebf751a3 fix(hooks): run worktree setup only when its content matches the approved script (#37977)
* fix(hooks): run worktree setup only when its content matches the approved script

Clients may send approvedSetupHash with a create. After git worktree add the
host hashes the created branch's shared setup and default-tab commands with
the prompt's function; on a difference it skips them and returns
setupTrustMismatch with the branch content. Creates without a hash (older
clients, CLI, mobile, orchestration) and older hosts behave as before.

* fix(hooks): send the approved setup hash and re-prompt on a changed branch

The composer and direct work-item creates send the hash of the setup content
the user approved (empty content included; none under repo-wide trust or
local-only policy). When the host reports different branch content, show a
setup-skipped toast and the existing trust prompt with that content.

* test(hooks): hash the prompt's and the host's orca.yaml from the same fixture

Covers CRLF and BOM primary checkouts, the plain-HTTP digest, the hash a
runtime host reports to remote and mobile clients, run-both and local-only
policies, creates without a hash, and pins the digest so a format change is
deliberate.

* style(worktrees): keep the creation flow under the line limit
2026-11-06 14:58:05 -08:00
NeilandClaude 4430743ab7 test(e2e): restart the WSL move fence spec from a phase startup recovery keeps (#39200)
Since #34683 a move journal promotes the WSL hosts gate to serve-only, so startup
recovery now runs and undoes a move interrupted before blobs-transferred. The
spec restarted at source-fenced and expected the fence to survive; assert the
undo there, fence from blobs-transferred, and expect the committed refusal to
name the host (#34880). Route fence and recovery sources to the spec.

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-06 22:55:03 +00:00
Neil 7b39d39aa4 test(e2e): measure terminal link tooltip geometry against the pane bottom padding (#39195)
Terminal padding now insets the bottom edge too (#36789), so the terminal sits
paddingY above the pane bottom. Route pane geometry sources to the spec.
2026-11-06 14:53:43 -08:00
Neil de80cd74c0 fix(agents): list agents found through a custom command path (#39178) 2026-11-06 14:52:08 -08:00
Neil a2ad899954 test(e2e): keep the client-hosted browser tour off the convergence spec's suggestions (#39197)
The one-time 'This page renders on your desktop' tour opens beside the address
bar of the first client-hosted page and intercepts clicks on the address-bar
suggestion. Seed it as seen for this spec via a new paired-client launch
option, and route address-bar conversion sources to the spec.
2026-11-06 14:46:25 -08:00
Neil 97530ccaff test(e2e): pair runtime-host recovery spec with two distinct servers (#39198)
Since #31080 a client keeps one saved entry per server, so pairing the same
host a second time under another name is refused. The steady 'Direct host' is
now a different server than the interrupted one. Tooltip checks name the host
so a closing tooltip from the previous card cannot match. Route the spec from
its pairing-store and runtime-status sources.
2026-11-06 14:45:00 -08:00
Neil 880d7ca1f0 test(e2e): align GitHub project board spec with click-wake and localized error toasts (#39193)
Board drops send wakeWslDistro (#36230) and network failures toast localized
copy (#34621). Route GitHub Projects sources to the board spec so PRs run it.
2026-11-06 14:43:04 -08:00
Neil 5ed96fbdd9 fix(browser): require a per-session token on the local CDP proxy (#37938)
* fix(browser): require a per-session token on the local CDP proxy

* fix(browser): reset the helper session when the CDP proxy refuses it

Explain a 403/404 handshake from Orca's CDP proxy and retire the session so
the next command gets a fresh proxy and helper. Drop an inherited
AGENT_BROWSER_CDP from the helper env so only Orca names the target, and pin
the env contract and minimum bundled agent-browser version in tests.
2026-11-06 14:42:33 -08:00
Neil 738396cc7f fix(setup): review imported setup scripts in a dialog before saving (#37937)
* fix(setup): show the detected command for every setup import source

* fix(setup): review imported setup scripts in a dialog instead of inline

Imported setup and archive scripts can be long, so the setup card now shows
the first command and a Review setup script button. The dialog shows the full
setup and archive scripts and is where non-package-manager imports are saved.
Package-manager suggestions stay inline and editable as before.

* fix(setup): use compact dialog title and description sizes
2026-11-06 14:42:01 -08:00
Neil b9a4b5fd2f fix(plugins): re-review any plugin whose catalog moves it to another repository (#36643)
* fix(plugins): drop a plugin's approval when its catalog moves it to another repository

* plugins: revokePluginConsent refuses when the plugin service is not running

* cli: orca plugin install/update ask again when a plugin moves to another repository, for every plugin kind
2026-11-06 14:41:29 -08:00
Brennan Benson 92590de7ea Allow Gemini Enterprise sign-in for Antigravity Chat (#38737)
* Support Gemini Enterprise authentication for Antigravity Chat

* Keep Antigravity account settings current across clients

* Type the mutable account snapshot fixture

* Keep account settings readable during Antigravity sign-in

* Use standard account form controls and localized placeholders

* Refresh Antigravity account settings after host reconnect

* Annotate the account form fixture without a cast

* Keep Antigravity auth settings at the ACP boundary

* Exercise host settings in the Enterprise sign-in regression

* Save visible Antigravity account settings before sign-in

* Remove obsolete account Apply copy and correct renderer test types

* Put Antigravity sign-in choices before the action

* Keep unchanged account fields editable on blur

* Preserve Antigravity sign-in status beside account choices

* Fix sign-in status predicate type narrowing

* Reject unconfirmed Antigravity account settings

* Show a shared Antigravity account failure once

* Type the Antigravity publication candidate

* Pair Antigravity settings failures with meaningful recovery

* Register account failure copy and refresh the schema catalog

* Keep the latest Antigravity save outcome ahead of delayed reads

* Type the retained account normalization fixture directly

* Keep RPC recovery coverage within its project boundary

* Keep Antigravity settings recovery in the Sign in action

* Keep unavailable Antigravity choices out of the recovery form

* Keep Antigravity settings reads stable across renders

* Retain the ACP task fixture deletion option type

* Hide unavailable Antigravity sign-in choices after a load failure
2026-11-06 14:36:37 -08:00
Neil a1650f78d0 test(e2e): route confirmed paired preview links through the in-app link preference (#39190)
Since #33622 a confirmed HTML preview link honors openLinksInApp (default off,
so it opens the system browser) and no longer calls
openBrowserProfileTabInActiveWorkspace, so the spec's store spy never fired.
Opt the client into in-app links and observe the opened page URL directly.
Route doc-preview sources to the spec.
2026-11-06 14:35:35 -08:00