Commit Graph
3012 Commits
Author SHA1 Message Date
Neil fb2f04aa4e fix(renderer): recover from failed lazy chunk imports instead of crashing (#5803)
Lazy chunk import() rejections (stale/corrupt chunk -> native SyntaxError, e.g. "Unexpected token ']'", re-thrown by React.lazy) now self-heal via lazyWithRetry: retry with backoff, one sessionStorage-guarded reload, then fall through to the error boundary (loop-safe). Adopted at every renderer lazy site. Fixes the recurring terminal.workbench / right-sidebar / page.mobile react-error-boundary crash.
2026-06-19 12:05:16 -07:00
Neil ae77156ab2 feat(worktree): reuse an existing branch when creating a worktree (#5181) (#5781)
* feat(worktree): reuse an existing branch when creating a worktree (#5181)

Adds an explicit "Reuse this branch" checkbox to the new-worktree composer.
When an existing local branch is selected in the smart name field, the
checkbox (default on) checks that branch out instead of creating a new
branch from it — and the choice now survives renaming the worktree folder.

Previously, reusing an existing branch only worked implicitly: it required
keeping the auto-filled worktree name equal to the branch, and editing the
name silently reverted to "create a new branch". There was no discoverable,
durable control — the gap the issue reports.

The fix is renderer-only: picking an existing local branch already sets
baseBranch === branchNameOverride, so the existing backend reuse path
(`git worktree add <path> <branch>`, preserveBranchOnDelete) checks the
branch out correctly across local/SSH/runtime. The checkbox pins that
override via the existing branchNameOverridePreservesNameEdits flag so the
worktree folder can be named independently while the branch is reused;
unchecking creates a fresh branch from the selected ref as base.

- New pure helper resolveComposerBranchReuse (local-vs-remote + default).
- Checkbox hidden for remote-only refs and non-branch sources.
- Tests: pure helper, card render/toggle, and a backend integration test
  proving a renamed folder still reuses the exact branch.

* fix(worktree): refine reuse-branch checkbox (placement, label, eligibility)

Address review feedback on the "Reuse branch" control:

- Move the checkbox directly under the branch (smart) selection instead of the
  Advanced "Name" field — the worktree folder name can legitimately differ from
  the branch, so the choice belongs next to the branch pick and is now visible
  without expanding Advanced.
- Rename the label "Reuse this branch" -> "Reuse branch".
- Make eligibility dynamic: reuse is impossible when the branch is already
  checked out in another worktree (git allows a branch in only one worktree), so
  the checkbox is now hidden in that case (it was already hidden for remote-only
  refs). When a busy branch is picked, the override is no longer pinned to it, so
  creation cleanly falls back to a new branch from that ref as base instead of a
  silently-suffixed branch.

Adds isBranchCheckedOutInWorktrees (pure, unit-tested) and threads the repo's
worktree branch list from the store into the selection logic.

* feat(worktree): animate the reuse-branch row's show/hide

Keep the "Reuse branch" row mounted and collapse it with a grid-rows
transition (same pattern as the Advanced drawer) instead of conditionally
rendering it, so the create-worktree dialog grows and shrinks smoothly when the
option appears/disappears as the selected branch changes. The checkbox is taken
out of the tab order while collapsed.

* refactor(worktree): address review nits on reuse-branch control

From a multi-dimensional review of the branch (all findings low severity):

- Reset reuse state (reuseEligibleBranch, reuseSelectedBranch,
  branchNameOverridePreservesNameEdits) on repo and project switches, matching
  the other reset paths — avoids carrying stale branch-scoped state.
- Disable the reuse checkbox while collapsed so no focusable control lives
  inside the aria-hidden row.
- Extract the busy-branch override decision into a pure resolveComposerReuseOverride
  helper and unit-test it (busy local branch drops the override; remote-only ref
  keeps it) — pins the "no suffixed-branch collision" guarantee.
- Note the worktreesByRepo visibility limitation near the busy-branch check
  (a branch busy only in a hidden external worktree is caught by the backend).
- Strengthen tests: reuse-checkbox toggle in both directions, empty worktree
  list case.
2026-06-19 02:47:05 -07:00
NeilandOrca c7e24059c7 fix(store): bound prRefreshSequences with an LRU cap (#5792)
* fix(store): bound prRefreshSequences with an LRU cap

prRefreshSequences (Record<cacheKey, number>) is keyed by PR cache key
(execution-host/repo/branch). applyGitHubPRRefreshEvent only ever wrote entries
and never removed them, so the map grew monotonically with the number of distinct
(host, repo, branch) tuples observed over a session — branches are ephemeral and
unbounded. The sibling prRefreshStates is pruned on settle, but prRefreshSequences
was not (its retained entries back the out-of-order sequence guard, so delete-on-
settle is unsafe).

Cap it to MAX_CACHE_ENTRIES, evicting the oldest-touched keys; the writer moves
each touched key to the most-recent position so active branches aren't evicted.
An evicted long-idle branch simply restarts sequence comparison from 0.

Regression test fails before the fix (map grows past the cap) and passes after.

Co-authored-by: Orca <help@stably.ai>

* test(store): cover the move-to-end behavior of the prRefreshSequences cap

Review follow-up: the prior tests passed even if the delete-then-set move-to-end
were removed. Add a test that refreshes the oldest key and asserts it survives
capping (evicting the next-oldest instead) — fails without the move-to-end.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-19 02:35:20 -07:00
NeilandOrca a15f6c2ea9 fix(runtime): stop leaking orphaned runtime-client-event subscriptions (#5793)
The runtime-client-events subscription sync had an overwrite-orphan race: a
subscribe is async, so if an environment id is removed from the desired set
while its subscribe promise is in flight (and another live subscription keeps
the generation from bumping), then re-added before the original resolves, the
de-dupe guard sees no live/pending entry and starts a SECOND subscribe. Both
resolve and the second set() overwrote the first's unsubscribe in the map,
leaking the first subscription's preload handle for the renderer's lifetime.

Extract the sync logic from the 5k-line useIpcEvents hook into a unit-testable
createRuntimeClientEventsSync module (previously had zero coverage), and guard
the resolution: if a subscription for the env already exists, unsubscribe the
duplicate instead of overwriting. A deterministic regression test reproduces the
race and fails before the guard (orphan never unsubscribed).

Co-authored-by: Orca <help@stably.ai>
2026-06-19 02:35:17 -07:00
NeilandOrca 30acfc1748 fix(store): evict runtime detected-agent caches when environments are removed (#5791)
* fix(store): evict runtime detected-agent caches when environments are removed

runtimeDetectedAgentIds and isDetectingRuntimeAgents are keyed by runtime
environmentId and gain an entry whenever an environment's tab-bar launch menu
probes for agents. The only removal action (clearRuntimeDetectedAgents) had no
production caller, so removed environments leaked their entries for the renderer
session.

Add a retainRuntimeDetectedAgents(keepIds) action (mirroring the slice's existing
retainRuntimeEnvironmentStatuses) and call it from setRuntimeEnvironments
(optional-chained, since minimal unit-test stores omit the detected-agents slice).
Also guard the in-flight detect resolve so an environment removed mid-detect is
not re-added. Regression test fails before the fix (stale entry retained).

Co-authored-by: Orca <help@stably.ai>

* fix(store): guard the detect .catch() path against re-leaking pruned entries

Review follow-up: the in-flight guard was applied to the detect .then() but not
.catch(). An environment removed mid-detect whose probe then rejects would re-add
its isDetectingRuntimeAgents entry (and clobber a re-added env's spinner). Apply
the same runtimeDetectPromises === pending guard to .catch(), and add in-flight
resolve/reject regression tests (the reject test fails before this fix).

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-19 02:35:14 -07:00
NeilandOrca d855c69fe3 feat(shortcuts): make Select Tab/Workspace 1–9 remappable (#5789)
* feat(shortcuts): make Select Tab/Workspace 1-9 remappable (#5741)

Expose Select Tab 1-9 and Select Workspace 1-9 as single remappable rows in
Settings -> Shortcuts. Previously both chords were hardcoded in
window-shortcut-policy.ts and absent from the Shortcuts UI.

Each is modeled as one ranged action whose stored chord is a representative
(digit canonicalized to 1) that fires for any of 1-9, mirroring the cmux
single-row UX. Defaults reproduce existing behavior (mac: tab Ctrl+1-9,
workspace Cmd+1-9; win/linux: tab Alt+1-9, workspace Ctrl+1-9). Swapping the
two modifiers - the headline use case - works without a false conflict.

Co-authored-by: Orca <help@stably.ai>

* refactor(shortcuts): tighten digit-index review nits

- Canonicalize digit-index overrides in getEffectiveKeybindingsForAction so
  display/conflict detection stay consistent regardless of stored digit.
- Use a shared DIGIT_INDEX_KEY_PATTERN regex instead of string comparison.
- Document that extra modifiers (e.g. Shift) are allowed on digit-index chords
  and that the matcher honors terminal-context gating.
- Clarify the workspace-first precedence comment.
- Add tests: Shift modifier, physical-code fallback matching, both ranges disabled.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-19 02:29:07 -07:00
NeilandOrca 2b37568588 fix(sidebar): tidy Live Ports card header (#5790)
Co-authored-by: Orca <help@stably.ai>
2026-06-19 01:56:59 -07:00
NeilandOrca 2881a6bf02 fix(store): evict PR & commit-message generation records on worktree removal (#5784)
Co-authored-by: Orca <help@stably.ai>
2026-06-19 01:49:57 -07:00
NeilandOrca 76f1f8cfbb fix(store): purge per-file editor and git-huge state on worktree removal (#5782)
Co-authored-by: Orca <help@stably.ai>
2026-06-19 01:49:34 -07:00
Jinjing b5b018cfd1 Add Cmd-J tab session search (#5775)
* Add Cmd-J tab session search

References docs/cmd-j-tab-session-search.md for the design.

* Support searching and activating all editor-family tab types

- Index and search editor, diff, conflict-review, and check-details tabs when their backing files are open.
- Deduplicate tab activation logic to ensure exact unified tab IDs are targeted correctly.
- Update palette placeholder texts and localized labels to use "tab title" and "agent prompt" instead of "page title" and "emulator".
- Localize missing tab error strings in Spanish, Japanese, Korean, and Chinese locales.
- Ensure cross-platform path compatibility in search tests using path.join.
2026-06-19 00:27:05 -07:00
Neil 238476f441 feat(sidebar): preview workspace board on card drag start with trigger cue (#5777) 2026-06-19 00:19:41 -07:00
Jinwoo HongandOrca 692d8d0124 Use platform Orca CLI command for Agent Teams (#5773)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 23:18:33 -07:00
7e6cc9ab49 fix(window): remove double title bar on Linux (#5726)
* fix(window): remove double title bar on Linux

On Linux the BrowserWindow titleBarStyle fell through to undefined, so
the native WM title bar stayed and stacked on top of Orca's own
renderer-drawn titlebar — two title bars. macOS (hiddenInset) and
Windows (hidden) already suppress the native one.

Drop the native frame on Linux (frame: false) and extend the renderer's
Windows-only custom-titlebar branches (logo/menu anchor, app-name
hiding, window-controls spacer + CSS vars, and the WindowControls
min/max/close cluster) to Linux via a shared `hasCustomTitleBar` flag,
so Linux gets one title bar with working window controls — matching the
Windows custom-titlebar path.

Fixes #5724

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

* review: harden Linux custom titlebar gating

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-06-18 23:13:30 -07:00
76317d6484 fix: dismiss stuck browser address bar autocomplete on webview click (#5769)
* fix: dismiss stuck browser address bar autocomplete on webview click

Electron webview guests never dispatch outside pointer events to the
renderer, so the address bar history dropdown could stay open after
clicking the page. Close it on guest focus, window blur, and Escape.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: cover browser address bar dismiss paths

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-06-18 23:00:31 -07:00
Jinwoo HongandOrca 6d6af7af1a Support browser panes on headless remote Orca servers (#5412)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 22:50:11 -07:00
Janderson Fagner e7af3676f2 feat(tray): Windows system tray with minimize-to-tray on close
Adds Windows system tray support and a minimize-to-tray setting for close behavior.
2026-06-18 22:30:44 -07:00
Brennan Benson 4a2dc069d5 Honor system-browser shortcut for port opens (#5756) 2026-06-18 22:23:56 -07:00
Brennan BensonandOrca f1384597f7 Update installed Orca skills without reinstalling (#5755)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 22:23:27 -07:00
slashdevcorpse f80704cc60 [perf] Speed up CLI launch through Orca
Speed up Windows CLI launch by delivering short startup commands through shell args, falling back to stdin for oversized commands, and moving Codex historical session bridging into an incremental background task. Includes review fixes for Windows symlink and WSL test reliability.
2026-06-18 22:21:48 -07:00
Brennan BensonandOrca 8c4e99ed2f Keep completed-agent hibernation pane-scoped (#5749)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 21:37:15 -07:00
Jinwoo HongandOrca fc17631af3 fix: preserve Jira description formatting (#5762)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 21:30:23 -07:00
Goo 4c5c2f4df3 fix(i18n): correct Korean mistranslations and particle spacing (#5761) 2026-06-18 21:26:12 -07:00
Jinwoo HongandOrca bbacb694cd Recognize Claude agents in sidebar (#5758)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 20:25:55 -07:00
Jinwoo HongandOrca e3ca72b2b5 Fix Jira credentials clearing on forbidden task reads (#5757)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 20:22:01 -07:00
b8f2f95100 fix(mobile): sync non-markdown editor files to mobile session tabs (#5582)
* fix(mobile): sync non-markdown editor files to mobile session tabs

A regression stopped non-markdown files opened on desktop from reaching the
mobile session-tab list: the group projection order surfaced markdown tabs but
dropped plain file tabs. Append any open editor file for the worktree that the
projection didn't emit, keyed by relativePath, so plain files show up on mobile
again (markdown still syncs via the projection).

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

* fix(mobile): preserve recovered editor session tab identity

Co-authored-by: Orca <help@stably.ai>

* fix(mobile): tolerate legacy active tab metadata

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-06-18 18:34:14 -07:00
Trevin ChowandJinjing 18bdef9ed0 refactor(sidebar): show more of repo, workspace, and group names (#4761)
* refactor(sidebar): give repo and group names priority over header chrome

Repo and group headers no longer show the workspace-count badge or the
collapse chevron, and the trailing action buttons (project menu, add
workspace) now collapse to zero width until the row is hovered, focused,
or its menu is open. The name takes the full row width by default and
only truncates once the actions reveal.

The count was secondary and the chevron was redundant -- the whole
header is already clickable to expand/collapse -- so both were spending
horizontal space better given to the name. The now-unused count field
and its subtree-counting logic are removed from the header row model.

* refactor(sidebar): drop the rename-pending badge from workspace rows

With auto-rename on, every freshly created workspace carried a "rename
pending" badge beside its name until the first agent message landed.
It was persistent clutter on the element we most want legible -- the
workspace name -- so remove it and the no-longer-needed handler.

* Remove unrelated formatting from PR 4761 merge

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-06-18 18:06:58 -07:00
Brennan BensonandOrca 445a389d77 Fix folder PR checks row icons (#5744)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 17:54:42 -07:00
Jinjing 0659ba0aa8 Prevent stale branch compare results on Git HEAD updates (#5663)
* Prevent stale branch compare results on Git HEAD updates

Track the status HEAD for each worktree to prevent race conditions
where a background branch compare request finishes after Git HEAD has
moved. Stale compare results are now rejected, and the compare state
is invalidated on status HEAD changes to avoid rendering incorrect
diffs. Also allows preserving the prior summary during refresh
requests to reduce UI flicker.

* Match '(initial)' status head with null branch compare head OID

Map the '(initial)' HEAD reported by git status for unborn branches
to a null head OID in branch compare results. This prevents false
mismatch positives during validation and state transitions, ensuring
unborn branch comparisons are accepted and stale ones are correctly
rejected.

* memoize hostedReview in SourceControl and extract support search

- Wrap the hostedReview calculation in useMemo in SourceControl to avoid redundant object recreation and re-renders.
- Move the general support search entries to their own dedicated file for improved code organization.
2026-06-18 17:40:01 -07:00
Carlos Baraza d46349ce82 fix: improve mobile link modifier handling (#5597) 2026-06-18 16:48:43 -07:00
Brennan Benson a34801934d Keep automation off by default in compact workspace cards (#5740) 2026-06-18 16:28:37 -07:00
Brennan Benson 53f2e50122 Keep linked workspace prompts as editable drafts (#5734) 2026-06-18 16:24:22 -07:00
Brennan Benson fe8b60b11c Show branch cues in experimental worktree cards (#5737) 2026-06-18 16:17:28 -07:00
Brennan Benson 1652f8ede1 Create PR worktrees from the PR head (#5733) 2026-06-18 13:59:00 -07:00
Brennan BensonandOrca 674639205c Show and Filter Automation-Created Workspaces (#5697)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 13:05:57 -07:00
Jinwoo Hong 281edba14a Fix premature project header truncation 2026-06-18 12:49:27 -07:00
1c603669c1 Send review notes to any running agent of a worktree (#5654)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: brennanb2025 <brennankbenson@gmail.com>
2026-06-18 12:42:27 -07:00
Jinwoo HongandOrca 93345e331b Fix workspace sidebar appearance setting (#5725)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 12:10:27 -07:00
99bc04609d Highlight the open file in the Source Control sidebar (#5667)
* Highlight the open file in the Source Control sidebar

Pending (uncommitted) rows had no persistent indicator for the file
currently open in the editor: a plain single click cleared the bulk
selection and only opened the diff, leaving no visual cue for which row
was active.

Derive the active editor file for the worktree from the store and mark
its Source Control row as the current row (full bg-accent + data-current),
outranking the lighter bulk-selection tint. Matching is area-aware so a
partially staged file lights up only the row that is actually open, and
the highlight clears when the visible tab is not an editor.

Extract the row-key mapping into source-control-active-open-file-keys.ts
and cover it with unit tests plus render tests for the highlight wiring.

* Update src/renderer/src/components/right-sidebar/SourceControl.open-file-highlight.test.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Refine source control open-file highlighting

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: brennanb2025 <brennankbenson@gmail.com>
2026-06-18 12:10:26 -07:00
Brennan Benson 20079a98ed Fix premature Codex completion notifications (#5682) 2026-06-18 11:51:46 -07:00
Brennan BensonandOrca bc0b1e28bd Improve Codex startup prompt reliability (#5686)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 11:39:40 -07:00
Brennan BensonandOrca 3ce1a269ab Keep hibernated agent completions visible (#5689)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 11:36:49 -07:00
Jinwoo HongandOrca b7d146dcb2 Move Prompt Cache Timer setting to Agents pane, simplify expired state (#5691)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 10:25:26 -07:00
Jinjing 4ca248383b Skip GitHub CLI preflight checks if no GitHub projects exist 2026-06-18 08:51:08 -07:00
Doan Bac Tam fd536d3e48 fix: restore font family keyboard navigation in settings 2026-06-18 08:36:49 -07:00
Jinwoo HongandOrca e22d2c2c26 fix(landing): make GitHub CLI setup nudge dismissible and provider-aware (#5688)
The empty-workspace landing screen showed an alarming "Missing
dependencies — GitHub CLI is not installed" banner even for users
whose registered projects are all GitLab-backed, where `gh` is never
used. `gh` only powers GitHub PRs/issues/checks, so this is a false
alarm for GitLab-only users (#5670).

Treat the GitHub CLI prompt as a soft, provider-scoped setup nudge
rather than a global missing-dependency error:

- Quiet the banner styling (muted surface, no amber frame) and cap its
  width so it reads as a soft nudge, not an error state.
- Add a persistent dismiss to the gh / gh-auth nudges. Git stays pinned
  as a hard global dependency.
- Dismissal snapshots the set of GitHub-backed project identity keys;
  the nudge re-surfaces only when a genuinely new GitHub-backed project
  is added (set-based, so remove+re-add of the same project doesn't
  retrigger, and GitLab/folder repos never do).

Adds isGitHubBackedRepo() to the host-setup projection (reusing the
existing GitHub-identity detection) plus unit tests for both the
predicate and the dismissal logic.

Co-authored-by: Orca <help@stably.ai>
2026-06-18 01:00:23 -07:00
Brennan BensonandOrca 048fc8c37a Fix nested workspace card indentation (#5684)
Co-authored-by: Orca <help@stably.ai>
2026-06-18 00:16:16 -07:00
Brennan Benson e7ef7681ae Fix flaky e2e tests (#5680) 2026-06-18 00:11:32 -07:00
Neil e179348fcc Replace plus icon with play button on quick command entry (#5674) 2026-06-17 23:58:01 -07:00
huqi 62fc723ea8 Remove spam prefix from zh locale (#5677) 2026-06-17 22:28:39 -07:00
Brennan BensonandOrca fd9e79a77a Celebrate onboarding and agent wins with GitHub star prompts (#5642)
Co-authored-by: Orca <help@stably.ai>
2026-06-17 22:21:32 -07:00