Commit Graph
16623 Commits
Author SHA1 Message Date
Jacob HonoréandNeil 8cfbfa5430 fix(daemon): warn when terminals inherit a zero RLIMIT_RTTIME (#29762)
On Linux, PTYs inherit the daemon's RLIMIT_RTTIME. When the soft or hard
limit is 0 the kernel kills timer-armed jobs (SIGXCPU / SIGKILL, exit 152
or 137) and unprivileged code cannot raise the hard limit. Read
/proc/self/limits at terminal-scope initialization and log a
rttime-limit-zero event with a remedy hint (rtkit, or the launcher /
systemd LimitRTTIME that starts Orca). No-op off Linux or when the limits
file is unreadable.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 07:18:52 -07:00
NeilandZrzzzz a1c6e1273d Continue remote CLI conversations in Chat UI on paired servers (#33954)
* Enable continuing remote CLI conversations in Chat UI

* fix(native-chat): send the host's own pane key; ask older hosts to update

On a paired host the desktop names a pane by its mirrored surface key, but
the host matches cliSource against its own agent-status rows, so every
remote "Continue in Chat UI" create was refused as unreadable. Translate
the key with toHostSessionPaneKey before sending.

A resume launch's join identity now includes its execution host, so a
remote resume never joins an in-flight resume of the same conversation id
on another host.

A verified host that lacks resume-history now shows the pane-header action
disabled, with "Update Orca on this host to continue in Chat UI." in its
tooltip and accessible name, instead of hiding it.

---------

Co-authored-by: Zrzzzz <1160026659@qq.com>
2026-10-26 07:17:41 -07:00
Neil 20f7bb6a69 fix(session-tabs): retire terminal rows the host closed, and offer Close Pane on a closed remote terminal (#33949)
* fix(session-tabs): retire kept terminal rows the host closed, and offer Close Pane on a closed remote terminal

* fix(session-tabs): a live handle outranks an older close record
2026-10-26 07:16:04 -07:00
NeilandClaude 6c815e80c8 fix(runtime): recognize hand-typed native Claude at its startup dialogs (#33826)
* fix(runtime): recognize hand-typed native Claude at its startup dialogs

A shell-typed claude emits no title at the trust dialog, so nothing asked
which process owned the pane, and native Claude's process name is its
version (2.1.310). agentWait now identifies a title-less, unowned pane
from its foreground process, confirming an unfamiliar name with one process
scan whose verdict is kept while that name stays in the foreground.

* fix(runtime): scan only native Claude's version-named binary, only when a dialog is on screen

Review follow-ups: an untitled, unowned pane earns a foreground read only
when its live screen shows a blocked dialog, so plain shells answer without
a round-trip; the process scan runs only for a semver-shaped foreground name
(native Claude's versions/<semver> binary), never on win32, and only an
answered scan is cached.

* fix(runtime): don't persist a titleless pane's scanned identity

A hand-typed native Claude identified for an interactive-wait query was
stored as the pane's foregroundAgent. If the user declined the trust
dialog before Claude set a title, no title transition fired, so the shell
stayed labelled Claude until the next inventory refresh.

The identity now answers only the current query; the per-pty scan cache
(keyed by foreground name) keeps repeat queries cheap. Concurrent queries
share one in-flight identify, and the version-name match is anchored.

* fix(runtime): keep scanned identity out of background refresh; null for disconnected panes

- load() matches main again; only identify() consults the confirm-scan cache
- disconnected/unreadable panes answer null so the tail path still answers; only timeout is unknown
- check pane ownership before projecting the screen
- cache only recognized agents, so a not-an-agent verdict is rescanned

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(runtime): drop a titleless identity read if the pane rebinds; trim tautological tests

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 07:13:36 -07:00
NeilandClaude b51d904ef0 fix(agent-status): show Claude/Codex panes waiting on the folder-trust dialog (#33804)
* fix(agent-status): show Claude/Codex panes waiting on the folder-trust dialog

Hooks only start after a folder is trusted, so a pane parked on Claude's or
Codex's trust dialog had no sidebar row (or an idle one) even though
agentWait already reported agent-trust-workspace. Main's headless-screen
observer now runs the same blocked-text detector on the screen and projects
a waiting row while the dialog shows, settling it with a session-boundary
done once the dialog leaves. The row is not first-party evidence: it skips
the prompt lifecycle and lastExplicitAgentStatus.

Refs #25854

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(agent-status): match the live trust dialog's structure and settle on agent exit

Require the dialog's key footer and trust choice so quoted wording in a reply
cannot raise a waiting row, settle the row once a killed agent's pane is back
at a shell, and cover dismissal with a Codex 0.164 recording.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(agent-status): settle the trust-dialog row only on positive evidence

ASCII-escape the dialog regexes for the orcad build, settle only after a quiet
settled screen without the dialog or a proven shell foreground (readLaunchedAgentForeground,
which is the only shell-alone proof on Windows), so a resize repaint split across
reads no longer flips the row and re-notifies.

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(agent-status): move trust-dialog status projection out of headless hydration

Keeps headless-terminal-hydration.ts under the max-lines lint limit.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(agent-status): drive the trust-dialog settle window with fake timers

Co-Authored-By: Claude <noreply@anthropic.com>

* test(agent-status): drop the Codex dismissal capture the serializer fuzz rejects

Its replay trips known serialize I2 diffs; cover Codex dismissal with a composer
repaint over the existing 0.158 capture, and compare only appearance/absence.

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(agent-status): track trust-dialog rows per PTY and clear on debounced screen reads

Keys state by ptyId so an emulator swap no longer strands the row, owns the
row by its receipt stamp instead of a toolInput tag, drops tracking as soon as
another writer replaces the row, and clears after two debounced reads without
the dialog instead of 3 s of total quiet.

* fix(runtime): clear the trust-dialog read timer when a screen read throws

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 07:13:29 -07:00
Konstantin StasenkoandNeil 2bcf5b27bd fix(codex): skip the Codex hook under a Claude background job (#24641)
Claude background-job workers, and the `codex exec` runs they spawn,
inherit the dispatching pane's ORCA_* env, so the Codex hook posted
events against a pane the run never lived in. The Codex hook now exits
when CLAUDE_JOB_DIR is set, like the Claude hook already does.

The guard moves into agent-hooks/claude-background-job-guard.ts and is
shared by the Claude hook, Claude statusline, Windows Claude entry and
Codex hook. POSIX exits after stdin capture; Windows exits before
owning stdin so an abandoned stdin cannot hang the drain.

Pane spawns now drop an inherited CLAUDE_JOB_DIR so an Orca launched
from a Claude background job does not silence its panes' hooks.

Fixes #24516

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 07:08:15 -07:00
Neilandoutof-place 88518900e2 fix(i18n): reject duplicate keys in localization catalogs (#33950)
JSON.parse silently keeps the last value of a repeated key, so the
catalog verifier could not see duplicates. Scan en.json and every target
catalog with ts.parseJsonText before parsing and fail with file:line and
the dotted key for each duplicate.

Fixes #27153

Co-authored-by: outof-place <contact@outofplace.space>
2026-10-26 06:52:19 -07:00
Neil 899d2aad96 fix(ssh): say why SSH failed when Connect never reaches the host (#33928)
When the SSH session itself could not open (key rejected, port refused,
host not answering, host key not trusted), Connect on a host Orca had not
set up yet said "Orca couldn't start its server on this host" and offered
a plain SSH terminal that could not work either. Errors from opening the
SSH session are now marked where they are dialed, and a setup that fails
on one ends the connect with SSH's own reason. A held move keeps its
status. The connect-failure toast also drops Electron's IPC prefix.
2026-10-26 06:51:39 -07:00
Tae Hyeong, SonandNeil 8b1f86dfa5 fix(windows): keep spaced batch launcher paths intact when spawning (#13501)
cmd /c strips the first and last quote of a line that starts with a quote
unless exactly one quoted, paren-free executable path is present. A spaced
.cmd launcher plus any quoted argument (or a Program Files (x86) launcher)
was cut at its first space and the spawn silently failed. Prefix the batch
invocation with `@` so the line never starts with a quote, in both the
waiting and detached start /B forms.

Add a real cmd.exe round trip in the Windows CI lane.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 06:46:57 -07:00
Wooseong KimandNeil 5b1e387895 docs: use the full stablyai/orca/orca cask name and warn that bare orca is Plotly (#14777)
Bare `brew upgrade --cask orca` resolves to the unrelated, disabled Plotly
cask in homebrew-cask. Add a warning and a qualified upgrade line to the
README install blocks (all locales) and qualify the upgrade command on the
docs site install page.

Fixes #14591

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 06:41:41 -07:00
zhangxaochenandNeil 67e42c90b9 fix(terminal): return chat tab to terminal when a confirmed shell foreground follows agent exit (#30614)
Agents that leave their OSC title behind on exit (grok, codex) never trip
the title-based exit, so ChatView stayed on top of the returned shell.
onConfirmedShellForeground now notifies onAgentExitedRef, except for
Orca's own hibernation stop, which keeps its chat surface.

Fixes #30613

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-26 06:36:12 -07:00
Neil a93f73c032 fix(terminal): skip an escape tail an abandoned hidden-output restore would print (#33905)
* fix(terminal): skip an escape tail an abandoned hidden-output restore would print (#33766)

Main drops a hidden pane's renderer delivery after its model ingests the
bytes, so the first chunk sent on reveal can begin inside an escape whose
start was dropped. When the restore is abandoned, the renderer resets its
parser and writes the queued chunks, and xterm printed the tail (';242m',
the rest of a Codex OSC title).

Main tracks each PTY's escape state over every accepted payload and labels
the first delivery after a hidden or pending-cap drop with the escape it
resumes inside (gapEscapeState). Only the abandon path strips that
continuation; a successful restore keeps every byte so the snapshot's
pending escape tail can complete. No label means no change.

* fix(terminal): make the escape-continuation scan's switch exhaustive (#33766)
2026-10-26 06:33:23 -07:00
Daniele SolombrinoandNeil 0ea1ac609c fix(terminal): release replay guards when a pane's xterm is disposed (#31095)
A disposed xterm silently drops its queued write callbacks, so replay
guards engaged on it never saw a parse completion. The stall probe then
certified a false wedge, logged a wedged-release breadcrumb and fired the
undeliverable-write recovery against a pane that was already gone.

Track each pending guard release per terminal and settle them with a
'target-disposed' reason from disposePane, and skip new replays into a
disposed xterm the same way certified-dead pipelines are skipped.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 06:30:47 -07:00
d290035e6e fix(cli): reject empty --terminal/--from handles instead of falling back to defaults (#16745)
An explicit empty --terminal (or orchestration --from) was treated as absent,
so `orca terminal send --terminal ""` targeted the active pane and
orchestration check/inbox/worker-start fell back to the ambient
ORCA_TERMINAL_HANDLE mailbox. Hoist the existing getPresentStringFlag into
flags.ts and use it for these handles so a present-but-empty value fails with
invalid_argument.

Fixes #16694

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: wusiyuan05 <wusiyuan05@zuoyebang.com>
2026-10-26 06:30:34 -07:00
Neilandzerone0x 4fda57bb11 feat(open-in): open SSH workspaces in Cursor and Zed (#33877)
* feat(open-in): open SSH workspaces in Cursor and Zed

Cursor shares VS Code's Remote-SSH argv and now opens SSH and SSH-reached
server workspaces the same way, in a new window like its local launch.
Zed opens them through its ssh://[user@]host[:port]/path URL, so manual
custom-port hosts work without a local SSH config alias.

Co-authored-by: zerone0x <soberzml2333@gmail.com>

* fix(open-in): keep manual Zed targets on their saved route

Always send the saved port for manual targets so a matching ssh config Port
cannot redirect them, ask for an ssh config alias when a manual host needs a
key, agent or proxy the URL cannot carry, reject option-like hosts, and accept
the zeditor CLI name.

* refactor(open-in): move the remote SSH editor launch into its own module

Keeps external-editor-launch.ts under the max-lines limit after the main merge,
and moves main's new macOS CLI fallback test onto the remote launch API.

---------

Co-authored-by: zerone0x <soberzml2333@gmail.com>
2026-10-26 06:28:29 -07:00
NeilandClaude 0cf40b1687 fix(session): show a toast when Force Reload is vetoed by a failed shutdown checkpoint (#33941)
Browser-initiated beforeunload (Force Reload, reload) had no caller to surface
the checkpoint veto, so the reload silently did nothing. Show a reload-specific
failure toast naming the cause for trusted unload events; synthetic close and
restart dispatchers keep reporting their own verdict. Paired web skips the toast
since trusted unloads there also cover tab close/navigation and the browser's
leave prompt already reports the veto.

Fixes #21017

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 06:25:13 -07:00
Neil 9f02111538 fix(persistence): a paired server's workspaces keep their saved tabs across desktop restarts (#33926)
* fix(persistence): a paired server's workspaces keep their saved tabs across desktop restarts

Main's per-repo terminal topology revision fences window saves so a stale save
cannot undo main's own membership change. The window never sends revisions, so
on a runtime partition, which mirrors a paired server, one removal or main-side
close froze every workspace of that repo: from then on each window save had its
terminal rows rebased onto the prior rows, and every restart reopened those
workspaces on the server's per-device tab pick.

On runtime partitions the fence now lasts only through the race it guards: a
repo main changed is fenced for RUNTIME_PARTITION_TOPOLOGY_FENCE_MS, then the
window's saves win again. Local and SSH partitions keep the permanent fence.

* test(persistence): pin that a window save can drop a tab the server closed after a restart (#21236)

* fix(persistence): fence the retirements the sanitizer makes from legacy tombstones on runtime partitions
2026-10-26 06:11:15 -07:00
Neil 639d52952d feat(ssh): per-host Reconnect on launch toggle (#33935)
* feat(ssh): per-host Reconnect on launch toggle

A host with Reconnect on launch turned off starts each launch as if the user
had disconnected it: main records the session user-disconnect for it and the
managed servers reached through it, so neither the startup restore, pane
mounts nor managed-server calls dial it until the user connects it. The
renderer also skips it in the startup restore. The switch lives in Settings ->
SSH -> Advanced for hosts this desktop dials; undefined keeps today's behaviour.

* fix(ssh): hold opted-out hosts before server status probes start

Server status probes start inside registerCoreHandlers, before the SSH
handlers register, so hold launch opt-outs right before it (once per
process). Relay-era panes that hit a held host now wait for Connect instead
of reporting a failed connect.
2026-10-26 06:01:54 -07:00
NeilandTian-yi Liang c9eee6b54c fix(runtime-environments): every window sees a server saved from the CLI (#33930)
`orca environment add` writes the saved-server file directly. Main already
watched that file but only repaired the Active Server preference, so every
renderer surface listing saved servers (the Agent Session History host
picker, host menus, the status bar) kept the old list until something
else refreshed it. Main now tells every window when the file changes, and
the renderer refreshes through the existing coalesced catalog refresher.

Co-authored-by: Tian-yi Liang <tianyilt@qq.com>
2026-10-26 06:00:15 -07:00
ae8e3e1c37 fix(computer-use): send the plain chord for uppercase hotkey letters on Windows (#27642)
SendKeys presses Shift for an uppercase letter (VkKeyScan reports the
shift state), so `orca computer hotkey --key CmdOrCtrl+A` (the documented
example) sent Ctrl+Shift+A on Windows. Lower-case a single-character key
when the hotkey has modifiers; Shift is still sent when written explicitly.

Extract ConvertTo-OrcaSendKeysHotkey so runtime-render.test.ps1 can assert
the SendKeys strings case-sensitively.

Fixes #27589

Co-authored-by: jespo2021 <joeespo@gmail.com>
Co-authored-by: Neil <neil@stably.ai>
2026-10-26 05:59:08 -07:00
99631994bc fix(ssh): move through the remote folder browser with the arrow keys (#33914)
* fix(ssh): move through the remote folder browser with the arrow keys

The browser had no highlighted row and its filter box ignored Up/Down, so
the keys only scrolled the list. The first entry is now highlighted, the
arrows move it into view, and Enter opens it. A filter that leaves one
folder still starts on that folder, and a fully typed path starts on no
row so Enter still goes to that path. Also drops the duplicated
"No matches" line.

Fixes #31555

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Name the remote folder listbox and point at no row while a listing loads

While a listing loads only the spinner renders, so the highlight and
aria-activedescendant had been left on rows that were no longer there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep Enter and the highlight off rows that are about to be replaced

While the committed listing loads, Enter fell back to the previous
listing's entries and could open a folder from it. While a path preview
resolves, its prior rows stay visible but are no longer targetable, so the
highlight and aria-activedescendant now clear. The filter input also gets
combobox semantics and a name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ssh): drop a moved highlight when a typed path previews the same listing

* fix(ssh): reset the folder highlight per keystroke and hold Enter until a typed path resolves

* fix(ssh): hold Enter on typed path input before its first preview

---------

Co-authored-by: Younghwan Chae <chyohw97@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 05:57:19 -07:00
NeilandMarkXian 94f562e634 fix(repos): prune each restored folder owner once its own host answers (#33863)
* fix(repos): prune a restored folder owner once its own host's catalog answers

One unreachable remote used to skip the restored-owner prune for every
workspace, so a local folder workspace stayed pinned to a dead runtime for
the whole session. Each host's applied catalog now counts on its own; a
missing workspace's owner is dropped only once that owner host hydrated.

Rebased from #11285 onto current main.

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>

* fix(repos): only the owner host's copy or catalog settles a restored folder owner

Folder ids can repeat across hosts, so a same-id copy on another host no
longer clears a runtime's restored owner before that runtime answers; an
owner the environment list no longer names counts as settled.

* fix(repos): a superseded all-host load's environment list settles no restored owner

---------

Co-authored-by: MarkXian <mark-xian@foxmail.com>
2026-10-26 05:51:42 -07:00
Neil 4a37a6b952 test(startup): transform the ready graph at collection, not inside the first test (#33925)
Each test resets modules and re-imports main-process-ready to reset the
browser session registry's one-shot latch. Without a static import, the first
tests paid the cold transform of that graph inside the 30s test timeout and
timed out under CI load; later tests re-evaluate cached transforms in ~200ms.
2026-10-26 05:49:58 -07:00
Neil 1a77543ee0 test(layout): drop the warm-up that calls a helper #33919 removed (#33934)
#33919 and #33923 both fixed this file's cold-import timeout and crossed: #33923's beforeAll calls switchedBuild, which #33919 replaced with static imports. Main fails typecheck (TS2304). The static imports already pay the transform once.
2026-10-26 05:36:41 -07:00
hwantageandNeil 1187abdbc2 fix(windows): mark PowerShell startup command boundaries with OSC 133 C/D (#18182)
A startup command embedded in the PowerShell -EncodedCommand payload runs
before the first prompt, and the prompt wrapper suppresses 133;D until it
has printed once. An agent launched this way exited with no
command-finished boundary, so its pane was never retired.

Emit 133;C before the embedded startup command and prime the prompt latch
so the first prompt reports 133;D with the exit code. Stdin-typed startup
commands keep readline's own marks. The encoded-command budget grows by
the mark's size so real commands keep the prior limit.

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-26 05:14:19 -07:00
Neil 90493a9879 perf(orcad): keep SSH hosts on the 10-minute scanner idle, give WSL hosts 3 (#33897)
* test(layout): load the runtime graph once before the layout capability tests

The first test paid the cold transform of the whole runtime graph inside its
30 s budget and timed out whenever a shard placed it without warm neighbors.

* perf(orcad): keep SSH hosts on the 10-minute scanner idle, give WSL hosts 3

Retiring the idle session scanner after a minute cost the next scan of a
large history ~14 s. SSH hosts have no memory budget to justify that, so
they return to the scanner's default; WSL hosts, which do, wait 3 minutes.
2026-10-26 05:08:34 -07:00
Neil cd1fcc5168 refactor(mobile): colocate native chat composer and drafts (#33922) 2026-10-26 05:07:28 -07:00
Neil f3059ddd6c test(layout): load the runtime graph once before the layout capability tests (#33923)
The first test paid the cold transform of the whole runtime graph inside its
30 s budget and timed out whenever a shard placed it without warm neighbors.
2026-10-26 05:06:21 -07:00
Anddy Sahir AgudeloandNeil fd25eb0872 fix(settings): open the deep-linked project setup, not the host's first (#12176)
A repo-only Settings deep link (sidebar "Project Settings") recorded just the
entry and host, so when one entry holds two setups on the same host (e.g. a
Windows and a WSL clone of one remote, or a provisioned plus a user clone) the
pane resolved the host's first setup and showed the other clone's settings.
Carry the setup id like the explicit-host path already does.

Addresses #11689.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 05:03:56 -07:00
audichuangandNeil 015996d1b1 fix(persistence): clear canonical active workspace key on worktree owner removal (#6255)
Worktree session owners are removed by their raw id, but activeWorkspaceKey
stores the canonical worktree:<id> form, so deleting a worktree left the
persisted active key pointing at the removed workspace in every partition.
Match both forms in deleteOwnerKeyedSessionFields so every owner-removal
path (worktree delete, repo pruning, invalid-layout purge) clears it.

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 05:03:44 -07:00
NeilandClaude f5b2cc5a79 fix(native-chat): say why Claude refused to start a chat, including Full access as root (#33812)
* fix(native-chat): say why Claude refused to start a chat, including Full access as root

Claude Code exits before initialize when Full access (--dangerously-skip-permissions)
meets a root uid, which is common on SSH hosts. Orca reported only that Claude
stopped before it finished starting, and retried four times. Classify that refusal
as fullAccessAsRoot with a next step, and show the CLI's own startup words behind
Details on the failure row and on the unsent message.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(native-chat): keep message Details to start failures; cover the exit path

Route the exit-error module and delivery notices to the managed e2e, explain its
timeout, and drop the exec non-null assertion. Match the zh Full access label.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(native-chat): type the refused fixture so the web typecheck passes

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 05:00:45 -07:00
Neil 5652de8872 test(layout): load the runtime and RPC registry once instead of per test (#33919)
The layout-owner tests reset modules and re-imported orca-runtime, the
dispatcher and the full RPC registry inside each test. Under CI load the
cold transform of that graph exceeds the 30s test timeout. The capability
check reads the switch at call time, so it only needs a flipped getter; the
window-owned registration check uses the default (switch-off) registry.
2026-10-26 04:57:53 -07:00
eatmoreduckandNeil 1ac1d40cd7 fix(automations): advance schedules past a DST fall-back hour (#20179)
floorToMinute recomposed local wall-clock fields via setSeconds(0, 0), and
the FREQ=HOURLY branches used setMinutes. Inside a repeated fall-back hour
both resolve to the earlier offset, so nextAutomationOccurrenceAfter could
return `after` itself and latestAutomationOccurrenceAtOrBefore could return
the first pass's instant.

Run dedupe by scheduledFor prevents duplicate launches, but the second pass
was mishandled: a `30 1 * * *` cron's second run started 30 minutes late (or
was recorded as skipped_missed past its grace window), the 01:00 EST run of
`FREQ=HOURLY;BYMINUTE=0` was dropped, and the scheduler re-evaluated and
flushed state on roughly every tick for the hour because nextRunAt stayed
in the past.

Floor with epoch arithmetic and route cron and hourly schedules through one
absolute-minute walk, so each pass of a repeated minute fires once, on time.

Fixes #20154

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 04:43:13 -07:00
Neil 34f55ca5e1 refactor(task-page): colocate cross-provider composition owners (#33913) 2026-10-26 04:30:52 -07:00
eatmoreduckandNeil 15fc7a6769 docs(settings): describe the GitHub integration as the local gh CLI login, not OAuth (#26609)
Orca has no OAuth app; it reads tokens from the gh CLI on the machine running
Orca. Document that, the per-host login for Remote Orca Servers, and the
repo/read:org/project scopes auth-diagnose expects.

Refs #26604

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-26 04:22:49 -07:00
Neilandbrynnclaw e50fe1e10e fix(ai-vault): delete a server-hosted session on the server that owns it (#33906)
Agent Session History now routes Delete for a session on a paired or
SSH-managed Orca server to that server through a new aiVault.deleteSession
RPC. The host revalidates the path against its own roots, removes the
transcript (into Trash on a desktop host; permanently on a plain-Node host,
which has none), and invalidates its caches. Hosts advertise
aiVault.delete-session.v1; an older host keeps Delete disabled with
"Update <host> to delete its sessions from here."

Co-authored-by: brynnclaw <261708852+brynnclaw@users.noreply.github.com>
2026-10-26 04:20:36 -07:00
67af384c4b fix(terminal): keep find-bar highlights when navigating with Cmd+G / Cmd+Shift+G (#18844)
The Cmd+G / Cmd+Shift+G path called findNext/findPrevious with only
{ caseSensitive, regex }. @xterm/addon-search only draws the active-match
decoration, fires onDidChangeResults, and keeps refreshing highlights on new
output when the call carries decorations, so the shortcut froze the active
highlight and the match counter.

Share one buildTerminalSearchOptions() between the find bar and the
shortcut path so both send the same decorated options.

Co-authored-by: Anton Kuligin <anton.kuligin@notraffic.tech>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-26 04:17:21 -07:00
Neil 2fc9ad54cf test(wsl): cover the bash bridge's argv, backpressure, fallbacks and cleanup (#33907)
Prove the relay reaches wsl.exe through --exec unchanged, carries every byte
value both ways, holds the desktop back under a stalled reader on either
side, falls back to Node for no bash, old bash, no /dev/tcp and refused
dials with unchanged sentinels, and leaves no bash or cat behind when
either side goes away.
2026-10-26 04:04:33 -07:00
Neil 5a973e29a7 fix(cli): show orphaned state in human-readable terminal list/show output (#33910)
Fixes #15313
2026-10-26 04:01:44 -07:00
Neil c5299b1169 fix(wsl-host): keep the bridge port across app restarts so the host isn't re-paired (#33109)
A WSL host's bridge listened on a fresh port each launch, which changed the saved
pairing endpoint. The renderer treats a changed WSL pairing as a different machine
and purges the host's workspaces, tabs and selection, then rebuilds them once the
host relists its projects.
2026-10-26 04:01:27 -07:00
OrcaWinandm4air bb5137969f fix(memory): show Activity Monitor's footprint in the resource panel on macOS (#33901)
The resource panel summed RSS. On macOS that counts the Electron framework's
shared pages once per helper process, so main and renderer read 2-8x too
high, while the GPU process read 3-5x too low because RSS excludes graphics
memory. The detached terminal daemon was also missing from the app total.

On macOS, sample per-process phys_footprint from top (the figure Activity
Monitor shows) at most every 10 s while the panel is open, and fall back to
RSS when top is unavailable. Count the local terminal daemon in the app's
'other' bucket; its PTY children stay attributed to their worktrees. Linux
and Windows keep RSS/working set.

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-26 03:57:41 -07:00
17621d5368 fix(editor): match external file changes across Windows path spellings (#14812)
On drive and `\\` UNC roots, an open tab whose filePath used a different
separator or drive-letter spelling than the watcher event (for example
`c:\Repo\File.ts` vs `C:/Repo/File.ts`) never matched, so external edits
did not reload the tab or raise the changed-on-disk banner.

Both direct-match sites (the indexed batch lookup and the non-indexed
fallback in getOpenFilesForExternalFileChange) now compare through
externalChangePathKeyFor(root), which reuses editorBufferPathKey to fold
separators, the drive letter, and the UNC server only. Path-tail case stays
exact, and WSL, POSIX, SSH, and `//` roots keep byte-exact keys.

Fixes #14801

Co-authored-by: VXNCXNX <VXNCXNX@users.noreply.github.com>

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 03:56:28 -07:00
Neilandoutof-place ac5c5ae4cf fix(process-table): pin macOS ps to en_US.UTF-8 so lstart and argv parse under any locale (#33898)
macOS ps formats lstart with the user's locale (%c) and vis-encodes
non-ASCII argv when no UTF-8 locale is set. Under de_DE/en_NZ/ja_JP the
process-table parsers dropped tty/startTime and folded them into command,
breaking agent recognition, pane fingerprints, agent-session start times
and daemon identity. Run those ps readers with LC_ALL=en_US.UTF-8 on
macOS; other platforms keep the inherited env.

Fixes #27004

Co-authored-by: outof-place <contact@outofplace.space>
2026-10-26 03:56:09 -07:00
Wooseong Kim ab62ae7e96 fix(diff): keep the collapsed section header in view (#24466)
Collapsing the section the View all diff viewport was inside kept the
scroll anchor's within-section offset, which pointed into the removed
body, so the structural restore landed on later sections. Pin the anchor
to the section header before the collapse is published.

Fixes #20665
2026-10-26 03:50:58 -07:00
OrcaWinandOrcaWin 819d273e27 perf(lint): one ast-grep scan feeds both the lint gate and the flaky-test ratchet (#33903)
lint:ast-grep and check-flaky-test-pattern-ratchet each parsed the whole tree.
ast-grep-gates.mjs scans once; the lint gate re-runs ast-grep only on files with
warning-or-error findings (ast-grep's own report and exit code), and the flaky
ratchet counts test-* matches from the shared scan.

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-26 03:50:42 -07:00
5ee6e42a3b fix(drops): keep remote drops out of git and say why drops or file opens fail (#33831)
* fix(drops): keep files dropped onto a remote workspace out of git status

Uploads into `.orca/drops` now write `.orca/drops/.gitignore` (`*`) the first
time it is missing, so dropped files no longer block a plain workspace delete
or get committed by `git add -A`. Callers share one constant for the folder.

Fixes #23856

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Re-check the import session after the drop staging ignore step

The ignore step swallows its own errors, including a stale session. When
nothing was staged the loop never asserted again, so the caller got
skipped/failed results instead of the retry error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(drops): say why a remote drop or file open failed

Co-authored-by: Jae Heo <83424878+jae-heo@users.noreply.github.com>
Co-authored-by: Bing.Z <zzb@gxsmjx.com>

* fix(drops): keep paths out of failure toasts and reuse the too-large classifier

* fix(drops): shorten whole quoted paths in failure toasts

* fix(drops): describe upload failures by category instead of host text

* fix(drops): match failure categories on unquoted text and name manual disconnects

---------

Co-authored-by: Younghwan Chae <chyohw97@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jae Heo <83424878+jae-heo@users.noreply.github.com>
Co-authored-by: Bing.Z <zzb@gxsmjx.com>
2026-10-26 03:48:47 -07:00
Neil dab0cd1766 refactor: colocate task page PR presentation rules (#33890) 2026-10-26 03:45:47 -07:00
Neil 2c0c6ac0c4 docs: stop promising cross-worktree split panes and Shift-Enter split in Jump Palette (#33902)
Panes are scoped to a single worktree and the Jump Palette has no
Shift-Enter handler, so replace those promises with the real flow:
watch sidebar status indicators and jump between worktrees with
Cmd-J (macOS) / Ctrl-Shift-J (Windows / Linux).

Fixes #10477
2026-10-26 03:45:32 -07:00
Neilandoutof-place c36378c2b9 fix(build): keep index.js source map aligned with the bootstrap banner (#33899)
The main bootstrap banner was prepended to index.js in generateBundle,
after Rolldown had already emitted index.js.map, so every main-process
crash trace decoded ~200 lines off. Emit it via Rolldown's output.postBanner
instead, which shifts the source map natively.

Co-authored-by: outof-place <contact@outofplace.space>
2026-10-26 03:45:15 -07:00
BingZandNeil 7e573331ee fix(shell): resolve VS Code CLI from standard app installs when code is not on PATH (#14010)
GUI-launched Orca often inherits a minimal PATH, so bare `code` fails with
spawn ENOENT for Open in VS Code, including Remote-SSH worktrees. When PATH
and install-dir lookup leave `code`/`code-insiders` unresolved, fall back to
the CLI bundled in the standard macOS app bundle (/Applications or
~/Applications) or the Windows user/system install. Linux packages already
link the CLI onto PATH, so no Linux candidates are added.

Fixes #14008

Co-authored-by: Neil <neil@stably.ai>
2026-10-26 03:39:45 -07:00