Commit Graph

6537 Commits

Author SHA1 Message Date
Kaynan Sampaio de Camargo c3ab805d12
fix(agent-hooks): drain stdin before hook script early exits so agents never hit EPIPE (#8430)
* Fix hook scripts to drain stdin before any early-exit path

Generated agent hook scripts and missing-script launchers could exit
successfully before consuming the payload written to their stdin,
leaving the writer with a broken pipe (EPIPE/ERROR_BROKEN_PIPE) once
the reader closed early. Capture stdin (or drain it via a shared
epilogue/fast-path guard) before any whole-script success exit across
all POSIX, batch, PowerShell, and Git Bash launcher variants, and add
a cross-agent lifecycle test suite plus a live Electron verification
script to guard the contract going forward.

* Harden hook scripts against unreadable managed scripts and add a Claude/

- Extend the POSIX launcher guard to also require `[ -r ]`, not just `-f`/`-x`,
  so an executable-but-unreadable managed script still drains stdin instead of
  erroring or silently misbehaving.
- Add a verifier case (`verifyClaudeDevinSkip`) that spins up a local HTTP
  server and confirms the Claude hook never forwards a request that Devin
  already imported, catching accidental double-forwarding.
- Update installer-utils tests and stdin-lifecycle docs to match the new
  readable-file guard and the added verification case.

* Fix hook-launcher verification to derive script paths from the installed

Extract the quoted path from the launcher's `if [ -f '...'` clause instead of
reconstructing it via join(home, ...), so missing/failing-script test cases
can't silently fall through to the real script if the install layout changes.

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-13 00:26:22 -07:00
github-actions[bot] 8303d955e8 Update README downloads badge 2026-07-13 07:25:50 +00:00
Trevin Chow 06ea55181d
Redesign Agents sidebar cards for cross-worktree scanning (#8420)
* Redesign Agents sidebar cards for cross-worktree scanning.

Lead with project and workspace identity, keep stable task titles across follow-up turns, and stop user replies from replacing agent status previews.

* fix(activity): honor generated-title setting and follow the active turn

Activity sidebar task-title/preview fixes surfaced in review of the
cross-worktree redesign:

- Apply generatedTitlesEnabled instead of ignoring it, so a disabled
  tabAutoGenerateTitle no longer resurfaces auto-titles (mirrors
  resolveTerminalTabTitle's gate).
- Guard orchestration labels with orchestrationLabelsMatchLiveDispatch so
  sticky completed metadata can't pin the title over new work.
- Prefer a substantive live prompt over history, and pick history by most
  recent startedAt (not longest), so the row title follows the active turn.
- Clear a stale status preview on a new substantive turn; only bridge a
  previous preview across a terse follow-up.
- Drop the duplicated workspace name in thread search text; index the
  branch instead.

Fixes two previously-red buildActivityEvents tests and adds coverage for
the generated-title gate and orchestration staleness.

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-12 23:52:23 -07:00
Jinjing b69c6043e3
Ssh watcher isolation e2e (#8494)
* Add a Docker SSH watcher-isolation E2E test to verify remote relay-watch

- Covers two scenarios: crashed watcher children are respawned under the
  same relay without dropping the terminal PTY or file-explorer view, and
  a missing deployed relay-watcher.js artifact is repaired on reconnect
- Extracts shared connect/disconnect/reconnect logic out of the perf spec
  into docker-ssh-relay-connection.ts, and adds docker-ssh-relay-processes.ts
  for inspecting/signaling remote relay and watcher PIDs
- Wires the new spec into a dedicated CI job and pnpm script

* Fix Windows and Linux-only issues in Docker SSH watcher-isolation E2E ha

- node-gyp override only applies on Linux runners now, since the CI job
  moved to ubuntu-latest but shares the workflow with non-Linux jobs
- spawn the e2e runner scripts through a shell on win32 to satisfy
  Node's CVE-2024-27980 restriction on unshelled .cmd spawns
- harden relay process row parsing against empty pid/ppid fields so a
  vanished /proc entry fails loudly instead of coercing to pid 0
- dedupe the reconnect helpers and export shellQuote for reuse across
  the docker-ssh-relay test helpers
2026-07-12 23:50:00 -07:00
Brennan Benson db9421dd3c
Prevent index churn from refreshing worktrees (#8431)
* Prevent index churn from refreshing worktrees

* Cover IPC contract in worktree reliability gate

* Refresh background worktree heads without re-entering structural fanout

External commits, amends, and soft resets in non-active worktrees now reach
store rows through spawn-free Git metadata reads diffed in the watcher's
existing debounce, emitted only on real head moves. HEAD reflog appends become
status-only triggers, config.worktree becomes structural for sparse-flag
freshness, and the non-darwin poller gains a periodic ungated index re-stat
so in-place rewrites on coarse-mtime filesystems cannot be missed forever.

* Reject unsafe symref paths and validate object ids in the head reader

Ref content comes from repo files an attacker can craft. Backslash segments
traverse on Windows where join treats them as separators, and colons are
forbidden in Git ref names; both now fail isSafeRefName before any path is
built. Resolved values are additionally emitted only when they match a hex
SHA-1/SHA-256 object id, so no file content can leak through the identity
event even in principle.

---------

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
Co-authored-by: Brennan Benson <>
2026-07-12 23:43:33 -07:00
Brennan Benson 43e481b1c3
Revert "Decouple feature copy from translated locale catalogs (#8488)" (#8500)
This reverts commit a5e9e139b1.
2026-07-12 23:43:07 -07:00
Brennan Benson a5e9e139b1
Decouple feature copy from translated locale catalogs (#8488)
* Decouple feature copy from locale catalogs

* Update PR workflow contract tests

* Address localization review findings

* Document localization cache context
2026-07-12 23:42:45 -07:00
Surprise233hhh 91f56c7255
Fix Windows focus stealing from agent foreground-process scan (hide conhost window) (#8053)
* Hide console window for Windows agent foreground-process scan

Agent foreground-process inspection re-forks powershell.exe (or the wmic fallback) to detect which agent runs in each terminal. Both spawns omitted windowsHide, so on Windows each fork popped a fresh conhost console window that flashed and stole keyboard focus from the foreground app — including Orca's own terminal — recurring roughly once every few tens of seconds while an agent session was open (and more often under continuous agent output).

Add windowsHide: true to both probes (matching the codebase-wide convention) plus a regression test asserting the spawn options.

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

* test(windows): include scan root in foreground fixtures

---------

Co-authored-by: xucongwei <xucongwei@bytedance.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
2026-07-12 23:32:17 -07:00
github-actions[bot] c15c2174ca release: v1.4.138-rc.5 2026-07-13 06:20:16 +00:00
Jinjing 34a9df7795
Fix wsl cli rc4 migration (#8471)
* fix(cli): migrate managed WSL launchers to native exe

* refactor(cli): reconcile managed WSL registrations

* fix(cli): harden WSL registration reconciliation

* fix(cli): serialize and harden WSL CLI registration lifecycle

- Cap per-distro concurrent repairs and add a filesystem lock so two
  Orca installs can't race the same distro's launcher/bridge files
- Skip re-adopting a legacy managed launcher when its bridge is user-
  owned, avoiding a doomed install retried on every startup
- Track per-distro reconciliation against launcher target + app
  version so unchanged registrations aren't re-probed each boot
- Replace command install with a single atomic rename instead of a
  move-based backup, closing a window where no orca-ide exists
- Remove the registry invalidate-on-persist-failure path now that
  writes are atomic and repair is disk-authoritative
- Add brief negative caching to WSL distro discovery to bound
  wsl.exe respawns on persistently broken hosts
- Extract keyed-promise-queue as a shared serialization primitive
2026-07-12 23:19:15 -07:00
Jinjing ec7cc2df56
Restyle Open/Start button as primary Button component (#8487)
Replace the raw <button> in the task list row with the shadcn Button
component so Open/Start gets consistent styling and hover/focus states.
Open uses the solid variant to read as the stronger action (resuming
existing work) versus outline Start (new workspace).
2026-07-12 22:48:01 -07:00
Jinjing 52388c1ab7
Fix worker done pane identity (#8473)
* fix(orchestration): bind lifecycle sends to dispatched pane

* fix(orchestration): bind injected worker messaging

* Fix worker_done pane identity gating and rename SSH linear CLI files

- Lifecycle reconciliation now returns an explicit `rejected` action
  (instead of `ignored`) for persisted sender_not_assignee markers, and
  only treats a payload's `_orcaLifecycleRejection` as trusted state
  when it exactly matches that reserved shape, preventing caller-
  supplied markers from spoofing a rejected send as success.
- SSH legacy fallback CLI now fails closed with
  `no_active_sender_terminal` when a worker_done/heartbeat send has no
  resolvable sender identity, rejects mixed raw/structured payload
  flags, and reconstructs structured lifecycle payload fields
  (task/dispatch id, files-modified, report-path, phase) instead of
  dropping them — extracted into ssh-remote-orchestration-send.ts.
- Renamed ssh-remote-linear-argument-error.ts to
  ssh-remote-cli-argument-error.ts since RemoteCliArgumentError is now
  shared beyond the Linear CLI.

* Add re-read logging for already-converted lifecycle rejections

Send-path reconcile converts worker_done/heartbeat rejections with a
no-op logger, so the coordinator's later re-read is the only chance
to surface the rejection message. Log it there instead of dropping it.
2026-07-12 22:45:33 -07:00
Jinjing 220811cbad
fix(e2e): repair release e2e suite (parking regression tests, stale/flaky specs, profile switcher gate) (#8486)
* fix(e2e): repair release e2e suite — parking regression tests, stale/flaky specs, profile switcher gate

Diagnosed 20 failing tests across the release e2e shards. Most are test debt,
plus two genuine product-side issues.

Product fixes:
- OrcaProfileSwitcher: the PROD gate hid the "Switch profile" button in the
  e2e build (electron-vite build bakes NODE_ENV=production). Exempt
  MODE==='e2e' so the specs render it while packaged prod builds stay hidden.

Parking cluster (8 tests): #8262 intentionally keeps the most-recently-hidden
tab warm (exempt from cold-park). The specs hid exactly one tab — always the
exempt one — so it never parked. Open a throwaway decoy tab that absorbs the
last-active exemption so the target parks. (terminal-hidden-view-parking,
terminal-pane-close-layout-consistency)

Stale tests updated to match intended product behavior:
- rich-markdown-link-bubble: match Edit link by aria-label (title dropped in #8307)
- terminal-codex-hidden-startup-background: drop the dead hiddenRendererSkipCount
  poll (Phase-4 main-side delivery gate #7214 bypasses that renderer path)

Brittle threshold/geometry/timing hardening (no product regression):
- agent-session-log-tail-stability: assert full-model length instead of a
  machine-specific word-wrap pixel baseline
- artificial-opencode revisit: dedicated under-backpressure latency bound
- terminal-history-size-typing-latency: gate p90 not max (tolerate one
  checkpoint-in-window spike; median stays strict)
- combined-diff-scroll-restore: assert viewport barely moved vs exact anchor key
- terminal-shortcuts: idempotent kitty-flag reset instead of a racing stack pop
- agent-session-live-force-exit-resume: drive the product quit-capture path
- renderer-crash-recovery-terminal-input: poll the transport probe over the
  recovery budget (still flags a permanently frozen pane)

terminal-push-delivery-loss-recovery left unchanged (no safe test-only
improvement; recovery is wall-clock bounded with ample slack).

* Extract shared parking helpers into terminal-hidden-parking.ts for e2e s

- Deduplicate waitForTabParked/parkHiddenTabBehindDecoy, previously
  copy-pasted across the parking and layout-consistency specs
- Parameterize parkDelayMs so the helper no longer depends on a
  file-local PARKING_DELAY_MS constant
2026-07-12 22:40:57 -07:00
Jinjing 5856a9f038
fix(agent-status): surface tool-failure errors across Cursor/Copilot/Grok (#8483)
* fix(agent-status): surface Claude tool failures

* Fix compact sidebar hiding tool-failure errors behind stale tool name

Extract a shared clearActiveToolFieldsUpdate() helper and apply it to
Cursor's postToolUseFailure, Copilot's PostToolUseFailure/ErrorOccurred,
and Grok's post_tool_use_failure events, matching the existing Claude
behavior so the failure message surfaces instead of the last tool name.
2026-07-12 22:21:37 -07:00
Jinjing 371d71a262
fix(agents): bundle agent icons instead of loading them from Google's favicon service (#8451) (#8474)
* fix(agents): bundle agent icons instead of loading them from Google's favicon service (#8451)

Agents without a hand-authored SVG glyph loaded their icon live from
Google's favicon service (www.google.com/s2/favicons). That service is
unreachable in some regions (e.g. mainland China) and offline, so ~23
agent icons rendered as broken images on the agent settings page, the
terminal title bar, and the status bar.

Bundle each favicon as a build-time asset under resources/agent-icons/
and render it via a new agent id -> URL map (agent-favicon-assets.ts).
The remote favicon service now only serves as a last-resort fallback for
any future agent that lacks a bundled icon. Follows the same pattern as
#7373, which bundled the OpenCode mark.

* fix(agents): bundle mobile agent icons too; drop dead omp faviconDomain (#8451)

Mobile had the same offline/region bug: MobileAgentIcon rendered every
non-glyph agent from Google's favicon service. It actually affected more
agents than desktop, since mobile lacks hand-authored glyphs for
Copilot, OpenCode, Kilocode, Droid, and OpenClaude — all fell through to
the favicon path.

Bundle the 28 favicon-path icons under mobile/assets/agent-icons/ and
render them via a Metro static require() map (mobile-agent-icon-assets.ts).
A node-env invariant test asserts every favicon-path agent ships a
bundled PNG and is wired into the map.

Also remove omp's vestigial faviconDomain from the desktop catalog — omp
renders the hand-authored OmpIcon glyph, so the favicon fallback was
never reachable.

* refactor(agents): share one set of bundled agent icons between desktop and mobile

Desktop and mobile each shipped their own copy of the favicon PNGs (23 +
28, with 23 byte-identical duplicates). Consolidate them into a single
source of truth at src/shared/agent-icons/, reachable by both bundlers:

- Desktop (Vite) imports them via `?url`.
- Mobile (Metro) requires them; Metro already watches src/shared via
  metro.config.js sharedRoot, so no config change is needed.

The two per-platform maps stay separate because the import syntax differs
(`?url` string vs `require()` asset ref), but they now point at the same
files. Verified with a real `expo export`: Metro bundles all 28 shared
icons from src/shared/agent-icons.
2026-07-12 22:10:09 -07:00
BingZ 81ed5734d6
fix(grok): prefer auth.x.ai session and mention Grok in OSC52 toast (#8392)
* fix(grok): prefer auth.x.ai session and mention Grok in OSC52 toast

auth.json can hold multiple issuer keys; Object.values order could pick a
stale entry before the live auth.x.ai OIDC session. Prefer auth.x.ai keys
and fall back only when none exist. Also list Grok in the OSC52 blocked
clipboard toast so Grok TUI copy failures point at the same setting.

* fix(grok): harden preferred auth session selection

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

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-12 21:45:36 -07:00
SeongHoon Ryu a67cbf2d24
fix(terminal): open hard-wrapped HTTP links exactly once (#8339)
* fix(terminal): open hard-wrapped HTTP links exactly once

* fix(terminal): narrow wrapped URL click handling

* fix(terminal): harden wrapped URL activation

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

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-12 21:36:13 -07:00
Jinjing e3c47eff17
Fix ssh watcher isolation (#8463)
* fix(ssh): isolate relay filesystem watchers

* Fix relay watcher fault-harness pid file and in-process fallback isolati

- Use exclusive ('wx') creation for the fault-harness pid file so a leaked
  ORCA_WATCHER_CHILD_PID_FILE env var can't clobber an existing file, and
  have the harness remove the file after reading a replacement pid.
- Force useInProcessVitestFallback to false in the relay watcher pool so a
  leaked VITEST env var can never load the native watcher addon in-process
  on the relay; fail closed instead when the isolated child is missing.
- Thread an injectable RelayWatcherProcessPool into FsHandler/
  RelayFilesystemWatchRegistry for tests, and add coverage for both fixes.
2026-07-12 21:34:59 -07:00
Sidd a5faf19631
fix(cli): wait for valid serve recipe JSON (#8361)
* fix(cli): wait for valid serve recipe JSON

* fix(cli): harden recipe output diagnostics

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

---------

Co-authored-by: Siddharth Ahire <siddharth@Siddharths-MacBook-Air.local>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-12 21:17:46 -07:00
Sidd deb8152c9a
fix(relay): treat staging paths as literals (#8358)
* fix(relay): treat staging paths as literals

* docs(relay): document pathspec collision fixture

* docs(relay): document staging mutation contracts

* chore(relay): remove redundant staging comments

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

---------

Co-authored-by: Siddharth Ahire <siddharth@Siddharths-MacBook-Air.local>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-12 21:04:13 -07:00
Jinjing 8abe093e86
fix(agent-status): label Cursor by identity, not a bare "cursor" token (#8445)
* fix(agent-status): label Cursor by identity, not a bare "cursor" token

The worktree card, status bar, and mobile all derive an agent label from the
terminal title via getAgentLabel / resolveTerminalTitleAgentType. Both matched
Cursor with `titleHasAgentName(title, 'cursor')`, a whole-token match. But
`cursor` is ordinary editor vocabulary, so a Claude/Codex tab working on Orca's
own code (title like `⠋ preserve cursor visibility across replays`) got
mislabeled as Cursor. The generic braille-spinner Claude fallback even had a
`!lower.includes('cursor')` guard that then dropped the title to no label at
all.

Gate Cursor on its closed identity title set (`isCursorAgentTitle`) instead —
the same predicate @cursor orchestration routing uses. A real cursor-agent
terminal still resolves as Cursor across working/idle/permission; a non-Cursor
tab that merely mentions a text cursor reverts to its true agent. Relax the
braille guard to the same predicate so those titles land on Claude, not null.

Makes display consistent with routing (the follow-up flagged in #8436).

* refactor(agent-status): address review on Cursor identity labeling

- Trim the four Cursor `// Why:` comments in both parallel resolvers
  (agent-title-identity.ts, terminal-title-agent-type.ts) to AGENTS.md's
  one-to-two-line rule; use identical wording so future drift is visible.
- Add a direct isClaudeAgent assertion in terminal-title-agent-type.test.ts
  pinning that file's parallel copy (previously only covered transitively),
  plus Cursor Agent / "Cursor - action required" activity-facet assertions.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-12 19:43:43 -07:00
github-actions[bot] 4a76a1c894 release: v1.4.138-rc.4 2026-07-13 01:19:26 +00:00
Jinjing 433df4be3c
fix(runtime): prevent file watcher SIGSEGV from crashing orca serve (#8370)
* Fix crash-isolated file watcher process pool for orca-serve SIGSEGV afte

Replace the worker-thread runtime file watcher with a forked, crash-isolated
@parcel/watcher child process pool so a native FSEvents fault can no longer
take down the main/serve process, and add bounded event batching, delivery
backpressure, and quarantine-based recovery for faulty watch roots.

* Fix crash-isolated file watcher teardown and shutdown leaks

- Fault harness could throw before mkdtemp/realpath completed, skipping
  cleanup; now tracks each temp path independently and races an async
  watcher-callback error so it can't escape the try/finally unhandled.
- In-process fallback swallowed unsubscribe failures via a bare rejection
  handler that could still throw; use .catch() instead.
- Watcher process entry's cancel-subscribe handler now reuses the async
  unsubscribe path when a crawl already finished, releasing the native
  handle instead of leaking it (blocks worktree unlock on Windows).
- Runtime watcher process pool exposed no real dispose(); shutdown now
  kills pooled children so they don't outlive the main process.

* Fix disposeSlot double-iteration bug in file watcher pool teardown

Remove the unnecessary array snapshot in dispose(): disposeSlot mutates
allSlots by deleting the slot being visited, and deleting the
in-progress element during Set iteration is well-defined, so the spread
copy was dead weight left over from prior debugging.

* Fix pending file watcher installs not aborting on unsubscribe

- Local/WSL watcher installs and SSH fs.watch setup now honor the
  in-flight AbortSignal, so the last unwatch cancels a slow native
  subscribe or remote setup instead of waiting for it to finish.
- Thread signal through IFilesystemProvider.watch and SSH-backed
  file explorer watches for the same early-cancel behavior.

* Fix crash-resubscribe hangs and SSH watch teardown races in file watcher

- Add a bounded deadline for post-crash resubscription crawls so one
  stuck root quarantines instead of pinning its whole shard forever.
- Report FSEvents overflow as recoverable so delivery continues after
  a dropped-events error instead of surfacing as terminal.
- Make WSL watcher abort errors real DOMException instances so
  AbortSignal-based cancellation checks recognize them.
- Rework SSH watch registration so ownership of the shared setup
  request (not just the first caller) decides teardown, preventing
  one caller's abort from cancelling another's shared watch and
  guaranteeing exactly one fs.unwatch per registration.
- Reformat reliability-gates.jsonc arrays and refresh WSL/SSH coverage
  entries and evidence runs to match the above.

* Add CI gate to run the file-watcher SIGSEGV fault harness under Electron

- The reliability gate and release workflows (mac, Linux) previously only
  exercised the crash-isolation harness under vanilla Node, which doesn't
  catch runtime differences in the actual Electron binary that ships to
  users.
- Adds an `ELECTRON_RUN_AS_NODE=1 pnpm exec electron ...` run of the same
  harness alongside the existing Node run, so #8212's SIGSEGV-survival
  contract is proven against both runtimes before packaging.

* Add CI gate blocking Linux/macOS release packaging on watcher fault reco

Adds a contract test asserting release-cut.yml and release-mac-build.yml
run the runtime-file-watcher-fault-harness after building and before
publishing artifacts, so a regression in watcher process fault recovery
fails release packaging instead of shipping silently.

* Fix use-after-clear crash in failAllWatcherSubscriptions

Snapshot the records map before iterating, since onTerminalError
hooks can dispose the supervisor and clear `records` mid-loop,
causing a crash. Also update the matching test to assert against
the shared buildParcelWatcherIgnoreOptions helper instead of a
loose arrayContaining match.

* Fix use-after-clear crash in failAllWatcherSubscriptions

Snapshot watcher records with Array.from instead of spread, since
spread syntax over an iterator that's mutated mid-loop by
onTerminalError hooks can produce inconsistent results.
2026-07-12 18:15:15 -07:00
Brennan Benson 00fc452c21
Split client-ui RPC schemas into client-ui-schemas.ts (#8446)
#7598 pushed client-ui.ts to 301 lines, one over the max-lines limit, which
breaks repo lint for every PR that merges current main (verify does not run
on main pushes). Follow the existing browser-schemas.ts/computer-schemas.ts
pattern: zod schemas move to a sibling module, the method registry stays.

Co-authored-by: Brennan Benson <>
2026-07-12 18:07:06 -07:00
Brennan Benson 3c87873dca
Fix Command Code smart-sort bump on new prompt while working (STA-350) (#5286)
Co-authored-by: Orca <help@stably.ai>
2026-07-12 18:05:11 -07:00
OrcaWin d5627638ab
fix(terminal): prevent focus prefix in startup drafts (#8433)
* fix(terminal): order startup drafts after focus input

* fix(terminal): preserve startup draft activity
2026-07-12 18:00:38 -07:00
Brennan Benson fcd60a03f8
Keep long live session logs stable while they update (#8432)
* Keep long live session logs stable while updating

* fix(editor): normalize content before append sync

* chore(editor): export e2e probe type and link gate motivator

Post-review cleanup: env.d.ts referenced the probe's method shape as an
inline literal, so a probe rename would only surface in the e2e spec;
the new reliability gate's motivatingLinks pointed at the repo root.

---------

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 17:56:49 -07:00
nikg24 67cd462b24
Add Cursor orchestration group routing (#8436)
Co-authored-by: nikg24 <228026988+nikg24@users.noreply.github.com>
2026-07-12 17:39:18 -07:00
Neil d452385bf7
fix(mobile): offer scoped Windows Firewall repair (#8439) 2026-07-12 17:30:22 -07:00
Brennan Benson 550c41a35c
refactor(editor): consolidate diff tooltip provider (#8429)
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 17:22:08 -07:00
Neil fb15d647c6
refactor: remove state-only React effects (#8437) 2026-07-12 17:11:08 -07:00
BingZ d197c5b864
fix(terminal): route Shift+Enter by PTY host (#8065)
* fix(terminal): route Shift+Enter by PTY host

* fix(terminal): resolve SSH platform from execution host

* fix(terminal): preserve restored runtime input routing

* fix(terminal): route Shift+Enter by PTY host

* fix(terminal): resolve SSH platform from execution host

* fix(terminal): preserve active PTY host routing

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

* test(terminal): remove superseded host-routing cases

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

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-12 17:10:26 -07:00
Jinjing 8086f9a3f5
Rework post-batch late-settlement reconciliation to report per-candidate (#8434)
- Late child/parent settlements now report individually instead of
  being batched into a single combined result, so toasts and
  onLateResult callbacks reflect actual per-candidate outcomes.
- Post-batch reconciler retains only unresolved provisional-ancestor
  state instead of the full batch arrays, and releases it once no
  provisional ancestor remains, avoiding unbounded retention for
  long-hung IPC promises.
- Unblocked ancestors retried post-batch now go through the same
  timeout/settlement tracking as in-batch removals, including
  further late settlement if the retry itself hangs.
2026-07-12 17:07:34 -07:00
github-actions[bot] 3eb805ce4f release: v1.4.138-rc.3 2026-07-13 00:00:00 +00:00
Jinjing 88d6fdad27
Harden SSH import path handling against traversal and Windows device nam (#8435)
- Validate each remote path segment (name, symlink target, directory
  entry) via assertSafeRemotePathSegment before it reaches the remote
  filesystem, since Windows canonicalizes reserved device names and
  NTFS streams in ways POSIX checks miss.
- Extract directory pre-scan/upload logic into
  filesystem-import-ssh-directory.ts and add captureLocalUploadRoot to
  detect a selected root swapped out from under an in-progress import.
- Add path-safety tests covering traversal, reserved Windows names,
  and TOCTOU root replacement.
2026-07-12 16:53:43 -07:00
yukei_lee c6029bea10
fix(terminal): handle Linux IME candidate digits without composition events (#8241)
* fix(terminal): preserve Linux IME candidate digits

* fix(terminal): preserve overlapping Linux IME keys

* docs(terminal): document Linux IME candidate state

* docs(terminal): describe IME candidate event handling

* docs(terminal): clarify Linux IME state callbacks

* fix(terminal): harden Linux IME candidate fallback

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

---------

Co-authored-by: yuqili03 <yuqili03@deeproute.ai>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-12 16:30:44 -07:00
sonhyrd f8ae1a489b
Add F7/Shift+F7 keyboard navigation for diff changes (#8240)
* feat(diff): add F7/Shift+F7 keyboard navigation for diff changes

Stacks on the Previous/Next change buttons (#6668) to add keyboard
navigation for single-file diffs, matching VS Code / JetBrains diff review.

- Register editor.nextChange (F7) / editor.previousChange (Shift+F7) in the
  keybinding registry (Editors group) so they show in Settings and stay
  rebindable.
- Teach the keybinding normalizer function keys (F1-F24) and make them
  first-class in the bare-key safety model (safe standalone or with Shift,
  opt-in per action) - F7 was previously unbindable.
- Install a capture-phase listener from DiffNavigationProvider so keyboard
  and the existing header buttons share one goToDiff path; works on
  read-only and editable single-file diffs.
- Translate the Previous/Next change strings for es/ja/ko/zh.

Refs #6215

* test(diff): cover change navigation shortcuts

* fix(diff): use shortcut chips in navigation tooltips

---------

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 16:13:21 -07:00
gatsby74 9dc1f253ad
feat(editor): add file editor word wrap preference (#8423)
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-07-12 15:17:06 -07:00
Neil 2306f82113
fix(terminal): gate Shift+Enter CSI-u on active protocol (#8427) 2026-07-12 15:09:20 -07:00
Brennan Benson b93ec86fef
Add Previous/Next change navigation buttons to the Diff View (#6668)
* feat(diff): add Previous/Next change navigation buttons to Diff View

Add up/down navigation buttons to the single-file Diff View toolbar so
users can jump between change regions (hunks) without scrolling, matching
IntelliJ/Android Studio. The buttons bridge the Monaco diff editor to the
header via an instance-scoped DiffNavigationProvider and call Monaco's
goToDiff('previous'|'next'); they disable when the file has no changes.

Closes #6215

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

* test(diff): cover stale onDidUpdateDiff guard in fast-swap

Address CodeRabbit nitpick: prove that an update fired from a replaced
editor is ignored after a new editor registers (the subscription is
disposed on re-register). The fake editor's dispose now clears its
callback, matching real Monaco subscription semantics.

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

* fix(diff): isolate navigation registration updates

* fix(diff): use arrows for change navigation

* fix(editor): tighten header action spacing

---------

Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 14:59:18 -07:00
Mark Xian d509ee7abe
perf(renderer): sweep suppressedPtyExitIds and pendingCodexPaneRestartIds on bulk worktree purge (#7656)
* perf(renderer): sweep suppressedPtyExitIds and pendingCodexPaneRestartIds on bulk worktree purge

Both are ptyId-keyed maps cleared alongside codexRestartNoticeByPtyId on the
normal pty-exit path, but buildWorktreePurgeState (remove-project / external
authoritative-scan / hydration-stale reconcile) runs no terminal teardown and
only swept codexRestartNoticeByPtyId and migrationUnsupportedByPtyId. A
suppression / pending-restart flag planted just before a doomed pty's exit
therefore stranded one entry per removed pty for the renderer session.

Add both to omitByPtyId, matching their two swept siblings; extend the
bulk-purge leak regression test to cover them.

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

* fix(renderer): cover dormant PTYs in bulk purge

* Fix worktree-purge PTY id leaks: proportional alias scan and stricter su

- purgeWorktreeTerminalState now short-circuits the surviving-alias scan
  once every doomed remote handle alias is matched, instead of scanning
  every surviving tab's terminals on each purge.
- Repo removal (removeRepo) no longer force-marks killed PTY ids as
  suppressed/pending-restart; those tabs are gone before async exit
  events fire, so retaining the guards just leaked entries.
- Update tests to cover raw remote-handle aliasing against surviving
  local PTY ids and to assert the tightened cleanup behavior.

* Fix environment-scoped remote PTY id handling for guards and lifecycle s

- Canonicalize legacy remote PTY ids at attach time so guard/restart/notice
  maps stay scoped per runtime environment instead of colliding on raw
  aliases shared across environments.
- Migrate suppressedPtyExitIds, pendingCodexPaneRestartIds,
  codexRestartNoticeByPtyId, and migrationUnsupportedByPtyId entries when a
  tab's PTY id transitions from a legacy alias to its scoped id.
- Narrow shutdown/purge guard sets to renderer-visible PTY ids only, since
  raw exact-stop RPC handles never emit pane exit callbacks and previously
  caused cross-environment leakage and unnecessary alias scanning.
- Prevent a late PTY exit from resurrecting a ptyIdsByTabId entry for a tab
  whose worktree/repo was already purged.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-12 14:46:15 -07:00
fsdwen ff104e523e
fix(i18n): use useTranslation hook in SidebarNav for reactive language switching (#7542)
* fix(i18n): use useTranslation hook in SidebarNav for reactive language switching

Replace plain translate() calls with the useTranslation() hook so the
React.memo-wrapped SidebarNav re-renders when the i18n language changes
after async catalog loading, fixing sidebar labels staying in English
on non-English locale startup.

Closes #7530

* fix(i18n): make sidebar language subscription race-safe

* refactor(i18n): use standard sidebar language subscription

---------

Co-authored-by: 文小松 <wenxiaosong@wenxiaosongdeMac-mini.local>
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 14:10:16 -07:00
Dzmitry Bachko 7fe6742b8b
fix(pr-comments): let users mark comment authors as bots for the Humans/Bots filter (#7598)
* fix(pr-comments): let users mark comment authors as bots for the Humans/Bots filter

Some review bots post from regular user accounts that defeat both provider
bot metadata and login heuristics, so their comments were misclassified as
human. Adds a persisted prBotAuthorOverrides setting with a "Mark author as
bot" comment action, applied consistently across desktop and mobile.

Fixes #7597

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(pr-comments): address review feedback on bot-author overrides

- Cap sanitized prBotAuthorOverrides at 500 entries so malformed payloads
  can't bloat GlobalSettings or slow comment classification
- Reuse the shared normalizePRCommentAuthorLogin in isBotPRComment on
  desktop and mobile instead of duplicating the normalization inline
- Pass botAuthorOverrides from CommentRow to CommentMoreMenu instead of
  re-subscribing per menu instance
- Re-fetch mobile bot-author overrides alongside each PR refetch so they
  don't stay a stale one-shot snapshot for the whole session

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(pr-comments): harden bot author override sync

* fix(pr-comments): bound and recover override updates

* fix(pr-comments): merge overrides from canonical settings

* fix(pr-comments): make bot override updates atomic

* fix(pr-comments): surface rejected bot overrides

* fix(i18n): translate bot override warning

* fix(i18n): translate bot author actions

---------

Co-authored-by: Dzmitry Bachko <dbachko@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 14:09:15 -07:00
Brennan Benson b01df38590
Show agent CLI failure output for branch auto-naming and generation instead of parsing per-CLI error formats (#8045)
* Surface the Pi CLI's real error when branch auto-naming and commit generation fail

Pi failures (missing provider credentials, HTTP 4xx/5xx, connection errors)
previously collapsed to the generic 'Pi CLI command failed with code 1.'
because extractAgentErrorMessage only recognized Error:-prefixed lines.
Add two stderr-only extraction passes for pi's failure formats and narrow
the unix-path redactor so pi's /login remedy token survives redaction.

Fixes the OP variant of STA-1492 (#7808).

* Replace per-CLI failure parsing with sanitized raw output excerpts

Every agent CLI formats errors differently, and the parsing passes only
ever covered the vendors someone had already debugged (the pi passes
fixed pi and nothing else). Show the output itself instead: a positional
excerpt (first two non-empty lines plus the last one) of stderr, falling
back to stdout when stderr is silent, path-redacted and capped as
before. Exit-0 runs with empty stdout now stay 'returned an empty
<result>' instead of misreporting a command failure. The sanitizer also
strips Cf characters (bidi overrides) now that provider-controlled
bodies flow through verbatim, and OSC sequences are stripped alongside
CSI.

* Keep the full CLI output of failed branch-name generation for on-demand viewing

The persisted rename-failed badge carries only a sanitized excerpt (it
syncs to paired clients), so the complete diagnosis was previously
buried in the main-process log. Failed generations now capture their
full stdout/stderr (bounded to 64 KiB per stream, head and tail) into a
main-memory-only store keyed by worktree — never persisted or synced.
The rename-failed dialog fetches it on demand and shows it in place of
the excerpt, ANSI/control/bidi-stripped; after a restart or on paired
web clients it falls back to the excerpt. Renderer-bound generation
results explicitly drop the capture so IPC payload shapes are
unchanged.

* Cover the rename-failed dialog's full-output fetch and excerpt fallback

* Split the folder-workspace title rename flow into its own module

first-work-branch-rename.ts sat at the max-lines ceiling; the folder
title flow is a self-contained concept and main's concurrent additions
to this file pushed the CI merge ref over the limit.

* Harden the failure-output capture and dialog against review findings

- Flatten bounded captures so V8 sliced strings no longer retain the
  multi-megabyte parent stream in the capture map (128 MiB -> ~4 MiB in
  a 32-entry probe).
- Require an OSC terminator and stop its char class at newlines so an
  unterminated/boundary-truncated sequence can no longer swallow the
  omission marker and diagnostic tail.
- Exclude stdout from the persisted branch-name failure detail (it can
  echo the prompt into synced metadata); the full local-only capture
  still keeps it for the dialog.
- Refetch and reset the dialog's full output when the persisted error
  changes so an open dialog never shows or copies a stale run.
- Report signal-terminated generators (null exit code) as 'was
  terminated before exiting' instead of 'code null'.

* Redact JSON-escaped Windows drive paths without breaking scheme URLs

Provider JSON bodies double backslashes (C:\\Users\\name), which slipped past the drive-letter redaction into the persisted, client-synced failure excerpt. Allow repeated backslashes only — a URL's :// must stay single so remedy links survive.

* Fix branch rename failure IPC re-registration

---------

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-12 13:02:29 -07:00
Jinwoo Hong 7b12d38b17
perf(terminal): tune cold-park keep-warm so common rotation never remounts (#8262) 2026-07-12 11:48:17 -07:00
github-actions[bot] 4de5329db1 Update README downloads badge 2026-07-12 18:35:15 +00:00
Jinjing 26934b11bf
fix(orchestration): complete tasks on worker_done + coordinator UX fixes (#8030)
* fix(orchestration): complete worker tasks and improve coordinator UX

* Fix orchestration lifecycle sender resolution and peek/check compat hand

- Lifecycle sends (worker_done/heartbeat) now use ORCA_TERMINAL_HANDLE
  verbatim, skipping the liveness probe and pane remint that could
  block delivery during restarts or mismatch stale-runtime assignee
  handles.
- --peek now round-trips as {peek:true, unread:false} so older runtimes
  that strip unknown params degrade to non-destructive "all" instead of
  mark-read, with client-side filtering to restore peek semantics and a
  clear error when --peek --wait can't be honored.
- Reject combined read-mode flags (--unread/--peek/--all) before calling
  the runtime.
- Distinguish suppressed (already-consumed) lifecycle messages from
  ignored ones so send doesn't wake --wait waiters for stale heartbeats.
- Fix task summary truncation to avoid splitting UTF-16 surrogate pairs
  and to not misreport whitespace normalization as truncation.

* Add shared helper to abbreviate orchestration task specs for brief listi

- Normalizes whitespace and caps spec length at 160 chars, flagging
  truncation separately from whitespace-only changes
- Truncates on UTF-16 code point boundaries to avoid splitting
  surrogate pairs and emitting malformed strings

* Add pane-key identity to worker_done/heartbeat reconciliation and server

- Records the sender's pane key on messages and dispatch contexts so
  worker_done/heartbeat ownership can be verified by the remint-stable
  pane leaf instead of the terminal handle, which is reissued across
  restarts.
- Rejects lifecycle messages from a genuinely foreign pane while still
  tolerating handle remints, tab break-outs, and older CLIs that lack
  pane identity.
- Moves task-spec abbreviation server-side (orchestration.taskList
  --brief) so full specs no longer cross SSH/relay transports, with a
  client-side fallback for older runtimes; consolidates the shared
  abbreviation helper under src/shared.
- Adds a stderr warning when a pre-peek runtime's --peek response hits
  the 100-row cap, since older unread messages may be missing.

* Isolate ORCA_PANE_KEY in CLI test beforeEach to fix leaked senderPaneKey

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

* Fix pane-key remint bypassing dispatch mutual-exclusion lock

- Dispatch locking only matched on assignee_handle, so a reminted
  terminal handle (tab break-out) could open a second concurrent
  dispatch on the same pane.
- Add leaf-UUID-based pane key comparison (parsePaneKey) as a
  secondary lock, falling back to exact handle match for legacy
  rows without pane keys.

* Update orchestration skill docs for lifecycle authority and CLI flag add

- Clarify that dispatch lifecycle is tied to taskId+dispatchId verified against
  the dispatched pane, not the terminal handle, since handles can be reminted
  after restart
- Document new `check --peek`/`--all` and `task-list --brief` flags, with
  fallback guidance for older CLIs that reject them
- Note that a valid worker_done auto-completes the task/dispatch, so workers
  shouldn't also call task-update manually

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-12 02:15:11 -07:00
Neil ee82d66a35
fix(cli): preserve multiline arguments on Windows (#8374)
* fix(cli): preserve multiline Windows arguments

* test(cli): run Windows launcher regression in CI

* fix(cli): support Windows Framework C# compiler
2026-07-12 02:13:41 -07:00
Myungjoo Jang 8b8e1bbab2
fix: restore the active top-level view across renderer reload (#8265)
Persist and safely restore the active top-level view on startup. Unknown, removed, legacy, or unavailable views fall back to the terminal, while cross-window UI sync cannot navigate the current window.\n\nCloses #8264
2026-07-12 01:40:39 -07:00
Neil 8b94875cf1
Remove redundant line on PR evidence images
Removed redundant line about committing PR evidence images.
2026-07-12 01:38:02 -07:00