Commit Graph
1428 Commits
Author SHA1 Message Date
7edcdca699 feat: hide default branch workspace (#1249)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
2026-05-03 15:55:43 -07:00
Jinwoo HongandOrca 66d596fe11 fix: zombie worktree PTY cleanup (issue #218) (#1376)
* fix(runtime): kill all PTYs for a worktree on removal (design §4.3)

Worktree deletion only shut down renderer-tracked terminals, so PTYs owned
by background tabs, split panes, or pre-reload sessions survived the
removal and kept leaking memory. Introduce killAllProcessesForWorktree
with three sweeps (runtime leaves, provider-prefix scan of daemon session
ids, pty-registry by worktreeId) and wire it into both teardown paths:
the CLI-initiated removeManagedWorktree and the renderer-initiated
worktrees:remove IPC handler. OrcaRuntimeService gets a lazy
getLocalProvider thunk so construction order stays robust.

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

* fix(renderer): purge worktree-scoped state on removal + hydration (design §4.4)

When a worktree is deleted, ~25 worktree-scoped maps (tabsByWorktree,
git caches, browser state, split-tab models, per-file editor drafts,
etc.) kept references to the gone worktree, so SessionsStatusSegment
kept mis-classifying orphaned PTYs as bound and dropdowns rendered stale
ids. Add purgeWorktreeTerminalState as a single atomic action that
wipes every scoped map plus cascades top-level actives. Fire it from
the worktrees:changed listener on the set-diff of removed ids, and once
more at hydration via fetchAllWorktrees to clean up persisted entries
from pre-fix sessions. The hydration-time purge is gated behind a
per-repo success check: a single transient IPC error or an all-empty
fetch defers the purge so a degraded launch cannot wipe legitimate
persisted state.

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

* test(zombie-worktree): regression coverage for design §4.5

Adds tests for every layer of the zombie-worktree fix:
- worktree-teardown: unit coverage of the three-sweep helper including
  best-effort error swallowing across provider/registry.
- orca-runtime: RPC-initiated removeManagedWorktree kills PTYs before
  any git mutation + verifies the lazy getLocalProvider thunk resolves
  on each call.
- worktrees IPC: renderer-initiated remove kills PTYs before git and
  skips the kill helper for SSH-backed repos.
- renderer slice: fetchAllWorktrees defers the purge when any sibling
  repo fetch fails or every repo returns empty (F1 regression);
  happy-path fires the purge once and does not re-run on subsequent
  calls. Direct purgeWorktreeTerminalState coverage pins the cascade
  across worktree-keyed, tab-id-keyed, and file-id-keyed maps.

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

* fix(runtime): log worktree-teardown kill counts (design §4.4 observability)

Breadcrumb lets ops distinguish a renderer-state-induced leak (diff-path
purge non-empty) from a backend-induced one (nothing to kill but memory
still pinned). Emit only when the sweep actually shut anything down so
steady-state logs stay quiet. Added at both call sites —
removeManagedWorktree (CLI path) and the worktrees:remove IPC handler.

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

* test(zombie-worktree): fix ptyIdsByTabId seed shape to match production type

The purge unit test seeded ptyIdsByTabId as Record<string, string> when
the runtime type is Record<string, string[]>. The unit tests passed
because they never hit the UI renderer, but live e2e surfaced a
TypeError: (ptyIdsByTabId[tabId] ?? []).some is not a function.

Corrected to arrays; 21/21 tests still pass.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-03 15:54:45 -07:00
github-actions[bot] 943f64a906 release: v1.3.33-rc.1 [rc-slot:2026-05-03-15] v1.3.33-rc.1 2026-05-03 22:17:47 +00:00
JinjingandOrca 4bf0c31c9c fix(sidebar): restore agent identity icon in inline worktree rows (#1377)
Partially reverts #1359: drop the hideIdentityIcon flag on the inline
agent list so the Claude/Gemini/… glyph renders again. The expand
chevron stays hidden — clicking the row still jumps straight to the
agent, and the chevron was the redundant part. Identity is useful when
a worktree has more than one agent of different types.

Co-authored-by: Orca <help@stably.ai>
2026-05-03 15:10:58 -07:00
Brennan BensonandOrca d0e3a64768 feat(telemetry): PR 1 — foundations (types, consent, migration, PRIVACY.md) (#1372)
Co-authored-by: Orca <help@stably.ai>
2026-05-03 13:13:26 -07:00
github-actions[bot] fcdd88964e release: v1.3.33-rc.0 [rc-slot:2026-05-03-03] v1.3.33-rc.0 2026-05-03 10:25:07 +00:00
Jinwoo HongandOrca a638215729 fix(pty): release ptmx fd on natural exit + defuse SIGHUP-to-recycled-pid (#1327)
* fix(pty): release ptmx fd on natural exit + defuse SIGHUP-to-recycled-pid

Daemons accumulated ptmx fds over time because node-pty's UnixTerminal
only releases the master fd when destroy() runs. On the natural-exit
path (the common case — user closes a tab, shell runs `exit`) nothing
ever calls destroy(), so the fd leaks until GC. On macOS this
eventually hits kern.tty.ptmx_max=511 and all new terminals fail to
spawn.

Fix: release the fd synchronously on every teardown path (natural
exit, explicit kill, stale SSH spawn, daemon shutdown) and close the
concurrent SIGHUP-to-recycled-pid hazard inside node-pty's
UnixTerminal.destroy().

- src/main/daemon/pty-subprocess.ts: synchronous POSIX proc.kill
  neutralization inside proc.onExit; dead guards on forceKill/signal
  so they never target a reaped-and-possibly-recycled pid
- src/main/daemon/session.ts: new disposeSubprocess() for already-
  exited sessions (fd release only, no SIGKILL) — avoids sending
  SIGKILL to a recycled pid during daemon shutdown
- src/main/daemon/terminal-host.ts: dispose loop routes on isAlive —
  live sessions get forceKillAndDisposeSubprocess (SIGKILL + fd
  release), exited sessions get disposeSubprocess (fd release only)
- src/main/providers/local-pty-provider.ts: same POSIX kill
  neutralization at top of onExit for the legacy local path
- src/relay/pty-handler.ts: same neutralization in wireAndStore;
  disposed flag guards all public entry points; dispose() uses
  SIGKILL (not SIGTERM) before destroy since the relay is exiting;
  killTimer fallback + immediate-shutdown + stale-spawn cleanup all
  call disposeManagedPty + ptys.delete so wedged children (D-state,
  bad NFS) can't leak map entries against the 50-PTY cap

Windows is exempt everywhere — WindowsTerminal.destroy IS a kill()
call internally (closes the ConPTY agent), so neutralizing would
turn destroy into a no-op and leak the agent.

See docs/fix-pty-fd-leak.md for the full design.

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

* fix(pty): patch node-pty native off-by-one leaking /dev/ptmx per spawn

node-pty 1.1.0's pty_posix_spawn on macOS walks low_fds[0..2] in an
allocation loop that breaks at the first fd >= STDERR_FILENO, then
cleans up via `for (; count > 0; count--) close(low_fds[count])`. In
the typical case (break at count=0) the cleanup body never runs and
low_fds[0] — a /dev/ptmx handle — leaks per spawn. Fixed upstream in
microsoft/node-pty af053f2 (PR #882), not in any 1.1.0 release.

Backport the 3-line cleanup-loop fix as a pnpm patch. E2E validated
against a dev daemon: 200 spawn/kill cycles kept the daemon's ptmx
fd count flat at baseline; prior runs reproduced linear 1-per-spawn
growth. Also documents the native root cause as a status addendum in
docs/fix-pty-fd-leak.md — the JS-side destroy() discipline previously
landed is still load-bearing for the SIGHUP-to-recycled-pid hazard and
for synchronous fd release on daemon shutdown.

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

* fix(pty): capture stable kill spy ref in pty.test.ts

destroyPtyProcess reassigns proc.kill = () => {} on POSIX to defuse
the SIGHUP-to-recycled-pid hazard (see docs/fix-pty-fd-leak.md). After
that reassignment, proc.kill.mock is undefined and the assertions
crashed in CI. Capture a stable reference to the vi.fn() before it
gets reassigned.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 23:12:14 -07:00
Jinwoo HongandOrca daaf2aa73d feat(settings): manage sessions panel + pid-recycling daemon guard (#1343)
* fix(daemon): guard killStaleDaemon against pid recycling

The daemon's pid file carried only a bare integer, so killStaleDaemon had
no way to verify the current owner of that pid was still the process it
forked. Unix pids recycle — on macOS the default ceiling is ~2048 and
wraps in minutes under load — so blind SIGTERM/SIGKILL on a recycled pid
could hit an unrelated user process (editor, language server, background
task) silently.

Three moving pieces:

1. Pid file now carries startedAtMs. daemon-spawner exports DaemonPidFile
   and serializeDaemonPidFile; daemon-init fills startedAtMs from
   getProcessStartedAtMs(child.pid) right after the daemon signals ready.
   parseDaemonPidFile tries JSON first and falls back to bare-integer for
   backward compatibility (startedAtMs: null on legacy files).

2. isDaemonProcess takes expected startedAtMs. In addition to the cmdline
   match, it consults getProcessStartedAtMs(pid) and compares with a
   ±1.5s tolerance. Null on either side is fail-open so the guard never
   strengthens existing behavior negatively (Windows, legacy pid files,
   kernel-thread /proc failures).

3. SIGKILL re-check. The SIGTERM-then-wait window is up to 3s — long
   enough for the pid to be recycled if the original daemon dies during
   the wait. Before escalating to SIGKILL, isDaemonProcess runs again;
   on mismatch we log reason=pid_recycled and skip SIGKILL.

Carried forward from #1323 as a standalone safety fix — independent of
that PR's router/drain machinery, which is not shipping.

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

* test(daemon): cover pid-recycling guard surface in daemon-health

Adds unit coverage for the new Phase 0 surface:

- parseDaemonPidFile: JSON round-trip, JSON without startedAtMs,
  bare-integer fallback for legacy pid files, malformed-input rejection.
- startTimeMatches: null-expected fail-open, null-actual fail-open,
  within-tolerance match, outside-tolerance rejection.
- killStaleDaemon: with a mismatched startedAtMs in the pid file,
  assert that no SIGTERM/SIGKILL is sent even though the liveness probe
  (process.kill(pid, 0)) runs.

startTimeMatches was promoted from module-private to exported so it can
be exercised directly — it's a pure function with no internal state.

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

* feat(settings): manage sessions panel for daemon staleness UX

Add a Manage Sessions settings panel with list/kill-all/kill-one/restart
backed by a new pty:management IPC surface. Rows are hover-highlighted and
click to reveal the corresponding terminal pane, mirroring the bottom
status-bar sessions popover. Kill-all and restart-daemon are icon buttons
(Trash2, RotateCw) with tooltips so the restart action doesn't collide with
the row-refresh RefreshCw icon.

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

* fix(settings): honest killAll counts + suppress post-kill spawn toast

killAll now snapshots the initial session IDs and polls listSessions every
100ms for up to 6.5s — past the daemon's 5s SIGTERM→SIGKILL ladder — so
well-behaved shells hosting long-running agents finish their SIGTERM
handlers before we classify them as "refused to exit." Shutdowns fire once
per initial session (no retry spam), and fresh session IDs that appear
mid-poll (renderer remounts) don't inflate remainingCount.

pty-transport's connect() catch now detects the adapter's
TerminalKilledError tombstone rejection ("...was explicitly killed") and
suppresses the red "file an issue" toast. After Kill All, a pane remount
would call pty:spawn on the dead session ID; surfacing the tombstone as
a scary error misrepresented an intentional user action. The pane still
renders "Process exited" via the normal lifecycle.

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

* feat(daemon): foundation for pty:management IPC surface

Adds the plumbing the Manage Sessions settings panel depends on:

- daemon-init exports getDaemonProvider / replaceDaemonProvider /
  restartDaemon / cleanupDaemonForProtocol so the pty:management
  handlers can access the current provider and coordinate a clean
  restart without importing window-services internals.
- daemon-pty-router exports getAllAdapters so the killAll / listSessions
  handlers can fan across the current adapter plus any legacy-protocol
  adapters still attached for in-flight sessions.
- daemon-pty-adapter gains a listSessions RPC and readonly
  protocolVersion so the handlers can annotate each session with the
  adapter it belongs to and route killOne back to the right adapter.
- types.ts exports DaemonSessionInfo (SessionInfo + protocolVersion)
  as the shared shape the preload API surface mirrors.
- ipc/pty.ts, attach-main-window-services, TerminalPane and
  terminal-search pick up the small bindings required to wire the
  router through existing code paths without regressions.

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

* fix(settings): remove high-session-count warning banner

The banner nagged at 20 sessions, which is well within normal use for
users with many open worktrees. Count is already visible in the header
bar, and the table supports per-row and bulk kills, so the banner added
noise without actionable value.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 23:05:44 -07:00
Jinwoo HongandOrca 827b84d27a fix(runtime): add single-instance lock + owned-metadata clear (#1312) (#1326)
* fix(runtime): add single-instance lock + owned-metadata clear to prevent orca-runtime.json corruption

Closes #1312.

Every AppImage/.app relaunch was booting a fresh Electron main that clobbered
`<userData>/orca-runtime.json` and `agent-hooks/endpoint.env`. When the newest
instance quit, metadata pointed at a dead pid and `orca status` reported
`stale_bootstrap` even though the original Orca was still running. SIGKILL'd
predecessors also left orphaned `o-<pid>-*.sock` files in userData.

Three surgical changes:

1. `app.requestSingleInstanceLock()` in a new
   `src/main/startup/single-instance-lock.ts` helper, wired into
   `src/main/index.ts` after `configureDevUserDataPath(is.dev)` so dev and
   packaged runs lock in separate namespaces. Losing instances focus the
   primary's window via `second-instance` and quit without touching userData.

2. `clearRuntimeMetadataIfOwned(userData, pid, runtimeId)` in
   `runtime-metadata.ts` — compares both pid AND runtimeId against the
   current file before clearing, so the auto-updater handoff window never
   erases the replacement process's fresh bootstrap. Called from a rewritten
   `will-quit` handler that folds `runtimeRpc.stop()` + owned-clear into the
   same `Promise.allSettled([disconnectDaemon, …]).then(app.quit)` chain
   (inside the `!daemonDisconnectDone` guard so the second-pass re-entry
   can't re-invoke stop+clear).

3. `sweepOrphanedRuntimeSockets()` in `runtime-rpc.ts` runs at the top of
   `start()` on POSIX, using `process.kill(pid, 0)` to probe liveness and
   remove `o-<dead-pid>-*.sock` orphans left by SIGKILL/OOM-kill.

Tests (37 new/updated):
- `single-instance-lock.test.ts` (3): lock-failed does not register listener;
  lock-acquired registers exactly one; callback dispatches correctly.
- `runtime-metadata.test.ts` (+4): clearRuntimeMetadataIfOwned matched /
  pid-mismatch / runtimeId-mismatch / no-file branches.
- `runtime-socket-sweep.test.ts` (4): own-pid-skip / alive-retain /
  dead-sweep / regex-miss separated via synthetic ownPid=1; two
  regex-invariant tests assert the sweep regex matches the real
  `createRuntimeTransportMetadata` output (including the 'rt' fallback).

Design doc: `docs/fix-missing-single-instance-lock.md`.

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

* fix(runtime): focus hidden windows on second-instance event

focus() alone is a silent no-op when the primary window is hidden
(close-to-tray on macOS via Cmd+W, or on a different macOS Space) or
behind other apps on Windows. Call show() before focus() so a second
launch attempt reliably surfaces the existing window regardless of
state.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 23:05:14 -07:00
JinjingandOrca 46a26252bb feat(browser): viewport-size emulation via CDP (#1369)
* feat(browser): viewport-size emulation via CDP

Adds a Viewport Size submenu in the browser toolbar "…" menu.
Presets apply width/height/deviceScaleFactor/mobile/touch via
Emulation.setDeviceMetricsOverride + setTouchEmulationEnabled, and
swap the UA to a mobile iPhone CriOS string on mobile presets.
Responsive clears the override. Selection persists per-tab and
re-applies on dom-ready so it survives navigations.

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

* chore(browser): rename 'Responsive' viewport option to 'Default'

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

* fix(browser): harden viewport emulation — serialize, validate, client-hints

- Chain per-tab setViewportOverride calls to prevent rapid-toggle races
- Validate viewport metrics at IPC trust boundary (reject non-finite/out-of-range)
- Emit userAgentMetadata alongside mobile UA to avoid UA/CH mismatch
- Always reapply on dom-ready (incl. null) to clear stale emulation
- Persist viewportPresetId in session schema (optional+nullable for back-compat)
- Convert preset submenu to DropdownMenuRadioGroup for a11y
- Log debugger.attach failures and cover with a unit test

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 20:22:40 -07:00
Trevin Chow fd3e62603d fix(hooks): generate worktree setup-runner from target worktree's orca.yaml (#1280)
* fix(hooks): generate worktree setup-runner from target worktree's orca.yaml

Extend getEffectiveHooks, getSetupCommandSource, and runHook with an
optional worktreePath parameter. When provided, loadHooks reads the
yaml from that path; otherwise it falls back to repo.path. Update
the worktree-creation paths in worktree-remote.ts and orca-runtime.ts
to thread the new worktreePath through after the worktree exists, so
the generated setup-runner reflects the yaml at the tip of the target
worktree's branch instead of the primary checkout's stale yaml.

Add a regression test in hooks.test.ts that mocks two distinct
orca.yaml files (primary and worktree) and asserts the worktree's
content wins when worktreePath is passed.

The legacy hooks:check IPC handler keeps reading from repo.path
unchanged.

Closes #1256

* fix(hooks): skip auto-setup when worktree script differs from preview

Add setupScriptsMatch helper that compares the primary checkout's
setup script (what the renderer shows the user before worktree
creation) to the target worktree's script (what would actually run
after creation). When they differ, createLocalWorktree skips the
auto-launch and logs a warning, so a base-branch yaml that introduces
or modifies setup commands cannot execute under the trust granted to
the primary's preview. CLI-created worktrees use the worktree-bound
load directly because trust is granted by the CLI invocation context,
which is annotated in orca-runtime.ts.

Adds regression coverage for both matching and differing script cases.

* test(hooks): add setupScriptsMatch to worktree IPC test mocks

The new setupScriptsMatch import in worktree-remote.ts means the
existing vi.mock('../hooks') blocks in worktrees.test.ts and
worktrees-windows.test.ts now need to expose it. Default the mock to
returning true so existing tests continue to exercise the run-setup
path; the new behavior gating is covered by the dedicated
setupScriptsMatch unit tests.
2026-05-02 18:27:09 -07:00
github-actions[bot] 1f99e81be3 release: v1.3.32 v1.3.32 2026-05-03 01:16:21 +00:00
Neil ae0fc9c49a Defer protected app data reads until user action (#1370) 2026-05-02 18:15:52 -07:00
Neil b309f49ee3 Allow large text files to open in editor (#1367) 2026-05-02 18:12:08 -07:00
Neil 0f1b842daf Update project description in package.json 2026-05-02 18:06:32 -07:00
Neil 52803a336b tab jump (#1368) 2026-05-02 18:00:48 -07:00
github-actions[bot] 3a8974c9aa release: v1.3.32-rc.0 v1.3.32-rc.0 2026-05-02 23:20:19 +00:00
SSWSer 6f606114a0 feat: add PowerShell 7+ support for Windows terminals
Adds PowerShell 7+ support for Windows terminal selection, with Auto resolving to pwsh.exe when available and falling back to Windows PowerShell.
2026-05-02 16:06:11 -07:00
github-actions[bot] 20b7456fed release: v1.3.31 v1.3.31 2026-05-02 22:34:44 +00:00
github-actions[bot] 6f796f5eed release: v1.3.31-rc.1 [rc-slot:2026-05-02-15] v1.3.31-rc.1 2026-05-02 22:16:59 +00:00
github-actions[bot] 4673310a91 release: v1.3.31-rc.0 v1.3.31-rc.0 2026-05-02 21:50:03 +00:00
Neil ddd70d650f Restore worktree sidebar scrollbar (#1365) 2026-05-02 14:49:44 -07:00
Neil e7b66d22a7 fix(terminal): bypass xterm for handled app shortcuts (#1364) 2026-05-02 14:48:28 -07:00
Neil 9dfdf6f839 fix(terminal): stabilize DOM renderer scrollbar (#1363) 2026-05-02 14:45:53 -07:00
Neil 8ae119558b fix: simplify release pipeline (#1362) 2026-05-02 14:17:21 -07:00
github-actions[bot] d71c6eef6e release: v1.3.30 v1.3.30 2026-05-02 20:21:39 +00:00
github-actions[bot] c2f6176a30 release: v1.3.30-rc.1 v1.3.30-rc.1 2026-05-02 19:52:46 +00:00
JinjingandOrca 3a40014e29 feat(editor): add CSV/TSV table viewer (#1361)
Adds a virtualized read-only table view for .csv/.tsv files, reusing
the markdown view-mode toggle (source/rich) with a Table icon override.
Hand-rolled RFC 4180 parser handles BOM, quoted fields, CRLF, and
preserves trailing quoted empty fields.

Co-authored-by: Orca <help@stably.ai>
2026-05-02 11:17:52 -07:00
JinjingandOrca 7de1213c54 fix(ssh): trigger reconnect on Enter in disconnected dialog (#1360)
Register a window-level keydown listener while the SSH disconnected
dialog is open so Enter triggers Reconnect regardless of which element
holds focus. Dialog-scoped handlers don't fire when focus is inside
xterm/monaco, which aggressively reclaim focus.

Co-authored-by: Orca <help@stably.ai>
2026-05-02 11:13:11 -07:00
JinjingandOrca c9071078c7 refactor(sidebar): drop agent identity icon + expand chevron from inline rows (#1359)
* wip

* refactor(sidebar): drop agent identity icon + expand chevron from inline rows

In the per-card inline agent list, the user already knows which worktree
they're looking at and clicking a row jumps directly to the agent — the
repeated identity glyph (Claude/Gemini/…) and a separate expand chevron
are redundant. Add hideIdentityIcon/hideExpand props to DashboardAgentRow
(default false) and set both on the inline list only; full dashboard is
unchanged.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 11:12:29 -07:00
686ed33544 feat: close settings on Escape key press (#1348)
* feat: close settings on Escape key press

* fix(settings): skip Escape-to-close when focus is in editable field

Why: Escape in an input/textarea/select or contenteditable region usually
means 'cancel this edit', not 'close Settings'. Closing the entire page
would discard in-progress typing. Defer to the field's own handler; a
subsequent Escape with focus on the body will close the page.

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

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-05-02 11:01:48 -07:00
JinjingandOrca 34f9e84d78 feat(sidekick): make overlay draggable with persisted position (#1357)
Allows the user to reposition the sidekick overlay by pressing and dragging. Position is clamped to the viewport (including on resize) and persisted to localStorage. Uses pointer capture so drag state can't get stuck if the pointer is released outside the window.

Co-authored-by: Orca <help@stably.ai>
2026-05-02 10:36:50 -07:00
github-actions[bot] cc28007071 release: 1.3.30-rc.0 [rc-slot:2026-05-02-03] v1.3.30-rc.0 2026-05-02 10:15:37 +00:00
Neil 2ed089d006 fix(terminal): preserve copy with kitty keyboard (#1347) 2026-05-02 00:48:10 -07:00
github-actions[bot] e2447dc961 release: v1.3.29 v1.3.29 2026-05-02 07:44:03 +00:00
Leynier Gutiérrez GonzálezandClaude Opus 4.7 37b2996ee0 feat(editor): add toggle to show minimap in file editor (#1346)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 00:40:53 -07:00
github-actions[bot] 812f13a627 release: v1.3.29-rc.0 v1.3.29-rc.0 2026-05-02 07:04:38 +00:00
f2d58e06e4 fix(browser): clean up closed browser sessions and webviews (#1321)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Nikolatesla-lj <Nikolatesla-lj@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
2026-05-02 00:04:33 -07:00
Neil 9f2ab5ed0d fix(terminal): mirror VS Code GPU rendering controls (#1344) 2026-05-02 00:04:14 -07:00
github-actions[bot] 5dc7fbdabc release: v1.3.28 v1.3.28 2026-05-02 06:01:53 +00:00
github-actions[bot] fb39a4954a release: v1.3.28-rc.0 v1.3.28-rc.0 2026-05-02 05:34:53 +00:00
NeilandOrca 74a7a3c790 fix(release): grant actions:write on callers of release.yml (#1341)
release.yml's publish-release job got `actions: write` in f6cc2aee so it
can dispatch homebrew-bump.yml, but reusable-workflow permissions are
capped by the caller. release-cut.yml and release-rc.yml only listed
`contents: write`, so the first cut after f6cc2aee died with
startup_failure (run 25244518794) before any job could start.

Grant `actions: write` on both callers to match what release.yml needs.

Co-authored-by: Orca <help@stably.ai>
2026-05-01 22:34:26 -07:00
NeilandOrca 1db7839570 revert(sidebar): restore unread bell, keep bold-title treatment (#1340)
Co-authored-by: Orca <help@stably.ai>
2026-05-01 22:13:06 -07:00
NeilandOrca e6d61d2f6c feat(sidebar): add Search button to nav, restore task-provider icons (#1339)
Co-authored-by: Orca <help@stably.ai>
2026-05-01 22:04:55 -07:00
Brennan BensonandOrca 70befde774 feat(github): per-repo issue-source selector (#1317)
Co-authored-by: Orca <help@stably.ai>
2026-05-01 21:48:51 -07:00
2c7dddbbc4 fix(terminal): dirty-file close prompts for split, bulk, and quit flows (#1338)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: shamounY <shamoun.yousuf04@gmail.com>
2026-05-01 21:39:15 -07:00
NeilandOrca f6cc2aee92 fix(release): grant actions:write + drop broken auto-merge on tap (#1336)
Two bugs surfaced on the v1.3.26 release:

1. release.yml's new `Trigger Homebrew cask bump` step failed with
   HTTP 403 "Resource not accessible by integration". The publish-release
   job's permissions block only listed `contents: write`, but
   POST /actions/workflows/:id/dispatches requires `actions: write` on the
   scoped-down GITHUB_TOKEN. Added the permission.

2. Even when the bump workflow does run, its `gh pr merge --auto` was
   silently no-op'ing against the homebrew-orca tap, leaving bump PRs
   open. `--auto` only activates when there's a required check or
   branch-protection rule to wait on; the tap intentionally has neither.
   Switched to a direct squash-merge so the tap stays hands-free as
   originally intended.

Co-authored-by: Orca <help@stably.ai>
2026-05-01 20:24:41 -07:00
github-actions[bot] dfee883f8a release: v1.3.27 v1.3.27 2026-05-02 03:15:09 +00:00
NeilandOrca 6303bdb50f fix(release): recover orphan tags instead of hard-failing the cut (#1335)
If a cut pushes the tag but the workflow is cancelled (or the dependent
release.yml job otherwise fails to start) before a GitHub release is
published, every subsequent patch cut recomputes the same version and
dies on "Tag already exists." This wedged the pipeline on 2026-05-01
when v1.3.26 was pushed by cancelled run 25237882049 — patch cuts kept
failing for hours until release.yml was dispatched by hand.

When the tag exists but no published release is attached, skip the
bump/push steps and emit the existing tag as the job output so
release.yml runs against it and finishes what the prior attempt
started. Still refuse the collision when a real published release
exists — that's a genuine conflict (e.g. a hand-tagged version) and
needs human attention.

Co-authored-by: Orca <help@stably.ai>
2026-05-01 20:13:46 -07:00
Leynier Gutiérrez GonzálezandAmp 6faf406511 fix(claude-hook): use forward slashes in Windows managed hook command path (#1329)
Co-authored-by: Amp <amp@ampcode.com>
2026-05-01 18:50:22 -07:00