* 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
* feat(plugins): Featured and Newly added rows in the plugin catalog
Featured shows the most installed plugin per category; Newly added lists plugins
by the catalog's new entry-level addedAt (hidden when no catalog dates entries),
with a New badge for 24h and an Added this week filter. Snapshots move to a v3
cache key so older builds never read addedAt.
* feat(plugins): derive Newly added dates from release dates, as the website does
Drops the catalog-level addedAt field (schema, docs, v3 snapshot key). Main now
estimates a listing date for each non-official plugin from its oldest dated
release, and the Newly added row, New badge and This week filter read it through
shared helpers that mirror orca-site's pluginNew.ts: 30-day window, newest first,
dates more than an hour in the future ignored, "just now / N hours ago / N days ago".
* feat(plugins): show nine Newly added plugins, drop the counts release dates inflate
Listing dates come from each community plugin's oldest kept release, and
catalogs keep only recent releases, so almost every plugin looks new: 181
of 182 fall in the 30-day window and 142 count as this week. Remove what
that inflates rather than flag it: the "N this week" count and its See all,
the This week filter, and the 24h New badge.
The Newly added row now offers the website's nine in the catalog's normal
wrapping grid, the same columns and card widths as the catalog groups.
* fix(plugins): pick Featured winners by every kind a plugin belongs to
Featured used only a plugin's first filter kind, while the category filters
count every kind, so category order could change winners or drop a kind's only
candidate. Each plugin, walked by installs with a key tie-break, now fills one
unfilled kind it belongs to (the one with the fewest candidates left, then by
name). Also note why Featured is a capped one-row teaser and pin the cap.
* fix(plugins): hide Featured when Newly added is empty
Without Newly added, Featured sat directly on the Official catalog, whose
leading cards are the same popular plugins in the same columns, so back-to-back
rows repeated and read as a render bug. Featured now shows only alongside
Newly added. Leaving featured plugins out of their catalog instead would move a
card into the catalog the moment it's installed and skew the catalog's N of M.
Adds a PluginManager test that no plugin card shows twice in the empty state,
and page-level fixtures (390, 600, 1440, empty 1440) for screenshots.
* fix(plugins): cap Newly added at two full rows of the current columns
At phone width nine stacked cards pushed the catalogs about 3.5 screens
down. The grid now shows two full rows of its container-query column
count (8 at four columns, 4 at two, 2 at one), hides a partial last row,
and the pick renders at most eight. Hidden plugins stay listed in their
catalog group, so there's no See all.
* Correct plugin catalog fixture evidence
* Make plugin highlight tests match observable behavior
* feat(wsl): turn WSL hosts on by default; ORCA_INTERNAL_WSL_HOSTS=0, false, off or no turns them off
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(wsl): review follow-ups for WSL hosts on by default
- Off words also match when quoted (cmd.exe's set NAME="0" keeps the quotes).
- The refusal now says WSL hosts are turned off for this launch, not missing from the build.
- New preload test pins when the renderer gets the WSL hosts API.
- Unit tests no longer inherit the gate state an Orca terminal publishes.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Tidy the Settings → Agents installed list
Rows line up on one line, the default agent gets a Default pill, and
Set as default moves into each row's ⋯ menu. Chat/CLI stays in place,
grayed out, when an agent is off. Click a row to expand its settings.
* Keep a saved default clearable when its agent isn't installed
The ⋯ checkbox follows the saved default, not the badge, so a saved
agent that isn't detected still shows Default and can go back to Auto.
Row hover uses the list-row accent token.
* Use plain items in the agent row's ⋯ menu
No checkmark column: Set as default, or Clear default agent on the saved
default, then Docs/Install aligned to the menu edge.
* test: remove 60 low-value cases and orphaned conversion fixtures
* docs(ci): list supported Windows SSH host cells
* test: recognize direct Windows orcad server entry
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(agent-status): skipping a Codex async question clears it on SSH panes too
An SSH pane's Codex hooks are normalized by orcad on the host, so the
desktop's own hook server had no row to apply the skip keystroke to. The
renderer now sends a remote pane's skip to the owning runtime through a new
terminal.inferCodexQuestionSkip RPC, which applies it to the host's tracker.
* test(e2e): skipping a Codex async question clears a managed SSH terminal's row
* feat(automations): redesign the automation detail overview
Group the overview into a run-health band (last run, next run, spend), Schedule and Execution property panels, and a Prompt panel with copy and a fading show-more. Run Now is now the primary action next to Edit; Pause and Delete move into an overflow menu with Delete separated as destructive.
* test(e2e): align prompt disclosure spec with the 8-line clamp
The redesign raised the collapsed prompt clamp from 4 to 8 lines and caps the
prompt at 80ch, so the resize prompt no longer overflowed at 820px. Lengthen it
so it wraps to ~11 lines at 820px and ~6 at 1400px, and assert line-clamp 8.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
The first-launch 'Trust <repo> for agents?' modal blocked agent launches
to ask a question that offered no real protection: undecided repos, and
every unattended launch, already pre-trusted. Drop the dialog, the launch
hold and the skipAgentWorkspaceTrust plumbing. Repos default to
pre-trust; the per-repo setting remains as an opt-out.
* Fix workspace delete shortcut targeting
Resolve the keyboard action from the current workspace and execution host,
keep clicked menu actions bound to their rows, and advertise the shortcut
only for the committed workspace copy. Preserve confirmation preferences.
Co-authored-by: Luca Critelli <lucacri@gmail.com>
Co-authored-by: Anton Kuligin <anton.kuligin@notraffic.tech>
* Document isolated deletion test fixture boundaries
* Type the shortcut command test input
---------
Co-authored-by: Luca Critelli <lucacri@gmail.com>
Co-authored-by: Anton Kuligin <anton.kuligin@notraffic.tech>
* refactor: finish terminal and Mobile defining-owner imports
* fix: retain completion coordinator type binding
* refactor: consolidate direct terminal tree imports
* refactor(renderer): import typography from defining owners
* fix(terminal): keep remote-viewer clipboard env on command-less creates (#39852)
A paired viewer's plain terminal reaches the host renderer's tab-create
bridge with spawn env (ORCA_REMOTE_VIEWER_CLIPBOARD, PI_CLIPBOARD_OSC52)
but no startup command. The bridge queued pendingStartup only when a
command existed, dropping the env, so the spawned shell never saw the
remote-viewer clipboard marker and copied text stayed on the host
clipboard (#39852).
- Queue the startup whenever the request carries launch material
(env/envToDelete/launchConfig/resume), not only a command.
- PtyPaneStartup.command becomes optional for env-only startups; spawn
options already tolerate a missing command.
- Keep the plain-shell pre-bind input hold for startups that plan no
post-bind work, so an env-only startup types as a plain shell does.
Co-Authored-By: Claude Code <noreply@anthropic.com>
* test(e2e): layout oracle marks only panes the user can see
A hidden tab with a queued startup is laid out at opacity 0 so it spawns at
real geometry. The marker check counted it as visible because it has a size,
then waited for output that the hidden-delivery gate correctly withholds.
Paired-client creates now queue spawn env, so their background tabs hit this.
---------
Co-authored-by: Chen <zwq19980411@gmail.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
* Simplify Settings chrome and organize General into focused views
* Preserve search and skill actions across Settings views
* Correct Settings validation leftovers
* Keep skill conflict details visible in compact Settings rows
* Refresh Settings search and protected copy catalogs
* Use Settings design tokens and button variants
* Keep Settings test setup and translation catalogs current
* Keep Settings search metadata independent of display labels
* Build repository search groups only for the selected pane
* Keep pending skill installs and server menu labels accurate
* Use the supported role locator in the skill regression
* Keep absent skill installation actions on their supported path
* Restore the Settings sidebar to its existing appearance
* Restore shared navigation title keys in pane headings
* Preserve the Settings shell entry animation
* Drop unused Voice labels after the main sync
* Preserve main Voice translations and the moved skill module import
* feat(agent-session): keep the permission mode a Claude session reports
Claude names its live permission mode on prompt, tool and Stop hooks. Keep the
root agent's latest value on the provider session, next to effort, so a resume
without a recorded launch can tell whether the session ran in bypass.
Ports the capture from #36359 by Nelef.
* fix(agent-launch): resume an unrecorded launch bare unless it reported bypass
Without a recorded launch, every restart path now resumes with no settings
Arguments, env or permission default; the configured Command still runs. A
session whose root agent last reported bypassPermissions keeps its bypass flag,
so a hand-typed claude --dangerously-skip-permissions keeps it while a bare
hand-typed claude never gains one (#29898).
Account-switch restart used the shared rule only for Claude; it now uses it
for every agent. Thanks to JustinCMR (#37304) for finding the account-switch
and cold-restore gaps.
* fix(terminal): keep the launch recipe of a window-started agent in main
A window spawn hands main its recipe, but main kept only the token and agent,
so restarts that main runs (workspace sleep capture, closed-worker reopen)
found no recipe and resumed bare. Keep it with the launch authority, the same
gate that admits the token.
* fix(orchestration): reopen a closed worker with the recipe it launched with
A closed worker's pane record goes away with its tab, so orchestration send
reopened it bare (#37693). The worker row now keeps the recipe Orca launched
the agent with, keeps it when a later capture of the same launch arrives
without one (main loses it on a daemon reattach), and a reopen prefers it over
a pane record that may hold another launch of the conversation.
Adapted from #37757 by Pr1p, without a new column.
* fix(terminal): keep a slept pane's earlier recipe only for the same launch
A host sleep capture without a recipe reused the pane's earlier record for the
same conversation. That is right after a daemon reattach, when Orca's launch
still runs but main lost its recipe, and wrong for an agent typed into the
shell that resumed the conversation: it never ran that launch.
* fix(agent-session): restore a paired pane with the recipe its host recorded
A client restoring a pane on a paired host sends only its recorded Arguments,
and the host filled the rest from its current settings. A saved restore now
replays the host's own record for that pane, or, with none at all, resumes
bare and keeps a bypass only when this host's hooks saw it reported. History
and other user-chosen resumes keep current settings.
* fix(terminal): replay a saved note only for the launch main still holds
A note belongs to the agent in a pane only while main holds that launch's
token: main admits it at spawn and retires it when the launch command
finishes, and a daemon reattach restores neither. Worker, host sleep and
hook/quit captures now take a note only from that attested launch, and no
longer copy an earlier record's note by agent or conversation match, which a
typed resume in the same shell also satisfies. With no attested launch the
unrecorded rule applies.
Replaces the inferred orcaLaunched / recipeLostPaneKeys flags and drops the
mock-only reopen and fixture-echo worker tests.
* fix(agent-status): take a pane's note from the launch main attests
The window carried a pane's saved note into each new record by agent and
conversation match, so an agent typed into the shell that resumed the same
conversation inherited an earlier launch's bypass. Main now sends the note of
the launch it still holds with each status, and the window records only that,
its own launch registration, or, for a restored replay of the very status a
record was written from, that record's note. /clear and compact keep the note
because main still holds the same launch.
* fix(orchestration): reopen a worker with its own recipe or none
A worker without its own note took the note of whichever pane record held the
same conversation. Its reopen now always passes a complete recipe: its own
note, or the unrecorded rule. The unrecorded bypass is also scoped to Claude,
whose hooks are the ones that report a root agent's permission mode.
* fix(agent-session): restore a paired pane from its source pane, never current settings
A saved restore on a paired host looked up the destination pane, which a Wake
opens as a new tab, and fell back to the host's current settings whenever the
client sent its partial Arguments. The client now names the source pane (to
hosts advertising agent-session.restore-source-pane.v1), and the host replays
its note for that pane or, with none, resumes bare keeping only a bypass its
own hooks saw there. Older hosts keep today's behavior.
* fix(terminal): re-arm a launch across a main restart while its agent still runs
The daemon outlives main, so it now keeps main's admitted launch (token and
note) and drops it when that launch's command finishes. On reattach main
re-arms the launch only when the same agent still runs in the foreground:
nothing can be typed into a daemon PTY while main is down, so a running agent
there is the one the unretired note launched. A shell foreground clears the
daemon's note; an unknown read, including every Windows read, declines.
Older daemons keep no note, so restore declines there as before.
* fix(terminal): the daemon retires a launch note when its command finishes
A launch can finish while main is down, so main's own retirement never sees it and a
hand-typed agent in that pane would later pass the reattach foreground check.
* fix(agent-status): a fresh Claude start never inherits the last process's permission mode
A hand-typed resume of the same conversation may run without the bypass the previous
process had, so only /clear and compact carry the mode forward.
* fix(agent-session): name a restore's source pane in the host's own keys
A mirrored pane's key carries the desktop tab prefix, so the host's exact lookup missed
its saved note.
* fix(terminal): retire a daemon launch note by its token from the one retirement owner
A delayed reattach result or a late retire could clear a newer launch's note. Retires now
name the token they retire, the reattach checks its PTY before clearing, and re-arming the
same launch keeps the daemon's completion scanner.
* fix(agent-status): only the launch owner's statement changes a pane's note
Main now states the attested note, or null for none, on every hook status. An OSC or
display update makes no statement, so after a completed turn it no longer erases an Orca
launch's note; a typed resume still drops it through main's null.
* fix(terminal): an attach leaves alone a launch main already holds
The renderer attaches a pane the CLI just launched before its agent starts, so the
attach saw the shell and retired the new launch's daemon note.
* fix(agent-status): a paired client keeps a pane's note only on its host owner's word
The host's session-tabs frame now says whether the Orca launch it admitted still runs on
the published incarnation, and the client applies that fact whichever writer wins the
status. With an owner's word the conversation no longer decides; an older host that says
nothing keeps the same-conversation rule.
* refactor(agent-status): one decision picks a pane's note for every reader
The live entry, quit capture, provider-session updates, account restart and cold
restore now ask the same owner-aware decision. An owner's none is final and, when it
turns, ends the pane's registry entry and saved note, locally and from a paired host's
frame. Cold restore and account restart take that answer for a live invocation and read
the saved record only when none is live. Inlines single-use wrappers.
* refactor(agent-status): a paired retirement test reaches the cold-restore command; trim comments
Replaces the projection and continuity tests with one transition: host frame retires the
launch, the next OSC keeps no note, and the cold-restore command has no old bypass.
* fix(agent-status): an owner's none retires the pane's matched launch registry entry
* chore: satisfy changed-code gates (type guards, SAFETY notes, fixed test clock)
* fix(agent-launch): a teams launch keeps its note; a legacy leaf id restores without throwing
* refactor(daemon): keep the session launch note on the process base so session.ts stays in budget
* fix(agent-launch): a restarted terminal main can't vouch for keeps main's earlier launch rule
* fix(agent-launch): read the pane's current terminal; a finished launch settles an undecided pane
* fix(agent-launch): undecided and held launches end with their process
A finished command, a fresh launch or a replacement process settles an undecided pane;
a newer attach or finish supersedes a foreground read still in flight; a legacy relay
reattach without an incarnation stays undecided; a held launch applies only to the
process it was recorded for.
* refactor(terminal): watch and arm a created terminal's launch in one call
Keeps terminal-create.ts within the 300-line budget after main's growth.
* refactor(terminal): keep main's launch evidence in one immutable record
Replace the undecided flag, the reattach check map and the re-arm's writes
to main's orchestration launch fields with one launchEvidence object
(unknown, gone for an incarnation, or held with its recipe), owned by
launch-evidence.ts.
- A fresh admitted launch is held; any other fresh process is gone.
- A finished command or confirmed exit is gone, sticky for its process:
no reattach, legacy or noted, can revive it.
- A replacement retires its predecessor's evidence without deciding the
newcomer, which may still prove its own launch through a reattach.
- A reattach note is held only after a foreground read sees its agent;
the evidence object fences that read.
- A gone launch clears its recipe and blocks both refill sites; a
deliberate sleep snapshot keeps its recipe past the launch it captured.
- launchToken, launchIncarnationId and launchAgent writes match main.
* fix(terminal): keep launch evidence through a first incarnation and sleep snapshots
- Learning a process's first incarnation binds its held or gone evidence
to it, so a later attach can neither revive a finished launch nor drop
a running one; a known X->Y replacement is fenced as before and now also
clears the predecessor's recipe.
- A status from no Orca launch leaves a sleep snapshot of its session for
the wake and never takes that snapshot's recipe into a live or quit
record.
* fix(terminal): record a runtime split's fresh shell as running no launch
* chore: rerun CI on main with the typecheck fix