Commit Graph

243 Commits

Author SHA1 Message Date
Brennan Benson be72e64a47
Improve source control discard flow (#1870)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 15:20:53 -07:00
Brennan Benson fdf7d9e97a
feat(onboarding): add feature wall tour (#1772)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 15:20:49 -07:00
Brennan Benson 28a5acb931
feat(sidebar): redesign Smart worktree sort around hook-reported agent state (#1701)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 12:20:57 -07:00
Brennan Benson 727226fed9
fix(agent-hooks): write managed hook script to shared ~/.orca path (#1546)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 11:57:48 -07:00
Brennan Benson ba0a5b47ed
feat(ssh): agent-status over SSH (#1702)
Co-authored-by: Orca <help@stably.ai>
2026-05-13 22:09:32 -07:00
Jinwoo Hong 9964d98107
Fix e2e worker teardown cleanup (#1785)
Co-authored-by: Orca <help@stably.ai>
2026-05-13 19:39:05 -07:00
Jinjing 14953089a2
fix: restore dead terminal setup e2e hook (#1787) 2026-05-13 18:48:14 -07:00
Brennan Benson 29e8eae70e
perf(session): prune local terminal scrollback from persisted sessions (#1753)
Co-authored-by: Orca <help@stably.ai>
2026-05-13 16:34:44 -07:00
Brennan Benson 180b5c29a7
test(e2e): make terminal-attention BEL emission PATH-independent (#1771)
Co-authored-by: Orca <help@stably.ai>
2026-05-13 16:32:33 -07:00
Jinwoo Hong abcd2d5836
fix: harden Windows computer use runtime (#1757) 2026-05-13 12:37:47 -07:00
Jinwoo Hong 954fb9f316
Add multi-select worktree actions (#1732)
Co-authored-by: Orca <help@stably.ai>
2026-05-13 00:18:17 -07:00
Brennan Benson daaea6acaa
Fix terminal output lag from background panes (#1699)
* Fix terminal output lag from background panes

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

* Fix scheduler edge cases: replay ordering, foreground gate, dispose race

- Drain queued background bytes before replay/snapshot writes so the
  scheduler's deferred drain cannot land older bytes on top of the replay.
- Gate foreground on isVisibleRef only — visible-but-inactive split panes
  should not be throttled; only hidden panes (background tabs) should be.
- Catch writes to disposed terminals in the drain loop so a late PTY ping
  after pane.terminal.dispose() drops the dead entry instead of crashing
  the scheduler for other panes still draining.
- Update App.tsx comment to drop stale agentStatusEpoch reference; epoch
  no longer ticks on every PTY event after the agent-status slice change.
- Guard e2e Math.max(...drainWrites) against empty array to avoid a
  vacuous pass.

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

* Fix flaky e2e: put background marker after burst payload

The terminal-output-scheduler e2e test asserts that a background marker
appears in the terminal buffer after switching to that tab. getTerminalContent
returns only the last 4000 chars of the serialized buffer; with the marker
prefixed before a 50000-char x-burst, the marker is always evicted and the
final assertion always fails.

Move the marker to the END of the burst so it survives tail truncation. The
burst itself remains the same length, so the chunked-drain invariants the
test exercises are unchanged.

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

* Add terminal scheduler regression coverage

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-11 17:00:44 -07:00
Jinwoo Hong 0f54103dda
Add native computer-use automation (#1683)
Co-authored-by: Orca <help@stably.ai>
2026-05-11 14:20:08 -07:00
Brennan Benson 1f43346c5f
fix(resource-usage): hydrate pty-registry at boot; render `· remote` only for SSH repos (#1667)
* WIP: Changes before auto-review fixes

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

* fix: address auto-review-fix-multi-agent findings

- Replace local ORCA_WORKTREE_ID_SEPARATOR with shared WORKTREE_ID_SEPARATOR
- Make hydrateLocalPtyRegistryAtBoot idempotent (one-shot per process,
  but stays retry-eligible until daemon provider is available)
- Strengthen daemon-pty-adapter strict-parser test to actually exercise
  the new short-circuit (test would have passed under the old loose
  parser too without the change)
- Add eslint-disable max-lines directive to oversized merge test file

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

* chore: archive auto-review context to .context/

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

* fix: address auto-review-fix findings

Drop the destructive reconcileOnStartup call from boot-time PTY registry
hydration: a transient listRepoWorktrees failure (returns [] and only
warns) would otherwise let the reconcile pass kill live local sessions.
The boot path is now read-only against the daemon — listSessions() only.

Also: tighten parsePtySessionId to reject degenerate `::` halves; replace
stale pty.ts:1005 references and a misleading local-unknown comment in
the hydrate module; narrow Store dependency to Pick<Store, 'getRepos'>;
log adapter listSessions failures instead of silently swallowing them;
re-anchor design-doc references on stable symbols and align §1b/§1c/§1d
with the implementation.

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

* docs(resource-usage): update remote badge spec

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

* test(resource-usage): cover boot hydration failure modes + warm-reattach e2e

Adds the regression coverage flagged in PR #1667's test plan that wasn't
already locked down.

vitest (`hydrate-local-pty-registry.test.ts`):
  - daemon offline at first call → no-op, hasHydrated stays false so a
    later macOS dock re-activation can retry.
  - listSessions rejection caught and logged, does not throw.
  - pid-write ordering: a pre-existing registry entry with pid=12345 is
    not clobbered by a stale `pid: null` from listSessions (§1d).
  - SSH-gate: a session whose repo has a non-null connectionId stays out
    of the registry, mirroring the spawn-time gate in pty.ts.
  - Happy-path: a local session is registered with the daemon's pid.

Playwright e2e (`resource-usage-warm-reattach.spec.ts`):
  Full quit→relaunch cycle against the same userDataDir; asserts that
  on the second launch the snapshot includes the warm-reattached PTY
  with a real pid before any pane mount, and that the seeded repo
  resolves as local (no connectionId). Mirrors the existing
  terminal-restart-persistence pattern.

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

* fix(test): satisfy Pick<Store, 'getRepos'> in hydrator vitest

CI typecheck failed because FakeStore's getRepos returned objects missing
Repo's required fields (path, displayName, badgeColor, addedAt). Fill with
placeholder values; the hydrator only reads id + connectionId, but the
type signature still has to line up.

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

* chore(resource-usage): drop bug-doc files; strip dead doc refs from comments

Remove docs/resource-usage-remote-mislabel.md (new in this PR) and revert
docs/resource-usage-merge-spec.md to the PR-base state. Strip the
matching `docs/...md §N` pointers from code/test comments, keeping the
surrounding "why" explanations intact so readers still get the
warm-reattach mislabel context.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-10 17:17:52 -07:00
Jinjing e8c56be897
test: harden terminal attention e2e (#1626) 2026-05-09 01:20:35 -07:00
Jinjing 68d42040f4
fix: isolate e2e daemon and onboarding state (#1606) 2026-05-08 17:45:02 -07:00
Jinjing e0851ec722
feat: onboarding flow for new users (#1596)
* wip

* WIP: Changes before auto-review fixes

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

* WIP: Changes before auto-review fixes

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

* WIP: Changes before auto-review fixes

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

* fix: address auto-review findings (iteration 1)

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

* fix: address auto-review findings (iteration 2)

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

* fix: archive review context and improve agent detection on wizard mount

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

* fix: address CI lint failures and split use-onboarding-flow.ts

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

* fix: mock ./onboarding in register-core-handlers test

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

* fix: also toggle light class on documentElement so onboarding e2e theme wait resolves

The onboarding e2e calls waitForFunction(() => classList.contains('dark') || classList.contains('light')) before snapshotting the starting theme. applyDocumentTheme only toggled 'dark', so on a host that resolves system to light the wait timed out (CI Linux headless). Toggle 'light' as the inverse class so consumers can observe the resolved theme symmetrically; Tailwind keys only on 'dark' so styling is unchanged.

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

* fix: add braces to Landing menu close-on-outside-click handler

oxlint config requires braces for all if statements.

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

* chore: trigger CI

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-08 14:17:50 -07:00
Brennan Benson 8de43cd3b4
fix(sidebar): stamp lastActivityAt on first worktree discovery (#905)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 16:17:51 -07:00
Neil 62e02a3b4c
feat(new-workspace): unified source picker + non-submitted URL drafts for agents (#1426)
* 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>
2026-05-05 01:07:52 -07:00
Jinwoo Hong 066c245d14
fix(terminal): force WebGL repaint after split when dimensions match (#1272)
Co-authored-by: Orca <help@stably.ai>
2026-04-29 23:33:36 -07:00
Jinjing 6cd8a92e20
fix(e2e): update worktree test for tabbed Create Workspace modal (#1202)
Remove assertions on StartFromField (deleted in #1191); keep getBaseRefDefault
IPC round-trip + render-error sweep as the #1186 regression guard.

Co-authored-by: Orca <help@stably.ai>
2026-04-27 23:30:09 -07:00
Brennan Benson 76a1c691e9
test(e2e): assert on rendered DOM in 5 specs previously store-tautologies (#1194)
Co-authored-by: Orca <help@stably.ai>
2026-04-27 20:55:47 -07:00
Brennan Benson 0ea27dfdd2
test(e2e): drive real composer flow for worktree creation (#1193)
Co-authored-by: Orca <help@stably.ai>
2026-04-27 17:42:03 -07:00
Brennan Benson 2154f032c2
test(tabs): guard first tab visibility when sidebar is collapsed (#1117) 2026-04-25 23:01:35 -07:00
Brennan Benson a5e5ce2900
feat(tabs): slimmer tabs with window-drag strip on top (#1059) 2026-04-25 19:06:39 -07:00
Brennan Benson 7c75e9a853
feat(terminal): show bell indicator until user interacts (#1068) 2026-04-25 19:05:53 -07:00
Brennan Benson 861f21fc81
feat(terminals): per-tab activity indicators (#944) 2026-04-24 14:05:09 -07:00
Neil 2ae9392b72
Rename add repo copy to add project (#1014) 2026-04-23 19:02:36 -07:00
Brennan Benson 38f6b550c7
fix(tabs): walk active group order on keyboard tab switch (#1011) 2026-04-23 16:09:50 -07:00
Brennan Benson 8922b1861c
feat(tab-drag): cross-group tab drag, gated on terminal daemon (#872) 2026-04-23 15:37:27 -07:00
Brennan Benson 89b85b828b
feat(nav): workspace back/forward navigation (#945) 2026-04-22 13:40:38 -07:00
Jinjing 0bbf2d7a8f
feat: cross-repo issues view in new workspace page (#942)
* feat: cross-repo issues view with multi-repo selection

- Add multi-repo selection via RepoMultiCombobox with persisted defaultRepoSelection setting (null = sticky-all)
- Stamp repoId on GitHubWorkItem at the renderer fetch boundary; merge items from all selected repos with per-repo failure tracking
- Extract task-query helpers (tokenize/strip/parseTaskQuery) to src/shared and add unit tests
- Refactor NewWorkspacePage row to <div role=button> to allow nested interactive elements without invalid-HTML hydration errors
- fix(repo-combobox): toggle all-repos selection on repeat click

* fix(tasks): route Use CTA to item's own repo in cross-repo view

handleUseWorkItem previously referenced a removed 'repoId' state; use item.repoId so launching from a merged cross-repo list targets the correct repo.

* test(e2e): add tasks page smoke test
2026-04-22 10:58:18 -07:00
Jinwoo Hong 7a64ee3a11
Revert "fix(terminal): add proportional scroll fallback for sidebar resize (#901)" (#930)
This reverts commit 2ab2db9132.
2026-04-22 00:44:37 -04:00
Jinwoo Hong 2ab2db9132
fix(terminal): add proportional scroll fallback for sidebar resize (#901) 2026-04-21 21:28:56 -07:00
Brennan Benson 5700f3dfee
feat(terminal): Ctrl+Left/Right word-nav on Windows/Linux (#857) 2026-04-21 15:56:01 -07:00
Brennan Benson 2da6159a25
fix(diff-notes): rename to "Note", highlight saved card, Enter submits (#902) 2026-04-21 12:52:57 -07:00
Brennan Benson 202f3d638f
test(e2e): stabilize terminal-shortcuts Cmd+W and Escape steps (#873) 2026-04-20 15:36:35 -07:00
Brennan Benson 57b0617e37
perf(terminal): remove 3-minute periodic scrollback save (#869) 2026-04-20 14:56:06 -07:00
Brennan Benson 0ef3a65635
fix(terminal): Cmd+Left/Right jump to start/end of line (#851) 2026-04-19 20:24:17 -07:00
Brennan Benson 6893923c73
feat: double-click tab to rename (inline edit) (#844)
Co-authored-by: heyramzi <ramzi@upsys-consulting.com>
2026-04-19 17:22:30 -07:00
Brennan Benson 08b0a3058a
test(e2e): cover worktree lifecycle and tab-close navigation (#846) 2026-04-19 15:50:19 -07:00
Brennan Benson 660b5f4149
ci: run E2E tests on every PR, surface on release (non-blocking) (#842) 2026-04-19 13:48:27 -07:00
Brennan Benson 222d70e063
feat: add idempotent E2E test suite with headless Electron support (#671) 2026-04-19 12:09:32 -07:00