* fix(computer-use): refuse macOS background actions that open a menu or dialog over the user
* fix(computer-use): let web comboboxes click in the background and stop probing a hung app
* fix(computer-use): refuse background drags that start on a menu owner
* docs(computer-use): note background drags on menu owners are refused
* fix(computer-use): classify the element under a drag's start and check AXConfirm/AXOpen secondary actions
* fix(computer-use): refuse Windows pointer fallbacks without --restore-window
Coordinate, right, middle, modified and multi-clicks, clicks on elements with no
primary pattern, unscrollable wheel scrolls and drags raised the window and
moved the real cursor without being asked. They now refuse with
background_unavailable before anything is sent. Coordinate and fractional
scrolls go through ScrollPattern first. With --restore-window only the target
window is raised (never a cloaked one), with a UIA activation fallback and a
second attempt, points are validated first and the cursor is put back behind
the input. A failing UIA pattern or disabled element is an error instead of a
real click, and delivery is measured after the post-action observe.
* fix(computer-use): settle Windows clicks before restoring the cursor and keep scroll writes honest
* fix(computer-use): restore the Windows cursor with SetCursorPos and hit-test coordinate scrolls
* test(computer-use): assert Windows raise outcomes, not attempt order
* fix(computer-use): report a Windows page scroll the provider ignores as not scrolled
* test: remove low-value automation and shared suites
* test: retire stale gate references and stabilize retained fixture date
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* feat(computer): type into a named text field without focusing it on Linux and macOS
* fix(computer): report unconfirmed Linux text readback and cover element typing
* test(computer): send an element with benchmark text only for targeted typing
* test(computer): pick gedit's editor, not its hidden overview map, in Linux e2e
* docs(computer): confirm focus before the unindexed type-text fallback
* fix(computer): report unreadable element text readback as readback_unsupported
* fix(computer-use): scroll, expand and set sliders on Windows without raising the window
* fix(computer-use): wait for Windows scroll and slider writes to settle before verifying
* fix(computer-use): reject NaN for Windows slider set-value
* test(computer-use): wait on the Windows fixture state with vi.waitFor and a schema
* test(computer-use): check activation per action against a holder window in the Windows fixture
* test(computer-use): log fixture window events for activation failures
* fix(computer-use): report foreground when a Windows app raises itself for a UI Automation action
WPF activates its own window for Scroll, ExpandCollapse, RangeValue and SelectionItem calls from any UIA client, so the runtime now compares the foreground window before and after a pattern action instead of assuming background. The Windows e2e checks delivery against the fixture's own activation count, with a holder window in another process.
* test(computer-use): skip an unstarted holder when closing the Windows fixture
* fix(computer-use): bound Windows pattern scroll paging and tighten slider read-back
* fix(computer-use): cap Windows slider read-back tolerance and run the UIA e2e only on CI
* fix(computer): verify macOS type-text and paste-text sent as keys by reading the field back
When text can't be written through AXValue (Chromium/Electron fields, fields
that refuse the write), type-text and paste-text send keys or Cmd+V and always
reported unverified. Now the helper predicts the focused field's value from its
value and selection before sending, then reads it back until it settles:
verified on a match, unverified (text_mismatch) otherwise. Secure fields and
fields without a readable value and selection stay unverified as before, and
the result never repeats the typed text or the field's contents.
* fix(computer): keep the caret put after a refused macOS text write and skip unprovable readbacks
A refused AX value write no longer moves the caret before falling back to keys, so the keys and the prediction both use the user's selection. Text with control characters, a value the field already holds, and a field still filling at the 2 s cap stay unverified rather than verified or text_mismatch. The quiet window starts after the first read answers.
* fix(computer): bound macOS text readback size and say a mismatch can mean keys went elsewhere
* fix(computer): treat a macOS text readback past the cap as undetermined
* fix(computer): refuse quit, log out and lock shortcuts unless explicitly allowed
* fix(computer): close Linux keysym bypasses in the system shortcut guard
* fix(computer): refuse Linux keycode, L1/L2 and VT-switch keysym bypasses
* fix(computer): catch control characters in Linux keycode tokens and point recovery at the stated effect
* feat(computer): show where snapshots were cut and read one element's subtree
* fix(computer): validate subtree targets against the fresh walk and keep scope for focused input
* fix(computer): return whole-window action results after subtree reads
* fix(computer): count kept records toward the macOS limit and index subtree reads against the latest cache
* fix(computer): index Linux/Windows subtree reads against the snapshot they started from
* feat(computer-use): add orca computer wait for text, enabled controls and window titles
* fix(computer-use): bound wait reads by the deadline and wait out missing Linux/Windows windows
* fix(computer-use): read disabled traits after role text with parentheses and bound the capability probe
* fix(computer): check macOS click targets are enabled, in view and on top before sending input
* fix(computer): scope macOS click cover checks to the target window
* fix(computer): scroll before trusting container hits and stop hit walks at the shared container
* refactor(computer): share the one-scroll rule in the macOS click check
* Hide projects from the sidebar without stopping them
Adds Repo.hiddenAt, a per-host, view-only flag. A hidden project's
workspaces, empty header and project-filter entry leave the desktop
sidebar, the paired phone's list, the new-workspace picker and the
palette's project filter. Its terminals, agents and automations keep
running, and repo.list / worktree.ps still list it.
- Hide Project in the project menu (toast with Undo), a collapsed
"N hidden projects" list under the workspace list with Show buttons,
and a Hide from sidebar switch in Settings > Projects.
- repo.setHidden RPC ({repo, repoHostId?, hidden} -> {repo, hostId,
hidden}) and `orca repo hide|unhide [--host]`; `repo list` marks
hidden rows.
- Opening a hidden project's workspace (notification, CLI, deep link)
focuses it without unhiding it, lifting sidebar filters, or leaving a
pending sidebar reveal.
- repo.update echo check: a host that drops hiddenAt reports failure
instead of reading as hidden.
* Address hidden-projects review: multi-host hide, picker scope, mute, stale filters, shared predicate, restore list styling
* Hidden projects re-review: keep saved filters, Agents filter, composer seed, per-toast Undo, shared default host
* Hidden projects: address review threads (pre-feed, palette search, notices, dialog default, seed remap, row keys, a11y)
* Hidden projects: no implicit dialog default when every project is hidden
* feat(plugins): host API 1.9: agent.listSessions (history:read), resume past sessions, agents.list task titles
* test(plugins): host API 1.9 coverage; regenerate plugin artifacts
* fix(plugins): host API 1.9 review fixes
- agent.resume starts a past session where the desktop's Resume would: the same preparation
request and answer handling (now shared), and the transcript in the home it pins
- AI Vault list cache keeps four scopes, so plugin reads never evict the panel's list
- list fingerprints ignore scan id and issues, so an unchanged history revalidates
- workspace mapping resolves symlinked workspaces and prefers a project over a folder
- agents.list task only for open dispatches, read at most once a second
- running matches OpenCode versions; history reads reset when the vault list is invalidated
- truncation, consent copy and limitations documented
* fix(plugins): forced history refresh supersedes cached scopes; resume legacy Codex sessions from their recorded transcript
* fix(plugins): address host API 1.9 review threads
- a scan that began before a forced history refresh no longer caches its older result
- list fingerprints count which issues there are (not their wording)
- symlinked workspaces rank by their resolved folder
- a session-only status row is no live pane: resume prepares the session
- a failed task-title read leaves agents.list rows intact
- the symlink test uses a junction on Windows
* test(ai-vault): order the stale scan before the forced refresh
* feat(plugins): proposed tier for host methods not yet frozen
A method spec may set `proposed: true`: only development plugins may call
it (others get not_permitted), and the minor, frame/worker method lists,
typings and skill references omit it. The reference renders such methods
in a separate Proposed section; dev workers' host.has answers for them.
* feat(plugins): param capabilities, host confirmations, automation provenance
- PluginHostMethodSpec.paramCapabilities: a passed param can require a
second capability; executePluginHostCall and the mock host refuse it with
capability_denied before any audit or effect, and the reference shows it.
- confirmPluginAction generalizes the external-open prompt into a host-owned
confirmation, exposed as PluginHostServices.confirm (desktop only; absent
in headless serve). It re-checks the plugin's approval after the answer.
- Automations record createdBy { kind: 'plugin', pluginKey, name }, set by
the runtime from the in-process plugin caller (RpcContext.plugin), never
from params; the Automations detail shows "Created by <plugin>".
* feat(plugins): workspace:create, automation:read and automation:write capabilities
New closed-enum kinds (older Orcas refuse such manifests with the engines
message), worker-only, with consent copy that names what each allows;
release floor PLUGIN_HOST_API_1_8_SINCE (1.4.259) joins
PLUGIN_SCHEMA_NEWEST_SINCE. agent:launch copy now says it also resumes.
* feat(plugins): host API 1.8 methods: workspace.create, agent.resume, automation.*
- workspace.create (workspace:create; agent also needs agent:launch): a
worktree in a Git project, as orca worktree create does; with agent, the
CLI's agent.launch create-worktree path, so the agent starts after setup.
Setup is skipped or follows the project's settings; never run, an
approved hash or a startup command.
- agent.resume (agent:launch): terminal.ensureAgentSession by session id;
started is false when a terminal already ran it. agents.list rows and
agent.status.changed carry sessionId.
- automation.list/create/update/delete (automation:read/write): create
forwards only name, prompt, agent, target, schedule, time zone and
enabled; update/delete of automations another plugin or the person made
ask the person first and report cancelled or consent-unavailable.
* test(plugins): host API 1.8 coverage; regenerate plugin artifacts
Covers param capabilities (host and mock host), workspace.create payloads
and refusals, agent.resume keys and adoption, sessionId on agents.list,
automation projection, forbidden create fields, confirmation outcomes,
runtime-set provenance and capability access growth. Regenerates the
reference, schemas, typings, declarative runtime and skill references.
* fix(plugins): host API 1.8 review fixes
- Confirmations spend the frame dialog budget, allow one question per
plugin at a time and pause after a refusal (rate_limited); a worker's
question shows in the focused window, else the first visible one.
- Changing what an automation with extra agent settings runs (prompt,
schedule, resuming) asks first even for its creator, showing the prompt.
- Removing, disabling or blocking a plugin pauses its automations and ends
its ownership (createdBy.endedAt), so neither re-enabling nor a reinstall
under the key resumes or edits them silently; the remove dialog says so.
- workspace.create and agent.resume record the terminals they return as
the plugin's own; a launch that fails after its worktree exists names it.
- Setup-decision refusals are told by the runtime's error class (kept as
the in-process RPC error's cause); generated names see every worktree
of the project; resume transcripts match the workspace and host.
- Created by shows the plugin id beside its name.
* fix(plugins): end automation ownership only on uninstall, disable or block
- The ownership sweep no longer reads discovery: only an uninstall
(announced by the removal path), the disabled list, the kill list or
the plugin-system switch end it, and only once the service is ready,
so an unreadable plugins folder pauses nothing. An install under the
same key after a removal keeps what it creates.
- A new time zone on an automation with extra agent settings asks first.
- A failed launch names only a new worktree made from the requested name.
- Settings' plugins-off state and the CLI's plugin system off and plugin
disable say that plugin-created automations are paused and stay so.
* fix(plugins): address host API 1.8 review threads
- Confirmations close when the worker's call ends, freeing the plugin's
turn; they name the automation (short id, project, workspace,
schedule), show any new prompt, and are refused as `changed` when the
automation was edited while the person was asked.
- automation.create takes hostId (through the project's setup on that
host) and a creationKey scoped to the plugin; the runtime rechecks the
plugin's approval right before the write.
- agent.resume records only terminals it started; both it and
workspace.create recheck approval before recording.
- automation.list never cuts a schedule (null when too long) or fails on
an id too long to show.
- The Automations detail says when a creator plugin was removed or
disabled.
* feat(plugins): host API 1.7 — workspace ids, project/terminal list, terminal focus/close
Plugins that track workspaces and terminals across Orca had to read the private runtime
token or shell out to the CLI. Host API 1.7 gives them the same through consented methods:
- workspace.readContext (and workspace.changed) carry `workspaceId`, the id workspace.list
gives; workspace.created/removed and agent.status.changed add `workspaceListId` beside
their existing raw `workspaceId`, which keeps its meaning.
- workspace.list rows name their `projectId`; opt-in `includeStatus` joins each row's agent
state, unread flag, live terminal count and last activity from worktree.ps.
- project.list (workspace:read), terminal.list (workspace:read), terminal.focus
(workspace:write, desktop only, steers only this window) and terminal.close
(terminal:send, reports whether the process is known to have stopped).
- Runtime refusals (unknown or ambiguous workspace, stale or exited terminal) reach plugins
as fixed messages instead of runtime wording.
- Consent copy for workspace:read, workspace:write and terminal:send says what they now
allow; terminal.focus and terminal.close are audited by terminal id.
- PLUGIN_SCHEMA_NEWEST_SINCE covers the editor typography and theme video floors it missed,
and the provisional 1.7 floor, so development builds accept plugins requiring them.
* fix(plugins): narrow terminal.close and harden host API 1.7 from review
- terminal.close closes only terminals of the focused workspace (the check terminal.sendText
uses) or ones this plugin opened with terminal.create or agent.launch, recorded in a bounded
per-plugin registry that is forgotten when its worker stops or it is disabled or removed.
terminal.focus stays any-terminal; summaries and terminal:send copy say so.
- Lifecycle events carry the worktree's identity and host: from the new row on create, and read
host-qualified before the purge on every removal path. agent.status.changed looks up the
identity on the reporting host only. The global removed-identity map is gone.
- includeStatus shares one in-flight worktree.ps and a 1 s cache across plugins, and reports
statusTruncated when that listing stopped short.
- Stored remote contexts get their identity host-qualified; panels and editors never get a raw,
path-bearing workspace id from readContext or workspace.changed.
- Runtime refusals map to fixed messages (tab pinned, no window, tab gone, host disconnected);
any other runtime error or malformed answer is a fixed action_failed with the detail logged.
- hostId is `local`, `ssh:` or `runtime:` in both workspace.list and project.list; rows past the
id or path bounds are left out with truncated set instead of failing the list.
- The mock testing host answers terminal.focus and terminal.close by default.
* fix(plugins): keep shipped host API values and codes; honest terminal results
- workspace.list hostId keeps the values 1.3 shipped (recorded host, else null; folder rows
their executionHostId); project.list always names the host. Both summaries say which.
- Methods that shipped before 1.7 report every runtime refusal as action_failed, as before;
the unavailable/conflict mapping applies to 1.7 methods only.
- includeStatus shares a pending worktree.ps however long it runs; the 1 s TTL starts when it
lands.
- The opened-terminal registry records only for a call still approved and not cancelled, and is
pruned on disable or removal only, so event-driven workers keep close rights across restarts.
- terminal.close answers { closed: true }: a local close cannot tell whether the process exited.
terminal.focus answers focused: false when the request was superseded or not navigated.
- workspace.list and project.list cut labels to 512 instead of failing the list.
- Removal events from the runtime job and the IPC retry are tested to carry the identity read
before the purge; folder deletion carries its host.
* fix(plugins): name the status-listing owner type
* fix(computer): stop echoing written text and secure read-backs in action results
* fix(computer): treat a truncated set-value read-back as unverifiable
* fix(computer): accept code-point truncated read-backs as unverifiable
* fix(cli): report connected agent hook status from the sqlite file
Status always said appliedBy offline and named orca-data.json, even when the app was connected and the setting lived only in profile-state.db.
* fix(cli): read agent hook status from the running app
When the runtime answers, status takes agentStatusHooksEnabled from
settings.get instead of the disk, so appliedBy: runtime is true. The
settings path rule lives next to the reader, and on/off report the
SQLite file when the runtime applied the change.
---------
Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
* perf(orchestration): read released worker output from its original instead of a saved copy
* fix(orchestration): keep refusal codes on released chat reads and locate legacy remote transcripts
* test(orchestration): prune flaky-pattern baseline for removed archive tests; guard a cursor read
* fix(orchestration): keep locator fields when stripping copies; never let the optional receipt page block remote release
* test(orchestration): drop removed archive tests from the node-runtime test list
* refactor(orchestration): drop the background strip; old rows keep their saved copy and its reader
* fix(orchestration): give reference rows the empty copy fields older Orca reads, with a note
* test(orchestration): give the slow-exit release mock a stored archive body
* fix(orchestration): record a transcript reference only for agents the reader can open
* fix(orchestration): hide approve from help; approval follow-ups
- Hide 'orchestration approve' from group help; its own --help still works.
- Mark a terminal worker's approval reported only once its escalation was sent,
so a prompt whose report was skipped gets no stray closing line.
- Hold back a worker approval receipt older than every loaded chat message
instead of drawing it below newer replies.
* fix(orchestration): count a stored stop report as sent when its wake fails
* feat(orchestration): let coordinators approve worker permission prompts when the user turns it on
One setting on the orchestration page, off by default. When on, the
escalation offers orchestration approve and deny, both with a reason, and
the user still sees Allow/Deny: the first answer wins. A prompt the
worker's agent lets only a person approve is refused and stays with the
user. The machine running the worker enforces its own setting.
* fix(native-chat): a worker approval's receipt shows the command, not its tool input as JSON
* test(orchestration): list every worker-side case in the coordinator approval table
* chore(i18n): ship the coordinator approval setting's search keywords in the runtime catalog
* fix(orchestration): a reasonless allow keeps the person's refusal, and terminal checks no hook may approve are person-only
* fix(orchestration): address review on coordinator approvals
- A person-only chat prompt answered meanwhile reports as closed.
- A terminal allow reads Claude's warning from the screen it checks, so a
late-painted person-only warning still refuses before the hook is used.
- The receipt keeps a chat worker's whole command.
- orchestration approve prints the reason it sent.
* fix(native-chat): read the receipt's command through a parsed shape, not Reflect
* docs(skills): drop worker permission prompt guidance; the escalation carries it
The numeric reasoning_effort a model sees is not on a 0-100 scale
(claude-opus-5-5: low=5, medium=10, high=15, xhigh=40). Workers launched
with --effort high read 15 as low and misreported their effort.
* Revert "Make chat wait check the chat's work state instead of reading its history every second (#41129)"
This reverts commit 9a10464bec.
* Revert "feat(cli): read, message and wait on agent chats with orca chat list/read/send/wait (#40836)"
This reverts commit c2e6ebbf0b.