Commit Graph
1008 Commits
Author SHA1 Message Date
Neil 8538b07f9a refactor(browser): group CLI and preload owners (#37182) 2026-11-01 14:57:05 -08:00
Brennan Benson 0fa5dae2f9 Read who each agent works with: its manager, workers and peers (#34890)
* Nest chat-UI orchestration workers under the agent that started them

Main's lineage projection only walked terminal panes, so workers running
in the chat UI never got a parent link and listed flat in the sidebar.
It now also projects chat workers, keyed by their visible chat row, and
resolves a chat creator or coordinator to that chat's visible row
instead of its handle or private mailbox pane key.

* Fix public worker lineage across assignment and row identities

* Complete terminal lineage provenance and bound active session selection

* Repair lineage test runtime boundaries and SQLite counters

* Provide read-only crew snapshots for each agent

* Batch public lineage verification after exact recency selection

* Derive crew relations once per meaningful host change

* Remove package manager lockfile churn from hook

* Use checked runtime values in lineage integration tests

* Document the trusted Dispatch SQL row boundary

* Keep lineage integration imports within their test programs

* Load native lineage fixtures before test execution

* test: complete lineage inputs in runtime and sidebar fixtures

* test: seed benchmark facts from active dispatches

* test: replace partial orchestration DB casts with typed fixtures

* test: complete stale-leaf mailbox fixture session input

* Derive durable crew parents from retained assignment proof

* fix(test): render worker lineage fixture with production list

* Add scoped terminal identity acquisition and preserve crew source wakes

* Share raw crew identity inputs through scoped production readers

* Exercise crew generation retirement through actual source owners

* Retire crew inputs on consumed ownership and visibility writes

* Use typed crew mutation and fixture access

* Repair crew fixture and RPC type contracts

* Align crew integration fixtures and RPC parameter contracts

* Encapsulate terminal identity mutations and captured reader contracts

* Seed terminal identity fixtures through canonical mutations

* Fix terminal identity fixture return type

* Cover terminal identity lifecycle schedules

* Align terminal fixtures with canonical identity sources

* Repair runtime fixture source contracts

* Use checked database fixtures for federation contracts

* Update crew source inventories and exit fixtures

* Preserve crew setup outcomes at existing subscription owners

* Match managed restore fixture to its nullable async return type

* Keep absent setup observations distinct from undefined failures

* Drive pending Crew questions from existing metadata

* Preserve nested pairing repair outcomes for shared callers

* Route attached workers to explicit local recipients

* Type Crew pending-question measurement receipts

* Match SSH repair fixture target absence to store contract

* Bound cold terminal layout construction and finite pane acquisition

* test: use public runtime identity in pane acquisition fixture

* Avoid repeated searches in cold workspace layout loading

* Verify cold loader fault identity and hook claimant effects

* Revert "Route attached workers to explicit local recipients"

This reverts commit f1335d1c06.

Keep attached workers on the existing Run-home routing path for this change.

* Omit crew peer addresses outside the active home route

* Keep crew retries on the verified runtime session

* Bound cold layout retirement and recorded-key construction

* Verify original cold layout failure identity

* fix: preserve surviving layout split references

* test: use typed retirement instrumentation properties

* test: preserve pane and retirement fixture contracts with checked types

* Prepare Crew record admission and wake identity changes

* Derive Crew recipient actions from current target owners

* Keep nested Crew process facts within selected acquisition

* Defer Crew legacy facts to consumers and complete raw coverage on success

* Use deterministic time in Crew command fixtures

* Document schema-owned Dispatch row assertions

* test: align Crew authority fixtures with typed project boundaries

* test: place Crew CLI integration in cross-surface project

* Type retained identity test meters with canonical source maps

* Document suffix Dispatch row boundary and preserve fixture unbinding

* test: migrate Crew authority arguments and mailbox observations

* Derive Crew attention and actions from complete recipient authority

* Fix Crew public-command fixture type contracts

* Align Crew fixtures with runtime reader and routing contracts

* Narrow receiving fixture calls to unary RPC methods

* Age pending question fixtures from every actual answer timestamp

* Complete Crew public-command workspace fixture result

* Test delegated helper follow-up through Crew advertised address

* Qualify Crew follow-up addresses through shared command admission

* Complete finite follow-up authority and lifetime evidence

* Assert exact remote authority acquisition error identity

* Consolidate Crew SQL test fixture imports

* Trim Crew read-model tests to the high-impact set

Keep the real CLI/RPC/database command paths, one regression per review-found bug, the cross-version contracts and one N vs 10N operation contract per scaling piece. Drop permutation matrices, equivalence oracles, near-duplicate scenarios and diagnostic output, and return the SSH, managed-server and WSL test files to main, since their production changes were reverted earlier in this PR.

* Drop diagnostic output and a duplicate error case from Crew tests

Remove two leftover console.log diagnostics, an unused 2x2 sample matrix and unused return fields in the follow-up cost contract, and the subscription AbortError serialization case that the subscription identity and preload tests already cover.

* Pass the recorded-leaf reader in main's check-details loader test
2026-11-01 13:28:53 -08:00
Kelvin Amoaba be3d9b7e86 fix(emulator): type and paste into the Android emulator pane (#37139)
The pane's keyboard only sent serve-sim HID frames over the iOS WebSocket.
Android sessions have no serve-sim socket, so every key was dropped and every
paste failed with "device is not ready".

Android panes now send typed characters, paste and editing keys over a new
emulator:scrcpyKeyboard IPC beside emulator:scrcpyTouch, keyed by the streamed
serial. Main writes them straight to the live scrcpy control socket (text
injection, and keycodes with SHIFT_LEFT held for Shift), so keys keep their
order with touches. iOS keeps the HID path.
2026-11-01 20:21:15 +00:00
Jinjing c24d916f31 Route hosted review operations to the owning host (#36003)
* Route hosted review refreshes to their owning host

* Route remote review operations to their owning host

- Refresh the correct hosted review after remote git operations
- Scope comment mutations and AI acknowledgements to the owner cache

* Route legacy paired SSH reviews through their server owner

- Recover proxied runtime owners for older SSH worktree listings
- Preserve direct and ambiguous host routing safeguards

* Preserve review ownership across remote workspace operations

- Route checks, comments, and linked-review clears through the selected repository owner
- Reject ambiguous or mismatched host context to prevent cross-machine mutations

* Keep check detail tabs scoped to their remote owner

* Preserve remote worktree ownership across reconstructed check tabs

* Preserve direct SSH check tabs when proxy listings overlap

* Scope PR refresh ownership state and safely roll back comment mutations

- Preserve linked-review clear scopes beyond cache eviction and clean them up on expiry
- Handle failed or refused comment reactions and thread resolutions without stale optimistic UI

* Preserve remote review ownership when SSH copies overlap

* Fix review routing for overlapping remote repository hosts

- Preserve server-owned review refreshes when a direct SSH copy exists
- Fail comment mutations and refetches safely when ownership becomes invalid
- Resolve check and sidebar data through the workspace’s owning host

* Relax cache-sensitive test expectations

* Route check refreshes to runtime owners and isolate restored requests

* Scope reconstructed check detail tabs by execution owner

* Fix review refresh ownership for shared remote hosts

- Prefer explicit execution owners when matching worktrees.
- Avoid repeated tab scans when restoring check details.

* Fix hosted review polling for workspaces on multiple hosts

* test: trim redundant review ownership scenarios
2026-11-01 12:57:45 -07:00
guangyu-reflexioandKelvin Amoaba 5467bf3d25 fix: preview remote HTML outside registered workspaces (#36791)
* fix: preview remote HTML outside registered workspaces

* fix(terminal): keep HTML from hosts without re-grantable files in the editor

* fix(doc-preview): check outside-workspace reads by host-canonical path and page large workspace assets

* fix(doc-preview): check approved folders for workspace assets of outside documents

* test(e2e): read the preview guest without a type assertion

* test(e2e): explain the outside-workspace preview timeout

* test(doc-preview): type the pinned grant target in the share test

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-01 18:05:22 +00:00
OrcaWinandOrcaWin 9ce650839c test: remove 56 low-value tests and two suites (#37057)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-01 16:01:33 +00:00
Neil e5b87cb8e6 Components catalog 2 and worker tests: forms, tabs, table, tree, markdown, code, images (#36997)
* plugins: components catalog 2 (forms, tabs, table, tree, markdown, code, images)

Adds 18 components to TSX components panels, drawn with Orca's own
primitives and gated by ui.catalog 2 / ui.has() (Orca 1.4.247):
Textarea, Checkbox, RadioGroup, Slider, Field, Tabs/Tab, Collapsible,
Toolbar, Grid, a virtualized Table with sort, selection and pull-based
paging, a keyboard Tree with lazy children, Markdown (sanitized, links
through the checked open path), CodeView (Orca's highlighter), Image
(header-checked plugin files read by main), KeyValue, Callout and
Skeleton, plus a tooltip prop on Button and IconButton.

Value controls share the edit protocol; handlers get plain JSON event
args, including small objects ({ keys }, { key, expanded }). The test kit
gains matching actions and hides unselected tabs and closed collapsibles;
a components-gallery example and e2e cover the catalog end to end.

* plugins: worker test harness, host refusals in tests and check

- orca/testing gains mountWorker(main, { host, events, commands }): it calls
  the default-exported activate(orca) with the orca object Orca itself builds
  (createPluginWorkerOrcaApi, moved to shared so the kit reuses it), backed by
  mockHost. emit() checks payloads against Orca's event schemas and only
  delivers subscribed events; command(), request() (the worker's
  orca.panels.handle, as a panel's plugin.request), posts, logs, refusals and
  deactivate(). Storage and settings share the mock host's in-memory store.
- orca plugin test loads a worker main's module graph as Orca's worker host
  does (.ts/.mts transform, Node resolution, no runtime orca import).
- mockHost records refusals (capability_denied, not_permitted, ...) even
  when plugin code catches them; panel.refusals exposes them and
  orca plugin check reports them as warnings. Check dedupes repeated issues.
- Typings, docs and a generated references/testing.md skill reference; the
  reference generator reads the split orca typings.
2026-11-01 05:43:15 -08:00
Neil 1392c8e894 Plugin dev loop: orca plugin open/shot, dev emit, and dogfood fixes (#37008)
* feat(plugins): orca plugin open and shot; dev watch --shot

- orca plugin open <key> [--panel|--editor] shows a panel in the right sidebar or a file in the
  plugin's custom editor, by changing renderer state only (no focus or window raise).
- orca plugin shot <key> [--panel] [--theme] [--width] [--out] [--json] waits for the panel's
  current code to draw, then crops webContents.capturePage to the panel (html guests included),
  with background throttling off while hidden. --width and --theme are temporary in-memory
  overrides; the PNG returns base64 (5 MiB cap), so --environment works.
- dev watch --shot <dir> writes a PNG per panel after the load and each good reload.
- The authoring skill's loop is now dev watch --check --shot → read the PNG → plugin test.

* fix(plugins): shots never disturb a visible Orca

- shot --theme is skipped while the Orca window is on screen (themeApplied: false with a
  themeReason); the override applies only to a hidden or minimized window.
- dev watch --shot opens the first panel (or --shot-panel <id>) once, then shoots it with
  ifShown: if the user moved the sidebar away it emits one shot_skipped instead of switching.

* fix(plugins): dev loop dogfood fixes; orca plugin dev emit

- dev watch: approval re-run command drops watch-only flags and old --approve; a folder added
  by a refused load is owned by the next approved load (Ctrl-C unloads it); check events
  carry the plugin's status (no green while pending/errored); reloaded prints before that
  reload's logs; --json errors are one NDJSON line.
- Errors: log, banner and check share source-mapped positions (a line-1 prelude hands sucrase
  mappings to the components runtime); check dedupes issues and locates syntax errors;
  Orca runtime frames and the error module's bogus location are dropped from logs.
- .orca/types tsconfig sets preserveSymlinks (tsc 7 loaded typings twice under /tmp).
- Templates' READMEs use dev watch.
- orca plugin dev emit <dir|key> <event> [--data] sends a test event to a dev plugin's worker
  through the real delivery rules (plugins.devEmit).

* test(plugins): fixed timestamp in the dev emit test

* fix(plugins): shot captures an html panel's guest itself

On Linux the main window's capturePage leaves a <webview> guest blank. The renderer now reports
the guest's rect, and main captures the guest's own webContents and draws it over the window
capture at that rect (raw bitmaps, nativeImage only). Components panels are drawn by the host,
so the window capture alone stays right for them.

* refactor(plugins): keep plugin-service and main-process-plugins under max-lines

After rebasing onto #37013 both files crossed 300 lines. The guest log sink moves into the
desktop view binding (bindPluginDesktopViews), and plugin-service tightens emitEvent and its
event-delivery imports.
2026-11-01 05:04:51 -08:00
Neil ec0d3cedd1 Plugin panels talk to their worker; panel storage, settings and agent events (#37013)
* feat(plugins): panels talk to their own worker, read storage, settings and events

- plugin.request (host API 1.2): a panel or editor asks its plugin's worker, which answers with
  orca.panels.handle(name); the worker pushes with orca.panels.post. Same plugin only, JSON
  checked, 1 MiB answers, 256 KiB/200-per-10s posts, a deadline and the panel's lifetime.
- Panels and editors get storage.*, settings.* and secrets.* behind the same capabilities, and
  storage/settings onDidChange on every surface; events.subscribe delivers workspace and agent
  events to panels that hold the read capability.
- contributes.settings: typed settings (a JSON Schema subset) with defaults and value checks.
- Frames get orca.plugin/storage/settings/secrets; components panels import plugin, storage,
  settings, secrets from 'orca', and atom(key, init, { persist: 'storage' }) shares a value with
  the worker. Workers get orca.panels/storage/settings/secrets sugar.
- One typed contract: declare module 'orca' { interface PluginRequests / PluginPanelEvents }.
- Desktop push channel per open panel session (plugins:openPanelPush).

* feat(plugins): Orca Settings shows and edits a plugin's contributes.settings

The plugin page lists declared settings with Orca's own controls (switch, picker, text and
number fields, Reset to default). Edits are checked against the declaration in main, written to
the plugin's settings, and reach open panels and the running worker through onDidChange.

* docs(plugins): hello-tsx talks to its worker; authoring guide covers panels, workers and data

The example now uses one of each: plugin.request answered by orca.panels.handle, a worker post
heard with plugin.on, a persist: 'storage' atom the worker watches, two contributes.settings and
agent.status.changed in the panel, all typed by one src/protocol.ts. The build-less TSX e2e
drives the whole loop.

* fix(plugins): typed bridge overloads, panel call budget, settings IPC and catalog keys

- PluginBridgeApi/PanelsApi use overloads: declared names are typed (and complete), any other
  name carries JSON; no never-unions for the type-aware lint.
- The per-plugin panel call budget is 120 per 10 s, since a panel loading storage atoms,
  settings and its first requests makes a burst; the hostile fixture floods past it.
- Settings IPC builds its host per call; the settings section's strings are in en.json.

* test(plugins): the example's declared settings show under the plugin with the person's value

* refactor(plugins): keep hello-tsx the minimal starter; the bridge demo is hello-worker-panel

hello-tsx goes back to a sandboxed-ui panel with no worker or capabilities. The worker, protocol,
storage atom, settings and events move to examples/plugins/hello-worker-panel, with their own
e2e (plugin-worker-panel) and PR route.

* feat(plugins): test kit covers the panel bridge and plugin data

mockHost keeps the plugin's storage, settings and secrets in memory (seeded with storage,
settings, secrets; read with host.data()) and fakes the worker with requests, so plugin.request,
storage/settings/secrets and persist: 'storage' atoms work under mount(), writes reach
onDidChange, and panel.post(event, payload) is what plugin.on hears. Typed by PluginRequests and
PluginPanelEvents.

* test(plugins): focusInGuest waits for the guest and retries focusing as one step

Under load the custom-editor guest could still be attaching, so executeJavaScript threw
'dom-ready' before the focus poll began. Wait for waitForGuestReady, then retry focusing the
webview and the element together, tolerating a guest that is still attaching or remounts.

* docs(plugins): the authoring skill covers panels, workers and data; persistence leaves the renderer

- skill-guides/orca-plugin-authoring.md gains Panels, workers and data (plugin.request/on,
  orca.panels.handle/post, persist: 'storage', contributes.settings, panel events, test kit), and
  its generated references read orca-services.d.ts for shell, files, on and the bridge types.
- After the dev-loop rebase, persisted-atom wiring (queue plus storage sync) moves to
  createDeclarativePersistence so the renderer stays under max-lines.

* feat(plugins): panels show agents: agents.list, terminal ids on agent events, workspace.changed

- agents.list (agent:read, every surface): the focused workspace's agents with terminalId,
  title, agent kind, state and stateStartedAt, from the hook server's store.
- agent.status.changed carries terminalId and title: paneKey mapped through the runtime's
  terminal list (tabId:leafId) or the status's terminal handle; looked up only while a plugin
  listens, in arrival order.
- workspace.readContext terminals carry title; workspace.changed (workspace:read) fires after
  workspace session writes when the focused workspace or its terminals change.
- Event subscriptions are kept per panel session, so one made before the push channel opens
  still counts.
- shell.openExternal never prompts on a hidden or minimized window: it settles
  { opened: false, reason: 'consent-unavailable' } and says so in the plugin log, which also
  notes 'waiting for the person to confirm' while a prompt is up; the rate budget is spent only
  when Orca acts. e2e launches never open a real browser or mail client.
- A worker may export activate as default or by name; docs, typings and the authoring skill
  document the entry, the agent events and a live agent status recipe.

* fix(plugins): the plugin page names the workspace.changed subscription

* fix(plugins): workers activate only by default export, and say so when it is named

Orca calls the worker module's default export. A module with a named `activate` and no default
now fails to start with an error naming the fix (`export default function activate(orca)`),
instead of being called by a fallback; docs, typings and the skill say default export.
hello-worker-panel gains a picker setting (suggestionOrder) the worker reads.
2026-11-01 04:40:17 -08:00
Neil b17d408416 Plugin dev loop: TS workers, hot reload with state, orca plugin dev watch, authoring skill (#36982)
* feat(plugins): build-less TypeScript workers

A worker's main may be .ts/.mts. The plugin host installs module.registerHooks scoped to the
plugin folder: .ts files are transpiled with the frames' sucrase options (lines kept, inline
source map, source maps on), relative imports fall back to the frames' candidate files, and a
value import of the type-only 'orca/worker' fails with a clear error. Needs engines.orca
>=1.4.246.

* feat(plugins): components panels hot reload with their state

- In dev folders a save swaps only the hidden guest: keyed memory atoms are handed to the new
  guest (ui.retain → ui.hydrate memory), dropped when an atom's version changes.
- A save that fails to load keeps the last good render and shows an inline file:line:col
  error banner; the next good save clears it. A subtle Reloaded mark follows a reload.
- Transpile and import errors carry line and column; dev worker restarts keep storage.

* feat(plugins): orca plugin dev watch

One command for the inner loop: refreshes .orca/types, dev-loads the folder, follows its frame
and worker logs (plugins.getLogs gains an optional cursor), prints reloads (optional
devChangeCount on list entries) and status changes, and unloads on Ctrl-C. --json streams
NDJSON events for agents.

* feat(skills): orca-plugin-authoring bundled skill guide

A guide for agents to build Orca plugins end to end (decision table, build-less rules, the
dev watch loop, test/check, validate, release-entry, approvals, gotchas) with references
generated from the component catalog, host API table, event schemas, manifest schema and CLI
specs, checked for drift. Fixes the components template's Reset to set(count, 0).

* feat(plugins): orca plugin dev watch --check; test kit details in the authoring skill

- --check runs orca plugin check after the load and after each reload (one at a time; saves
  made meanwhile fold into one rerun) and prints each panel's render or errors inline, as a
  `check` event with --json. Local folders only, since it runs the plugin's code here.
- The orca-plugin-authoring guide's Test and check section now documents orca plugin test and
  check from #36969 exactly (JSON results, exit codes, test placement, the orca/testing kit and
  its common mistakes), and the loop uses dev watch --check.

* refactor(plugins): move the components renderer's timing and helper constants to their own module
2026-11-01 03:32:25 -08:00
Neil 89f9ce08de refactor(shared): organize session contracts and projections (#36979)
* refactor(shared): organize session contracts and projections

* chore: tighten dropped-path flaky pattern allowance

* docs: preserve current agent instructions with valid formatting
2026-11-01 03:14:46 -08:00
Neil 4b4c833e10 feat(window): working background opacity and blur on macOS, Windows and Linux (#36580)
* feat(window): working background opacity and blur on macOS, Windows and Linux

One window material model (opaque / translucent / blurred): macOS vibrancy without transparent, Windows 11 22H2+ acrylic, Linux transparent windows. Terminals paint their translucent background once, the transparent WebGL frame clears before drawing (#6491), and Reduce Visual Effects drops modal/backdrop blur and honors prefers-reduced-transparency.

* perf(window): drop hidden macOS vibrancy while a theme image covers the window

* refactor(settings): move Reduce Visual Effects into its own setting and search files
2026-11-01 01:41:07 -08:00
Neil 57454e6d7e refactor(agent-session): group lifecycle records and direct owners (#36909) 2026-11-01 01:24:37 -08:00
Neil 7df246b9d1 feat(plugins): components (TSX) plugin panels (#36814) 2026-11-01 01:32:36 -07:00
Neil abbbdd7714 feat(plugins): isolated plugin frames, off by default (#36813) 2026-11-01 01:03:13 -07:00
Kelvin Amoaba 92fc8bc26d fix(accounts): restart running Claude sessions when the account is switched from the phone (#36933)
A switch over runtime RPC (the phone's Accounts screen) changed the
selection but never reached the window's running-session handling, which
only the status bar and Settings called after their own IPC switch. The
RPC path now reports the lane and outgoing/incoming account to the main
window, which runs the same handler. The web client handles its own
switches and opts out.
2026-11-01 08:00:08 +00:00
Neil 25a8418018 feat(skills): silently update unedited Orca skills per skill; prompt only for the rest (#36889)
* feat(skills): auto-update unedited Orca skills; ask only for edited copies

Planner already hashes each installed SKILL.md against every shipped release
digest (legacy installs included). When a plan's only writes replace such
hash-verified copies, the freshness nudge now applies it silently. Edited
copies and repairs still go through the consent toast; edited copies now raise
it too instead of only showing attention in settings.

* feat(skills): decide silent skill updates per skill and per location

Add skills.autoUpdateBundledOrca (capability-gated): the host plans the named
installed skills under their locks and applies only hash-verified released-copy
updates, re-checking each location before writing. The nudge auto-updates each
unedited skill and names only edited, unknown or repair-needing skills; the
try-once guard is keyed per skill and observed state, so one failure falls back
to the toast for that skill alone.

* fix(skills): surface preserved edits, share run ownership, re-show retracted nudges

- A silent update that moved a racing edit to a backup now shows a warning
  naming the skill and backup path instead of passing as success.
- Silent updates run under skill-update-run-store's per-target ownership, so
  manual and automatic runs never interleave and the dialog shows busy.
- Programmatic toast retraction releases its session marker; only a user
  dismissal suppresses the nudge.

* fix(skills): report stranded edits, isolate silent runs, bound attempt memory

- An old copy whose late edits cannot be backed up now fails the op with
  strandedPath naming where the edits remain; the silent caller warns with that
  path, and the next plan's backup cleanup is nudged, never deleted.
- Silent runs never start over a running or unacknowledged foreground result
  and never surface in the status bar.
- Auto-update attempts are keyed per target and pruned to the states the
  current scan observes; unchanged states stay suppressed.

* fix(skills): warn when a silent update's result is lost

Any rejected or timed-out auto-update request may follow a committed swap
whose racing edit went to a backup. Show a persistent warning naming the
target and its skill backup directory, and settle the attempt so the same
state is handed to the nudge instead of retried.

* test(skills): guard version skippers; ledger also walks release tags

Audit of every v* tag and HEAD history found no SKILL.md bytes missing from
released-digests.json. The generator now also walks release tags (falling back
to HEAD) so a release cut off-branch can never ship unrecognized bytes. Add a
real-disk test that installs the oldest shipped orchestration (v1.3.24-rc.2) in
the npx-skills and agent-folder layouts and auto-updates it silently.

* test(skills): type the nudge mock's error without an assertion

* chore(i18n): add the silent skill update warnings to the English catalog
2026-11-01 00:31:23 -07:00
OrcaWin b59ce5a6b5 test: remove 262 low-value test cases, including 39 suites (#36901) 2026-11-01 05:29:02 +00:00
Carlos MoránandKelvin Amoaba 7ed518562c fix(emulator): send Android input through the scrcpy control socket (#36530)
* fix(emulator): restore scrcpy control encoders and track the video size

Bring back the scrcpy v2.4 control-message encoders removed as unwired
in #13528 (touch, keycode, text), re-checked against control_msg.c and
the server's ControlMessageReader: generic-finger pointer id, the
official u16 pressure fixed point, and text split into <=300-byte
messages on code point boundaries.

The server drops touch events whose screen size differs from the
current video size. v2.4 reports the size once in its codec meta; after
a rotation the new size is only in the next SPS, so the session reads it
from every config packet. ScrcpyStreamSession.sendControl() returns,
the control socket disables Nagle, and the registry keeps the live
session's control target next to its video.

* fix(emulator): send Android input through the scrcpy control socket

Android pane input ran one `adb shell input` process per action (~150 ms
each on a USB phone) and replayed drags only on pointer-up as a fixed
300 ms straight swipe between the endpoints.

Pane pointer phases now go to main as they happen over a new
fire-and-forget `emulator:scrcpyTouch` IPC and are written to the live
session's scrcpy control socket, so drags and scrolls track the pointer.
CLI and agent tap, gesture, type and button use the same socket whenever
a stream is live; `adb shell input` remains the fallback without one.
Input routing and the `wm size` cache the fallback needs move into
AndroidDeviceInput. iOS is unchanged.

* test(emulator): keep the adb fallback test from leaking a failing sendControl

* docs(emulator): explain why pane touches have no per-phase adb fallback

* fix(emulator): keep iOS touch callback stable across interact changes

sendTouch depended on canInteract only for the scrcpy branch, but the new
dep also rebuilt it for iOS, so a canInteract flip mid-drag ran the frame's
cleanup, ended the live touch early and replayed the drag over RPC. The
frame already gates touch begins on canInteract.

* fix(emulator): narrow scrcpy touch payloads without a type assertion

The changed-code casting gate forbids `as`; use `in` narrowing like
the other IPC payload guards.

---------

Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-11-01 04:58:23 +00:00
Neil b2842603e4 refactor: finish shared native-chat model and transcript organization (#36843) 2026-10-31 20:19:28 -07:00
Neil 964fe5b73c fix(wsl): a restored chat or a web hooks check never starts a stopped distro (E9) (#36779)
* fix(wsl): a restored chat or a web hooks check never starts a stopped distro (E9)

A chat pane mounting on launch restore or a remount read its transcript as a
user open and booted the transcript's stopped WSL distro. Only the mount that
the user's own switch caused, and paging, now ask main to start it; otherwise
the read refuses and the pane shows the distro's stopped copy at once (a
stopped UNC transcript was reported as missing and spun as pending).

A web client sent repo.hooksCheck without background, which a server treated
as a launch that may open the distro. The server now opens it only for an
explicit wakeWslDistro; clients send it for launches and keep background for
older servers.

* fix(native-chat): key a chat's open wake on its own workspace; update wake assertions

A chat in another workspace mounting inside the switch window no longer takes the
switch's wake. The paging and worktree-removal assertions now expect the explicit
wakeWslDistro flag.

* fix(native-chat): set the pane-key ref in the layout effect, not during render
2026-10-31 16:17:55 -07:00
NeilandClaude f2731a2cfc feat(wsl): a WSL hosts block learned mid-run stops new work at once (#36776)
* feat(wsl): a WSL hosts block learned mid-run stops new work at once

The live policy fetch caches a newly published block, but the gate is
fixed for the run, so the add-host and move entry points and the
in-context offer stayed until the next launch. A block the fetch learns
now stops new work in-session through one predicate,
wslHostsAcceptNewWork(): adding hosts, starting or previewing moves,
automatic and opened-project moves, and Retry. Main pushes the capability
to the renderer, which hides the offer and entry points. The gate and
what is served are unchanged until the next launch, so saved hosts and
moved projects keep working, and cancel, Restore and Not now stay.

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

* fix(wsl): a live block also ends Stage 1 opt-in and stops mid-step host adds

Review follow-ups:
- wslHostsOptedIn now also needs wslHostsAcceptNewWork, and the Git router
  re-applies its opt-in when a block lands, so the D1c router and the
  background WSL Git gate uninstall at once, as turning the setting off does.
- D1c conversions (wslDriveProject preview/convert, wslDriveUnc:convert)
  gate on the opt-in; the new-project Git default already did.
- The orchestrator re-checks before adding a host, so a step already past
  its start gate adds nothing after a block.
- The window broadcast and capability push move to
  wsl-host-window-broadcast.ts, keeping wsl-host-handlers.ts under max-lines.

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

* test(wsl): keep gate mocks whole, and pin cancel after a live block

The visible-work lifetime suite mocked the gate with one export, so the
handlers' new wslHostsAcceptNewWork and onWslHostsNewWorkChanged calls
failed it; it now spreads the real module and overrides only what it
needs. A new case pins that cancelling a running move still works after
a live block while a new move is refused.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-31 15:45:48 -07:00
OrcaWin a489b24748 test: remove 246 low-value tests (#36780) 2026-10-31 21:52:07 +00:00
OrcaWin 47a2a953c6 test: remove 206 low-value tests (#36759) 2026-10-31 20:34:03 +00:00
OrcaWin 10e35fd76d test: remove 226 low-value tests (#36737) 2026-10-31 18:55:29 +00:00
Brennan Benson cca9ed5a7a fix(github): make Checks refresh start a new PR read (#36651)
* fix(github): start explicit Checks refreshes after the action

* fix(github): give explicit Checks refreshes fresh checks and comments

The same Refresh or Link click that now reads PR metadata after the
action also reads checks and comments after it: an explicit request no
longer joins or waits on a read begun before the click, in the renderer
or (for checks) the host coalescer. A superseded read's callers show the
owner's answer, so a late pre-click reply cannot repaint the panel, and
comments posted during either read are kept.

A lost IPC/RPC reply is reported only to the click that asked; polls stay
silent as before, and a later answer clears a failure older than itself.
The manual hook takes its verdict from its own lookup, the link flow's
card-read failure no longer skips checks, and the web shim forwards the
intent.

* fix(github): land the older Checks reply when a newer explicit read fails

When a click's checks or comments read fails while the read it replaced
succeeds, the click's read now lands that older reply through its owner
path instead of leaving the cache behind it. Post-write comments
refreshes (mutation events, bulk resolve) carry the explicit intent so
they cannot be answered by a read begun before the write.

* test(github): drop type assertions from the explicit-refresh tests

The RPC tests call the handlers with a real runtime service and spies,
and the panel test passes typed fixtures straight to the hooks.

* test(github): type the Checks panel fixtures for the renderer project

The renderer tests build their PR fixture locally instead of importing a
main-process harness, and the panel setter mocks take the hooks'
SetStateAction form.
2026-10-31 11:10:38 -07:00
OrcaWin 3c5773c04d test: remove 187 low-value cases including six whole suites (#36724) 2026-10-31 18:05:10 +00:00
OrcaWin fe4595d6d6 test: remove 11 low-value suites and 157 individual cases (#36703)
* test: remove low-value suites and cases

* test: preserve historical reliability gate evidence
2026-10-31 15:27:20 +00:00
OrcaWin a0f75207ce test: remove 17 low-value suites and 133 individual cases (#36700) 2026-10-31 14:38:33 +00:00
Brennan Benson 233b3dc704 Make explicit hosted review refresh fetch current provider state (#36522)
* Make explicit hosted review refresh read current provider state

* Name the right provider and keep GitHub's own copy when a Checks refresh fails

A failed manual refresh now names the repo's provider (from the review, its link, or the remote), clears once a newer read lands for the panel, never stops GitHub checks and comments from refreshing, and gives way to GitHub's classified sign-in or rate-limit copy. The copy is one interpolated line in every locale.

* Read after the write when Orca merges, closes, reopens or edits a GitLab MR

Every GitLab merge request write now drops the host's cached review lookups for the repository, and the Checks panel's follow-up read can't join a poll that began before the write, so merging in Orca shows Merged and Delete Workspace without a manual Refresh. A user refresh also forgets Gitea's shared repository scan before reading.

* Clear a failed Checks refresh only on a real provider read

The host now tells the desktop store, when asked, whether its answer came
from a provider read it stored as current or from a cache or last-good
fallback. The Checks panel keeps a failed Refresh until such a read lands,
a click succeeds, or the context changes. On GitHub the PR read owns the
refresh status, so a failed review-card read no longer raises the generic
failure.

* Don't let a joined host lookup clear a failed Checks refresh

A poll that joins a lookup already running for an earlier request didn't
start that read, so its answer can't show the provider recovered after the
failure. Only the request that started the stored lookup reports a provider
read now. The host read also uses the shared reply outcome directly, and the
renderer writes the provider-read generation where it publishes the entry.

* Type the Checks refresh breadcrumb for every review provider

The breadcrumb already received Bitbucket, Azure DevOps and Gitea values; its
annotation now says so. Tests build typed fixtures instead of asserting types.

* Test the read-outcome reply at IPC, RPC and runtime, and the post-merge read

The flag reaches the runtime, and only a caller that asks gets the envelope,
including for a definitive null. After Orca merges, the card read starts after
the write, and its failure leaves the merge reported as done.

* Use a boolean for the empty-state fixture's remote-operation flag

* Trim redundant hosted-review refresh tests

* Keep the signed-out GitHub empty-state test
2026-10-31 01:26:38 -07:00
OrcaWin 5edb1b6f9a test: remove 14 low-value suites and 119 individual cases (#36617)
* test: remove low-value suites and cases

* test: shrink flaky-pattern counts after case removals

* test: remove empty suite and stale release workflow fixture
2026-10-31 00:20:27 -07:00
Neil 85edf1bba6 feat(plugins): show public install counts in the plugin catalog (#36537)
* feat(plugins): show public install counts in the plugin catalog

* fix(plugins): tolerate the empty stats placeholder; count bundled official plugins

* test(plugins): pin install-stats test clock
2026-10-30 19:57:26 -07:00
Neil 584e672df8 fix(plugins): accept plain repo, release and tag page URLs in Git install (#36525)
* fix(plugins): accept plain repo, release and tag page URLs in Git install

The Git URL install dialog refused anything without a #ref suffix, so pasting a
repository or GitHub release link failed with "Add a #tag or #commit". It now
reads owner/repo, repository URLs with or without .git, SSH URLs and GitHub /
GitLab release, tag, tree and commit pages, pins the newest version tag (or the
default branch's commit when there is none) with git ls-remote, shows that
version and commit, and installs only that exact commit.

* fix(plugins): let the Git install dialog close while a version check runs
2026-10-30 19:10:28 -07:00
Brennan Benson 5cf236730f Add Chat UI upgrade tip and Chat/Terminal default tiles (#36171)
* Chat UI leaves Experimental: each agent's Chat | CLI choice decides launches

Remove the experimentalNativeChat switch and every gate on it. The Chat
settings page, Default Agent Chat | CLI choice, + menu Chat/CLI rows,
source-control surface choice, Antigravity chat section and orchestration
chat-error switch are always present. What a new launch opens comes only
from the per-agent choice (no saved choice opens a chat) plus the existing
support checks.

- One lookup, nativeChatPreferenceFor, keyed by agent id so host-registered
  agents read the same way; unreadable settings still open a terminal.
- A relayed desktop stamp (nativeChatDefault) maps onto the launched agent;
  an explicit surface still wins. Old phones' createSupport keeps admitting
  by the host's per-agent choice.
- settings.get stops publishing the retired switch keys; nothing in the
  repo reads them from a host.
- Startup chat sync and hydration run when some agent can open as a chat
  or the machine already holds chats.
- The retired key is stripped on load. The one-time upgrade tip from the
  chat upgrade is retired with its audience record; a new record, captured
  once from the raw profile, marks which existing profiles had Chat UI off.
- The window-side AI-button tab path, which only ran with the switch off,
  is deleted.

* Keep profiles that had Chat UI off on the terminal

Existing users who never turned Chat UI on would otherwise see new agent
launches open as chats, since an agent without a saved choice now opens as
a chat. The one-time load step that records the new audience also sets
every known agent to CLI for those profiles, in the same save and only
when the record was absent, overwriting saved chat choices the old switch
masked. Profiles that had Chat UI on and new profiles are untouched.

Browser profiles keep their own settings, so the web client does the same
once: a stored switch that is not on seeds CLI choices, and dropping the
key marks the step done.

Agents first seen after this step open as chats.

* Agents without a saved Chat | CLI choice open as their CLI

An agent with no saved choice now opens in the terminal for everyone,
including fresh installs and agents first seen later. The one-time load
step carries what launches opened while Chat UI was experimental: with
the switch on, every known agent without a saved choice is saved as
chat; with it off, chat choices the switch masked are saved as CLI.
Existing profiles join the launch tip audience whether the switch was on
or off. Browser profiles get the same carry from their saved key.

The startup chat restore and host agent list now run only when some
agent is saved as chat or the runtime holds chats.

* Chat UI is here: a one-time tip for profiles that upgraded

Profiles saved before Chat UI left Experimental see a "Chat UI is here"
tip once, on the first launch after updating. Fresh installs, unreadable
audience records and the web client never see it.

- Had Chat UI off: says agents can now open as a chat and that the
  terminal stays fully supported. "Use Chat UI" saves Chat for every
  agent Orca knows (the roster the load step carries), then closes;
  "Stay in terminal", close and Escape change nothing.
- Had Chat UI on: says Chat UI is now part of Orca and the terminal
  stays supported; one "Got it" closes without changes.
- Both link to Settings -> Agents. The visual is an animated miniature
  chat that sends a question, reads a file and draws a flow diagram,
  then fades as one and repeats; reduced motion shows the finished
  frame.
- The variant comes from main's once-decided audience record over a
  new onboarding IPC read; the startup gate waits for it.
- FeatureTipActions takes a secondary label; the frame takes a copy
  column class, used here so the buttons line up with the card's
  composer. Other tips are unchanged.
- Telemetry: chat_ui_feature_tip_shown and chat_ui_feature_tip_action.

* Preserve owned terminal launches and local chat choices

* Chat UI tip: translate the miniature, honor reduced motion mid-loop

- The miniature's conversation (tab title, prompt, reply, diagram and
  arrow labels) is translated in every locale; the composer, permission
  chip, working row and Read verb reuse the chat's own strings. File
  names, the /login route and the model name stay as written.
- The reply is one paragraph that wraps naturally; words (segmented per
  locale, so scripts without spaces still stream) reveal in turn.
  Diagram boxes size to their labels and arrow labels never widen the
  row.
- Turning reduced motion on mid-loop jumps to the finished still with
  no transitions.
- Telemetry records use_chat_ui only after the save succeeds and has a
  distinct stay_in_terminal action.
- The dialog renders its own title, so the duplicate catalog copy is
  gone; Use Chat UI writes the full roster without re-spreading saved
  choices.
- Buttons: the primary's focus ring meets the card's bottom edge.

* Clarify chat and terminal support

* Explain worker CLI integration timeout budget

* Use checked annotations for chat graduation test fixtures

* Store agent surface default separately from per-agent overrides

* Preserve explicit Chat intent across default changes

* Preserve current browser settings during host replies

* Correct browser settings factory and regression types

* Name exported launch fixture mock types and clarify agent defaults

* Preserve settings fallbacks and complete launch test lifecycles

* Check allocated tab identity before launch fixture interpolation

* Drop file links from the Chat UI tip copy

* Register combined integration project for compiler parity probes

* Use checked settings in the launch test fixture

* Settings → Agents: "Open agents as" Chat or Terminal tiles

A new top section in Settings → Agents sets this computer's default for
how agents open: two tiles, Chat ("Rich messages, visuals and images.")
and Terminal ("Each agent's own CLI."), each with a still preview. The
chat preview reuses the tip's copy and flow diagram; the terminal preview
draws Claude Code's interface in the user's terminal theme and font.

- Picking a tile writes only agentDefaultSurface, through the same queue
  as the per-agent Chat | CLI rows. The tiles show the saved default; an
  agent set on its own row keeps its choice and is not reflected up top.
- If any agent's own choice differs from the new default, one toast names
  them ("Claude and Codex stay in the terminal, as you set.") with "Set
  all to Chat" / "Set all to Terminal", which drops those choices so they
  follow the default. Only agents whose row offers Chat | CLI count. No
  toast when nothing differs, and never from the tip.
- "Choose per agent" scrolls to and focuses the Installed list.
- Shown for this computer only (not on a paired host's page); the web
  client gets it too. Searchable as "Open agents as".
- Copy in all locales; the tip's intro copy in other locales also drops
  "file links", matching English.

* Fix Chat UI settings navigation and acknowledged preference actions

* Keep the agent default surface controls in full Settings

* Keep the per-agent navigation button free of link underlining

* Use checked types and existing presentation primitives for Chat UI tips

* Preserve retired Chat preference data privately

* Align chat E2E fixtures and capture pane lifecycle evidence

* Use typed raw settings in retention contracts

* Fix Chat UI settings search types and localization catalogs

* Consolidate transcript diagnostic imports

* Keep setup-only dependency changes out of the branch

* Update dev education history expectation for Chat UI tip

* test: align chat fixtures with live pane and native menu contracts

* test: capture relay tab selection loss diagnostics

* test: wait for owned shells before synthetic chat fixtures

* test: preserve all-host visibility in SSH observer

* test: bind synthetic transcript fixtures before provider seeding

* test: assert selected chat owner after narrow image preview

* ci: allow fifth compiler project to complete comparison

* Drop 'keeps getting better' from the Chat UI tip's terminal line

* Trim the empty space above the Chat UI tip's visual

* Tighten the space above the Chat UI tip's flow diagram; undo the card resize

* Tighten the Chat UI tip's reply and diagram spacing

* Give the tip's flow diagram a little more room and shorten its tab bar

* Type the web-terminal fixture's chat map without an assertion

* Right-click the selection itself in the chat copy spec
2026-10-30 17:46:12 -07:00
Brennan Benson 76cf164cf9 Chat UI leaves Experimental: each agent's Chat or CLI choice decides what opens (#36110)
* Chat UI leaves Experimental: each agent's Chat | CLI choice decides launches

Remove the experimentalNativeChat switch and every gate on it. The Chat
settings page, Default Agent Chat | CLI choice, + menu Chat/CLI rows,
source-control surface choice, Antigravity chat section and orchestration
chat-error switch are always present. What a new launch opens comes only
from the per-agent choice (no saved choice opens a chat) plus the existing
support checks.

- One lookup, nativeChatPreferenceFor, keyed by agent id so host-registered
  agents read the same way; unreadable settings still open a terminal.
- A relayed desktop stamp (nativeChatDefault) maps onto the launched agent;
  an explicit surface still wins. Old phones' createSupport keeps admitting
  by the host's per-agent choice.
- settings.get stops publishing the retired switch keys; nothing in the
  repo reads them from a host.
- Startup chat sync and hydration run when some agent can open as a chat
  or the machine already holds chats.
- The retired key is stripped on load. The one-time upgrade tip from the
  chat upgrade is retired with its audience record; a new record, captured
  once from the raw profile, marks which existing profiles had Chat UI off.
- The window-side AI-button tab path, which only ran with the switch off,
  is deleted.

* Keep profiles that had Chat UI off on the terminal

Existing users who never turned Chat UI on would otherwise see new agent
launches open as chats, since an agent without a saved choice now opens as
a chat. The one-time load step that records the new audience also sets
every known agent to CLI for those profiles, in the same save and only
when the record was absent, overwriting saved chat choices the old switch
masked. Profiles that had Chat UI on and new profiles are untouched.

Browser profiles keep their own settings, so the web client does the same
once: a stored switch that is not on seeds CLI choices, and dropping the
key marks the step done.

Agents first seen after this step open as chats.

* Agents without a saved Chat | CLI choice open as their CLI

An agent with no saved choice now opens in the terminal for everyone,
including fresh installs and agents first seen later. The one-time load
step carries what launches opened while Chat UI was experimental: with
the switch on, every known agent without a saved choice is saved as
chat; with it off, chat choices the switch masked are saved as CLI.
Existing profiles join the launch tip audience whether the switch was on
or off. Browser profiles get the same carry from their saved key.

The startup chat restore and host agent list now run only when some
agent is saved as chat or the runtime holds chats.

* Preserve owned terminal launches and local chat choices

* Clarify chat and terminal support

* Explain worker CLI integration timeout budget

* Use checked annotations for chat graduation test fixtures

* Store agent surface default separately from per-agent overrides

* Preserve explicit Chat intent across default changes

* Preserve current browser settings during host replies

* Correct browser settings factory and regression types

* Name exported launch fixture mock types and clarify agent defaults

* Preserve settings fallbacks and complete launch test lifecycles

* Check allocated tab identity before launch fixture interpolation

* Register combined integration project for compiler parity probes

* Use checked settings in the launch test fixture

* Preserve retired Chat preference data privately

* Align chat E2E fixtures and capture pane lifecycle evidence

* Use typed raw settings in retention contracts

* Consolidate transcript diagnostic imports

* test: align chat fixtures with live pane and native menu contracts

* test: capture relay tab selection loss diagnostics

* test: wait for owned shells before synthetic chat fixtures

* test: preserve all-host visibility in SSH observer

* test: bind synthetic transcript fixtures before provider seeding

* test: assert selected chat owner after narrow image preview

* ci: allow fifth compiler project to complete comparison

* Type the web-terminal fixture's chat map without an assertion

* Right-click the selection itself in the chat copy spec
2026-10-30 17:43:04 -07:00
Neil 8c777ea465 plugins: tell once when an automatic update waits for your review (#36462)
* plugins: tell once when an automatic update waits for review

When the auto-updater holds back an update because it asks for more access
or moved repository, show one toast per plugin version (grouped when several
wait). Review opens the existing per-plugin update review or the Updates list;
it never installs or approves. Told versions persist across restarts, kill-listed
plugins are skipped, and the copy is protected from language packs.

* test(plugins): wait on the update pass instead of sleeping in the review toast e2e
2026-10-30 15:01:54 -07:00
67d09d7653 feat(cli): open a browser tab in a split pane with tab create --split (#35665)
* feat(cli): open a browser tab in a split pane with `tab create --split`

`orca tab create` could only add a tab to an existing pane, so an agent
had no way to put a page beside its terminal. `--split <right|left|down|up>`
creates a new pane next to the calling terminal (ORCA_TAB_ID), falling back
to the active pane, and opens the page there without taking focus.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNtbMA9iVj9T4rBUjn5u6W

* refactor(browser): share one type for the tab-create IPC payload

The preload listener, its callback, the preload API contract and main's
sender each declared the payload separately, and the listener copy had
already drifted from the new split fields.

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

* fix(browser): open the CLI split pane and its tab in one step

Creating an empty group and then filling it fails when main owns the
layout, because the window's group doesn't exist until main's frame
lands. createBrowserTab's split option carries both to whichever owner
draws them, so the rollback for a half-made pane goes away.

SSH hosts already cannot choose a new tab's group, so their CLI's split
is stripped like targetGroupId.

* fix(browser): split in the caller's workspace and refuse splits that can't happen

A CLI run outside its workspace's directory sends no workspace, so the
renderer fell back to the active one and missed the caller's terminal.
The caller's tab now picks the workspace when none was named.

An SSH host's split and an empty --split= both turned into a plain tab
reported as success; both are refused instead.

---------

Co-authored-by: Kalvin Mizzi <kalvin@mizzi.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-30 17:19:50 +00:00
OrcaWinandOrcaWin 5a925965d5 fix(git): compare staged renames against their HEAD source (#34779)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-30 06:25:03 -07:00
Kelvin Amoaba 4410ef318e fix(browser): let agents and users answer page alert, confirm and prompt dialogs on their page (#36268)
* fix(browser): let agents and users answer page alert, confirm and prompt dialogs on their page

* fix(browser): watch a replacement guest for dialogs and ignore the opening keypress

* fix(browser): ignore a repeated Enter in a guarded prompt field
2026-10-30 07:39:38 +00:00
Neil 8f2e24f893 Revert "Warn macOS 12 users about upcoming support changes" (#36209) 2026-10-29 20:26:46 -07:00
Kelvin Amoaba dc99281085 feat(source-control): resolve merge conflicts and complete merges from the phone (#36160)
* feat(source-control): resolve conflicts with one host operation shared by desktop and mobile

* feat(mobile): resolve merge conflicts and complete merges from Source Control

* test(mobile): pin Complete merge refusals and the older-desktop message

* fix(source-control): only resolve paths Git still reports as conflicted

* fix(source-control): refuse to keep a missing file and serialize conflict resolution per worktree

* fix(source-control): resolve only the exact conflicted path

* fix(source-control): match conflicted paths in Git's separator form on Windows and WSL

* fix(source-control): accept only the resolutions the live conflict offers

* fix(source-control): refuse to keep a both-modified file that is gone from disk

* feat(mobile): translate the merge conflict actions

* test(runtime): keep the mobile allowlist test under its line cap

* fix(mobile): let VoiceOver reach conflict action buttons
2026-10-30 03:18:48 +00:00
Neil 3bae99a2bb Warn macOS 12 users about upcoming support changes (#36182)
* feat: warn macOS 12 users about upcoming support changes

* fix: use explicit border tokens in macOS support notice

* fix: route compatibility guides through the app link setting

* fix: balance support notice columns in narrow windows

* test: include macOS notice in suppressed feature-tip history

* Simplify macOS 12 notice and isolate compatibility checks

* Clarify Apple compatibility wording in macOS notice
2026-10-29 20:08:48 -07:00
Kelvin Amoaba 6b937c7e5f fix(source-control): resolve delete/modify conflicts and complete merges from the panel (#35347)
* fix(source-control): resolve delete/modify conflicts and complete merges from the panel

* fix(source-control): address review findings on conflict resolution

* fix(source-control): save every view of the file before marking a conflict resolved

* fix(source-control): match unsaved conflict views by physical file only

* test(source-control): prove completeMerge refuses with a commit template set

* refactor(source-control): reuse autosave view matching and refresh only after a completed merge

* fix(source-control): drop the untranslated Complete merge fallback text

* fix(source-control): refuse Keep file when the file is gone and re-read unsaved views on retry

* fix(source-control): let Keep file stage conflicted symlinks with missing targets

* fix(source-control): run one conflict resolution per file at a time
2026-10-30 02:56:42 +00:00
Neil a17b6706f5 fix(explorer): open folder links that lead outside the project again (#36191)
* fix(explorer): open folder links that lead outside the project again

#24489 replaced in-memory path grants with declared file access, and the
explorer started refusing folder links out of the project with a toast.
fs:readDir now accepts user-named access; the explorer retries a contained
listing that main refuses only as outside the project, and files listed
that way open by absolute path so their tabs keep access after restart.

* fix(explorer): let main verify outside folder links, and list them only on a gesture

Review follow-ups:
- New project-folder-link access kind, accepted only for fs:readDir: main
  lists a folder only when the nearest project folder above it holds a
  symlink on the path, so an unregistered root's child or an arbitrary
  folder stays refused. user-file no longer lists folders.
- The explorer follows a link only on a user act or under a folder already
  listed as outside; refreshes never upgrade a contained listing.
- A link target that fails to list (EPERM, ENOENT) shows its own error.
- Open Markdown Preview opens outside rows by absolute path too.
- New/Duplicate/Rename/Delete are disabled on rows listed through an
  outside link, since writes stay inside projects.

* fix(explorer): keep keyboard edits off outside-link rows, and follow listed link rows on reveal

- Enter-to-rename and the delete binding skip rows listed through an outside
  folder link, matching the disabled context-menu items.
- A folder the parent listing shows as a symlink may follow the link without
  a click, so reveal and re-expansion after a workspace switch list it; a
  folder that only became a link stays refused until clicked.
- Pass followProjectFolderLink only when set, so existing read-call
  expectations hold.

* fix(explorer): limit folder-link listings to project roots; no rename on outside-row double-click

- Orca's floating folder is not a project, so a link there no longer
  authorizes an outside listing (direct IPC callers included).
- Double-clicking an outside-link row's name pins the preview instead of
  starting a rename main would refuse.
2026-10-29 19:48:09 -07:00
Neil b187d55e15 fix(computer-use): cap every macOS permission helper launch path at one per 5 s (#34390) (#36150)
* fix(computer-use): replace the macOS permission status gate with one 5s launch floor (#34390)

Follows up #36028. The earlier gate grew background/explicit flags, epochs,
backoff and a setup pgrep path that reviewers could not make correct.

- Status: one probe at a time and one 5s launch floor shared by every reader, so
  every path stays at <=12 helper launches/min. Readers inside the floor join the
  running probe or ride one trailing probe that fires only if someone waits.
  Only grants are cached (until the floor expires); denials and errors are never
  served, so a grant shows within one floor locally and on web. No app epochs:
  without a denial cache they bought nothing. Off macOS the gate is skipped.
- Setup: one launch per 5s across every permission, claimed synchronously; a
  request inside the window is queued (latest wins) and reported as
  launchQueued. Kill-and-relaunch stays so a click always re-shows the helper.
  Setup reuses the gate's in-flight/cached/last result instead of probing.
- Reset checks helper availability from the bundle and invalidates after any
  tccutil attempt, including partial failures.
- Remove the background flag from preload/IPC/renderer/web, the app-activity
  binding, and the sidecar permission_denied invalidation.

* fix(computer-use): close the remaining gaps in the permission launch floor (#34390)

- Clear the trailing timer whenever any probe launches and re-check the floor
  when it fires, so a late timer can never launch inside the floor.
- Setup reuses a denial only until the floor expires.
- A reader that joins a probe older than 300ms and gets a denial rides the next
  probe, so a grant shows within about one floor even after a stale web/RPC probe.
- Setup requests are numbered on arrival, including ones that coalesce, so the
  latest request wins (A, B, A launches A); a queued launch already covered by a
  newer launch is dropped. Reset and will-quit cancel any queued launch.
- The settings pane says "Opening…" and the CLI says queued for queued launches.

* fix(computer-use): measure permission launch floors from real spawns and cancel setup on every host (#34390)

- Both 5s floors use performance.now, so a wall-clock step cannot stretch or skip them.
- The status floor counts from the later of claim and the actual `open` spawn, and
  the setup window from after its spawn, so a slow mkdtemp or pkill can't allow a
  13th spawn in a 60s window.
- Setup cancellation registers through AppEnvironment quit handlers (desktop,
  headless Electron serve, orcad) and orcad's shutdown trigger; reset and
  shutdown bump a generation so an Open still waiting on status never launches.
- Reset cancels queued setup before its first await.
- A setup request leaves the coalescing map when it launches, so a later request
  for the same permission queues and wins (latest-wins across microtasks).
- A failed probe clears the remembered denial.

* fix(computer-use): drop setup coalescing and gate setup on a host-wide shutdown flag (#34390)

- Remove the per-permission setupInFlight map. Every Open goes through the 5s
  window and seq-ordered queue; a queued request with the same args that arrived
  before the last spawn was already shown by it, so concurrent same-permission
  Opens still spawn once. This fixes stale entries after reset turning the next
  Open into a no-op or a cancelled one.
- A cancelled Open (reset or shutdown) rejects with an error instead of returning
  launchedHelper: false, which every client rendered as "setup complete".
- Replace the per-host cancel calls with src/main/host-shutdown-state.ts, set
  synchronously by Electron will-quit and orcad's shutdown admission; setup
  checks it before every spawn, including the queued timer.
- Track the status cache's expiry from the probe that produced it, so starting a
  new probe cannot revive an expired grant.
- The queued setup timer re-checks its deadline and re-arms when early, and both
  timers round delays up; a throwing spawn there is logged, not uncaught.

* fix(computer-use): keep setup latest-wins after slow probes and surface cancelled setups (#34390)

- Record the launching request's seq; an older request that resumes or is queued
  after a newer one spawned is dropped, so latest-wins holds when requests
  resume out of order behind a probe.
- orcad sets the host shutdown flag on every cleanup entry, including failed
  startup.
- The web facade only falls back for hosts without computer.permissions; other
  failures, such as a cancelled Open, reject so the pane and onboarding show them.
- The cancellation check runs before an untargeted Open can report everything granted.
- Opens that arrive mid-reset wait for it, so reset's helper cleanup cannot kill
  what they open.
- Queued wording now says a newer request or a reset may replace it.

* fix(computer-use): wait out a reset before an Open reads permission status (#34390)
2026-10-29 16:33:52 -07:00
Neil 0426223be5 feat(telemetry): count plugin installs from Orca's public catalogs (#36132)
* feat(telemetry): report plugin installs and removals from Orca's public catalogs

* refactor(plugins): move marketplace install origin out of the installer
2026-10-29 16:32:49 -07:00
Brennan Benson 6d76f5a77b Keep a sleeping conversation resumable when the terminal limit is reached (#35401)
* Keep a sleeping conversation resumable when the terminal limit is reached

Resuming a slept pane while the host terminal limit was reached could drop
the Resume screen and fall back to a plain spawn. Route capacity refusals back
into the deferred sleep state, retry through the main-owned resume, and keep
the original session and provider until space frees up. A later Sleep or
cancellation still wins.

* Retain sleeping pane retries after transient owner failures

* Verify sleeping pane retry lookup bounds at scale

* Correct sleeping pane retry test fixture types

* Use transport attach contract in terminal test fixture

* Construct complete terminal transport test fixture
2026-10-29 12:17:37 -07:00
Neil 53e80ef9d4 fix(computer-use): stop relaunching the macOS permission helper on every status read (#34390) (#36028)
* fix(computer-use): stop relaunching the macOS permission helper while Accessibility is denied (#34390)

Every computerUsePermissions:getStatus / computer.permissionsStatus call launched a
fresh helper via open -n that polls TCC for up to ~3.5s. Three always-mounted
setup-guide hooks re-read on every window focus, so a denied Accessibility state
produced batches of helper launches and continuous TCCAccessRequest traffic.

Gate status reads in main: coalesce concurrent reads, reuse granted results for 2s,
and back off denied/failed results 10s doubling to a 120s cap. Window focus lowers
the backoff to a 10s floor; openSetup/reset invalidate it.

* fix(computer-use): never serve stale macOS permission status after the user acts (#34390)

- Re-probe once per real return to Orca (blur then focus) instead of a 10s floor,
  so grants and revocations made in System Settings show without another focus.
- computer.permissionsStatus accepts an optional fresh flag (web clients send it)
  that bypasses the denied backoff; older hosts strip it, older clients omit it.
- A provider permission_denied reply invalidates the cached status.
- Invalidate again after a TCC reset; stale in-flight probes get one follow-up
  probe instead of an overlapping helper.
- Failed checks are shared for 2s and retried, not backed off like a denial.

* fix(computer-use): gate macOS permission re-probes on app-level returns only (#34390)

- Track did-resign-active/did-become-active instead of BrowserWindow blur/focus,
  so moving between Orca's own windows never re-launches the helper.
- If the renderer's focus read reaches main before did-become-active, treat it as
  the return when a window is focused, so the first read after return is fresh.
- Passive badges (setup-guide progress, feature-wall status) opt into the denied
  backoff with background: true; omitted flags (older clients, active setup
  screens) keep near-live reads with 2s reuse. Replaces the unreleased fresh flag.
- Obsolete probes no longer record outcomes or advance the denied backoff.

* test(computer-use): drop casts from permission IPC wiring test

* fix(computer-use): keep remote permission reads near-live and count startup as away (#34390)

- Web clients never forward background: browser focus can't activate the host,
  so remote setup surfaces get 2s reuse instead of a stale denial.
- Seed the departed state when binding app activity, so a grant made during a
  slow startup is picked up on the first return.
- Drop the mock-only sidecar invalidation test; keep gate constants private.

* fix(computer-use): never serve a cached denial to foreground permission reads (#34390)

- Active screens, web clients and older clients only reuse a denial by joining
  an in-flight probe; granted and error results keep the 2s reuse.
- Revert the unreleased RPC background option so remote reads stay foreground.
- Drop the IPC test half that exercised events production no longer listens to.
2026-10-29 10:55:44 -07:00
Kelvin Amoaba 7c5314196a feat(native-chat): preview cards for web links, fetched with a private-address guard (#35221)
* feat(native-chat): preview cards for web links in chat

Hovering an http(s) link that isn't the repo's own PR or issue shows the
page's image, favicon, site name, title and description. The chat's host
fetches the page with no cookies, refusing private, loopback and
link-local addresses after DNS and on every redirect, and returns images
as data URLs. A Chat > Behavior setting turns web previews off.

* perf(native-chat): cap link preview caches at 20 MB each

Preview images are held as data URLs, so a count limit alone let the
renderer and main caches grow to hundreds of MB in a long session.

* fix(link-preview): keep a > inside quoted attribute values

Page tags ended at the first >, so content="Home > Docs" was cut short
and an og tag whose content came before its property was dropped.

* fix(native-chat): keep link preview caches within budget and keyed by host

A preview that finished after newer ones stopped eviction at itself, so
both caches could stay over their byte limit. The GitHub card's load key
also left out the host its repo lives on.

* fix(link-preview): decode the named entities page titles use

Only five named entities were decoded, so titles like
Docs&nbsp;&ndash;&nbsp;Guide showed the raw codes in preview cards.
2026-10-29 16:12:07 +00:00
Kelvin AmoabaandOliver Mee badab9cc41 fix(browser): import a cookie file into a client-hosted browser under a remote runtime (#35989)
* fix(browser): import a cookie file into a client-hosted browser under a remote runtime

A paired runtime refused every cookie-file import before the picker
opened, even when this desktop hosts the runtime's browser pages. The
file import now asks main, like the native-browser import does, and
imports into the page's route partition; it is still refused when the
pages are not hosted here.

Co-authored-by: Oliver Mee <102673257+oliver-mee@users.noreply.github.com>

* chore(browser): lower the focus-read baseline for the cookie import actions

---------

Co-authored-by: Oliver Mee <102673257+oliver-mee@users.noreply.github.com>
2026-10-29 15:53:48 +00:00