Commit Graph
6493 Commits
Author SHA1 Message Date
Neil 6964f75cd0 refactor(renderer): share metadata list request lifecycle (#13524) 2026-08-10 20:40:26 -07:00
Neil 8c53e9e1b6 Share usage recent-session table (#13467) 2026-08-10 20:40:23 -07:00
Neil ef19809778 refactor(renderer): share usage provider slice lifecycle (#13527) 2026-08-10 20:39:51 -07:00
Neil fc9fd7208d refactor usage provider IPC plumbing (#13543) 2026-08-10 20:39:18 -07:00
Jinwoo Hong 665e0ead83 Fix repo-scoped Quick Commands across remote hosts (#13727) 2026-08-10 20:38:40 -07:00
Neil 65e2b5b598 refactor(usage): share provider store lifecycle (#13558) 2026-08-10 20:38:31 -07:00
Neil f9f8d7a8bf refactor(relay): remove obsolete status parser (#13475) 2026-08-10 20:25:48 -07:00
Neil bb6f0c1cb5 refactor(renderer): remove superseded GitHub background create (#13479) 2026-08-10 20:25:45 -07:00
Neil 34f46398d7 refactor(daemon): remove superseded PTY provider (#13477) 2026-08-10 20:25:43 -07:00
Neil f805189bff refactor(automations): remove unused Hermes output limits (#13497) 2026-08-10 20:25:39 -07:00
Neil 3203b0c405 refactor(onboarding): remove retired tour outcome tracker (#13498) 2026-08-10 20:25:36 -07:00
Neil 573eace89f refactor(persistence): remove unwired state bounds (#13499) 2026-08-10 20:25:33 -07:00
Neil d19f511786 refactor(reviews): remove retired queue foundation (#13500) 2026-08-10 20:25:30 -07:00
Neil ee8b9b2cc9 refactor(profiles): remove retired switcher UI (#13502) 2026-08-10 20:25:27 -07:00
Neil 01102536c6 refactor(daemon): remove obsolete production launcher (#13504) 2026-08-10 20:25:24 -07:00
Neil aa5e275026 refactor(sidebar): remove retired activity helpers (#13505) 2026-08-10 20:25:20 -07:00
Neil 1979f5a3e3 refactor(linear): remove replaced team combobox (#13506) 2026-08-10 20:25:16 -07:00
Neil 9359edc2b0 refactor(workspaces): remove replaced host combobox (#13507) 2026-08-10 20:25:13 -07:00
Neil 837ea3feec refactor(onboarding): remove retired capability checklist (#13509) 2026-08-10 20:25:09 -07:00
Neil d5c5322442 refactor(computer): remove orphaned helpers (#13511) 2026-08-10 20:25:06 -07:00
Neil a276e54e62 refactor(relay): remove unwired PTY replay index (#13518) 2026-08-10 20:25:03 -07:00
Neil a45adcfff0 refactor(emulator): remove unwired scrcpy control encoders (#13528) 2026-08-10 20:25:00 -07:00
Neil fb39308dfe refactor(daemon): remove abandoned binary framing (#13530) 2026-08-10 20:24:56 -07:00
Brennan Benson 3e3f48fe89 fix(native-chat): restore Codex model picker dispatch (#13669)
* fix(native-chat): restore Codex model picker dispatch

* fix(native-chat): type Codex effort picker command
2026-08-10 20:03:48 -07:00
OrcaWin 8c975b9d15 fix(terminal): avoid Windows PATH registry subprocesses (#13485) 2026-08-10 19:55:29 -07:00
Jinwoo Hong c7850eb59c fix(terminals): prevent retired workers from cold-resuming (#13708) 2026-08-10 19:49:34 -07:00
Brennan Benson c065a2d7e1 Preserve AskUserQuestion waits during parallel tool completions (#13714)
* fix(agent-hooks): preserve parallel question waits

* fix(agent-hooks): preserve child question waits
2026-08-10 19:23:40 -07:00
Brennan Benson 2f26e61647 fix(dashboard): keep agent map rings open while the pointer works inside them (#13682)
* fix(dashboard): keep agent map rings open while the pointer works inside them

The project and workspace rings drove their hover styling from `:hover` on the
ring element itself. A ring is a sibling of everything drawn inside it, so the
style dropped the moment the pointer crossed onto a workspace or an agent, and
a pan drag killed it outright — pointer capture retargets `:hover` to the
`<svg>` for the whole gesture. Both read as the ring pulsing open and shut.

Move the trigger to the containing group, wrapped in `:where()` so the existing
`.is-open` / `.is-selected` / status rules keep winning the same properties, and
add `.is-held` for the pan, driven by which rings the press landed in. The hold
releases on the first move after the button comes up, when the browser
recomputes `:hover` in that same event, so the two signals never both read off.

Hovering a workspace now also always shows its name and agent count. That label
was gated behind the declutter pass, which suppresses any label overlapping an
agent — at fleet zoom that is nearly all of them, so hover revealed nothing. It
now bypasses declutter and draws in a layer above every project, so a
neighbouring ring cannot wash it out.

* fix(dashboard): complete agent map ring interaction lifecycle
2026-08-10 19:04:50 -07:00
Neil 600b0b1c15 refactor(renderer): split WorktreeCard (#13715) 2026-08-10 18:45:11 -07:00
Jinwoo Hong 550eabe921 feat(workspaces): review preserved branches after bulk delete (#13693) 2026-08-10 18:37:45 -07:00
Neil b015b16436 perf(native-chat): stop abandoned tail reads (#13588) 2026-08-10 18:32:26 -07:00
Neil f3f654cd1f perf(renderer): collapse terminal host selectors (#13643) 2026-08-10 18:32:19 -07:00
Neil 5cd7b0a904 perf(renderer): keep shutdown rollback buffering linear (#13510) 2026-08-10 18:32:12 -07:00
Neil fc7387b28b perf(runtime): index PTY worktree inventory lookups (#13690) 2026-08-10 18:32:04 -07:00
Neil 1874ac325b perf(renderer): own oversized automation output tails (#13581) 2026-08-10 18:31:57 -07:00
Brennan Benson f2984e2230 fix(terminal): skip a too-wide alt frame on snapshot replay (#13014)
* fix(terminal): skip a too-wide alt frame on snapshot replay

Reopening a parked worktree could paint a stale full-width TUI frame
through a narrower viewport, leaving clipped gutter fragments and
mid-word omissions until the live application repainted.

Replay pins xterm to the snapshot grid so soft-wrapped normal-buffer
history stays exact (#7279), then the post-replay fit returns the pane
to its container grid. Alternate buffers have no scrollback and do not
reflow; an absolutely positioned frame remains at its capture layout,
so narrowing exposes only clipped portions of those fixed-grid rows.

Skip only the visual frame when its capture is wider than the grid the
fit will land on. The alt buffer is still entered and cleared, so the
resize signal lands on a clean screen that the live application can
repaint. Equal-width and wider restores retain the frame, while normal
history always replays at its capture grid before fitting.

The target width comes from proposeDimensions, not terminal.cols: an
unfitted pane can still read xterm's default grid even when its actual
container matches the capture.

* fix(terminal): preserve offline SSH prepaint frame

* fix(terminal): drop a too-wide daemon alt frame on reattach

The renderer-only gate did not run on the user-visible remount path.
Instrumentation showed that daemon-connectResult-snapshot won before
the model-snapshot branches, so the composed snapshot painted in full
and the later narrower fit exposed its stale fixed-grid frame clipped
at the new viewport.

The daemon branch could not omit only the visual frame while main sent
one merged string. Publish the normal-buffer/mode prefix and visual alt
frame as additive optional metadata while retaining the merged snapshot
for mixed-version fallback. New renderers can keep history and restore
state without painting a frame captured for a wider grid.

Replay ordering remains capture-grid, write, then fit so normal-buffer
soft wrapping stays exact. The application owns the foreign-width alt
frame and repaints it after the resize signal rather than Orca trying to
transform an absolutely positioned screen.

* fix(terminal): preserve split daemon snapshot payload

* fix(terminal): preserve live state when dropping alt frame

* fix(terminal): restore DECOM cursor state exactly

* fix(terminal): preserve ordinary snapshot bytes

* test(terminal): cover fixed-grid alt replay resize

* fix(terminal): repaint after dropping mismatched frames

A hidden snapshot can omit an alternate-screen frame before the pane has a measurable target grid. If reveal later lands on the capture grid, a same-size PTY resize emits no SIGWINCH, so pulse the local PTY size whenever that frame was skipped.\n\nKeep performSafeFit's measurable-pane contract intact, publish daemon snapshot prefix and frame as explicit optional strings, and fall back to the merged payload when either field is absent. Cold owner-gone restores now omit a mismatched frame while retaining history and fresh-shell reset treatment; offline SSH preconnect remains unchanged.\n\nPin the vendored SerializeAddon out-of-range-row behavior used to capture live SGR state.
2026-08-10 18:24:04 -07:00
NeilandBrennan Benson 868bfbe8ce fix(terminal): release retained output slice parents (#13402)
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-08-10 18:19:10 -07:00
Jinjing 20848169e0 Improve automations page UI: full-page detail and table redesign (#13292)
* improve automations page ui

* Improve automations page UI: fix menu interactions, extract components,

- Extract status cell to reusable component
- Fix portaled context menu clicks re-selecting rows
- Use explicit selection IDs instead of resolved objects for reliable detail state
- Close detail when selection is lost during refresh or deletion
- Improve escape key navigation through nested detail views
- Use native input for search field to avoid unwanted shadow elevation
- Add i18n keys for table and button labels

* fix: merge duplicate type imports in AutomationListLocalRows test

Static analysis fails under --deny-warnings when the same module is
imported twice; combine the Automation and external types into one import.

* Fix row keyboard activation to not intercept nested controls

Row handlers for Enter/Space were preventing the actions menu button from
opening when activated via keyboard. Extract a reusable check that only
treats these keys as row activation when they originate on the row itself,
not on child controls. Also consolidate the search input to use the shared
Input component for consistency.

* fix: use stable keys for automations page skeleton rows

React Doctor no-array-index-as-key failed static analysis on the
loading skeleton map. Give each static row an id for the React key.

* Reorganize i18n keys for automation components

Move translation keys to their proper component namespaces (rowActions to AutomationListLocalRows, normalize loading key), update all locale files.

* fix: move automations detail selection refs out of render

React Doctor fails CI when refs are mutated during render. Sync
selectedExternalKey and isDetailOpen into refs in effects instead.

* style: soften automation search field focus state

- Reduce focus ring opacity to 70% for a subtler focus indicator
- Set focus-visible:ring-0 to eliminate elevation effect
- Add dark:bg-background for consistent dark mode appearance
2026-08-10 17:37:49 -07:00
Neil 090678a32b [Perf-SS] Keep reattach live queues linear during replay (#13478) 2026-08-10 17:33:46 -07:00
Neil 2ade803522 [Perf-SS] Remove redundant native Ripgrep probes (#13462) 2026-08-10 17:25:26 -07:00
Brennan Benson 2ee43bfc0d fix(agent-hooks): refresh existing Orca launchers when agent CLIs are unavailable (#13378)
* fix(agent-hooks): refresh existing shared hook scripts when the CLI is no longer detected

A CLI that falls off PATH (moved npm prefix, relocated shim) keeps its user-wide
config invoking Orca's launcher script under ~/.orca/agent-hooks, but the
presence gate skips install() with no removal — freezing the script at whatever
Orca generated last. Anyone in that state kept the pre-#11568 more.com-leaking
.cmd forever, because no launcher script is ever deleted and Windows startup
deliberately skips shell PATH hydration.

Reconcile before gating: every existing shared launcher/statusline script is
rewritten to the current template on each install pass. Creating scripts stays
behind the presence gate — an existing file is proof of a prior install; a
missing one means the gate did its job. Amp and Hermes are deliberately absent:
they write provider-native plugin code with its own install lifecycle, not
shared launchers.

- refreshManagedScriptIfPresent() in installer-utils (no-op unless the file exists)
- refreshManagedScripts() on the 11 launcher-writing services (openclaude via
  the shared Claude class)
- reconcile pass in installManagedAgentHooks before presence detection,
  filtered by the agents option, best-effort per agent
- coverage gate: a launcher written to ~/.orca/agent-hooks without a matching
  refresher entry fails the suite, in both directions

* perf(agent-hooks): refresh launchers off the main thread

* test(agent-hooks): keep refresh mode assertion POSIX-only
2026-08-10 16:34:15 -07:00
Brennan Benson a70291a918 perf(orchestration): index mutation receipt capacity (#13647) 2026-08-10 16:17:52 -07:00
bokjkandBrennan Benson 1b02cedfff fix(tabs): keep widths stable during title updates (#11476)
* fix(tabs): keep widths stable during title updates

* review(tabs): reduce the width rule to the definite width and harden its tests

Why: once the tab container has a definite width the shrink-wrapped strip never
has free space, so flex-grow and max-w-[280px] were unreachable and only
duplicated the 180/220 numbers across two properties. Measured widths, strip
scrollWidth and clientWidth are identical to the flex-based version across four
window widths, five tab counts and short/long titles.

Tests: pin the width classes literally so the guarantee cannot be edited away
via the constant, and guard the e2e check against passing vacuously on a
saturated strip.

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-08-10 16:11:19 -07:00
Brennan Benson 6b9852af2b perf(terminal): remove output-driven WebGL atlas resets (#13657)
* perf(terminal): stop clearing glyph atlas on output

* test(terminal): gate output atlas reset removal

* test(terminal): harden atlas recovery gates
2026-08-10 16:10:47 -07:00
Brennan Benson 03e740fa50 Fix notification clicks with Agent Dashboard pop-out (#13680)
* fix(notifications): route clicks to main window

* fix(notifications): reveal hidden main window on click
2026-08-10 16:05:48 -07:00
Brennan Benson 8da362919e perf(runtime): batch legacy worker recovery persistence (#13649)
* perf(runtime): batch legacy recovery persistence

* fix(runtime): preserve concurrent recovery state

* fix(runtime): require durable recovery retry
2026-08-10 15:58:17 -07:00
Brennan Benson d50adec2d2 feat(ai-vault): isolate scanning from terminal workloads (#13411)
* feat(ai-vault): isolate scanning in service processes

* fix(ai-vault): retire idle service processes

* fix(ai-vault): discard unverified cache processes

* fix(ai-vault): clear relay sidecar cancel watchdog on acknowledgement

A cancelled relay call is settled before its 2s cancel watchdog is armed, so the acknowledgement path bailed out of settle() before clearing the timer. The watchdog then faulted a healthy sidecar two seconds after every aborted scan, killing whatever request had since become active.

* fix(ai-vault): clear the pending restart before scheduling another

recordFault overwrote this.timer, stranding a restart that dispose() could no longer cancel.

* refactor(ai-vault): drop the orphaned first-prompt IPC wrapper

session-first-user-prompt-handler.ts now owns this entry point and routes through the service; the copy left in the read module had no callers.

* fix(ai-vault): retry a faulted cold start before surfacing it

A slow first start surfaced a raw 'did not become ready' error to the caller even though the supervisor was already respawning. Requeue an unsent call once onto the scheduled respawn instead.

Also stop arming the cancellation watchdog for a call the child never received: no acknowledgement is coming, so it killed a healthy service and stalled the lane.

Invalidation bookkeeping and ready-waiter construction move to the state module to stay under the max-lines cap.

* fix(ai-vault): give relay title reads their own lane

Before this branch the relay read title files directly, concurrently with scans. Routing both through one sidecar lane put title resolution behind a list scan that may run up to 130s, so SSH tab titles could lag minutes behind.

Split cache and interactive lanes in both the relay client and the sidecar entry, mirroring the desktop service.

Also: clear the ready deadline on fault, so a sidecar that dies before ready cannot fault its healthy replacement five seconds later; retry an unsent call once across a respawn; and skip the cancellation watchdog for a call the sidecar never received.

Restart/circuit bookkeeping moves to its own module, mirroring the desktop policy, to stay under the max-lines cap.

* fix(ai-vault): degrade relay title resolution on sidecar failure

listSessions already returns a host issue when the sidecar is unavailable; titles propagated the raw RPC error instead. Return no titles so callers fall back to preview text, and keep cancellation propagating.

* fix(ai-vault): scrub the service child environment

The children are forked with a 384 MiB heap cap and no loader, but both
spawn sites handed them the full parent environment, so an exported
NODE_OPTIONS silently raised the cap or --require'd code into them.

Allowlist both, following the plugin worker. The desktop child keeps the
eleven agent-root overrides it resolves its own roots from; the relay
sidecar takes remoteHome and hostPlatform from its init message and so
needs none of them. Both children share one priority module while they
share this one.

* fix(ai-vault): soft-disable relay vault when the service is missing

A missing service threw out of the constructor, so a Vault wiring bug
would abort relay startup and take every PTY on the host with it. The
unsupported-platform branch three lines above already treats a Vault
failure as a soft disable; do the same here.

Threading the service through the two handlers instead of a field also
retires the definite-assignment assertion the throw was propping up.

* fix(ai-vault): drain consumed cache invalidations

invalidatedPaths was re-applied in every request's finally and never
drained, so once N paths had been invalidated every later request paid N
evictions for the life of the process; the 4096 cap only bounded how bad
that got.

The re-apply exists to cover a read that overlapped the invalidation, so
drain once nothing is executing. Clearing unconditionally would drop the
re-apply for a request still running on the other lane.

* fix(ai-vault): keep a busy child through slow invalidation acks

invalidate() reused the 5s ready budget as its acknowledgement deadline
and killed the child on expiry, so a delete issued during a large scan
could kill a healthy process mid-scan and burn a slot toward the restart
circuit.

Fault only when nothing is executing. Fork IPC ordering already puts the
invalidation ahead of any later request, so a busy child owes no ack
here, and the 130s/15s request deadlines still catch a wedged one.

The start-retry predicate moves to the state module to stay under the
line cap, matching the shape the relay client already uses.

* fix(ai-vault): report a failed local scan as a host issue

A local-scope scan let its error escape to the renderer, which paints it
over the session list. Service supervision now produces those errors, so
"AI Vault service restart circuit is open." replaced the list.

Route local scope through the degradation the all-hosts leg and every SSH
leg already use, so it lands as a retryable host issue row instead. Same
result shape either way, so no IPC or wire contract changes.

* test(ai-vault): cover the relay restart circuit transitions

The relay policy shipped without tests. Pin both circuit edges, the
aging-out case, the forced-refresh reopen the relay has and the desktop
does not, and the backoff schedule.

* fix(ai-vault): keep the OpenCode roots in the service child env

The scrubbed allowlist dropped XDG_DATA_HOME and OPENCODE_DB, which the child
reads to locate the OpenCode store and database. The pre-PR worker thread
inherited them, so a user who sets either lost every OpenCode session.

* test(ai-vault): anchor the service spawn env assertion
2026-08-10 15:52:59 -07:00
Brennan Benson fb80f91921 Clear stale terminal selection during pane recovery (#13677)
* fix(terminal): forward copy to TUI selections

* fix(terminal): narrow recovery selection cleanup
2026-08-10 15:52:25 -07:00
Brennan Benson 84bd306949 perf: Stop unchanged worktree refresh churn (#13662)
* fix: stop unchanged worktree refresh churn

* fix: preserve smart sort telemetry recomputations

* fix: preserve duplicate worktree host identities

* perf: skip reconciled catalog traversal

* test: strengthen worktree refresh regressions
2026-08-10 15:44:05 -07:00
makoto-developerandBrennan Benson 0b5c5d6e74 fix(i18n): restore identifiers and commands machine translation localized in ko/zh/es (#13124)
* fix(i18n): restore identifiers and commands machine translation localized

39 values in ko, zh and es are code rather than copy — shell commands, CSS
class strings, git-style identifiers, sample filenames and hostnames — and had
been machine-translated. pnpm install read pnpm 설치, text-foreground read
文本前景, pr-view read PR视图, and localhost:3000 read 本地主机:3000.

pnpm install is the font-mono placeholder of the setup-script input, and
gh auth login / glab auth login are the commands the integration panes tell the
user to run, so the translated forms are shown to users as text to type.

Catalog-only. Running repair-locale-catalog.mjs over these locales fixes the
same values but rewrites several hundred unrelated ones, because the catalogs
are stale against the current policy.

* fix(i18n): restore the zh code strings found by call-site context

@smwbev scanned by where a translate() renders — inside <code> or a font-mono
element — rather than by value shape, and found nine more in zh: upstream read
上游 in the base-ref picker, nbformat read nb格式, orca.yaml read Orca.yaml,
LIN-329 read 林-329, GH #1799 lost its space, and orca · zsh read Orca·zsh.

The matching NEVER_TRANSLATE_VALUES entries landed with #12934.

* test(i18n): guard restored technical literals

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-08-10 15:43:36 -07:00