Merges the Memory and Terminal Sessions status-bar segments into a single
Resource Usage segment with a Resources / Terminal Sessions tab strip,
daemon Restart and Kill-all-sessions actions in the popover footer, and a
'Daemon not responding' banner when both subsystems are unreachable.
The new segment is gated by a single 'resource-usage' StatusBarItem that
defaults ON; legacy 'memory' and 'sessions' values migrate in place on
load so users who had either enabled keep the new segment visible.
Daemon restart + kill-all dialog flows are extracted into a shared
useDaemonActions hook so the settings pane and status bar stay in sync.
Co-authored-by: Orca <help@stably.ai>
Persist transient Tasks page position (GitHub mode, active preset/query,
Linear preset/query) in PersistedUIState so reopening Tasks restores the
user's working context instead of falling back to defaults. Source, repo
selection, team selection, and active project keep using their existing
settings paths.
Co-authored-by: Orca <help@stably.ai>
* fix(layout): align right sidebar to top in non-workspace views
Wrap the left + center columns in a flex-col that owns the conditional
titlebar, and lift <RightSidebar /> to be a sibling of that wrapper.
The titlebar now spans only the left+center area, so the right sidebar's
own header anchors at the top of the window in landing/settings/tasks
views — matching the workspace-view alignment.
Also gate the titlebar's right-sidebar toggle on !rightSidebarOpen so
it no longer double-renders alongside the close button inside the
right sidebar's own header when the sidebar is open.
Closes#1354
* fix(titlebar): shrink non-workspace .titlebar to 36px
PR #1381 shrank .titlebar-left to 36px but left .titlebar at 42px.
Before the right-sidebar top-alignment fix, the 6px mismatch was
hidden because the right sidebar was pushed below the titlebar in
non-workspace views. With top-alignment, the 36px right-sidebar
header no longer lines up with the 42px titlebar — visible as a
6px seam on the Landing page when the right sidebar is open.
Match all three (titlebar, titlebar-left, right-sidebar header) at
36px so the top strip is uniform across views.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* Fix new workspace composer focus restore
* Unify new workspace source selection
* WIP: selected source pill in smart workspace name field
Co-authored-by: Orca <help@stably.ai>
* fix(new-workspace): truncate source pill so it doesn't expand the dialog
Co-authored-by: Orca <help@stably.ai>
* feat(new-workspace): add open-in-browser button to source pill, fix vertical alignment
Co-authored-by: Orca <help@stably.ai>
* refactor(new-workspace): drop redundant kind suffix, distinct PR/issue icons, tooltips on pill actions
Co-authored-by: Orca <help@stably.ai>
* fix(new-workspace): type linked URL into agent input without auto-submit
Co-authored-by: Orca <help@stably.ai>
* fix(new-workspace): use bracketed-paste for draft URL injection so it actually appears in the agent input
Co-authored-by: Orca <help@stably.ai>
* feat(agents): per-agent draft injection strategy (codex slow paste, pi/opencode type-chars)
Co-authored-by: Orca <help@stably.ai>
* fix(agents): smarter TUI-ready heuristic + bracketed paste for codex/pi/opencode
Replaces per-agent strategy guesswork with a measured readiness check:
title-idle / non-shell-foreground stable for 1.5s / 2.5s minimum floor.
Verified against codex, pi, opencode, claude in a node-pty + xterm-headless
test rig — bracketed paste lands in the input buffer for all four.
Co-authored-by: Orca <help@stably.ai>
* refactor(agents): drop unused per-agent draft strategy abstraction
The TUI-ready heuristic in agent-paste-draft.ts works for every tested
agent (claude/codex/pi/opencode), so the AgentDraftInjectionStrategy
field, type-chars + bracketed-paste-slow code paths, and per-agent
overrides are dead. Keep the `agent` arg on pasteDraftWhenAgentReady
for future per-agent escape hatches without touching every call site.
Co-authored-by: Orca <help@stably.ai>
* feat(agents): skip draft URL injection for copilot + cursor-agent
Both TUIs open with a 'Do you trust this folder?' menu on first launch
that consumes keystrokes as menu input — pasting a URL there either
selects an arbitrary option or quits the session. Mark them with
skipDraftUrlInjection so the workspace still opens cleanly; the user
types/pastes the URL themselves once past the trust menu.
Co-authored-by: Orca <help@stably.ai>
* feat(agents): native --prefill for claude, trust pre-write for cursor/copilot
Replaces the empirical TUI-ready waits with two deterministic mechanisms:
1) `claude --prefill <text>` flag — Claude launches with the URL already in
its input box, no submit. Eliminates the readiness/paste race entirely
for the most common agent.
2) DECSET 2004 (`\x1b[?2004h`) detection on the PTY data stream for every
other agent. That escape is the protocol-level "input layer ready,
accepting bracketed paste" handshake — emitted by claude/codex/pi/
opencode/gemini/cursor-agent/copilot the moment the input box mounts.
We tap it via a sidecar subscription on pty-dispatcher (no interference
with the primary xterm handler) and paste as soon as it lands. The
8s budget is now an upper bound, not a target.
Cursor-agent and Copilot's "Do you trust this folder?" menus are bypassed
by writing the same trust artifacts the CLIs themselves write after the
user accepts:
- Cursor: `~/.cursor/projects/<slug>/.workspace-trusted` (slug = abs path
with leading `/` stripped, remaining `/` → `-`).
- Copilot: append cwd to `trustedFolders` in `~/.copilot/config.json`
(the same array the bundled `addTrustedFolder` writes).
Verified against the cursor-agent CLI bundle (versions/2026.04.17-787b533/
index.js: `_=".workspace-trusted"`) and the @github/copilot 1.0.32 bundle
(`isFolderTrusted` / `addTrustedFolder` both read/write `trustedFolders`).
Both check via realpath() before string-comparing, so the trust preset
canonicalizes too.
skipDraftUrlInjection is dropped — both agents now get the draft URL
paste once the trust menu is pre-resolved.
Tests: 24 passing across tui-agent-startup, agent-trust-presets,
pty-dispatcher routing.
Co-authored-by: Orca <help@stably.ai>
* fix(agents): wait for post-?2004h render burst to settle before paste
OpenCode emits DECSET 2004 at ~500ms during alt-screen setup, then runs
a 1.3s splash render with NO bytes on the PTY, then paints the actual
input box at ~1.85s. Pasting on the bare ?2004h signal lands during the
silent gap and the bytes are dropped.
The fix: take ?2004h as the necessary precondition, then wait for the
TUI's render burst to finish — defined as 1500ms of stream silence
after the most recent post-?2004h byte. This captures both the fast
TUIs (claude/pi/codex emit setup escapes in one burst then go quiet)
and the slow ones (opencode emits, sleeps for the splash, emits again,
then goes quiet).
Verified against opencode/claude/pi in a node-pty rig: paste lands on
the first try with the new strategy. The hard 8s timeout still caps
the wait when an agent fails to launch.
Co-authored-by: Orca <help@stably.ai>
* fix(agents): guard agentTrust IPC so stale preload doesn't crash launch
If the preload bundle is older than the renderer (a real situation in
electron-vite dev because preload changes only apply on full restart,
not HMR), `window.api.agentTrust` is undefined and the launch crashes
with "Cannot read properties of undefined (reading 'markTrusted')"
before the worktree even opens.
Guard the call sites in launch-work-item-direct and useComposerState
to skip the trust pre-write when the IPC isn't exposed, and wrap the
invoke in try/catch so an IPC error never blocks the launch — the user
just sees the trust menu and accepts it manually, same as before this
feature shipped.
Co-authored-by: Orca <help@stably.ai>
* feat(tasks): route 'Use' through the New Workspace dialog instead of yolo-create
The Use CTA on the Tasks page used to create+activate a worktree
synchronously, which surprised users — the worktree appeared in the
sidebar before they had a chance to confirm name / agent / setup. The
unified New Workspace dialog landed in this branch already supports
opening with a linked work item pre-filled (see openComposerForItem /
openComposerForLinearItem), so just route Use through it.
The launchWorkItemDirect helper stays exported for ProjectViewWrapper,
which has its own UX where the immediate-create flow is the right call.
Co-authored-by: Orca <help@stably.ai>
* test(agents): include `agent` field in autohand startup-plan assertion
Merging main brought in the Autohand Code agent test (PR #1382), which
predated this branch's addition of `agent` to AgentStartupPlan.
Aligning the assertion fixes the lone CI test failure on this PR.
Co-authored-by: Orca <help@stably.ai>
* refactor(agents): drop unused expectedProcess arg + snapshot sidecar set
Two minor follow-ups from self-review:
1. `pasteDraftWhenAgentReady` no longer reads `expectedProcess` — readiness
is gated on DECSET 2004 alone now, not on PTY foreground process. Drop
it from the signature and from the two callers (launch-work-item-direct,
new-workspace).
2. The pty-dispatcher's sidecar fan-out iterates the live Set, which is
safe against deleting the current element but not against a watcher
that synchronously subscribes a sibling. Snapshot via Array.from
before the loop. Cheap (Set is tiny) and removes the latent footgun.
No behavior change.
Co-authored-by: Orca <help@stably.ai>
* test(e2e): match the unified smart-name input's new placeholder
The CreateFromTab refactor in this branch replaced the separate "Workspace
name" Input with a single SmartWorkspaceNameField whose default-mode
placeholder is "Type a name, #1234, branch, GitHub or Linear URL". The
worktree-create e2e test was still anchoring on the old "Workspace name"
text and could not find the input.
Update the placeholder regex to match the new copy. Free-form text typed
into smart mode is treated as a workspace name by submitQuick — same
contract the test used before.
Verified locally: targeted e2e passes in 2.2s.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* Add support for custom desktop notification sounds
* perf(notifications): cache custom sound + restart-on-play
Avoids re-reading the configured audio file (up to 10MB) from disk and
re-transferring it over IPC on every notification. Adds a path-only
resolver so repeated dispatches with an unchanged sound skip the heavy
load entirely.
For burst handling, follows the VS Code AccessibilitySignalService /
GNOME canberra pattern: one shared HTMLAudioElement per sound, restarted
from t=0 on each play, with an in-flight guard that drops new plays
while the sound is still ringing. This self-dedupes by the sound's own
duration without any magic time constant — distinct sounds remain free
to overlap. The Test button passes force: true so an explicit user
action always plays through.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* Add an Appearance setting for the app/workbench UI font family. It will be independent from terminal typography and will not change Monaco, diffs, markdown editor text, or terminal panes.
* Update IDE font copy
* feat(cli): add browser tab profile controls
* feat(cli): add tab profile automation primitives
* refactor(cli): narrow tab profile automation scope
* chore: retrigger PR checks
* review: harden tab profile automation CLI
- Wait for tab re-registration after browser.tabSetProfile so a follow-up tab list --show-profile reads the new sessionProfileId from BrowserManager instead of the stale one from the previous webview
- Wait for tab registration after browser.tabProfileClone, matching browser.tabCreate, so the cloned browserPageId is operable when the CLI returns
- Short-circuit browser.tabSetProfile when the tab is already on the requested profile so we do not tear down and remount the webview for a no-op switch
- Switch TabShow.worktree from OptionalPlainString to OptionalString to match every other tab schema; empty --worktree should fall back to the active worktree, not pass through as the empty string
- Add max-lines disable to browser.test.ts (file grew past 300 lines after adding the new tab-profile and tab-show tests)
* review: fix useIpcEvents test setup for tab profile API
CI failure: useIpcEvents.test.ts threw at module load with TypeError: window.addEventListener is not a function. The chain: the rebased useIpcEvents.ts imports destroyPersistentWebview from webview-registry, which calls window.addEventListener at module load. The test stubs window via vi.stubGlobal as a plain object without addEventListener, so the typeof window check passes but the call throws.
- webview-registry.ts: tighten the module-load guard to also check that window.addEventListener is callable, so importing this module from a non-DOM-ish test env (vitest node env with stubbed window) does not throw at module load
- useIpcEvents.test.ts: add the new onRequestTabSetProfile and replyTabSetProfile stubs to all 8 window.api.ui mocks so the new IPC subscription registered by useIpcEvents resolves
* review: restore profile CRUD lost during rebase onto 1397-merged main
The rebase brought commit 3242aa27 (refactor: narrow tab profile automation scope) onto a main that already had the lifecycle CRUD from 1397. The refactor commit removes BrowserProfileList/Create/Delete types, runtime methods, RPC registrations and schemas, plus the help/specs entries, because those were the precursor versions in commit 1 of this branch. Post-rebase those removals land on the hardened versions inherited from main, breaking 1397.
Restore:
- runtime-types.ts: BrowserSessionProfile import; ProfileList/Create/Delete result types
- orca-runtime.ts: ProfileList/Create/Delete result type imports; browserProfileList/Create/Delete methods
- browser-core.ts: ProfileCreate, ProfileDelete schema imports; browser.profileList/profileCreate/profileDelete RPC registrations
- browser-schemas.ts: ProfileCreate, ProfileDelete zod schemas
- help.ts: list/create/delete subcommand lines under Browser Automation
- specs/browser-basic.ts: list/create/delete spec entries
---------
Co-authored-by: Nikolatesla-lj <Nikolatesla-lj@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Fixed symlinks settings search index (4 not 3); removed experimental flag gate on remove-symlinks cleanup; switched pre-existing target check to lstat; hid WorktreeSymlinksSection for SSH repos.
Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
Co-authored-by: Neil <neil@orca.local>
- Scope pruneLastVisitedTimestamps per-repo so not-yet-hydrated SSH repos retain persisted Cmd+J recency instead of being wiped at startup.
- Parse lastVisitedAtByWorktreeId leniently: drop only bad entries rather than failing the whole workspace session on one corrupted timestamp.
- Route sidebar agent-tab clicks through activateAndRevealWorktree so cross-repo activation and nav history are not silently skipped.
Co-authored-by: Orca <help@stably.ai>
Adds ssh:needsPassphrasePrompt IPC so tab focus / Cmd+J auto-connect
waits for user-driven connect when a passphrase dialog would otherwise
pop unprompted. No-passphrase targets continue auto-connecting.
Co-authored-by: Orca <help@stably.ai>
* feat(orchestration): transport keepalive + delivered_at split for check --wait
Implements the four §3 fixes from the check-wait design doc:
- §3.1 Transport keepalive: long-poll RPCs (orchestration.check --wait) emit
`{"_keepalive":true}` frames every 10s so neither server nor client tears
the socket down on idle. A `longPoll` admission counter capped at 16 fails
fast with `runtime_busy` when saturated; an AbortController wired through
the RPC dispatcher cancels the inner waiter the moment the socket closes.
- §3.2 delivered_at split: push-on-idle now stamps `delivered_at` instead of
flipping `read`, so the check caller remains the sole consumer of its
queue. Adds a synchronous idempotent schema migration that hard-fails on
error.
- §3.3 inbox/check parity: `orchestration inbox --terminal <handle>` and
`orchestration check --all` agree on the same rows (sequence DESC, no
mark-read). `check --unread=false` kept for one release as a compat shim.
- §3.4 CLI heartbeat: `orca orchestration check --wait` emits JSON heartbeat
lines to stderr every 15s so Claude Code's Bash tool sees continuous
output and doesn't auto-background the subprocess.
Tests: extends runtime-rpc, orca-runtime, envelope-schema, orchestration
method, and formatter suites; adds a subprocess test that spawns the built
CLI and verifies stderr line-flushing, heartbeat cadence, and stdout
cleanliness end-to-end.
Co-authored-by: Orca <help@stably.ai>
* feat(orchestration): preamble rules + heartbeat schema
- Preamble (#7, #15, #9): worker_done body ("3-sentence summary" + reportPath),
BEHAVIOR RULE #1 forbidding AskUserQuestion, heartbeat every 5 minutes with
taskId+dispatchId payload, AFTER YOU SEND grace window.
- Schema v2 migration: adds 'heartbeat' to messages.type CHECK, adds
dispatch_contexts.last_heartbeat_at, gated by user_version PRAGMA with
transactional rebuild + explicit CREATE INDEX to avoid silent perf regress.
- DB helpers: recordHeartbeat (dispatched-only), getStaleDispatches,
getThreadMessagesFor (thread+handle scoped for ask).
Co-authored-by: Orca <help@stably.ai>
* feat(orchestration): coordinator heartbeat + stale detector
Handle incoming 'heartbeat' messages by calling recordHeartbeat keyed on
payload.dispatchId (strict — log-and-skip if missing, no taskId fallback so
a straggler heartbeat from a previously-failed dispatch cannot mask a hung
retry per §5.3.4). On every tick after the 10-minute threshold, emit one
log per stale dispatched row — no auto-fail.
Also threads dispatchId through buildDispatchPreamble so workers can
attribute their heartbeats back to the correct dispatch context.
Co-authored-by: Orca <help@stably.ai>
* feat(orchestration): orca orchestration ask verb
Adds a CLI verb that sends a decision_gate message and blocks on the
coordinator's reply, scoped to the outbound message's thread. Group
addresses (@all, @idle, …) are rejected — fan-out questions must use
send --type decision_gate explicitly.
--json emits bare single-line JSON (bypassing printResult) so workers can
pipe `orca orchestration ask … --json | jq -r .answer` without unwrapping
an RPC envelope; human mode prints just the answer. On timeout the verb
exits 1 and returns {answer: null, timedOut: true}.
This is the CLI surface BEHAVIOR RULE #1 in the dispatch preamble points
workers at instead of AskUserQuestion.
Co-authored-by: Orca <help@stably.ai>
* feat(orchestration): QoL bundle — preamble visibility, status enum, dispatch cross-ref, inbox --full
Addresses four items from ORCHESTRATOR_FEEDBACK:
- #5 preamble visibility: `dispatch-show --preamble` regenerates the preamble
text for a task; `dispatch --inject --dry-run` previews without mutating
state; `dispatch --return-preamble` echoes the injected preamble in the JSON
response so coordinators can audit what a worker received.
- #6 status enum validation: CLI rejects unknown `task-update --status` values
with `invalid status '<x>', expected one of: pending, ready, dispatched,
completed, failed, blocked` before the RPC's generic Zod message. Valid
statuses are listed under Notes in `task-update --help`.
- #13 task-list dispatch cross-ref: `task-list --json` now includes
`assignee_handle` and `dispatch_id` for tasks in status=dispatched via a
read-only LEFT JOIN on dispatch_contexts. Non-dispatched rows keep their
legacy shape so existing consumers are unaffected.
- #14 inbox body visibility: `inbox --full` prints body + payload verbatim;
default output is unchanged (id/from/to/subject only).
No DB migrations; join-only change on dispatch_contexts so the sibling
preamble PR's `last_heartbeat_at` column addition will not conflict.
Co-authored-by: Orca <help@stably.ai>
* fix(worktree): prevent stale-base worktree creation and dispatch
Addresses feedback #16 per DESIGN_DOC_STALE_BASE_FIX.md §0. Four v1
components coordinated by a single shared fetch cache on the runtime:
1. Concurrent-fetch-with-gate in UI create path: `createLocalWorktree`
fires `git fetch` BEFORE the suffix loop / PR probe / path
resolution, then awaits right before `addWorktree` so the new branch
always spawns from a fresh remote tip. Renderer sees a two-phase
spinner via the new `createWorktree:progress` IPC event. The cache
is a `Map<repoPath::remote, Promise<void>>` + 30s success-only
timestamp on `OrcaRuntimeService` (§7.1 — shared with dispatch).
2. Dispatch pre-flight drift guard in `Coordinator.dispatchTask`:
probes `rev-list --left-right --count` against the target worktree
and silently returns (preserves `ready`, no circuit-breaker burn)
when `behind > 20` unless the task spec carries
`allow-stale-base: true`. Parsing strips the flag so it never leaks
into the worker's `--- TASK ---` block.
3. Preamble drift section: populated only when dispatch detected drift.
Workers see `--- BASE DRIFT ---` with the N-most-recent subjects
they don't have, so they can pull them in before running.
4. §3.3 Lifecycle: `.finally()` evicts Map entries on BOTH success and
rejection; timestamp is written ONLY on success. Prevents a single
DNS hiccup from wedging every future create on the repo until
restart, and keeps the freshness window honest.
Defers the DB `allow_stale_base` column (§0.2) and the create-time
warn toast; both can layer in later without migration.
Tests: 35 new/updated unit tests covering drift preamble, dispatch
refusal, spec-text flag parsing, fetch Map eviction after rejection,
freshness-window short-circuit, and concurrent-caller serialization.
Co-authored-by: Orca <help@stably.ai>
* test(orchestration): seed v2 DB in migration hard-fail test
After consolidating the schema bump, fresh DBs are initialized directly at
v3 via createTables(), so the v2→v3 ALTER TABLE is skipped on new installs
and the prior test's stub never fired. Seed a v2-shape file on disk so the
guarded ALTER actually runs and the "simulated migration failure" stub
propagates as intended.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
Delete agent-nesting-options.html, agent-nesting-stacked.html, and
agent-row-design.html — leftover design mockups not referenced anywhere
in the codebase.
Co-authored-by: Orca <help@stably.ai>
* feat(shortcuts): cycle Cmd/Ctrl+Shift+]/[ within current tab type by default
Extract a shared getNextTabWithinActiveType selector into a new
tab-type-cycle.ts helper and route both useTerminalShortcuts.ts and
ipc-tab-switch.ts through it. Cmd/Ctrl+Shift+]/[ now cycles within the
active tab's type (terminal cycles only terminals, editor cycles only
editor tabs, browser cycles only browser tabs). Ctrl+PageDown/Up
remains the dedicated terminal-only chord (PR #1094) regardless of
focus.
useTerminalShortcuts gains optional activeBrowserTabId and
onActivateBrowserTab parameters so browser tabs can dispatch through
the same path. The default behavior matches VS Code's
TerminalContextKeys.focus-gated cycling and Superset's per-scope
chord registry referenced in the issue.
Adds tab-type-cycle.test.ts covering single-type, mixed-type, and
single-tab no-op cases. ipc-tab-switch.test.ts updated to assert
same-type cycling under the new selector.
Closes#1100
* fix(shortcuts): use direction-aware fallback when active tab is missing
When the active tab id is not present in the same-type subset (e.g.
during hydration when an editor is active and Cmd+Shift+]/[ targets
terminals), findIndex returns -1 and the previous modulo math made
backward navigation land on the second-to-last tab instead of the
last. Branch on the -1 case to return the last tab for direction=-1
and the first tab for direction=+1, so both directions are
predictable. Adds a regression test covering 3 terminal tabs with no
active match.
* feat(shortcuts): add Cmd/Ctrl+Alt+[/] to cycle across all tab types
Adds an "all types" variant of the tab cycle chord so users can page
through every tab in the active group regardless of type (terminal /
editor / browser), complementing the type-scoped Cmd/Ctrl+Shift+[/].
- Wires the chord through the main-window keydown handler, the browser
guest shortcut forwarder, and a new ui:switchTabAcrossAllTypes IPC
channel
- Factors getNextTabAcrossAllTypes alongside getNextTabWithinActiveType
and shares the ipc-tab-switch dispatch logic via resolveCycleContext
and applyNextTab helpers to avoid drift between the two chords
- Narrows useTerminalShortcuts activeTabType to 'terminal' | 'editor'
(the hook's unifiedTabs never contains browsers) and drops the
unsound TypeCyclableTab cast
- Updates ShortcutsPane to list the new chord and expands tests
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* fix(install): regenerate cpu-features buildcheck.gypi before rebuild
cpu-features@0.0.10 ships without buildcheck.gypi and relies on its
own install script to generate it via `node buildcheck.js` before
node-gyp runs. @electron/rebuild with force:true calls node-gyp
directly and bypasses that hook, so a missing gypi (fresh install,
store prune, or prior failed run) aborts postinstall with
"buildcheck.gypi not found".
Generate the file ourselves for every cpu-features copy under .pnpm/
before invoking @electron/rebuild on platforms where cpu-features is
not in ignoreModules.
Co-authored-by: Orca <help@stably.ai>
* fix(install): satisfy oxlint curly rule
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
- release-cut.yml: require `^v[0-9]` tag shape when picking "latest
stable" from GitHub releases. Previously only `-rc.*` was excluded, so
publishing `mobile-v0.0.1` made it the latest stable, `strip_pre()`
reduced it to `mobile`, `Number("mobile")` → NaN → 0, and a patch-bump
produced `v0.0.1` (run 25304336767).
- homebrew-bump.yml: drop the blanket `release.published` trigger and
add tag-shape guards. Any published release in this repo (including
mobile) would otherwise fire the tap bump. Workflow_call from the
desktop pipeline is the only intended path now.
- Inline create-release / build / publish-release / e2e / homebrew-bump
jobs from release.yml into release-cut.yml, and delete release.yml.
Co-authored-by: Orca <help@stably.ai>
Typing a path like `Documents/orca-internal` in the browse filter now resolves the path on the remote instead of producing "No matches". Supports `~`, absolute, and relative paths with live preview and Enter to navigate.
Co-authored-by: Orca <help@stably.ai>
* fix(cmd-j): rank empty-query worktrees by focus recency
Persist a per-worktree focus-recency timestamp and use it as the primary
ordering signal for Cmd+J's empty-query Worktrees section, so SSH and
other quiet worktrees surface based on user focus rather than background
activity. See docs/cmd-j-empty-query-ordering.md.
Co-authored-by: Orca <help@stably.ai>
* fix(tests): guard lastVisitedAtByWorktreeId and mock markWorktreeVisited
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>