Commit Graph
18 Commits
Author SHA1 Message Date
Kelvin Amoaba ada69cba8c fix(browser): stop agent clicks from opening the system file picker over your work (#41299)
* fix(browser): stop agent clicks from opening the system file picker

An agent click on a file input opened the macOS Open panel, which brought
Orca's window forward over the app the user was in. Page actions now catch
the picker the way upload does and tell the agent to use upload.

* fix(browser): enable Page, cancel the picker, and clean up outside host scope

* fix(browser): limit picker blocking to input delivery and bound its setup

* perf(browser): skip picker blocking for actions without user activation

* fix(browser): bound picker interception cleanup on a hung page

* fix(browser): bound the picker interception setup as a whole
2026-11-12 00:18:39 +00:00
Kelvin Amoaba cab41b4075 fix(browser): tell agents when a page waits on a passkey, and let them cancel it (#41048) 2026-11-11 23:27:38 +00:00
Kelvin Amoaba 6dfb4dc60d feat(cli): add orca tab annotations so agents can read a tab's unsent notes (#40873)
Prints the notes the user left on a browser tab and has not sent, the same text the tab's Copy button gives (--json returns them). Reads the saved session, so it works for closed-and-restored tabs; SSH hosts reach it through the desktop browser bridge. A page drawn by a paired desktop reports that its notes stay there.
2026-11-10 22:02:43 +00:00
Jinwoo Hong f138493be3 fix(browser): a split tab create joins a browser pane already beside the caller (#38006)
* fix(browser): a split tab create joins a browser pane already beside the caller

* fix(browser): the joined page is the pane's visible tab

* fix(browser): a split with an unknown caller still splits beside the active pane
2026-11-03 21:30:03 -05:00
Kelvin Amoaba eb55a5a6d3 feat(browser): --expect-url refuses a browser command when the page is at another URL (#37575)
* feat(browser): guard page commands with an expected URL

* fix(browser): refuse an empty --expect-url and check it on dialogs and the forwarding desktop

* fix(browser): recheck the expected URL right before keys go out

* refactor(browser): drop duplicate session type, dialog alias and per-capability sidecar fields

* chore(browser): satisfy the changed-code gates for the expected URL guard
2026-11-03 02:11:23 +00: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
Kelvin Amoabaandfanzzzd 0a12f82757 fix(browser): list browser tabs restored after a restart in tab list and load them on switch (#35563)
* feat(browser): list restored tabs in tab list and load them on demand

After a restart Orca restores browser tabs lazily: a tab gets a page only once
the user opens it. tab list only reported tabs with a live page, so an agent in
a worktree with 26 restored tabs saw one and concluded there were none.

tab list now reads the tab bar from the session snapshot the renderer already
publishes on every tab change, and reports every tab in tab-bar order. Tabs
without a page carry loaded: false. tab switch and tab close --index resolve
indexes against the same list, and switching to an unloaded tab loads it in
the background first. Waking a page now also waits for its first load to
finish, so the next command does not read a blank page.

Headless serve keeps every page live, so it lists as before.

* fix(browser): list the tab bar even when Orca has no window open

With the window closed the app keeps running and its restored tabs still exist,
so tab list should report them. Headless snapshots are built from live pages
only, and the merge dedupes those, so dropping the window check lists nothing
extra there.

* fix(browser): list an id held by a live page and a client page once

* fix(browser): wait for the first load of a tab headless serve wakes

Headless serve starts a restored page and returned at once, so the next
command could read a blank page mid-load. It now waits for the first load,
as the window path already did.

* refactor(browser): keep the tab listing beside the browser tab catalog

Main moved the runtime browser commands into runtime/browser/ since this was
written. Also drops a window lookup the catalog no longer uses, and corrects the
headless note: those snapshots list saved pages that have not started yet.

* fix(browser): keep paired-server mirrors out of tab list and close indexed rows like --page

A window also publishes the browser tabs it mirrors from paired runtimes,
which this host can never load, so the tab bar is read only for workspaces
this host owns. tab close --index now closes the listed row exactly as
--page does, keeping its worktree, so an unstarted headless tab is retired
instead of reported closed and left saved. With nothing active, the first
live page is marked current again, matching where a pageless command goes.

* fix(browser): wait for first load only on tab switch, and show tab indexes from the listing

Every --page command wakes an unloaded page, including the tab show a
remote browser pane awaits before streaming, so waiting up to 10 s for the
first load there held the stream back. Only tab switch waits now. tab show
reports a tab's index from the same listing tab list and close use.

* fix(browser): list restored tabs in an SSH host's bridged workspace, and reject fractional close indexes

An SSH host's workspace can have no repo row on the desktop, yet its pages
render in the desktop window, so the bridge's scoped workspace counts as
this host's own. A non-integer --index no longer falls through to closing
the active tab.

* test(browser): give the restored-tabs e2e's timeout and lease wait their reasons

* test(browser): read restored-tabs RPC results through the shared e2e reader

Reuses the browser e2e rpc helper instead of a local Reflect.get copy, and
types the listing test's snapshot rows.

* fix(browser): index tab show in the caller's scope, as tab list does

* fix(browser): report an out-of-range close index as browser_tab_not_found

Matches tab switch, so agents can recover by re-listing. The restored-tabs
e2e now asserts the raw loaded value instead of coercing a missing one.

---------

Co-authored-by: fanzzzd <fanzzzd@outlook.com>
2026-10-30 16:57:48 +00:00
Kelvin Amoaba 26675e7649 feat(browser): upload through file-picker buttons in any frame, including cross-origin iframes (#36390)
* feat(browser): upload through picker buttons in any frame

* fix(browser): catch pickers the page opens for a frame button and click SVG controls

* docs(cli): note server-hosted pages need the file input ref for upload

* test(browser): assert both picker interceptions are released

* refactor(browser): flatten picker upload and arm frame sessions in parallel

* test(browser): emit picker events through a real emitter instead of Reflect.apply
2026-10-30 16:14:17 +00:00
Kelvin Amoaba dd7496be80 feat(browser): let agents drive sign-in and payment popups as pages (#36253)
* feat(browser): let agents drive popup windows like OAuth sign-in as pages

window.open popups that keep their opener stay native windows, but the
agent bridge now lists each one in tab list as popup-<n> with its opener,
so --page, tab switch and tab close reach it. When a popup the agent
switched into closes, its next command lands on the opener.

* fix(browser): reach popups over SSH, through the Electron sidecar, and by implicit tab close

* fix(browser): keep sidecar popups ordered after tabs and handing back to their opener

* fix(browser): skip the tab wake-up wait for popups and keep the agent's claim when a popup hands back

* fix(browser): refresh the opener's claim on hand-back and settle tab close after the popup is gone

* refactor(browser): share routing retarget and idle-window helpers for popup hand-back

* refactor(browser): move popup routing helpers into bridge state to keep tabs under its line cap

* test(browser): expect the popup's url and title in its snapshot result
2026-10-30 15:51:17 +00:00
Kelvin Amoaba dcaeaaa1fc feat(browser): typed snapshot flags, screenshots saved as files, and a guide that keeps browser work in Orca (#36257)
* feat(browser): typed snapshot flags and screenshots saved as files for agents

orca snapshot takes --interactive, --compact, --depth, --selector, --urls,
--delta and --full, passed to agent-browser on every route. The header
now shows the page title and URL. orca screenshot and full-screenshot save
the image where the CLI runs and print its path, in CSS pixels, with
--if-changed and --annotate. Flag help for exec, wait and download is
written for those commands, and the orca-cli guide sends web pages to
Orca's browser unless the user picked another tool.

* fix(browser): scale screenshots by the scrollbar-free axis and keep snapshot metadata behind SSH admission

* fix(browser): upscale low-DPR screenshots and wrap a torn-down tab's screenshot error

* fix(browser): give each screenshot its own file and keep typed screenshot errors

* refactor(browser): share the agent-browser screenshot reader between Electron and orcad

* refactor(browser): move snapshot and screenshot params under the line cap
2026-10-30 15:07:05 +00:00
Kelvin Amoaba d3595c3304 feat(browser): agent browser actions report what they caused (#36278) 2026-10-30 14:44:16 +00: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
Kelvin Amoaba b67c5254f0 fix(browser): agent fill, select, upload and type change the page or fail with a reason (#36263)
* fix(browser): fill, select, upload and type act on the agent's element or fail

* refactor(browser): move agent key commands into their own bridge layer; fix test sender call
2026-10-30 06:48:58 +00:00
Kelvin Amoaba 324f138de2 fix(browser): keep an agent on its own tab when the user picks or opens another (#36108) 2026-10-30 03:27:56 +00:00
Kelvin Amoaba 92f9431416 fix(browser): give agent set device and viewport --mobile touch input and pointer: coarse (#35982)
* fix(browser): turn on touch when an agent sets a mobile device or viewport

* docs(orca-cli): say every page load resets agent device emulation
2026-10-29 16:34:03 +00:00
Jinwoo Hong fb322046e8 skills: rewrite and trim the seven non-orchestration guides (#19128)
* skills: rewrite the seven non-orchestration guides to one outcome-first standard

Every guide leads with Result / Done / Safe failure, states conditions instead of case lists, keeps one done bar and one autonomy envelope, and loads references at the point of use via `skills get <topic> --full`. orca-cli drops from 424 to 260 always-loaded lines with three references; orca-per-workspace-env from 794 to 397 with five.

Defects fixed in shipped guides: `emulator camera` (no such command), iOS `permissions` (backend refuses it), Android pane described as in development, `relayGracePeriodSeconds: 0` documented as immediate teardown (it is unbounded), doctor `ok: true` hiding `warn`, an SSH exemplar setting both `jumpHost` and `proxyCommand`, a provisioned-root fetch from `origin`, and the Linear unconfirmed-write rule keyed on four verbs when ten emit it.

The resolver ladder, placeholder rule, and older-binary fallback shared by every installable SKILL.md now come from one skill-stubs/_shared/cli-resolution.md fragment composed by the generator, which also bundles per-guide references into --full. New guards: every ORCA invocation and flag resolves against COMMAND_SPECS, descriptions carry no angle-bracket tokens, reference routing is checked both ways, and an always-loaded size ratchet (300 lines) that guides may leave but never join.

* skills: address review on the SSH recipe and the parity guard

- ssh-host create script: route the bootstrap ssh through the chosen jump host or proxy command, refuse both at once, use StrictHostKeyChecking=accept-new instead of a blind ssh-keyscan append, and pass gh_token/project_root/repo_url/repo_ref to the remote bash via printf %q so a quote in a value cannot break out of the command.
- per-workspace-env envelope: the step-10 workspace test the user asked for is no longer forbidden by the same paragraph.
- linear guides: name the full verb, ORCA linear list-issues.
- parity guard: a prefix reference such as ORCA linear --help or ORCA emulator --webcam now has its flags checked against every command under that prefix; only an exact path or an explicit ... was checked before.

* skills: tighten prose in the seven rewritten guides

Shorter outcome spines, one idea per sentence, no restated rationale after a rule. No rule, command, or pinned phrase changes; 47 net lines fewer across the guides and references.

* skills: route orca-cli and per-workspace-env gates through --reference

Both guides told agents to load --full at a gate because the per-reference
selector did not exist when they were written. Now that main serves
`skills get <topic> --reference references/<file>.md`, load only the
named file and keep --full as the fallback for an older CLI, matching the
orchestration kernel.

* skills: drop outcome-spine boilerplate from the CLI-wrapper guides

The Result/Done/Safe-failure preambles and Next Action closers restated
rules the body already carries. Agents stop fine without them, and for
a CLI wrapper the command surface is the guide. Keeps the one substantive
rule computer-use's Done block added (never report unverified as success)
inside Action Rules. orchestration and per-workspace-env keep theirs:
those are multi-step workflows where the done bar is load-bearing.

(cherry picked from commit 44a74baf73)

* skills: trim the guides and stubs to what agents actually need

- Drop the Result/Done/Safe-failure preambles and Next Action closers from
  the six CLI-wrapper guides; the one substantive rule (never report an
  unverified computer-use action as success) moves into Action Rules.
- Drop the 'guide may be stale, trust --help' lines: the guide is served by
  the binary that runs the commands, so it cannot be stale relative to it.
- Drop the status --json / open --json preflight from every guide; the stub
  no-guessing paragraph now says to start Orca only when a command reports
  it is not running.
- Cut the ORCA placeholder paragraph in each guide to one line that points
  back at the stub's resolution.
- Trim the orchestration, orca-cli, and computer-use descriptions to trigger
  phrases plus one line of scope.
- Remove the older-binary fallback section from every stub (and its two
  shared blocks); a binary without skills get gets one sentence.
- Remove the guide size ratchet test.

* skills: apply independent review cleanup

* skills: clarify guide loading and Linear command discovery

* skills: harden environment recipe examples

* test: complete branch rename journal doubles

* skills: clarify custom Codex launch and refresh model example

* test: deduplicate journal fix now present on main
2026-09-07 00:03:48 -04:00
Jinwoo Hong b8311d509a Revert "skills: rewrite the seven non-orchestration guides to one outcome-first standard (#18724)" (#19126)
This reverts commit 15d0f8aedf.
2026-09-06 17:01:49 -04:00
Jinwoo Hong 15d0f8aedf skills: rewrite the seven non-orchestration guides to one outcome-first standard (#18724)
<!-- orca-pr-loc -->
<!-- Programmatic LoC summary. Do not edit by hand; rewritten on every commit. -->

| | Files | Added | Deleted | Net |
| :--- | ---: | ---: | ---: | ---: |
| Test | 6 | $\color{#1a7f37}{\Huge{\mathbf{+}}}$​544 | $\color{#cf222e}{\Huge{\mathbf{−}}}$​49 | $\color{#1a7f37}{\Huge{\mathbf{+}}}$​495 |
| Prod | 36 | $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1719 | $\color{#cf222e}{\Huge{\mathbf{−}}}$​1703 | $\color{#1a7f37}{\Huge{\mathbf{+}}}$​16 |

<!-- /orca-pr-loc -->

## ELI5

Orca ships eight skill guides that agents read before running the CLI. Seven of them (everything except `orchestration`, which #16904 rewrites) were command catalogs that had drifted from the binary. This PR rewrites them so an agent reads the outcome, the done bar, and the safe-failure rule first, loads reference material only at the step that needs it, and never sees a command or flag the installed CLI does not define.

## What changed

- **Seven guides rewritten** to one standard: outcome spine first (Result / Done / Safe failure), conditions instead of case lists, one done bar, one autonomy envelope, references loaded at the point of use via `skills get <topic> --full`, every runnable invocation spelled `ORCA`. `orca-cli` is 424→260 always-loaded lines with three references (browser, automations, publishing); `orca-per-workspace-env` is 794→397 with five (provider-vercel, ssh-host, docker-ssh, windows-scripts, failure-modes).
- **Defects fixed in shipped guides:** `emulator camera` (no such command), iOS `permissions` (backend refuses it), Android pane described as "in development" (shipped in June), `relayGracePeriodSeconds: 0` documented as immediate teardown (it is unbounded), doctor `ok: true` hiding `warn`, an SSH exemplar setting both `jumpHost` and `proxyCommand`, a provisioned-root fetch from `origin`, the Linear unconfirmed-write rule keyed on four verbs when ten emit it. Linear and emulator descriptions dropped embedded commands and angle-bracket placeholders (651→329, 732→404 chars).
- **Generator bundles references.** `skill-guides/<name>/references/*.md` is appended to `--full`; `skills get` help says compact by default, full with references.
- **Stubs single-authored.** The resolver ladder, placeholder rule, and older-binary fallback shared by all eight installable `SKILL.md` files come from one `skill-stubs/_shared/cli-resolution.md` fragment composed by the generator. Projections were byte-identical before the content fixes.
- **Guards:** every `ORCA <cmd>` and flag in every guide and reference resolves against `COMMAND_SPECS` (this found the camera defect); descriptions ≤1024 chars with no angle-bracket tokens; reference routing checked both directions; an always-loaded size ratchet (300 lines) that guides may leave but never join. `orchestration` (440 lines on main) is recorded as an exception until #16904 lands its kernel.

## Relationship to #16904

Split out of #16904 so that PR carries only the orchestration guide. On main, `terminal send` has no `--wait-submit` / `--retry-request` and the orchestration kernel still carries the resolver ladder and worktree-selector rule, so this branch pins `accepted: true` for handoff receipts and leaves the orchestration pins where main has them. The merge in either direction is mechanical: #16904 rebased on this becomes a one-file `orchestration.md` change plus dropping the two exceptions.

## Standard

Compound Engineering's portable skill-authoring guidance (outcome spine, conditions not cases, pinned fragile commands with an ordered hatch, references at point of use). NVIDIA SkillEvaluator Tier 1 (`schema,pii,license,quality,unicode,lint`) was run on every guide; its deterministic checks pass, its template nudges (Instructions/Examples sections, 50–150 char descriptions) do not apply to Orca's stub architecture and were not applied.

## Testing

- `pnpm typecheck:tsc:cli` clean; `check:code-quality:changed` and `check:react-doctor:changed` 0 findings
- `pnpm verify:bundled-skill-guides` and skill-bundle manifest verify clean
- vitest over `config/scripts`, `src/cli/skill-guide-cli-parity.test.ts`, `src/cli/skills.test.ts`, `src/cli/specs/skills.test.ts`, `src/cli/help.test.ts`, `src/main/skills`: 240 files / 2,019 pass
- Live smoke on the built CLI of every `skills get <topic>` and `--full`, every emulator, linear, and vm verb named in the guides, and every projection's resolver, GNOME warning, and bounded fallback (done on the #16904 branch before the split; the guide bodies are identical here except the send-receipt vocabulary noted above)

## Deferred product decisions

Merging `orca-emulator` and `orca-emulator-android` into one skill with a platform branch; collapsing `linear-tickets` to a guide alias; a `skills get --reference <name>` selector so a gate table can load one file; a fresh-agent routing eval before trimming the `orca-cli` (1,015 chars) and `orchestration` descriptions, whose quoted triggers each fixed a routing misroute.
2026-09-06 16:10:16 -04:00