Commit Graph
8614 Commits
Author SHA1 Message Date
4930c87219 fix(github): load PR details on fork checkouts by preferring upstream (#9384)
On a fork checkout (origin=fork, upstream=parent) PR details failed to load because getOwnerRepo() resolved only the origin remote while GitHub PRs live on the upstream parent. Make getOwnerRepo() prefer upstream (mirroring getIssueOwnerRepo), and pin the call sites that genuinely need the checkout's own origin identity (getRepoSlug, getRepoUpstream, createGitHubPullRequest, resolvePrWorkItemSource) to the origin-only primitive.

Lands the fix community-identified in #7332 and hardened in #7513.

Closes #7331

Co-authored-by: fsdwen <1214772+fsdwen@users.noreply.github.com>
Co-authored-by: brennanb2025 <79079362+brennanb2025@users.noreply.github.com>
2026-07-18 14:53:22 -07:00
Neil 403d681d83 fix(terminal): re-linkify streamed URLs so links underline/click on first hover (#9320)
Invalidate xterm's linkifier hover cache (throttled) when output streams into a visible pane, so a URL printed under a stationary pointer underlines and becomes Cmd/Ctrl+clickable on the next pointer move instead of after several clicks. Skips while a link is hovered (no flicker) and re-arms so the reset is never dropped mid-hover. Reuses the visibility-resume primitive (#9061).
2026-07-18 14:27:34 -07:00
Jinjing b45a222f03 docs: remove terminal garble investigation notes
Scratch investigation doc is no longer needed on main.
2026-07-18 12:56:29 -07:00
Jinjing 4ae67e863a Merge branch 'docs/wechat-group-3-qr' 2026-07-18 12:47:18 -07:00
Jinjing 5cdf83be5e docs: rotate WeChat QR to group 3
Groups 1 and 2 are full; point readers at the new third-group QR in EN/ZH README.
2026-07-18 12:46:58 -07:00
github-actions[bot] 54cb772b9c release: v1.4.146-rc.0 v1.4.146-rc.0 2026-07-18 17:17:15 +00:00
Brennan Benson bb71a3a991 fix(terminal): bypass rejected macOS login sessions (#9301)
* fix(terminal): bypass rejected macOS login sessions

* fix(terminal): bound macOS login preflight

* test(terminal): isolate macOS login preflight

* fix(terminal): avoid blocking macOS login preflight

* fix(terminal): cancel pending PTY preparation

* fix(terminal): cancel preparation on daemon shutdown
2026-07-18 10:16:21 -07:00
github-actions[bot] d8629c41c8 Update README downloads badge 2026-07-18 12:35:43 +00:00
NeilandOrca 057a81493a fix(sidebar): guard every worktree sort against undefined displayName (crash 99657ab1) (#9315)
* fix(sidebar): guard every worktree sort against undefined displayName (crash 99657ab1)

Worktree.displayName is typed non-optional but arrives undefined at runtime for
persisted/discovered worktrees (crash 99657ab1). PR #8683 fixed the kanban board;
this extends the same guard to the five other sort sites that share those worktree
objects — including the Cmd+J switcher (order-empty-query-worktrees) — via one
shared compareWorktreeDisplayName helper in lib/. Behavior-neutral when names are
present; a missing name now sorts as '' instead of throwing.

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

* docs(agents): add over-commenting anti-pattern example to the comment rule

Anchors the existing 'document the why, briefly' rule with a concrete
before/after (the worktree-displayName guard) so agents stop dumping the
crash id, mechanism, file location, and every call site into a comment.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-18 01:55:00 -07:00
Jinho Choi 72d0a403a3 fix(editor): use Monaco's registered proto language id for .proto files (#9286) 2026-07-18 00:22:20 -07:00
Jinjing 45c4a1f61e refs/heads/create-pr-should-handle-sync (#8534) 2026-07-18 00:21:00 -07:00
NeilandOrca b8502b21bb perf(terminal): bound recent-PTY-output with a chunk deque (drop per-chunk 64KB concat) (#9291)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 23:57:24 -07:00
NeilandOrca 2783f758df perf(persistence): compact JSON for durable-state save payload (drop pretty-print) (#9290)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 23:56:05 -07:00
hanjoonchoe 0c73e3c33d fix(i18n): use full-sentence keys in RemoveFolderDialog description (#9296) 2026-07-17 23:55:12 -07:00
Brennan Benson 0532765b7f fix(pty): stop daemon reattach/kill race from orphaning restored terminals (#7742 sub-issue B) (#7836)
* fix(pty): stop daemon reattach/kill race from orphaning restored terminals

Two cold-start defects let a PTY kill silently orphan a live daemon session
after a renderer/app restart — the PTY-orphaning-on-restart half of #7742:

- DaemonPtyAdapter.shutdown() was the only session op that skipped
  ensureConnected(). The daemon client connects lazily, so a kill arriving
  before the first spawn (startup sleep/hibernation sweeps, closing a
  restored tab) threw "DaemonProtocolError: Not connected" against a
  HEALTHY daemon; the renderer swallows the rejection and the live session
  survives detached. Fix: connect first, like every other session op.

- pty:kill had no startup barrier while pty:spawn did. A kill issued before
  initDaemonPtyProvider swapped the provider resolved against the pre-daemon
  LocalPtyProvider, whose shutdown() silently no-ops on daemon ids; the
  handler then reported success and sent a synthetic pty:exit, permanently
  clearing the persisted tab->ptyId binding so the session never reattaches.
  Fix: pty:kill awaits the same getLocalPtyStartupPromise gate as spawn.

Both reproduced red-first (real DaemonServer socket rig for the adapter;
deferred-barrier IPC rig for the handler) and pass after the fix.

Scope: this restores the reattach/teardown invariant. It does NOT address
the renderer crash trigger or the daemon-process-death path that produces
the Windows PowerShell FailFast symptom (separate follow-ups).

* fix(pty): gate runtime shutdown on daemon startup

* fix(pty): keep shutdown independent of hook startup
2026-07-17 20:10:59 -07:00
Jinwoo-HandOrca ab0f220c60 fix(runtime): return authoritative visible TUI output
Co-authored-by: Orca <help@stably.ai>
2026-07-17 20:09:33 -07:00
OrcaWinandBrennan Benson cb9c42d605 fix(terminal): filter focus reports after Codex history resume (#9259)
* fix(terminal): filter focus reports after Codex history resume

* test(terminal): preserve focus reports outside Codex resume

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-07-17 19:25:13 -07:00
Brennan Benson bd7205684a test(pty-connection): drain async confirm reads between tests (#9260)
The connectPanePty suite intermittently fails in CI on
`clearAgentLaunchConfig` call-count assertions (e.g. expected exactly
once, received 5 with pane keys belonging to other tests).

Root cause is cross-test async leakage: pane foreground-agent trackers
kick off `confirmForegroundProcess` reads whose continuations settle on
the microtask queue, not on fake timers. A test that ends with one still
in flight leaks it into the next test, where it resolves against that
test's fresh store mock and calls clearAgentLaunchConfig with the prior
test's pane key.

Drain pending microtasks in afterEach (before tearing down fake timers,
while the test still owns its store mock) so each test absorbs its own
async fallout. No behavior change; full suite stays green (446/446).

Note: this is a CI-timing flake not reproducible locally in isolation
(ordered runs pass repeatedly, incl. under GC pressure); the fix targets
the confirmed leak mechanism and removes the timing dependence.
2026-07-17 19:17:33 -07:00
Brennan Benson d1532956fd fix(keybindings): AltGr-safe default for Add Review Note (#9257)
* fix(keybindings): use AltGr-safe default for Add Review Note

The editor.addReviewNote default was Mod+Alt+N, which resolves to
Ctrl+Alt+N (AltGr) on Windows/Linux. On diacritic layouts AltGr+N
types a real character (e.g. Polish n-acute), so the editor-scope
chord hijacked normal typing. Switch the default to Mod+Shift+A,
which is AltGr-safe and keeps a mnemonic (A for annotate).

* test(keybindings): cover Add Review Note chord end to end
2026-07-17 18:57:26 -07:00
Brennan Benson 3e276d78ba fix(ssh): probe npm via prepended PATH, not colocated with node (#9165) (#9255)
* fix(ssh): probe npm via prepended PATH, not colocated with node (#9165)

The remote Node/npm toolchain gate invoked npm by its absolute path
<nodeBinDir>/npm (POSIX) / npm.cmd (Windows, behind a Test-Path
colocation check). But deploy (commandWithNodePath) runs bare `npm`
with nodeBinDir merely prepended to PATH, so npm can resolve from
anywhere on PATH.

A host whose only resolvable node has npm elsewhere on PATH (e.g. node
symlinked into a dir without npm) deployed fine on v1.4.144, but after
upgrade the candidate is rejected with no fallback → SSH/relay
connection fails to establish.

Make the probe resolve npm exactly the way deploy does — bare
`npm --version` under the same prepended PATH — so it still confirms npm
is runnable (the #8450 concern) without requiring colocation. Windows
now prepends the backslash-form dir (matching deploy) so bare-command
PATH lookup resolves reliably.

* test(ssh): cover split Node npm PATH resolution
2026-07-17 18:51:10 -07:00
NeilandOrca c436df0551 feat(tray): mark dev-instance tray icons with a DEV indicator (#9253)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 18:50:21 -07:00
Brennan Benson 64c7f14c3b fix(codex): clarify account-switch restart card actions (#9254)
The account-switched restart card had two near-synonymous dismissive
buttons (Dismiss / Collapse) whose distinct behaviors weren't legible,
and body copy that attributed "keep working with the current account"
to Collapse — which only minimizes the notice.

Remap to intent-named actions:
- Dismiss  -> "Keep old account" (clears the notice; pane stays on the
  old account)
- Collapse -> "Not now" (minimize to the pill; decision deferred)
- Body no longer claims the minimize action commits you to an account.

Restart, the title, and the heading are unchanged. New English strings
get fresh auto keys so stale es/ja/ko/zh translations don't persist;
catalog re-synced.
2026-07-17 18:42:59 -07:00
slashdevcorpse ad206027b8 fix(terminal): replay cold restores at recovered grid (#9043) 2026-07-17 18:42:31 -07:00
NeilandOrca 3a27fb59cd fix(settings): stop shortcut filter rail overlapping the list below xl (#9252)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 18:37:55 -07:00
NeilandOrca ed28dec592 feat(new-workspace): always offer "Add a new project" in Create worktree picker (#9251)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 18:37:20 -07:00
Jinwoo HongandOrca 360b2423ea Fix duplicate and lost IME terminal commits (#9235)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 18:29:44 -07:00
Brennan Benson 2f5fc65ba4 fix(terminal): don't report agent exit on a degraded foreground scan (#9244)
* fix(terminal): don't report agent exit on a degraded foreground scan

On Windows/ConPTY the foreground scan (a Get-CimInstance Win32_Process
PowerShell fork) can exceed its 3s budget under load, and there is no
wmic fallback on Win11 24H2+. A timed-out scan returned the shell name,
which the completion coordinator reads as "agent exited" and fires a
false "agent done" notification while the agent is still working.

Prefer the last positively-recognized agent across a degraded
(available:false) scan so a transient failure no longer looks like an
exit. An authoritative (available:true) scan still refreshes/clears the
memory, so a genuine exit or crash is still detected. No-op on macOS,
where the scan is always available.

* fix(terminal): drop stale foreground scan results
2026-07-17 18:09:39 -07:00
Jinwoo HongandOrca cbdd750f73 fix(terminal): keep redraw transcript cursors stable (#9081)
Co-authored-by: Orca <help@stably.ai>
2026-07-17 18:07:24 -07:00
Brennan Benson 24ac5a556e fix(updater): humanize update-error card and hide raw error behind Show details (#9248)
* fix(updater): humanize update-error card and hide raw error behind Show details

Windows auto-update failures surfaced the raw electron-updater message as the
card headline — most visibly the PowerShell "Command failed: … Get-Authenticode
Signature …" dump when antivirus/EDR blocks the post-download signature check.
That reads as a crash, not an actionable state.

Classify each failure and lead with one plain-language sentence + the right
action, keeping the raw error one click away:

- New shared classifier (updater-windows-signature-check): distinguishes an
  AV/EDR-blocked signature check (environment) from a genuine wrong-publisher
  mismatch (security). The two are mutually exclusive so a real integrity
  failure is never softened into "try again".
- UpdateCard: raw error moves behind a collapsed "Show details" toggle; adds a
  security-stop variant (wrong publisher → no retry, "Open official releases")
  and the AV-blocked variant ("Update Verification Blocked"). HTTP/2 and generic
  paths keep their existing actions, now with the same details disclosure.
- Main process records a windows_signature_check_blocked lifecycle event so we
  can size the affected Windows cohort in the field.

Verified each error scenario in a running Electron build (signature-check
blocked, wrong-publisher security stop, HTTP/2, generic, and the expanded
details view).

* fix(updater): make Show details a caret disclosure above the action row

Move the raw-error toggle directly above the Retry/Download buttons and give it
a rotating chevron; the Last error block now expands in place beneath the caret
instead of appearing above the summary, with the action buttons pinned below.

* fix(updater): prevent signature-check bypass

* fix(updater): surface retry start immediately
2026-07-17 18:00:06 -07:00
github-actions[bot] 2668af035c Update README downloads badge 2026-07-18 00:50:48 +00:00
github-actions[bot] 212b79a03a release: v1.4.145-rc.3 v1.4.145-rc.3 2026-07-18 00:30:55 +00:00
eisen0419andJinjing 3f335efdb9 feat(agents): pi session resume support (#8876)
* feat(agents): pi session resume support

* fix(pi): require persisted session files for resume

* test(sleeping-agent): use non-resumable sentinel in malformed-record fixture

The 'drops malformed sleeping agent resume records' test used agent:'pi' as
its example of an unknown/non-resumable agent, expecting the record to be
dropped. This PR added 'pi' to RESUMABLE_TUI_AGENTS, making that fixture
valid and retained, so the toBeUndefined assertion broke. Switch the
malformed-case fixture to a genuinely non-resumable sentinel
('definitely-not-an-agent') so the drop-malformed path is still exercised;
no other assertions changed.

* Add durable resume identity for Pi sessions without fabricating turn sta

Pi's `session_start` hook now carries the session file needed to resume
a sleeping pane, but until now Orca either discarded it or treated it
as a fake status transition. Thread a `providerSessionOnly` envelope
through the hook listener, relay, main-process server, and renderer
store so resume identity (and its session-file-scoped equality/claim
key) can be persisted and replayed without emitting prompt telemetry
or a visible working/done row.

* Add durable resume identity for completed Pi sessions

Pi's agent_end hook marks a turn done, but the underlying TUI session
stays alive and resumable. Previously a `done` status wiped sleeping
records and launch config as if the session ended, so hibernation,
manual worktree sleep, and quit-capture all lost Pi's resume identity.

- Track a "live recovery" record for done-but-still-resumable Pi
  sessions, exempting it from the usual done-state cleanup paths in
  agent-status.ts and agent-hibernation-planner.ts
- Gate providerSessionOnly rows and sleeping-agent schema records on
  actual resumability (getAgentResumeArgv) instead of trusting the
  presence of a provider session
- Wait for Pi to persist its session file before advertising resume
  metadata, and treat `/reload` as a non-terminal event so it doesn't
  clobber visible status
- Extend SSH relay envelopes to carry providerSessionOnly so remote
  hosts get the same behavior

* Add explicit periodic/quit mode to sleeping-agent session capture

Split captureAllSleepingAgentSessions into 'periodic' and 'quit' modes
so a background checkpoint can no longer downgrade a confirmed-quit
record or promote a completed Pi session without an authoritative
transcript path. Updates all call sites and tests accordingly.

* Use normalizeAgentStatusPayload for default pi status

Remove unnecessary JSON.stringify wrapper and call the appropriate normalization function directly.

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-17 17:29:04 -07:00
Asurada 7c7bf259a2 fix(i18n): correct Chinese UI terminology (#9154) 2026-07-17 17:27:18 -07:00
1bd757ad2f fix(i18n): correct zh translation of "Pin Tab" to 固定标签 (#9157)
Co-authored-by: weixin <weixin@thunisoft.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 17:25:55 -07:00
hanjoonchoe 2a22dd0f2a fix(i18n): translate untranslated Korean catalog strings (#9019)
Translate 105 ko.json entries that were still identical to their English
source after the machine bootstrap — dialog bodies, settings descriptions,
shortcut recorder labels, Windows firewall notices, Jira connection copy,
crash-report notices, and source-control panel text.

Intentionally left in English: brand/product names, command and config
examples, CSS/selector strings used by animated visuals, and lowercase
concatenation fragments whose word order cannot be reordered safely.
2026-07-17 17:23:44 -07:00
slashdevcorpseandBrennan Benson 803a442868 test(e2e): harden terminal restart regressions on Windows (#9064)
* test(e2e): harden Windows terminal restart regressions

* test(e2e): cover renderer replacement rejection

* test(e2e): tolerate ESRCH when force-killing the daemon on POSIX

* fix(ci): preserve Windows restart test selection

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-07-17 17:18:36 -07:00
Jinjing 546cc8237f Improve native chat ui (#9246)
* refactor(native-chat): extract option appliers and improve toggle UI

- Extract setOption apply logic to native-chat-session-option-apply.ts
- Add invokeAction method for toggle-only options without tracked baseline
- Replace checkbox UI with On/Off radio groups for boolean options
- Display option values only in pills (remove redundant label prefixes)
- Serialize concurrent applies so later dispatches win in order

* Remove focus-visible border from composer container

The container uses a steady hairline border (no focus/click flash), with focus-visible styling delegated to the inner textarea. The container is a layout wrapper, not a focus target.

* Prevent option commits on model switch during dispatch

When a user changes an option and the model switches before dispatch
completes, committing the stale option would overwrite state under
the new model. Guard by capturing the baseline option state before
dispatch and validating it hasn't changed post-dispatch.

* Use invokeAction for model option in NativeChatComposer test

Codex model is an agent picker mid-session, so setOption rejects.
Update test to use invokeAction to match the actual UI behavior.
2026-07-17 17:18:27 -07:00
Brennan Benson 49e625d41a fix(mobile): harden WebSocket accept path against socket overload (#9247)
* fix(mobile): make the :6768 WebSocket accept loop leak-proof and self-healing

The desktop runtime's mobile WebSocket server on :6768 could wedge with the
socket in LISTEN but the TCP accept loop stalled — new connections piling up in
SYN_RCVD with zero ESTABLISHED, even from localhost, with no self-heal. Since
Orca mobile has no APNs (the persistent WS doubles as the push channel), a
wedged accept loop silently drops every notification while the app still shows
cached UI.

Root cause: connections were only capped at the WebSocket-upgrade layer
(MAX_WS_CONNECTIONS), after the socket is already accepted. TCP-level sockets
were unbounded, so leaked/half-open sockets (backgrounded phones, flaky relay,
reconnect storms) could grow until the process ran out of file descriptors and
accept() started failing with EMFILE.

- Bound TCP sockets via httpServer.maxConnections (2x the WS cap). At the cap
  Node accepts-then-closes, so the accept loop always keeps draining and the
  EMFILE/SYN_RCVD wedge is structurally impossible on this listener.
- Handle accept-level errors: ws forwards httpServer 'error' onto the
  WebSocketServer; with no listener Node rethrows it as an uncaught exception.
  Swallow + log and keep listening.
- Force-terminate over-capacity sockets: a bare ws.close(1013) left half-open
  phones lingering at >cap forever, rejecting everyone after them. Add an error
  handler + a 1s terminate fallback so the descriptor is always freed.
- Log heartbeat reaping / near-cap live counts so the leak is observable.

* fix(mobile): avoid masking fatal accept failures
2026-07-17 17:12:27 -07:00
Rod BoevandBrennan Benson 72a5c6f199 fix(terminal): paint paired remote terminals on first subscribe (#8954)
* fix(terminal): paint paired remote terminals on first subscribe

* test(terminal): cover desktop legacy subscriber PTY wait

The widened terminal.subscribe gate (isMobile -> params.client) had no
regression test: reverting it to the mobile-only gate left the suite
green. Add a desktop legacy-subscriber case asserting the mount request
and late-PTY wait fire before the scrollback-only fallback.

* fix(terminal): cancel abandoned multiplex PTY waits

Desktop subscribers can close while the new late-PTY wait is pending. Register provisional slot cancellation and abort all pending waits on unsubscribe, connection abort, or multiplex teardown so a late PTY cannot resurrect a ghost output stream.

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-07-17 17:08:53 -07:00
Brennan Benson 5907816457 feat(keybindings): swap tab-switch chords to the common convention for new users (#9240)
* feat(keybindings): swap tab-switch chords to the common convention for new users

New installs now get the widespread mapping — Mod+Shift+[ / ] cycles across
all tabs, Mod+Alt+[ / ] cycles within the active tab type. Pre-existing installs
keep today's mapping: a one-time cohort seed (frozen on first launch via the
fileExistedOnLoad signal, mirroring the telemetry migration) pins the legacy
chords into keybindings.json, skipping any action the user already customized.

- shared registry: swap the four tab.*SameType / tab.*AllTypes defaults; export
  LEGACY_TAB_SWITCH_BINDINGS for the seed
- persistence: migrateTabSwitchKeybindings freezes the existing-vs-fresh cohort
  (tabSwitchKeybindingSeed = pending | done)
- keybinding-file: seedLegacyTabSwitchBindings writes the legacy pins into the
  active-platform section so Settings reset still works
- refresh stale default-chord comments
- tests for the swapped defaults, the seed (fresh/existing/customized/idempotent),
  and the cohort migration

* test(keybindings): prove existing-user parity + make the seed strictly per-action

seedLegacyTabSwitchBindings now pins each un-customized action individually
instead of skipping all four when any one is customized. A partially-customized
existing user keeps their rebound action AND the pre-swap default on the rest;
no existing user's behavior changes. The skip check keys on this platform's
effective overrides so a foreign-platform-only override can't leave the active
platform on a new default.

Adds keybinding-service.test.ts: constructs a real KeybindingService and asserts
effective bindings + real keystroke matching for both cohorts across darwin/
linux/win32, plus partial-customization, idempotency, and seed-failure retry.

* fix(keybindings): preserve legacy files during tab shortcut seed

* fix(keybindings): preserve valid pre-swap overrides
2026-07-17 16:58:04 -07:00
Trevin Chow 613dcd8c9b fix(pr-comments): make the review sidebar legible for structured bot markdown (#9209)
Restore readable block flow, typography, nested spacing, and heading semantics for structured review Markdown in the PR sidebar. Preserve the compact renderer's existing remote-image trust boundary.
2026-07-17 16:39:02 -07:00
Brennan Benson 7c0b84f2b6 fix(terminal): invalidate cached glyphs when WebGL atlas changes (#8899)
* feat(terminal): add flag-gated render-desync sentinel for WebGL panes

Detects the buffer-clean/render-stale glyph garble class in the field: per
visible WebGL pane, compare the cells the xterm buffer says hold glyphs
against the ink actually present on the canvas, sampled in the same task as
a forced synchronous redraw so a divergence proves the render model/atlas is
wrong rather than a missed present. A trip requires the same screen cells to
stay divergent across three samples (real desync is pinned; scroll lag moves),
then records a webgl-render-desync breadcrumb, stashes evidence (canvas PNG +
buffer text) for bug reports, and runs the same shared-atlas recovery a tab
reveal performs, so a stuck-garbled pane self-heals within seconds.

Off by default; arm on any build via
localStorage.setItem('orca:render-desync-sentinel', '1') and reload.

* fix(terminal): invalidate glyph cache on atlas replacement

Reproduce the WebGL atlas identity mismatch with two live terminals and force cached geometry to rebuild whenever a different shared atlas is attached. Persist flag-gated render-desync evidence and retain the investigation tooling used to validate the field signature.

* fix(terminal): harden render desync diagnostics

* docs(reliability): clarify Linux WebGL evidence gap
2026-07-17 16:16:17 -07:00
Brennan Benson 14116e3573 feat(settings): unify skill card status and add Linear agent-skill section (#9218)
* feat(settings): unify skill card status and add Linear agent-skill section

Show the freshness-aware status pill ("Up to date" / "Update available")
on the Orchestration skill card, matching the Computer Use card — it was
the only installed-skill card still limited to a presence-only "Installed"
pill because it omitted the freshnessSkillName prop.

Add a Linear capability section under Settings → Agents that only appears
once the Linear provider is connected. It mirrors the other skill panes:
an orca-linear skill card (Update / Re-check + freshness pill) and a "How
to use it" grid of copyable /orca-linear prompts.

The Orchestration and Linear "How to use it" surfaces now share extracted
SkillUsageExamplesSection / SkillUsageExampleDialog components (the old
orchestration-only dialog is renamed/generalized with a slashCommand prop).

The nav registry and Settings page gate the Linear section on one shared
useLinearProviderConnected() selector so the sidebar entry and the section
appear and disappear together.

* fix(settings): tighten Linear skill section behavior

* fix(settings): preserve Linear freshness and dialog translations

* fix(linear): migrate legacy skill installs

* Revert "fix(linear): migrate legacy skill installs"

This reverts commit 3ff45f9245.

* fix(settings): show Linear freshness in sidebar

* fix(settings): type Linear navigation target
2026-07-17 16:15:58 -07:00
Jinjing ba25e4306c Replace assistant-prose heuristic with explicit turn lifecycle markers (#9121)
* Replace assistant-prose heuristic with explicit turn lifecycle markers

Extract provider-authored turn boundaries (completion, interruption) directly
from Claude/Codex transcripts so the chat view knows when work ends without
guessing from message presence. Reconciles live hook state with transcript
lifecycle: when a terminal boundary lands, it settles a dropped Stop hook
instead of letting prose mislead the UI into showing 'working' after done.

* fix(review): cover Claude terminal stop_reasons and RPC lifecycle frames

Treat max_tokens/stop_sequence/refusal as completed markers so capable hosts
do not stay working after a dropped Stop, and assert lifecycle payloads on
runtime subscribe/read frames plus mid-turn non-terminal stop_reason cases.

* test(native-chat): clarify that lifecycle field is optional

Add type assertion and comment documenting that lifecycle field is optional and can be omitted in truncation-gating test fixtures.

* fix(native-chat): settle status on interruption despite working subagent

When Claude's turn is explicitly interrupted, the session should show ready
immediately — even if background subagents are still running. Add an
interruption check before consulting the hook's working-subagents flag so
interruptions take precedence. Also normalize omitted lifecycle timestamps
to null instead of leaving them undefined, and add test coverage for both
cases.

* fix(native-chat): settle loading spinner on explicit turn boundaries

Explicit transcript turn-lifecycle markers now fully replace the prose-fallback
settlement path. Remove the now-unused `turnLifecycleCapable` flag and wire
lifecycle to suppress spinner even when hook status lingers. Refine Claude
lifecycle detection to distinguish terminal stops from mid-turn tool_use rows,
exclude harness noise from new-generation detection, and apply clock-skew slack
over SSH/relay. Serialize PTY sends per line to prevent rapid prompts from gluing
before Enter, clearing unsubmitted input on cancel. Update working suppression to
detect epoch rollovers so interrupt+next-turn without a ready gap resets the
spinner correctly.
2026-07-17 15:59:38 -07:00
Brennan Benson e719ef1a57 fix(mobile): survive connection-migration cutovers during worktree create (#9234)
* fix(mobile): survive connection-migration cutovers during worktree create

A worktree.create in flight when the mobile transport migrates (relay/direct
hand-off on shoddy cellular, relay lease rotation, relay recovery) rejects with
"RPC interrupted by connection migration" even though the host completed it —
leaving the Create Workspace modal stuck while the worktree exists on desktop.
A naive retry hits a name collision and spawns a duplicate.

Mirror the existing mobile terminal-create idempotency: worktree.create now
accepts an optional clientMutationId that the host dedupes (in-flight + brief
post-success TTL), and mobile mints one key per candidate name and re-issues
the create on a cutover so the retry reconciles instead of duplicating.

* fix(mobile): gate worktree cutover replay by capability

* fix(mobile): await worktree replay capability
2026-07-17 15:56:43 -07:00
b259300032 perf(worktrees): bound runtime discovery scans (#8915)
* perf(worktrees): bound repeated runtime discovery scans (#8882)

* fix(worktrees): invalidate scans on SSH state changes (#8882)

* fix(worktrees): key scan reuse by execution runtime (#8882)

* test(worktrees): prove cached lineage variants (#8882)

* test(worktrees): exercise lineage through the shared scan cache (#8882)

* fix(worktrees): prevent stale runtime scans from repopulating cache (#8882)

* test(worktrees): prove stale generations stay out of cache (#8882)

* fix(worktrees): invalidate hidden SSH scans on relay state (#8882)

* fix(worktrees): scope SSH scan invalidation to provider changes (#8882)

* fix(worktrees): preserve enriched hidden SSH state notifications (#8882)

* test(worktrees): pin SSH provider generation monotonicity (#8882)

* test(worktrees): drain cached scan mock responses (#8882)

* fix(worktrees): scope resolved SSH invalidation to affected repos (#8882)

* fix(worktrees): separate SSH scan invalidation from client events (#8882)

* perf(worktrees): preserve raw scan reuse across metadata updates

# Conflicts:
#	src/main/runtime/orca-runtime.ts

* perf(worktrees): scope repo-local scan invalidation

# Conflicts:
#	src/main/runtime/orca-runtime.ts

* perf(worktrees): scope all repository scan invalidations

* fix(worktrees): drop scan cache on orphan-cleanup removal (#8882)

The orphan-cleanup fallback in removeManagedWorktree (git worktree remove
fails with 'not a working tree', Orca deletes the directory and prunes)
invalidated only the resolved cache, so the removed worktree kept being
served from the bounded raw scan cache for up to its 30s TTL.

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

* Simplify SSH deploy-success handling to use broadcastSshState

Route the post-deploy "connected" notification through the shared
broadcastSshState helper instead of manually reimplementing window
broadcast and runtime cache invalidation inline, keeping SSH state
propagation consistent with other call sites.

* perf(worktrees): defer SSH enrichment, consolidate cache invalidation

- Skip enriching ephemeral-VM SSH state since it's not broadcast to the
  renderer, avoiding unnecessary withSshRemotePlatform() calls.
- Move invalidateResolvedWorktreeCache() outside the conditional branch
  to eliminate redundant calls (previously called in both if and else).

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-17 15:34:30 -07:00
Brennan Benson 3fd73ee848 fix(crash-reporting): disambiguate renderer recovery from app relaunches (#9223)
* fix(crash-reporting): disambiguate main process relaunches

* fix(crash-reporting): trace all app relaunch causes
2026-07-17 15:27:39 -07:00
Brennan Benson ef03a50b1d fix(github): attribute GitHub API outages instead of blank/"failed" states (#9106)
* fix(github): attribute GitHub API outages instead of blank/"failed" states

When GitHub's API is unreachable (5xx outage, network, or rate limit), Orca
showed no PR data with no explanation, so it read as an Orca bug rather than a
GitHub-side problem.

- Add a shared classifier (classifyGitHubUnavailable) reused by the main
  process and the renderer so every surface attributes an outage identically.
  A live outage returns HTTP 5xx, which the PR-refresh classifier previously
  had no branch for (fell through to the un-attributed "refresh failed").
- Right-sidebar Checks panel: show GitHub-attributed copy in the error
  empty-state, plus an inline banner over stale cached PR data so an outage
  doesn't look like a normal (silently out-of-date) panel.
- Tasks/PR-list page: replace the vague "N of M projects failed to load" with
  a GitHub-attributed banner when the failure is a reachability problem.

Copy names GitHub as the source and reassures it isn't an Orca problem, with no
status-page link. Stays GitHub-scoped so GitLab/other providers aren't
mislabeled.

* fix(github): keep outage attribution accurate

* fix(github): preserve outage attribution edge cases

* fix(github): preserve Tasks outage attribution

* fix(github): avoid false outage attribution

* fix(runtime): tolerate absent browser certificate state

* fix(ui): preserve exhaustive optional state handling

* fix(github): preserve outage attribution for combined queries

* fix(github): preserve runtime failure attribution

* chore: restore unrelated UI files to main (out of scope)

native-chat-session-option-labels.ts and skill-freshness-group.tsx switch
tweaks were unrelated to GitHub API outage attribution — they fix pre-existing
switch-exhaustiveness lint on main, which this PR's CI (oxlint) doesn't gate on.
Restore them to origin/main so this PR's diff stays focused; the exhaustiveness
cleanup belongs in its own change. (sync-runtime-graph.ts is already identical
to main, so no diff there to revert.)

* fix(github): drop Orca self-reference from outage copy

* fix(github): drop em-dashes from outage copy
2026-07-17 15:16:07 -07:00
Brennan Benson e70842fe2c fix(terminal): recover floating input after app refocus (#9233)
* fix(terminal): recover floating input after app refocus

* fix(terminal): preserve newer focus ownership
2026-07-17 15:10:08 -07:00
Brennan Benson e6933fed84 fix(grok): honor zero-usage weekly reset (#9219)
* fix(grok): honor zero-usage weekly reset

* fix(grok): preserve ambiguous monthly billing fallback
2026-07-17 15:09:22 -07:00