Commit Graph
11808 Commits
Author SHA1 Message Date
OrcaWinandm4air f4557bfef1 fix(renderer): release retired store snapshots from selector caches (#23187)
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 12:46:48 -07:00
Jinjing a85057ef48 Simplify filter-flatMap patterns to single flatMap operations (#23242)
- Replace .filter().flatMap() chains with .flatMap() using conditionals
- Use constructor parameter shorthand in PreflightHandler
- More concise conditional filtering across agent detection and tab rebasing
2026-09-26 11:45:03 -07:00
github-actions[bot] 3990076fa3 Update README downloads badge 2026-09-26 18:30:10 +00:00
Jinjing 0647e6d6d2 fix(i18n): correct duration and turn-status copy across locales (#23243)
* fix(i18n): correct duration and turn-status copy across locales

The Cmd+J session-age badge and the native-chat turn row carried
machine-translated strings that read wrong in several locales:

- zh read the "m" in the age badge as the metre character (米), so a
  session showed as "17米" instead of "17分".
- zh/ja/ko/fr rendered "Working for N" as a location/preposition phrase
  ("为 N 工作", "N で働いています", "N에서 근무", "Travailler pour N"),
  i.e. "works for/at N" rather than "has been working N".
- The turn-details aria-label read the conversation "turn" as a road turn
  (转弯 / 회전 / virage) in zh/ko/fr.
- ja/ko left the age-badge and cleanup duration units as bare Latin
  "m/h/d"; ko's cleanup "N days ago" mixed "d" with 전.

The English source values are ambiguous ("{{value0}}m", "Working for N"),
so a value-only re-translation cannot disambiguate them. Pin the reviewed
strings per locale and guard them with a focused test.

* fix(i18n): use a type guard instead of an assertion in the guard test

CI's type-aware lint rejects `as Record<string, unknown>`; narrow with an
`isStringRecord` predicate instead.
2026-09-26 11:29:11 -07:00
Jinjing 0bad8b7490 Better add ai notes ui (#21719)
* feat(diff-comments): draft inline notes as editor view zones

Move comment drafting from floating popover to inline view zone. The draft card now appears in the editor flow, preventing overlap with code and integrating naturally with the diff layout. Includes styled margin indicator, auto-resizing textarea, and keyboard/submission handling.

* Preserve inline draft comments when switching diff views

- Reanchor draft zones to new models when file/line mapping changes
- Disable draft mode on large diffs to maintain performance
- Enhance draft card UX: shadow depth, outside-click handling, toast errors
- Carry draft body and position when reopening comments

* Ensure draft comment textarea auto-focuses and preserve drafts through e

- Focus textarea on mount via requestAnimationFrame for reliable focusing
- Add onDomNodeTop callback to focus textarea when zone reaches viewport
- Preserve pending draft when editor model refreshes and re-anchor on reload
- Add editor.getModel() checks before opening and re-anchoring drafts
- Test that textarea is focused on creation and errors are surfaced

* fix(diff-comments): prevent draft loss and duplicate submission on swap

- Track submission state to prevent carrying in-flight text to new cards
- Restore failed submissions for retry after model swap with unmount safety
- Use effects for proper ref management per React patterns
- Add isDraftOpen() guard to prevent re-opening the keyboard chord while composing
- Separate concerns between user clicks and draft-open state in decorator

* fix(diff-comments): show save error and restore focus intelligently

- Toast error when draft submission fails, so users see why it didn't save
- Return focus to editor only if the card still holds it when save completes, preventing focus theft on slow saves

* minor fix

* fix(diff-comments): park focus before submit button disables

Chromium moves focus to <body> when a focused button becomes
disabled, causing the draft zone to lose focus context. By
explicitly moving focus to the textarea before the button disables,
the zone can properly return focus to the editor after save.

* add all translation
2026-09-26 11:09:36 -07:00
OrcaWinandm4air da6d483ab9 fix(vault): read OpenCode SQLite inside WSL and SSH hosts (#23128)
* fix(vault): read OpenCode SQLite on WSL and SSH execution hosts

* fix(vault): bound host setup and preserve cancellation across readers

* fix(vault): keep WSL discovery visible and isolate probe tests

* fix: retry local Vault runtime downloads without reserving remote stages

Preserve verified remote cache reuse and latch only unresolved host work.
Update WSL source-guard and remote dedup test integration.

* fix(queue): discard aborted requests before respawn

* fix(vault): preserve host paths and recover setup after reconnect

* fix(ssh): fence every runtime platform probe across reconnects

* fix(vault): reject setup results from superseded SSH connections

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 03:59:38 -07:00
OrcaWinandm4air d20cb69c48 Optimize CI follow-up workflows (#23190)
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 02:53:37 -07:00
Neil 711bacd408 perf(editor): skip unchanged draft publications (#23173) 2026-09-26 02:36:10 -07:00
Neil f24ed20043 perf(chat): share matching concurrent transcript reads (#23172) 2026-09-26 02:35:53 -07:00
OrcaWinandm4air 3a081abf71 fix(persistence): reclaim Windows profile locks after PID reuse (#23122)
* fix(persistence): identify reused Windows profile-owner processes

* fix(persistence): preserve absent-owner recovery without native registry

* ci: build Windows registry before native profile identity checks

* fix(cli): include native profile-owner dependencies in typecheck

* test: register native profile owner test in Windows PR lane

* test: use resilient Windows profile-owner cleanup

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 02:26:10 -07:00
OrcaWinandm4air 9700030689 refactor(pty): make renderer delivery optional for headless runtimes (#23117)
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 02:25:16 -07:00
Neil d3434a2db4 Improve pull request template for issue linking
Updated the pull request template to clarify issue linking for outside contributors and maintainers.
2026-09-26 02:18:22 -07:00
Neil d9d5993cd5 fix(markdown): return focus to editor from find bar (#23175) 2026-09-26 02:10:29 -07:00
OrcaWinandm4air 8b7a2a5393 Wait for foreground job readiness before testing Ctrl-Z (#23158)
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 01:28:55 -07:00
OrcaWinandm4air d17a17684b Reduce redundant CI runs, pnpm uploads, and fixture startups (#23145)
* Reduce redundant CI runs, store uploads, and fixture processes

* Avoid repeating draft-independent mobile checks on readiness

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 01:17:51 -07:00
2afb9a385b fix(terminal): damp park-verdict churn that is too slow to burst (#20851)
* fix(terminal): damp park-verdict churn that is too slow to burst

The cold-park verdict flip damper only engaged on a burst: 3 flips inside a 1s
window, a threshold derived from React's 50-commit nested-update bail. The
notice limit — 12 flips in 60s — was explicitly breadcrumb-only, on the
reasoning that churn that slow was never near React's bail and damping it would
spend a mounted pane's memory for no crash-safety gain.

The field disagrees about the cost, though not for the reason first recorded.

WHAT THE BUNDLE SHOWS

Bundle Nz4kzIG_NwLd8KObgjJDKA (v1.4.201, win32) carries 52 park-verdict churn
crumbs. They are two unrelated episodes across four launches, not one run:

  L3  09-14 00:53   35 crumbs, 1 tab,  46.9 min, 34 window + 1 burst
  L4  09-14 17:07   17 crumbs, 4 tabs,  8.9 min, 17 window + 0 burst

L3's 46.9 min counts a lone trailing burst; the window-triggering run itself is
35.2 min, with an 11.7 min quiet gap before that final burst.

Per-flip cadence is elapsedMs / (NOTICE_LIMIT - 1), not / NOTICE_LIMIT: the
window opens ON a flip, so the 12th sits 11 intervals later. L3 runs 3.19s /
4.63s / 5.44s per flip (min/median/max); L4 runs 3.19 / 3.20 / 5.01.

Across 321 field bundles, 24 carry this churn and all 24 burst at least once —
though those 24 are roughly 17 devices, and 23 of them are burst-only, so the
load-bearing fact is narrower than it sounds: this install is the ONLY one that
ever tripped the window rule, and that is what ran undamped.

WHAT IT COSTS, STATED ACCURATELY

Each flip remounts the pane. A remount does NOT reconnect a terminal: parking
deliberately keeps the PTY alive (terminal-parked-tab-watchers runs a pane-less
byte watcher), SSH restores from main's snapshot, and a remote runtime
re-subscribes a stream on a per-environment multiplexer that outlives the pane.
The cost is a remount each time, indefinitely.

The user who filed wrote "The connection closes, reconnects and again and again
and again all the time. Is a cycle." An earlier draft of this change took that
as the mechanism. It is not: the bundle carries no remote-terminal stream-stall
recovery crumbs, no daemon session churn inside either churn window, and one
pane-recovery remount two hours earlier. And the report was filed in L4, 12.3
minutes AFTER that launch's churn had already stopped. The churn is real and
worth damping on its own terms; the causal link to that sentence is not
established, and this change should not be read as proving it.

THE FIX

The notice limit now engages the same unpark pin the burst does, backing off ×2
per consecutive notice window to an 8-minute ceiling, clearing once a full
window closes below the limit.

Measured closed-loop — driving the pin back into the verdict the way
useTerminalParkVerdictPin does — over 47 simulated minutes, counting pane
remounts, which is the user-visible quantity:

  per flip    transitions before -> after   ceiling reached
  3193 ms     884 -> 96   (9.2x fewer)      8x
  4627 ms     610 -> 96   (6.4x fewer)      8x
  4800 ms     588 -> 96   (6.1x fewer)      8x
  5000 ms     564 -> 126  (4.5x fewer)      8x
  5442 ms     519 -> 156  (3.3x fewer)      8x

These count verdict TRANSITIONS; a mount/unmount cycle is two, so actual pane
mounts are half each figure. The ratios are unaffected. The harness applies the
pin in the same commit cascade as the flip that caused it, which is what the
hook does and what three rounds of review showed an open-loop harness cannot
see.

TRADE-OFFS AND LIMITS, NONE OF THEM HIDDEN

- This does not fix the driver. Whatever keeps re-proposing the park is still
  unidentified; the pin masks the rendered verdict and the driver resumes when
  each pin lapses. This caps the remount rate of an oscillation; it does not end
  one.
- A pinned pane stays mounted and holds its memory, re-armed while churn
  persists. One oscillating per-worktree flag flips every tab in that worktree
  in the same pass, so all of them can pin at once. The merged verdict includes
  the retention-budget force-park, so a churn-pinned pane can stay mounted
  through memory reclamation that was trying to free it — and the reclaimer
  records success either way, because its only anomaly breadcrumb fires on a
  different condition.

  The honest number is a duty cycle, not a ceiling. Measured per cadence:
  89.7% of wall time pinned at 3193ms/flip, 84.3% at 4627, 83.9% at 4800,
  77.8% at 5000, 69.1% at 5442, with a peak contiguous pin of ~480s. Before this
  change none of these cadences pinned at all, so blocked reclamation goes from
  roughly 0% to 69-90%. Repo-stated cost is ~2.5MB per mounted pane at the 5k
  scrollback default and ~19MB at 50k. This is the strongest form of the
  original "memory is not free" objection and the change does not answer it.
- Only the notice path backs off; a burst still takes a flat one-window pin.
  The corpus supports leaving it: repeat bursts arrive a median 673s apart
  (n=29, grouped by bundle/launch/tab; 356s if physical pairs are deduped), and
  1 of those 29 inter-arrivals falls in the band that would mean re-firing the
  instant a pin lapsed. That margin is thin — the next gap above the band is
  75.3s, 0.3s outside it.
- One hard edge, geometric: reaching 12 flips takes 11 intervals, so churn
  slower than 60s/11 = 5454.5ms per flip never reaches the limit at all. The
  field's slowest observed episode runs 5441.8ms, 12.7ms inside it. Past roughly
  4.7s per flip each window only barely makes the limit, so damping engages
  later and the win shrinks from 9.2x to 3.3x — but the back-off reaches the
  8-minute ceiling at every cadence measured.
- Crumb volume drops by roughly 6x, a loss of
  telemetry sensitivity for the very corpus scan that found this. The surviving
  'window' crumbs carry sustainedPinCount, which discriminates sustained churn
  better than raw volume did; 'burst' crumbs do not carry it. The detection
  method changes either way.

REVIEW: TWO ROUNDS, AND BOTH FOUND THE FIX ITSELF

Round 1 found the back-off never left 1x in production. While a tab is pinned
the hook subtracts it from the rendered verdict, so no flip is recorded and
windowStartMs never advances; by the time a pin lapsed, windowStartMs was always
older than a full window, so the quiet branch wiped sustainedPinCount on the
first pass after EVERY pin. Closed-loop, that shipped 3.6x the remounts
intended. The 24 tests then in the file passed either way, because the harness
was open-loop. A second lens found five wrong claims in the commit message,
including a per-flip divisor of 12 where the code uses 11 — which made the
stated safety margin 37x too generous — and a reconnect mechanism the source
contradicts.

Round 2 attacked round 1's fix and found two more:

  - The back-off RATCHETED. The flip path cleared it on `flips < noticeLimit`,
    and the notice path leaves `flips` at exactly noticeLimit, so a window
    reopening after hours of silence did not clear it. Four isolated episodes
    six hours apart reached the 8-minute ceiling — the precise behaviour the
    code comment claimed was impossible.
  - And it was INERT above ~4.7s per flip, because a lapsing pin knocks the next
    window out of alignment so it closes at 11 of 12, which that same
    `flips < noticeLimit` test read as the churn easing. At the field's slowest
    observed cadence round 1's fix changed nothing at all: 519 -> 346 both with
    and without it.

Both come from one wrong question. The reset now asks whether the tab has been
genuinely quiet — a full window with no flip and no live pin, tracked on an
explicit lastFlipMs — or whether the closing window held fewer than half the
notice limit. A window closing at 11 of 12 is neither.

Round 3 found the defect inside round 2's fix, and it was one line. Engaging the
pin IS a rendered verdict transition: the hook drops the tab from the parked
set, the effect re-runs on the changed dep, and that flip lands while the pin is
live — overwriting the future deadline with the current time. The back-off then
cleared one window after the pin STARTED rather than one window after it ended.
Round 3 also showed the residual slow-cadence weakness was this bug and not the
geometry the round-2 message blamed, and that reverting to round 2's threshold
still passed all 31 tests. `lastFlipMs` no longer moves backwards off a live
deadline, and a closed-loop test that records a flip inside a live pin now kills
both that clobber and round 2's threshold.

Round 4 found no defect inside round 3's fix and judged it mergeable. It did
find that the eased-flip clause was itself untested — four mutations of it,
including reverting to round 2's threshold, passed every test — and that the
test whose comment claimed to cover it was satisfied by the other disjunct. A
sparse-churn test (three flips per window, indefinitely: eased but never silent)
now separates the two and kills all four.

Also from the review rounds: two separate dead clauses in this function, one
added by each of the previous two rounds, are gone; the burst-interval median in
the shipped comment was one row off (673s, not 732s) and n is 29, not 30. That
median is grouping-fragile — 702.7s by (bundle,tab), 356.1s deduped — but the
facts it supports are not: 1 value in the 59-75s band under every grouping, and
the next gap above it is 75.3s.

Known and not fixed: a tab churning continuously at 6-10 flips per window sits
in the gap between both reset conditions and holds its back-off indefinitely, so
the next notice after it speeds up pins for the ceiling rather than one window.

Stated rather than fixed: because quiet is measured from the pin deadline, a tab
at the 8-minute ceiling needs roughly nine minutes of real silence before the
back-off clears, not one window. The record's doc says so.

* test(terminal): check churn breadcrumb values without assertions

* fix(terminal): let sustained churn pins yield to retention eviction

* test(terminal): preserve an existing burst pin during forced eviction

* test(terminal): verify sustained churn pin expiry and cleanup

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 00:29:10 -07:00
Neil 0a5e73e3bb Leave Open Settings unbound by default (#23136) 2026-09-26 00:20:00 -07:00
OrcaWinandm4air 9b30c7f60a ci: verify mobile disposal and balance unit-test costs (#23114)
* ci: verify mobile disposal and reduce unit scheduling costs

* docs(ci): clarify timing assignment validation

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-26 00:12:06 -07:00
OrcaWinandOrca Worker 4cafa50ec0 fix(windows): reuse shared PowerShell literal quoting at every hand-rolled escaper (#23083)
Co-authored-by: Orca Worker <orca-worker@localhost>
2026-09-25 23:13:31 -07:00
OrcaWinandm4air 80ff6c4e3e fix(startup): read the install-dir package ACL as SDDL so a repaired folder reads clean on Chinese/Japanese/Korean Windows (#22490)
* fix(startup): read the install-dir package ACL as SDDL so a repaired tree reads clean on every Windows language

The Windows install-dir permission probe parsed icacls's display output and
recognized the well-known package grants by their English names. On
Chinese/Japanese/Korean Windows icacls keeps 'NT AUTHORITY' in English but
translates the package names, so a tree the repair had just fixed read as
poisoned AND reliable: the pre-window repair re-armed every launch, the dialog
blamed the install, and the safe-graphics fallback was withheld.

Read the DACL with 'icacls <target> /save <tmpfile>' instead, which writes
SDDL (SIDs, AC alias) on every locale, and drop the English-name heuristic and
its wellKnownNameCheckReliable flag.

* fix(startup): reject incomplete saved Windows permission records

* fix(windows): reject ACL exports from unsuccessful probes

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 23:03:17 -07:00
OrcaWinandm4air 029b5ba1cb fix(startup): hold desktop activations until the startup window exists (#22495)
* fix(startup): hold desktop activations until the startup window exists

A second-instance, open-url, or open-file activation that landed after app
ready but before the startup window was created opened its own main window.
The startup open then built a second window, threw on the duplicate
'window:isMaximized' handler, and aborted runtime launch: no runtime RPC,
no orca-runtime.json, an orphan hidden window holding the trusted-renderer
id, and the visible window refused trusted IPC.

The desktop activation gate now starts 'initializing' for every launch mode.
The startup window opener releases it once that window exists, so queued
activations focus it, and a desktop launch that fails first releases it so
later activations can still open a window. Serve mode keeps settling the
gate after its RPC is ready.

* fix(startup): release desktop activation after failed ready prerequisites

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 23:02:23 -07:00
OrcaWinandm4air df8164f7d6 fix(sidebar): "Hide default branch" hides a folder project's root workspace (#22744)
* fix(sidebar): "Hide default branch" hides a folder project's root workspace

A folder project's root is its main workspace but has no branch, so the
non-empty-branch check never matched it. Folder projects can now hold several
workspaces, so the root is the same noise the setting hides for git projects.
Decide by repo kind so detached-HEAD and offline-SSH git mains stay visible.

* test(sidebar): name the empty-branch git main case for what it tests and refresh the entry-point comment

* fix(sidebar): reveal imported folder roots with archived siblings

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 22:59:33 -07:00
OrcaWinandm4air d9bc75752c fix(terminal): a remounted new SSH tab keeps the shell its old pane was still spawning (#22578)
* fix(terminal): a pane disposed mid-spawn no longer kills its successor's shell

A new terminal tab whose pane remounts while its first pty:spawn is in flight
is handed the SAME PTY by main's pane-spawn reservation. The disposed first
transport then killed that PTY as an orphan, so the tab closed on pty-exit
(focus fell back to tab 1) or stayed bound to a dead shell. Reported on SSH
worktrees (scan 22).

A transport destroyed mid-spawn now asks the pane surface first and keeps the
PTY while the tab exists, the worktree is not being deleted, and any layout
still names the leaf (leak-over-kill). A live transport refusing the id via
admitPtyId still kills unconditionally (#11003).

Adds rate-limited, id-hashed crash breadcrumbs for the next report:
terminal_fresh_spawn_retired (killed vs retained), terminal_tab_pty_exit
(host kind, ms since spawn, synthetic), terminal_active_tab_auto_move
(active-terminal repair, createTab orphan sweep). The two duplicated tab
pty-exit handlers now share handleTerminalTabPtyExit, and the FNV id hash
used by two crumbs moves to crash-breadcrumb-id-hash.ts.

Ports and supersedes #19386 (disposed-spawn-retention and its unit tests,
credit to its author); its Docker SSH e2e specs are not included.

* fix(terminal): scope spawn retention to its host and keep the PR focused

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 22:59:27 -07:00
OrcaWin 6fc3cdcad6 Bundle Bun for headless Orca and profile persistence (#22635)
Bundle a pinned, verified Bun runtime for headless Orca so existing Node launch commands can hand off before opening a profile. Keep desktop execution on Electron.

Add the Bun SQLite adapter and terminal backend, bounded shutdown, process inspection and cross-platform artifact qualification. Keep future managed SSH deployment separate from current production launch paths.
2026-09-25 22:49:06 -07:00
OrcaWinandm4air 38bcdf76ac perf(ci): reduce queue pressure without paid runners (#23053)
* ci: measure complete unit file costs for shard balancing

* perf(ci): reduce repeated PR setup and capture complete shard timings

* perf(ci): seed reusable main-branch native and typecheck caches

* fix(ci): stop superseded unit workflows from resisting cancellation

* perf(ci): reuse bundle fixtures and share the baseline Git build

* ci: record hosted gains and refresh main hook parity

* ci: retain default workers after performance-budget regression

* docs: record hosted mobile timing flake

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 22:48:28 -07:00
OrcaWinandm4air 49d7ed31c6 fix(native-chat): keep chat visible when detaching its pane (#23096)
* fix(native-chat): persist current pane ownership across lifecycle events

* fix(native-chat): retain ownership when client chat rendering is disabled

* fix(native-chat): preserve chat mode when detaching its pane

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 22:47:44 -07:00
OrcaWin 82412dab8b Persist profile state in SQLite with background writes (#22612)
Migrate profile state to SQLite and move writes and backups into a background worker. Acknowledge terminal, SSH and automation changes only after durable saves. Preserve JSON import, recovery, rollback and compatibility exports.

Validate migration, worker failures, maintenance, cross-profile moves and terminal lifetime races with unit, integration and end-to-end coverage.
2026-09-25 22:47:33 -07:00
Jinwoo Hong f0a3610928 test(terminal): re-pin the pane hook-order parity past #23049 (#23090)
#23049 added a useRef, a useLayoutEffect and a useEffect to the terminal pane's
chat-state, layout-persistence and title-effects hooks and merged with the
parity shard red, so main fails 'preserves the recursively flattened render
hook order' (211 vs 214). Pin 214 hooks, 7 useMemo, and the new order hash.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-26 01:34:12 -04:00
457a84d5a1 fix(mobile): label direct paths with the shared Tailscale check (#23039)
directPathForEndpoint hand-rolled Tailscale detection that called any 100.x
address a tailnet and missed Tailscale IPv6, so the same endpoint could be
labelled differently from the direct connection log. It now uses the shared
isTailscaleEndpoint. Also: a stale no-relay comment, a duplicate routing doc
line, and the overlay chain settling to Promise<void>.

Co-authored-by: mmarabel <166927047+mmarabel@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
2026-09-26 01:05:55 -04:00
OrcaWinandOrca Worker 58d1ff3b6a Provide the Orca CLI automatically in managed WSL terminals (#22761)
* Provide the Orca CLI automatically in managed WSL terminals

* Simplify managed WSL CLI provisioning

Never block a shell on CLI availability, keep the shared WSL login-shell
builder unchanged, provision from PTY env assembly only, drop the error
variable and command probing, and reuse the existing WSLENV helper.

* Scope the managed WSL CLI to WSL terminals

Provision only for WSL panes and publish the directory through
addOrcaWslInteropEnv, so daemon terminals keep inherited WSLENV entries and
non-WSL builds never see the variable. Write the bridge with a UTF-8 BOM so
Windows PowerShell 5.1 keeps non-ASCII user-data paths, give the dev bridge the
dev launcher's app-launch env, and drop the unused skill-setup wiring and
runtime capability.

* Tighten the managed WSL CLI bridge and setup

Launch the bridge child exactly like the registered bridge (no hidden
window or output relay; verified through WSL with Node and Electron), give
the dev bridge the dev launcher's NODE_OPTIONS stash, clear the guest-only
directory before starting Windows processes, collapse setup into one
function, warn once, and guard WSL env routing with tests.

* Harden managed WSL CLI quoting and inheritance

PowerShell also ends single-quoted strings at typographic quotes, so a
user-data path such as O'Brien with a curly apostrophe broke the managed
bridge. Fix the shared quotePowerShellLiteral and reuse it. Drop an inherited
ORCA_WSL_CLI_DIR on the daemon path, remove the unreachable PATH dedupe, and
cover failed setup with a stale caller value.

* Cover the managed WSL CLI in zsh and on POSIX CI

Add a live zsh case that reaches a real prompt, a POSIX test that runs the
PATH restore snippet in bash and zsh under set -u, and a null result for
unwritable user data. Say what a failed write actually costs, and document
per-spawn write logging and older-daemon behaviour.

* Keep system bashrc out of the PATH restore test

CI runners make bash -c read /etc/bash.bashrc, which fails under set -u.

---------

Co-authored-by: Orca Worker <orca-worker@localhost>
2026-09-25 21:55:21 -07:00
Neilandmmarabel 85ac14e9c2 fix(codex): retain runtime MCP entries without losing revocation (#22426)
* Retain runtime-only MCP entries

Adapted from the investigation and proposal by @mmarabel.

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

* fix(codex): respect inline and dotted canonical MCP ownership

* fix(codex): retain canonical MCP removal across upgrades

* fix(types): include MCP ownership in CLI project

* Keep unrelated main test formatting unchanged

---------

Co-authored-by: mmarabel <mmarabel@users.noreply.github.com>
2026-09-25 21:37:54 -07:00
Jinjing aed59a797a chore(i18n): translate 113 new keys to es/fr/ja/ko/zh (#23067)
* Add translations for chat resume, Git toolchain, and notebook support

* Fix translation terminology in French and Korean locales

- Standardize Korean terminology from "restart" to "resume" for chat
  resume functionality
- Clarify French error message for conflicting Orca windows/terminals
- Fix Korean context translation (문맥 → 컨텍스트)

* fix jupyter notebook translation

* chore(i18n): translate 113 new keys to es/fr/ja/ko/zh

Delta since last scan (80e0bee23b): 113 new en keys (session search,
resume-modal activity, ipynb venv, Cursor accounts, feature tips) plus 4
changed values (mid-turn -> working resume copy, screenshotsHint +maxSize).
es +111, fr/ja/ko/zh +100 each; strictly additive, 0 keys removed.

Three subagent review rounds: R1 fixed 20, R2 fixed 5 (incl. reverting an
NBSP convention misread), R3 signed off clean with full placeholder parity.

Gates: catalog verify, coverage --check, extraction, and locale vitest
suites all pass; fr/ja/ko/zh at 100% coverage.
2026-09-25 21:33:37 -07:00
Neil e13631ee53 Prioritize workspace opening over replacement checkout preparation (#23013)
* Prioritize workspace opening over replacement checkout preparation

* Preserve Git hook semantics and exercise preparation edge cases
2026-09-25 21:31:25 -07:00
OrcaWinandm4air f6eab381ce fix(types): describe command environments independently of Expo globals (#23073)
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 21:22:29 -07:00
Brennan Benson 067975bfd1 fix(native-chat): every lease latch has a way to die (#22820)
* fix(native-chat): every lease latch has a way to die

A failed exit settlement no longer leaves the lease in recovery: the release
writes no stage and keeps the exit in its death evidence, and whatever the dead
generation left running is settled from that evidence at the next acquire or
read restore. The settlement retry flag, its disposition and every branch that
read it are gone. A reservation that recorded no process is released at
startup and after a failed start, the never-written conflicted status and the
processless proof are deleted, recovery resolution always concludes, and Codex
records its child's identity at spawn, before the handshake.

* test(native-chat): a re-create needs a release proven by death evidence

* test(codex): the child's pid is reported before the handshake

* test(native-chat): type the crash and exit fixtures without casts

* fix(native-chat): wait out a terminal owner an older build recorded, in recovery rather than manual recovery

* test(native-chat): a chat mid-turn at quit reopens idle, and an older build reads an unproven release

* test(native-chat): explain the baseline store cast

* fix(native-chat): a terminal owner's refusal names the process instead of recursing

Opening a chat whose terminal owner an older build recorded threw a stack
overflow instead of the refusal that names the process to quit.

* fix(native-chat): wait out a terminal owner recovery cannot verify instead of releasing it

A terminal agent an older build recorded keeps its PTY across an Orca
restart, so a probe that cannot answer (a start-time read that fails on a
loaded host) is not evidence its transport is gone. Releasing it let a
native child resume the same conversation beside the live terminal agent.
Only proof of its exit now ends the claim.

* ci(cross-version): run the unproven-release downgrade test

The sharded unit job excludes tests/e2e/cross-version-wire, and the
cross-version job runs an explicit list that did not name the new test,
so it never ran in CI. A change to the record validator now also starts
the job.

* refactor(native-chat): map the retired manual-recovery stage to recovering at decode

Nothing in this build writes manual-recovery, and restart reconciliation
already rewrites it. Mapping it where the other retired handoff stages are
mapped removes it from the in-memory lease type and deletes the branches
that could only see it: the acquisition refusal, the renewer skip, the
unproven-release stage check, and the handoff-status 'manual recovery is
required' answer. Older builds accept recovering, so a record written back
still loads after a downgrade.

* docs(native-chat): say what happens to a live child an ownerless reservation leaves

The reaper runs once at store open, while the unreconciled lease still
claims the child's token, so it does not stop that child on this launch.
The comment claimed it did.

* test(native-chat): name the each-case label for its role

* fix(native-chat): continue a create retried after recovery released its reservation

The client retries a create it never heard back from under the same operation id.
Recovery had released that create's reservation, so the retry was refused
agent_session_ownership_unknown while its row was pending, and
agent_session_operation_expired once the row aged out, and the chat never started.
A retry whose lease nothing holds now continues as a fresh reservation at the next
fence, which also stops the old reservation's spawn from committing.

* test(native-chat): name the refusal a replayed create used to get

* fix(native-chat): one quit-the-terminal-agent message for a chat a terminal agent holds

A chat held by a terminal agent an older build recorded frees only when that agent
exits. Sending said to reopen the chat and opening it said two runtimes claimed
it; both now say the chat is open in a terminal agent, name its process, and say
to quit it. Error codes are unchanged.

* ci: run PR checks on the rebased head

* fix(native-chat): name a terminal owner's process only when its start time can tell it from a reused pid

* test(native-chat): relaunch from the dying host's durable state, so its still-pending attach cannot race the new host
2026-09-25 21:04:31 -07:00
d06b43e634 fix(tasks): read a malformed saved Linear team selection as sticky-all instead of crashing the page (#22279)
* fix(tasks): read a malformed saved Linear team selection as sticky-all instead of crashing the page

A persisted defaultLinearTeamSelection that is not a string array (a string
reached 1.4.207, report 0a2b6e7f) threw '(t ?? []).filter is not a function'
inside a commit-phase effect and tripped the page.tasks error boundary. The
value is now normalized where the page reads it and where a host projects it
to paired clients; anything but a string array means sticky-all.

* fix(mobile): read a malformed saved Linear team selection as sticky-all

A host that predates the desktop fix projects its raw store value, so the
mobile Linear list must tolerate the same string shape. Also trims the
desktop helper's comments to the why.

* fix(tasks): validate projected Linear team IDs and refresh parity contract

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 21:01:32 -07:00
Jinwoo Hong 27ca6a229a test(mobile): repin RPC goldens to main after #22956's squash (#23046)
#22956 re-recorded with baseline = its own branch commit c5c1477ad4, which
the squash merge left unreachable from main, so the RPC recording pin guard
fails on main and every open PR. Repin to main's tip and re-record: only
baseline and lockfileSha256 (main's lockfile moved in #22961/#22964) change;
every recorded body is identical.
2026-09-25 23:56:00 -04:00
Neilandcarlosbaraza 15baf86660 fix(agents): honor environment prefixes in generation commands (#22427)
* fix(agents): preserve environment prefixes in generation commands

Adapted from the proposal by @carlosbaraza.

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

* test(agents): respect Windows environment key normalization

---------

Co-authored-by: carlosbaraza <carlosbaraza@users.noreply.github.com>
2026-09-25 20:50:39 -07:00
NeilandSungjae-Heo d929bd8f56 Keep large Windows file identities distinct (#22424)
Adapted from the investigation and proposal by @Sungjae-Heo.

Co-authored-by: Sungjae-Heo <Sungjae-Heo@users.noreply.github.com>
2026-09-25 20:50:36 -07:00
Neilandmidego 094fbef08c fix(toast): keep folder errors above standard modal backdrops (#22423)
* fix: make folder errors visible above dialogs

Co-authored-by: midego <61051030+midego1@users.noreply.github.com>

* test(toast): explicitly isolate background app launches

---------

Co-authored-by: midego <61051030+midego1@users.noreply.github.com>
2026-09-25 20:50:34 -07:00
NeilandPr1p f851d18e91 Preserve Kimi config permissions (#22422)
Adapted from the investigation and proposal by @Pr1p.

Co-authored-by: Pr1p <Pr1p@users.noreply.github.com>
2026-09-25 20:50:31 -07:00
Neilandmmarabel 18d00ccfe6 fix(projects): refresh stale automatic GitHub icons during enrichment (#22421)
* fix: repair a bounded stale project-icon case

Based on the report and proposal by @mmarabel.

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

* fix(projects): preserve peer-owned remote metadata

* fix(projects): keep enrichment within the owning host

---------

Co-authored-by: mmarabel <mmarabel@users.noreply.github.com>
2026-09-25 20:50:27 -07:00
7d4413b3d7 fix(pdf): keep the search counter in sync with selected matches (#22420)
* fix: update the PDF search counter

Co-authored-by: BM Cho <bm1016bm@gmail.com>
Co-authored-by: makoto-developer <72484465+makoto-developer@users.noreply.github.com>

* test(pdf): respect explicitly headful launch mode

* test(pdf): wait for rendered folder search highlights

* test(pdf): wait for rendered text before initial search

---------

Co-authored-by: BM Cho <bm1016bm@gmail.com>
Co-authored-by: makoto-developer <72484465+makoto-developer@users.noreply.github.com>
2026-09-25 20:50:24 -07:00
Neilandchaiyapod 9d5591b791 fix(jira): bypass collection caches on explicit refresh (#22419)
* fix: refresh Jira lists immediately

Based on the report and proposal by @chaiyapod.

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

* fix(jira): ignore superseded collection auth failures

---------

Co-authored-by: chaiyapod <chaiyapod@users.noreply.github.com>
2026-09-25 20:50:21 -07:00
NeilandJoao Nicola 7889a25b7f fix(cli): preserve the WSL distro when adding managed accounts (#22418)
Keep the caller distro across the Windows bridge, including drive-mounted
working directories, and pass it through the existing account imports.
Retain the contribution from PR #17093 and cover empty/space-containing
bridge arguments, platform boundaries, and ambient environment conflicts.

Co-authored-by: Joao Nicola <jgrnicola@gmail.com>
2026-09-25 20:50:18 -07:00
Neilandbbingz 14087c8e32 Accept repeated leading BOMs in agent hooks (#22414)
Adapted from the investigation and proposal by @bbingz.

Co-authored-by: bbingz <bbingz@users.noreply.github.com>
2026-09-25 20:50:15 -07:00
OrcaWinandm4air 2ed6505a41 fix(native-chat): preserve current pane ownership through toggles and restore (#23049)
* fix(native-chat): persist current pane ownership across lifecycle events

* fix(native-chat): retain ownership when client chat rendering is disabled

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
2026-09-25 20:46:24 -07:00
NeilandJonghwa Hong d1eb64ea41 fix(editor): use the bundled ABAP grammar (#22417)
Co-authored-by: Jonghwa Hong <zzzonghwa@gmail.com>
2026-09-25 20:42:41 -07:00
Jinwoo Hong ce2f75e172 refactor(mobile): the live input's composing range comes from a platform seam pair (#23037)
#22958 made the page on Android report no composing range with a user-agent check inside the shared
live-input hook. Host facts live in a `src/platform` pair, so the check moves to
`live-input-composing-range.web.ts`; the native file passes the event's range through. Behaviour is
unchanged. The hook test mocks the seam; the user-agent cases move to the seam's own test.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-25 23:41:46 -04:00
77bc0d77d8 fix(editor): highlight scoped dotenv filenames on desktop and mobile (#22416)
Co-authored-by: willydallas <willy.dallas@pm.me>
Co-authored-by: Wooseong Kim <innocarpe@gmail.com>
2026-09-25 20:40:53 -07:00