Commit Graph
4757 Commits
Author SHA1 Message Date
Jinjing 008ad62d3f Add HTML preview-to-side support for single unstaged/staged diffs (#8018)
- Move the preview button before the single-diff tooltip in the header
- Extend canOpenPreviewToSide to allow single diffs (not commit diffs)
  when the modified file still exists on disk, since the preview
  renders the working-tree file rather than diff content
- Add tests covering HTML edit tabs, unstaged diffs, deleted files,
  commit diffs, and non-HTML diffs
2026-07-09 21:57:38 -07:00
79abeeaa2a fix(browser): allow CDP browser target attach (#7033) (#7891)
* fix(browser): allow CDP browser target attach (#7033)

* review: preserve nested CDP session identity

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

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-09 21:57:01 -07:00
Jinjing 44d5ed0439 1.4.131 rc2 release prep (#8020)
* Support WSL Codex settings promotion and harden config write-back

- Enable settings promotion for WSL runtimes using per-distro baselines.
- Create parent directories if missing to prevent promotion ENOENTs.
- Keep restrictive permissions (0600) and follow symlinks on promote.
- Respect CRLF line endings when inserting keys into CRLF config files.
- Skip redundant baseline file writes when settings are unchanged.
- Include the release scan report for the 1.4.131-rc2 prep.

* Refactor sleeping agent wake flow and fetch rate limits via backend

- Background-mount only targeted terminal tabs during passive wake to
  prevent spawning unnecessary PTYs for unvisited tabs.
- Latch edge-triggered wake requests that arrive mid-hibernation and
  track active claims to prevent double-resuming a provider session.
- Query the ChatGPT wham usage backend API directly with fetch for
  rate limits, avoiding launching Codex or WSL login shells.
- Asynchronously probe and serialize WSL auth files with timeouts to
  prevent synchronous I/O from stalling Electron's main process.
- Fix config promotion edge cases such as missing parent directories,
  dangling symlinks, and atomic write permission widening.

* Support WSL dotfile-symlink write-back and lengthen redeem timeout

- Preserve symlinked Codex config on WSL by writing through the
  existing file instead of atomic-rename, since \\wsl$ symlink
  metadata isn't reliably detected and rename would clobber the link.
- Tighten new ~/.codex directory creation to 0700 (holds auth.json).
- Give explicit reset-credit redemption a 30s backend timeout instead
  of the 10s background-poll default, since it's user-triggered.
- Read sleeping-agent session state from the worktree's actual
  execution-host partition instead of always the local one, so the
  headless-wake check works correctly for SSH-hosted worktrees.
- Isolate serve-sim watcher tests from the real $TMPDIR/serve-sim
  state file to avoid leaking unrelated events.
2026-07-09 21:54:22 -07:00
Jinjing d280a7cbe8 Make sidebar reveal always jump instantly instead of smooth-scrolling (#8019)
- Removes the `behavior`/`sidebarRevealBehavior` plumbing throughout
  activation and reveal call sites now that every reveal jumps
  immediately, eliminating the need to special-case newly created
  worktrees.
- Reworks worktree-sidebar-reveal.ts to center the target row within
  the viewport and temporarily pad list boundaries so first/last rows
  can still center instead of clamping to the edge.
- Drops the reduced-motion e2e workaround since reveals no longer
  animate.
2026-07-09 21:50:03 -07:00
BingZ 946eb52e6b fix(terminal): make xterm scrollbar gutter transparent (#7876)
* fix(terminal): style xterm scrollbar gutter

* fix(terminal): reuse the canonical scrollbar style
2026-07-09 21:35:01 -07:00
Brennan BensonandOrca 7a733862cb Harden cleanup removal review findings (#8010)
- Fail queued removals that reveal concrete git risk (dirty files or
  unpushed commits) discovered after an unverifiable force approval.
- Clear a failed row's queued-for-deletion sidebar overlay as soon as the
  row fails instead of when the whole batch settles (new onRowFailed).
- Skip the auto-scan on dialog reopen while a removal batch is running;
  the removal's scan invalidation would discard it immediately.

Co-authored-by: Orca <help@stably.ai>
2026-07-09 21:22:06 -07:00
Brennan BensonandBrennan Benson feac6a5104 Prevent continuous git status scanning in large repositories (#8005)
* Prevent continuous git status scanning in large repositories

On repos where `git status --untracked-files=all` takes tens of seconds,
the background status poll restarted a fresh scan 3s after the previous
one finished, keeping a git process at high CPU almost continuously
while the workspace sat idle (#7983).

The coalesced poll runner now paces reruns by the previous run's
duration, split by trigger class:

- Evidence-free timer ticks wait 5x the last refresh duration (capped
  at 5 minutes), bounding idle polling to ~1/6 duty cycle.
- Change signals (file-watch events, repo metadata pushes, finished
  terminal commands, window reveal after hidden) wait only 1x, so real
  changes in a slow repo still surface promptly; a change signal can
  pull an already-scheduled tick run earlier, and the strongest pending
  trigger wins for trailing reruns.
- Backoff-deferred scans are skipped while the window is hidden; the
  becoming-visible run catches up on the short lane.

Fast repos keep the exact 3s cadence (the multiplier never drops the
gap below the existing floor), and user-triggered refreshes are
unaffected (they bypass the poll runner). The stale-conflict poll gets
the same pacing, which also spaces slow remote SSH probe chains.

Fixes #7983

* Skip hidden-window stale-conflict probes like the status poll

---------

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-09 21:06:00 -07:00
Brennan BensonandBrennan Benson 5662bf49d8 Restore Linear agent-skill setup prompt and add provider-card install CTA (#7990)
PR #5071 (36277801e) accidentally dropped the LinearAgentSkillSetupPrompt
modal from WorktreeCard, orphaning the component. Restore the exact
wiring: render on the active worktree when it has a linked Linear issue.

Also surface the decoupled orca-linear agent skill on the Linear task
provider settings card: install state via useInstalledAgentSkillNames,
copyable install/update command resolved for the agent runtime, and a
remote-setup note when a runtime environment is active. The legacy-aware
update-command selection moves into a shared lib module so the sidebar
prompt and the new CTA stay in sync.

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-09 20:06:47 -07:00
Jinwoo Hong f55d753721 fix(codex): use WSL login shell for account setup (#7993) 2026-07-09 19:40:11 -07:00
Jinwoo Hong 27f30c2548 fix(windows): open WSL workspaces in VS Code remote (#7982) 2026-07-09 22:37:40 -04:00
Jinwoo HongandOrca 6731773e4e Route provider account surfaces through the active Remote Orca Server (#7999)
Co-authored-by: Orca <help@stably.ai>
2026-07-09 19:30:23 -07:00
Jinwoo HongandOrca e8c84bb704 fix: propagate hook-only agent status to Remote Orca Server clients (#7970) (#7998)
* fix: propagate hook-only agent status to Remote Orca Server clients

On a headless Remote Orca Server, agent-status hooks (OSC 9999) updated the
retained row map but never republished PTY-backed session snapshots — only
terminal *title* changes did. Paired desktop/web/mobile clients therefore
kept a stale agent state (e.g. opencode working/idle) until relaunch, and
even title-driven updates carried an empty prompt and no agent identity
because the snapshot builder only used the title heuristic (#7970).

- retainAgentRowSnapshot reports client-visible changes (state, prompt,
  agent type, tool, interactive prompt, interrupted) so handlePtyData can
  republish snapshots on hook-only transitions without fanning out a
  rebuild per repeated same-state hook ping.
- buildPtyMobileAgentStatus prefers the fresh retained hook payload over
  the title-only fallback, so clients see the real state/prompt/agentType
  and interactive prompts. The non-agent-title suppression (#1437 stuck
  spinners) still wins unless the hook shows a live tool/question signal,
  and it now also covers leaf-backed panes with no PTY record.

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

* fix: refetch remote projects when the client-events stream replays

worktreesChanged/reposChanged emitted during a transport gap are lost, not
queued. A quick drop can replay without flipping the environment
unreachable, so the reachability-transition refetch never runs and a
server-created worktree stays invisible until relaunch (#7970). Request a
debounced project refresh on the replay tag, mirroring the SSH-state
refetch that already rides it.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-09 19:21:55 -07:00
Jinwoo Hong 4ead072a16 Fix Codex WSL runtime status hooks (#7969)
* Fix Codex WSL runtime status hooks

* Harden Codex WSL hook restart handling

* Harden Codex WSL hook path handling

* Fix Codex hook CLI type boundary
2026-07-09 17:16:49 -07:00
BingZandJinwoo Hong 5b1b8cc61f fix(preflight): resolve WSL/SSH agent paths past shell aliases (#7867)
* fix(preflight): resolve WSL/SSH agent paths past shell aliases

LeanCTX and similar tools wrap claude/codex as interactive shell aliases.
command -v then returns alias text, which fails absolute-path detection and
hides installed agents (#7816).

Prefer bash type -P, then zsh type -p, then command -v for dash/sh fallback
in WSL agent discovery, WSL isCommandOnPath, and remote relay probes.

* fix(preflight): harden alias-safe PATH lookup chain

Require non-empty results between type -P, type -p, and command -v so bash
type -p empty success cannot skip later lookups.

* fix(preflight): resolve agent executables directly from PATH

---------

Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
2026-07-09 17:08:35 -07:00
e7ee15f4b2 Improve workspace cleanup list (#7053)
* Improve workspace cleanup list

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

* Address workspace cleanup review feedback

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

* Fix workspace cleanup perf findings

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

* Avoid stale cleanup progress cache

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

* Complete workspace cleanup perf fixes

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

* Fix worktree list option forwarding

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

* Address workspace cleanup review nits

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

* Fix workspace cleanup removal review findings

- Fail a queued removal that now needs a force the user never approved
  (confirm-time approvedCandidates snapshot compared in preflight)
- Reword the 120s removal timeout to say removal continues in background
- Wire suppressPreservedBranchToast into cleanup removals
- Stop statting a repo after the first activity metadata timeout
- Document the WSL 9P best-effort stat gap; drop unused locale key

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

* Split workspace-cleanup slice test to satisfy max-lines

Rebasing onto latest main pushed the combined store-slice test over the
800-line cap. Extract shared fixtures into a test harness and split the
suite into scan-progress and removal-preflight files instead of adding a
forbidden max-lines suppression.

---------

Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-09 16:24:20 -07:00
Jinjing 69befad13e Harden layout validation, watcher lifecycle, and connection robustness (#7924)
* Harden layout validation, watcher lifecycle, and connection robustness

- Throw instead of silently skipping when the packaged daemon-entry is
  missing, preventing layout regressions from passing build checks.
- Terminate idle parcel-watcher processes to reclaim native handles and
  avoid crash-prone native node module teardowns on shutdown.
- Bind the persisted WS fallback port first to prevent orphaning active
  mobile pairings when the preferred port becomes free again.
- Cap concurrent disk reads for restored dirty tab verification at three
  to prevent startup connection bottlenecks on remote SSH workspaces.

* Queue file IDs instead of snapshots in restored conflict scans

This avoids using stale file snapshots (e.g., outdated disk signatures)
if a tab is saved, closed, or re-baselined while waiting in the queue
behind the concurrency limit. The live state is now fetched from the
store and validated immediately before initiating the disk read.
2026-07-09 16:09:09 -07:00
Jinwoo Hong e537953d8f Fix GitLab auth diagnostic waking WSL (#7967) 2026-07-09 18:06:30 -04:00
Jinwoo Hong 20ed764211 Fix WSL source control path separators (#7966) 2026-07-09 18:04:06 -04:00
Jinjing ad43dd19ed Disable experimental new worktree card style by default (#7977) 2026-07-09 14:52:03 -07:00
Rod BoevandJinwoo Hong 33f59ad99e fix(rate-limits): recover WSL Codex usage RPC refresh (#7567) (#7658)
* fix(codex): launch WSL usage RPC through interactive shell (#7567)

* fix(codex): harden WSL usage RPC shell startup

---------

Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
2026-07-09 14:47:28 -07:00
Brennan BensonandOrca 1b0febc4cc Wake slept agents when opening a worktree on mobile (#7906)
Co-authored-by: Orca <help@stably.ai>
2026-07-09 13:05:32 -07:00
Jinwoo HongandOrca 94662c8445 feat(codex): write in-Codex setting changes back to ~/.codex config (#7960)
Co-authored-by: Orca <help@stably.ai>
2026-07-09 12:17:35 -07:00
Brennan Benson 1534edc073 Separate pane identity from liveness in the tab-agent resolver (fixes OMP tab flicker) (#7860) 2026-07-09 11:38:26 -07:00
OrcaWin 81e4f0fa68 fix(sidebar): only show the projects scrollbar when the list overflows (#7845) 2026-07-09 11:21:35 -07:00
Jinjing b32924bf59 Chunk offline audio decoding to prevent ONNX SIGTRAP crashes (#7932) 2026-07-09 05:00:58 -07:00
JinjingandOrca 52c7de1adb fix(terminal): guard PTY handler unregistration against detach/attach remount races (frozen pane) (#7894)
Co-authored-by: Orca <help@stably.ai>
2026-07-09 03:11:27 -07:00
Jinjing ee823b766c Move notification status helper to Contents/MacOS (#7931)
On macOS 26, UNUserNotificationCenter aborts when executables are run
from Contents/Resources because bundleProxyForCurrentProcess returns
nil.

Moving the orca-notification-status helper to Contents/MacOS next to
the main Electron executable ensures proper bundle resolution and
avoids immediate crashes.
2026-07-09 03:07:05 -07:00
Brennan BensonandOrca 7e85db4130 Update mobile 0.0.25 Android download links (#7917)
Co-authored-by: Orca <help@stably.ai>
2026-07-09 02:44:52 -07:00
NeilandOrca 06afbc4a4b Add optional Orca account sign-in (#7515)
* auth v1

* fable review

* lint

* Account menu with org membership management

Default UX is a compact account menu (sign in, organization selection, sign
out) that renders only when cloud auth is configured; adds an organization
members dialog (invite, role, remove) gated on server-side role checks. The
multi-profile switcher UI is preserved behind ORCA_MULTI_PROFILE_UI=1.

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

* Gate the optional account sign-in UI to dev builds

The account switcher stays hidden in packaged builds while the feature is
in progress. Dev builds still show it when the client env vars are set, and
a dev-only Settings > Dev Tools > Orca Cloud section mirrors it.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-09 02:13:13 -07:00
Brennan BensonandBrennan Benson 24d7f6b790 Align per-workspace environment toggle (#7908)
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-09 00:47:25 -07:00
Neil 7efbe10394 fix(onboarding): dismiss on notifications step + drop skipped steps from stepper (#7909)
Two onboarding-screen bugs:

- The final "notifications" step blocked click-off/Escape dismissal, unlike
  every other step. Remove the notifications-only guard so the skip
  confirmation opens on all steps; the footer "Skip to project setup" stays
  hidden there since the primary button already hands off to Add Project.
- A skipped "integrations" step (GitHub CLI already installed) still rendered
  as a dead, disabled stepper dot the user skipped past on Continue. The
  stepper now drops all skipped steps (integrations + Windows terminal)
  entirely instead of showing an unreachable dot.

Allowing dismissal on the last step let a click-off race the "Add your first
project" completion handoff (both call closeWith) and double-write onboarding
state / double-fire telemetry. Make closeWith idempotent with a first-wins
latch. Also map the displayed step index through resolveStepIndex so a
momentarily-skipped resume step can't flash "1 of N".

Verified: onboarding unit tests, full onboarding e2e spec (rewritten
notifications test locks in the new dismiss behavior), typecheck, lint, and
live Electron.
2026-07-09 00:46:03 -07:00
Jinwoo HongandOrca 2c20089080 fix(codex): stop 'hooks pending review' from reappearing on every Orca-launched Codex session (#7896)
Co-authored-by: Orca <help@stably.ai>
2026-07-08 23:05:40 -07:00
Brennan BensonandOrca ed529a011b fix(updater): restore Windows update signature verification (#7861)
Co-authored-by: Orca <help@stably.ai>
2026-07-08 22:28:13 -07:00
NeilandOrca 25ea2bbfd1 onboarding: seamless macOS notification permission step with live state detection (#7684)
* feat(onboarding): state-aware macOS notification permission step

The Set up notifications step showed a one-size-fits-all 'Open Mac
Settings' button that simultaneously fired the macOS permission prompt
and opened System Settings — two competing system UIs, with System
Settings unnecessary for the common fresh-install case.

Electron exposes no API to read macOS notification authorization, but
scheduling outcomes do reveal it: a silent probe notification's 'show'
event means permission is granted, 'failed' means delivery is blocked.
A new notifications:probeDelivery IPC runs that probe (cached via
passive delivery evidence and a persisted confirmation flag), and the
onboarding card now renders the real state:

- fresh install: the probe itself pops the native Allow dialog the
  moment the step opens; the card flips to 'Notifications are enabled'
  automatically when the user clicks Allow (silent 2.5s re-probes)
- blocked: amber card with an Open System Settings deep-link, which
  also self-heals once the user flips the toggle
- granted: green confirmation card

The test-notification button now feeds the same card instead of the
ambiguous 'if no banner appeared…' toast during onboarding.

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

* fix: don't log expected probe rejections while polling for permission

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

* fix: amber warning styling + single stable dev bundle id for notifications

- Blocked card now uses the app's shipped amber idiom (tinted surface with
  amber title/body) instead of white-on-amber-wash, which read muddy in
  dark mode; macOS permission card split into its own module to stay under
  the max-lines budget.
- Dev instances previously minted a unique macOS bundle id per
  branch x Electron version, registering a new Notification Settings entry
  every time ('Orca: <branch>' rows piling up forever) and pointing the
  settings deep-link at ids System Settings can't resolve. All dev
  instances now share com.stablyai.orca.dev: one Notification Center
  entry, one permission grant covering every dev build.

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

* fix: tighten macOS permission card copy

Body copy was one long sentence; now a single short instruction with
'Updates automatically.' as a separate dimmer line. Also repairs locale
catalog parity for keys introduced by commits rebased into this branch.

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

* fix: drop 'Updates automatically.' line; ad-hoc sign dev app copies

The extra line read as confusing filler — the cards now carry one short
instruction each.

Dev Electron copies had broken code signatures (the Info.plist identity
edits invalidate the ad-hoc seal), which macOS punishes by refusing
Notification Center registration outright: every dev notification failed
with UNErrorDomain error 1, the app never appeared in System Settings >
Notifications, and the settings deep-link had nothing to land on. The dev
runner now ad-hoc re-signs the copied bundle after the plist edits
(bundleLayoutVersion bumped so stale unsigned copies are recreated).
Verified end-to-end: runner-built copy passes codesign --verify --deep,
probe delivery returns delivered, the onboarding card flips green in dev,
and the deep link opens the dev app's own notifications pane.

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

* fix: drop confusing copy line; session-only permission evidence

Removes the 'Updates automatically.' line from both permission cards.

Also drops the persisted notificationDeliveryConfirmed flag: OS-level
permission changes between sessions, and a stale positive rendered a
false green card. Delivery evidence is now session-scoped only.

Documented detection ceiling (verified empirically on macOS 26): while
the permission dialog is unanswered — and when notifications are toggled
off in System Settings after being authorized — macOS accepts requests
and silently swallows them, with no public API (Notification Center
delivered-history and legacy ncprefs both included) able to distinguish
that from real delivery. 'failed' remains definitive for unsigned builds
and dialog-level denials.

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

* feat: real macOS notification permission readout via native helper

Electron has no API for UNUserNotificationCenter authorization, and every
observable fallback lies: scheduling succeeds (and getHistory lists the
notification) even while macOS silently swallows display because the
permission dialog is unanswered or notifications were toggled off in
System Settings. The onboarding card therefore showed 'enabled' after the
user disabled notifications.

Adds native/notification-status-macos: a tiny Swift binary that prints
the app's real authorization status. It runs from inside the app bundle
(NSBundle resolves the bundle by walking up from the executable) and
embeds the app's CFBundleIdentifier in a __TEXT,__info_plist section so
every codesign --force pass — electron-builder's signing or the dev
runner's ad-hoc deep sign — derives the identifier macOS keys
notification records to. Spawning it from the app returns authorized /
denied / not-determined exactly matching System Settings.

notifications:probeDelivery now prefers this readout (authoritative,
silent), firing at most one dialog-trigger probe per session while the
decision is pending, and falls back to the previous delivery-probe
heuristics when the helper is unavailable. The card polls the readout
silently in every state, so toggling Allow notifications in System
Settings flips the card within a poll — both directions, verified live.
Test notifications also consult the readout so 'delivered' is no longer
claimed for swallowed notifications.

Packaged builds ship the helper via extraResources and sign it in
afterPack like the computer-use helper; dev copies compile it on demand
(swiftc, non-fatal when missing) with the shared dev bundle id.

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

* feat: in-app fallback for swallowed notifications + permission card in Settings

- Dispatch now consults the authorization readout before creating a
  native notification: when macOS would silently swallow it (denied or
  prompt unanswered) it returns reason 'blocked-by-system' instead of
  piling invisible notifications into Notification Center. The terminal
  notification path surfaces that as a once-per-session in-app toast
  with an Open System Settings action. Mobile fan-out is unaffected.
- Settings > Notifications now shows the same live permission card as
  onboarding (moved to components/notifications/), polling the readout
  so System Settings changes reflect within seconds, and the test
  button updates it inline.
- Test sends that are blocked at the OS level now show the
  settings-pointing failure toast instead of a generic error.

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

* fix: hide macOS permission card while Orca notifications are disabled

A green 'Notifications are enabled' card next to a disabled Enable
Notifications toggle read as a contradiction — the card now renders (and
the readout polls) only while Orca's own notifications setting is on.
Also single-flights the authorization helper so simultaneous agent
completions share one readout process.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-08 22:21:40 -07:00
Jinjing c170866180 fix(terminal): clear leaked mouse-reporting modes on pane reattach (#7893)
* fix(terminal): clear leaked mouse-reporting modes on pane reattach

A TUI that enables mouse tracking (?1000/1002/1003 + SGR 1006/1016) and
dies uncleanly never emits the disable sequence, so the daemon's snapshot
records the mode and buildRehydrateSequences re-arms it on every reattach.
POST_REPLAY_REATTACH_RESET cleared cursor/focus/kitty state but not mouse
modes, so a plain shell in the reattached pane echoed every pointer-motion
report (`<35;col;rowM`) as literal text.

Add RESET_MOUSE_REPORTING (?9l ?1000l ?1002l ?1003l ?1006l ?1016l) to both
POST_REPLAY_REATTACH_RESET and POST_REPLAY_MODE_RESET. Live agent panes keep
mouse modes via POST_REPLAY_LIVE_AGENT_REATTACH_RESET, so agent scroll is
unaffected.

Verified against the real daemon serializer + real xterm: the old reset
leaves mouseTrackingMode armed, the new reset returns it to 'none'.

* test: add regression tests for terminal mouse mode leak on reattach

- Add an E2E test to verify that a warm reattach disarms mouse modes
  left armed by an uncleanly exited TUI.
- Add a test fixture that writes the mouse tracking enable sequence
  without a matching disable sequence.
- Ensure the reattached pane disarms mouse tracking and that actual
  mouse movement produces no reports.

* Add types to isMouseReport in terminal reattach leak test

Explicitly annotate parameter and return types for the isMouseReport
helper function inside the page.evaluate block.

* Refactor mouse-mode leak E2E test to use shell printf and live pane

Eliminate the external Node.js fixture file and streamline the E2E test
by using a POSIX printf shell builtin to arm the mouse tracking modes.

Additionally, verify the leak precondition by inspecting the active pane's
live terminal state (mouseTrackingMode) rather than querying internal
daemon buffer snapshots via window.api.pty.getMainBufferSnapshot.
2026-07-08 22:14:08 -07:00
Jinjing 404804737d Change GitHub issue layout from sidebar to top columns (#7887)
Replace the sidebar layout in the GitHub issue details view with a
responsive grid of top columns placed above the description body. This
ensures the description content is not squeezed by a right rail and fits
the header's full content width.
2026-07-08 22:06:46 -07:00
Jinjing 4ded642a3a Detect and surface recoverable zero-turn sessions in AI Vault (#7889)
Identify Claude sessions with no saved conversation turns but possessing
recoverable signals such as queued prompts or subagent transcripts.
This displays them in the sidebar with a "Not saved" badge instead of
filtering them out as empty, and provides detailed notices to recover
them via logs while disabling standard resume actions.

Additionally, extract Gemini session parsing logic into a separate
module and support counting sibling subagent transcripts across local
and remote SSH session scans.
2026-07-08 21:47:02 -07:00
Neil 8dbcb2be3e feat(floating-terminal): amber attention dot for unacknowledged bells and completions (#7888)
Show a small amber dot on the floating-workspace launcher (both the
floating-button and status-bar triggers) whenever any floating-workspace tab
still has an unacknowledged terminal bell or agent completion, and a
composited amber dot on the Windows tray icon when the window is
minimized/hidden. Both clear through the existing show-until-interact paths —
engaging with or closing the offending tab drops the dot with no stale unread
state left behind.

The launcher dot derives from the existing per-tab/per-pane unread maps via a
new selectFloatingWorkspaceHasUnread selector (primitive boolean, empty-
workspace early return, no bespoke state). The tray dot rides the notification
dispatch and clears on window show/restore.
2026-07-08 21:39:49 -07:00
Jinjing 5c6f0ad52d Fix stale open pr after merge (#7886)
* docs: design fix for sticky OPEN PR after merge

Capture root cause and primary fix for Checks panel preserving open/draft
PR cache on authoritative no-pr after merge + HEAD diverge.

* Clear open and draft PR caches on fallback refresh misses

Avoids preserving non-terminal ("open" or "draft") PR states in both
the PR and hosted-review caches when a fallback refresh returns an
authoritative "no-pr" result. This resolves a sticky "OPEN" UI bug
where a merged PR continued to show as open.

- Removes fallback PR preservation from the main PR cache check.
- Gates the hosted-review cache fallback preservation to only accept
  terminal states ("closed" or "merged").
- Updates unit tests to assert cache clearing for open/draft states.

* Remove stale open PR refresh design document

Delete the design and diagnosis document for the stale open PR checks
panel refresh issue now that the investigation and planning phase is
complete.
2026-07-08 21:38:49 -07:00
Jinjing 040e61e13f Keep explicit push and force push actions available without upstream (#7864)
- Keep the explicit "Push" and "Force Push" dropdown options enabled when
  there is no upstream or the upstream status is loading, letting Git
  resolve the target at execution time.
- Stop auto-upgrading regular push operations to force push in the background,
  ensuring normal push actions stay non-force.
- Explicitly route the primary action and commit-and-push flows to the
  "force_push" action when a lease force push is required.
2026-07-08 21:22:49 -07:00
JinjingandOrca 6b4831d5ef Fix Grok and Pi terminal title normalization and status detection (#7880)
* fix(mobile): normalize Grok rotating OSC titles at the main observation boundary

Desktop already collapses Grok Build's rotating working frames via the
renderer's normalizeTerminalTitle, but the main process stored raw OSC
titles, so mobile session tabs (fed from pty.lastOscTitle) still saw a
distinct title every spinner frame and re-touched snapshots each time.

Apply normalizeTerminalTitle once where main records an observed OSC
title, before the prevTitle comparison that gates session-tab and
mobile-snapshot touches, and normalize hydration-seeded titles the same
way so the first live frame after a seed compares equal. Agent status
stays detected from the raw title, mirroring the renderer tracker.

Covers remoted/SSH PTYs too since they surface through the same main
observation path.

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

* Fix Grok and Pi terminal title normalization and status detection

- Require a strict "spinner - phrase - grok" pattern for Grok working
  titles to prevent false positives on other agent tasks ending in
  "- grok" (such as Claude or Codex).
- Treat collapsed "Pi" and "OMP" synthetic titles as idle by default
  to prevent them from reverting to neutral status after normalization.
- Prevent duplicate mobile session tab updates during Grok status
  frame rotations by ensuring they normalize to a stable title.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-08 21:22:06 -07:00
JinjingandOrca 7e1a77728b fix(renderer): preserve live agent cursor visibility across replays (#7858)
Cursor Agent parks the real cursor on a blank row and hides it (?25l),
drawing its own caret. Orca's post-replay resets forced ?25h, painting a
stray cursor block below the agent's prompt after reattach and after
hidden-to-visible snapshot restores.

Root cause fix: stop re-showing a cursor the replayed bytes intentionally
hid, instead of compensating afterwards.

- Live-agent reattach reset now preserves the payload's final DECTCEM
  state (last ?25l/?25h wins); the post-parse viewport veto re-shows the
  cursor when the screen disproves a live parked agent, so a shell can
  never inherit a permanently hidden cursor from a dead TUI's leftovers.
- Hidden-output restore now uses a live-agent variant of the snapshot
  reset when status/title corroborates a live agent: forcing ?25h
  re-showed the parked cursor, and ?1004l permanently silenced the
  focus-in the agent needs to unpark (agents only enable focus reporting
  at startup, so nothing ever re-armed it).

Co-authored-by: Orca <help@stably.ai>
2026-07-08 19:08:00 -07:00
Jinjinganddalveytech-vincent 070a956a72 feat(source-control): add push failure AI recovery (#7826)
* feat(source-control): add Fix push failure with AI for pre-push hooks

Detect pre-push hook failures separately from auth/transport errors so
push toasts and inline messages no longer suggest checking repo access.
Mirror the commit-failure recovery flow with a fixPushFailure action,
summary panel, details dialog, and agent launch recipe in Settings.

Fixes #6497

* feat(source-control): add push failure AI recovery

Co-authored-by: dalveytech-vincent <vincent@dalveytech.com>

---------

Co-authored-by: dalveytech-vincent <vincent@dalveytech.com>
2026-07-08 18:59:28 -07:00
Jinjing 2af8fb886f Collapse Grok rotating working titles to stable label (#7863)
Grok Build's working OSC titles interpolate a rotating status or tool
phrase between the spinner and its name, causing tab and sidebar
titles to fluctuate rapidly. Collapse these working frames to a stable
"⠋ Grok" label, while leaving idle and session titles untouched.
2026-07-08 18:57:07 -07:00
Jinjing 29cbe2d8cb Show empty sessions by default in AI Vault Panel (#7853)
* Show empty sessions by default in AI Vault Panel

Change the default state of `hideEmptySessions` from true to false, and update the active filter count calculation to treat false as the new default.

* Centralize AI Vault view defaults and fix reset state alignment

Consolidate the default values for sorting, grouping, and hiding empty
sessions into a single place. This prevents inconsistencies between the
initial state, the badge count adjustment checks, and the "Reset" view
action, where the reset previously toggled hideEmptySessions to true
contrary to the initial false value.

* Count agent adjustments by membership instead of list length

Ensure that swapping one agent for another (which keeps the total
array length the same) is correctly identified as a deviation
from the default of having all agents enabled.
2026-07-08 18:44:54 -07:00
Jinjing 9e23b8963b fix(agent-status): show waiting for Claude AskUserQuestion, stop stale-title worktree spinners (#7852)
Claude's AskUserQuestion tool is auto-allowed, so it emits a PreToolUse (not
PermissionRequest) while blocked on a human answer. normalizeClaudeEvent mapped
that to `working`, so the sidebar showed a spinner that decayed to grey while
the question sat. Map the auto-allowed AskUserQuestion PreToolUse to `waiting`
instead, mirroring the Kimi/OpenCode handling, so the row and worktree dots read
amber "Waiting for input".

Separately, a frozen braille-spinner title left by an exited agent (e.g.
"⠐ Review branch for regressions" over a shell prompt) kept classifyTitleActivity
returning `working`, spinning the worktree dot forever with 0 agents — the row
builder rejects the same unattributable title, so no agent row is shown. Gate
tabHasStatus's title-derived working/permission on the same agent attribution the
row builder uses (resolveAgentTypeFromTerminalTitle), so a title only spins the
dot when it would also show a row. Hook-driven status (hasLiveWorking/
hasPermission) is untouched.
2026-07-08 18:44:43 -07:00
JinjingandOrca c2b074bd15 fix(terminal): shape Arabic/RTL text on the cell grid via xterm character joiner (#7665)
* fix(terminal): shape Arabic/RTL runs on the cell grid via xterm character joiner (#5262)

Register a character joiner that groups contiguous RTL runs (tunneling
through neutral spaces/digits/punctuation between RTL words) so both the
WebGL and DOM renderers draw each run as one string, applying native
contextual shaping and BiDi ordering inside the run's grid-aligned cell
box. Buffer and PTY stream are untouched; xterm un-joins ranges holding
the cursor or a partial selection, keeping cursor visibility and
selection cell-accurate. Non-RTL lines early-return via a single
charCodeAt sweep.

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

* Deregister Arabic shaping joiner when disposing pane

Since xterm.js does not automatically remove registered character joiners
upon terminal disposal, they must be explicitly deregistered to avoid
memory and registration leaks.

- Update `registerArabicShapingJoiner` to return a cleanup function.
- Store and call the cleanup handler when disposing a managed pane.
- Update tests to assert proper registration and deregistration.

* fix(terminal): gate RTL joining on live WebGL, tunnel ZWNJ/ZWJ/RLM, lock joiner lifecycle in tests

Review findings on the Arabic shaping branch:
- The DOM renderer sizes a joined span with one letter-spacing value applied
  per character, so joined RTL runs blew out row grid alignment whenever the
  WebGL renderer was unavailable (GPU off, auto policy, context loss). The
  joiner now only returns ranges while the pane's WebGL addon is live.
- ZWNJ/ZWJ/RLM (mandatory in Persian orthography) hard-broke RTL runs,
  rendering word halves in swapped visual order. They are now transparent
  inside a run without extending or counting toward it.
- openTerminal's existing unicode-ordering test failed at HEAD because the
  fake terminal lacked registerCharacterJoiner; the harness now implements
  the joiner API and a new test locks register-on-open/deregister-on-dispose.

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

* fix(terminal): keep zero-width RTL marks from opening joined runs, treat ALM as transparent

Round-2 review findings:
- A combining mark (tashkeel/niqqud) orphaned after an LTR base could open
  an RTL run mid-cell; xterm rounds that string range to an empty joined
  cell range and the WebGL renderer draws an empty glyph over the next
  character. Marks now extend and count only in runs opened by a spacing
  RTL letter.
- ALM (U+061C) sat inside the strong-RTL block scan, so it opened and
  counted toward runs unlike RLM. It now joins the transparent set.
- New test locks openTerminal wiring the joiner predicate to
  pane.webglAddon (previously () => true would pass the suite).

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

* fix(terminal): treat zero-width Cf controls in RTL blocks as run-transparent

Round-3 review finding: zero-width format controls that live inside the
strong-RTL scan ranges (Arabic number signs U+0600-0605, end of ayah U+06DD,
Syriac abbreviation mark U+070F, disputed end of ayah U+08E2) and the BOM/
ZWNBSP U+FEFF are width-0 in xterm. Like combining marks they could open a
run mid-cell, producing an empty joined cell range that blanks the following
glyph in the WebGL renderer. They are Cf not Mn, so canOpenRtlRun could not
catch them. Fold them into the run-transparent set (never open, count, or
break a run) and document the upstream standalone-width-0-cell join skew.

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

* Document WebGL decoration limitation for Arabic shaping joiner

Add comments explaining a known upstream limitation in xterm.js WebGL
renderer where search-match highlights inside a joined run render
all-or-nothing, similar to ligatures.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-08 18:29:36 -07:00
Brennan BensonandOrca 47389990a5 fix(mobile): surface disconnected source-control states + keep the mobile WS fallback port stable (STA-1511) (#7855)
Co-authored-by: Orca <help@stably.ai>
2026-07-08 18:28:59 -07:00
01d21cdce1 fix(agents): route WSL OMP hooks to the Windows listener (#7565) (#7641)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-07-08 17:05:21 -07:00
Brennan BensonandOrca 95f3933ea2 feat(native-chat): upload composer attachments over SSH (#7832)
Co-authored-by: Orca <help@stably.ai>
2026-07-08 16:56:16 -07:00