Commit Graph
8449 Commits
Author SHA1 Message Date
Jinwoo-H c7c8a2e32d test(skills): cover Windows junction ownership 2026-08-11 11:17:22 -04:00
Jinwoo-H f1fc8f7242 docs(skills): record Windows contention evidence 2026-08-11 11:16:26 -04:00
Jinwoo-H 18fe31f107 fix(skills): return retryable rename exhaustion 2026-08-11 11:15:41 -04:00
Jinwoo-H 8b1b434048 test(skills): observe locked source without opening it 2026-08-11 11:14:19 -04:00
Jinwoo-H 74d2e6b42a test(skills): pass lock fixture through environment 2026-08-11 11:13:22 -04:00
Jinwoo-H 2415708c99 test(skills): fix Windows lock harness 2026-08-11 11:12:31 -04:00
Jinwoo-H 82321779f2 test(skills): exercise real Windows rename contention 2026-08-11 11:10:47 -04:00
Jinwoo-H c456fdd68e docs(skills): close adversarial ingress gates 2026-08-11 11:05:30 -04:00
Jinwoo-H 534abb8908 test(skills): reject download host confusion 2026-08-11 11:05:11 -04:00
Jinwoo-H 6fd37cbcfa docs(skills): record cloud observability evidence 2026-08-11 11:03:08 -04:00
Jinwoo-H 38202d3c1b security(skills): harden private staging 2026-08-11 10:54:51 -04:00
Jinwoo-H ea873c6134 docs(skills): record real Windows workspaces 2026-08-11 10:50:36 -04:00
Jinwoo-H 1e2d2e806f test(skills): use Windows junction fixtures 2026-08-11 10:49:19 -04:00
Jinwoo-H 7094c05985 test(skills): cover real Windows workspaces 2026-08-11 10:47:33 -04:00
Jinwoo-H 42de7a0058 feat(skills): bound install diagnostics 2026-08-11 10:44:23 -04:00
Jinwoo-H 5cc9b99011 docs(skills): record Windows long-path gate 2026-08-11 10:37:58 -04:00
Jinwoo-H 6d3ce582aa test(skills): cover Windows long paths and case collisions 2026-08-11 10:36:55 -04:00
Jinwoo-H f21c2866f7 docs(skills): record current Windows validation 2026-08-11 10:35:19 -04:00
Jinwoo-H 41bede4c78 test(skills): use portable git config fixtures 2026-08-11 10:34:05 -04:00
Jinwoo-H 9bf732de49 docs(skills): refresh pushed baseline 2026-08-11 10:32:25 -04:00
Jinwoo-H 980e558850 docs(skills): record boundary and host evidence 2026-08-11 10:32:13 -04:00
Jinwoo-H 149d2dc2b5 fix(skills): recover interrupted remote transfers 2026-08-11 10:31:09 -04:00
Jinwoo-H 83d26e09fd docs(skills): refresh implementation evidence 2026-08-11 10:15:11 -04:00
Jinwoo-H 8963bb3bef feat(skills): harden shared installation lifecycle 2026-08-11 10:13:40 -04:00
Jinwoo-H c8e5d0d5c4 docs(skills): record implementation validation 2026-08-11 09:39:14 -04:00
Jinwoo-H 4eeb30ddc8 feat(skills): harden sharing and install lifecycle 2026-08-11 09:38:51 -04:00
Jinwoo-H 9eeb388af5 docs: reconcile skill sharing implementation checklist 2026-08-11 08:41:46 -04:00
Jinwoo-H ed2781fbc1 fix: support Windows-backed WSL skill installs 2026-08-11 08:33:38 -04:00
Jinwoo-H dc7d5a20ab test: cover Windows-backed WSL skill workspace 2026-08-11 08:31:57 -04:00
Jinwoo-H 6ffd14c987 test: add real WSL skill transaction harness 2026-08-11 08:30:37 -04:00
Jinwoo-H 9bf12760d4 test: cover skill transaction recovery and management 2026-08-11 08:28:16 -04:00
Jinwoo-H d364750ad2 test: account for native Windows skill semantics 2026-08-11 08:21:32 -04:00
Jinwoo-H ff6674e1f5 feat: add private skill sharing and installer 2026-08-11 08:16:39 -04:00
Neil 0aa7d0b5c1 refactor(renderer): unify the window park-visibility primitive (#13778)
The stream-gating hook (#13608) and the subscription parking installer
(#13621) each reimplemented `isWindowVisible() || isDocumentVisibilityProvenStale()`
plus its visibilitychange + stale-recovery subscription, and each carried
its own 500ms park delay that agreed only by coincidence.

Extract both into `lib/window-park-visibility.ts` and leave the two
consumers as thin wrappers: `useWindowStreamVisible` feeds the snapshot
and subscribe into `useSyncExternalStore`, the parking installer calls
them imperatively. The subscribe now always uses the defensive
`typeof document` guard the parking side already had, and registers
stale recovery before the visibilitychange listener so the stale latch
is cleared before the callback reads it.

Both park delays now derive from one `WINDOW_HIDE_PARK_GRACE_MS`: they
debounce the same signal against the same user behaviour (a quick
app-switch round trip). The parking side's 8x reveal-side backoff stays
where it is - that models its own resume cost, not the grace window.

Renderer-authoritative gating (#13622 native chat, #13634 editor panels)
is deliberately left alone; it keys off Zustand routing state, not OS
visibility.

Also switch the active-runtime ref writes in web-session-tabs-sync to
`useLayoutEffect` so no resume event can land between paint and the
passive flush, and correct the stale comment above them - the install
effect reads neither ref (both readers are gated on `isVisibilityResume`).
2026-08-11 01:43:47 -07:00
NeilandOrca 12f58f6bee fix(editor): keep an invalidated diff visible until its reload lands (#13777)
Mark invalidated diff content stale instead of dropping it, mirroring the file-content treatment from #13634. The diff read-generation fence (diffReadGenerationRef) already rejects a superseded read's write-back, so retaining the bytes and swapping them on arrival is safe and keeps every RPC saving -- it just stops the loading placeholder flashing on each reveal.

The git-status reload effect now treats a stale entry like a missing one so the lazy-load effect stays the single fetcher for it.

Co-authored-by: Orca <help@stably.ai>
2026-08-11 01:43:44 -07:00
NeilandOrca b3965f3205 perf(native-chat): suspend hidden transcript streams (#13622)
* perf(native-chat): suspend hidden transcript streams

* fix(native-chat): keep assembly renders pure

* fix(native-chat): keep a transient error from stranding a revealed chat

- An error snapshot frame no longer latches frameArrived, so the in-flight
  read can still seed the pane instead of leaving it on the error surface.
- Retained history is shown over a full-pane read error for the same source.
- The paged read window survives a hide/reveal; only a source change resets it.

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

* fix(mobile): match the trimmed native-chat retention signature

The shared retention type no longer takes `loading`, so mobile's call was an
excess-property error that broke the mobile typecheck job. Dropping it also
lets mobile inherit the desktop behavior: a stream error or dropped client
keeps the last transcript instead of swapping it for the error empty state.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 01:27:25 -07:00
NeilandOrca 33e8d89d48 [perf-remote] perf(renderer): park hidden remote browser screencasts (#13608)
* perf(renderer): park hidden remote browser screencasts

* test(renderer): pin stale-visibility term and parked-unmount teardown

Restores the WHY behind the '|| isDocumentVisibilityProvenStale()' term the
emulator-module dedupe dropped, and pins it plus the close-tab-while-parked
path with tests. Extracts the lifecycle harness so the spec stays under
max-lines without a suppression.

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

* fix(ci): exclude test-support modules from the localization audit

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 01:27:02 -07:00
NeilandOrca 94a4756095 [perf-remote] perf(renderer): park hidden remote session mirrors (#13621)
* perf(remote): park hidden session mirrors

* perf(renderer): bound visibility resume cost and repair fences

- Back off the park delay after a park the user undoes quickly; each resume
  re-enumerates every paired host, so short hide/reveal churn now stops
  parking instead of paying that cost per cycle.
- Expire the active-worktree omission fence one visibility generation after
  the inventory that set it, and name the unfiltered-inventory invariant it
  depends on.
- Never skip the unchanged resume inventory for a worktree whose repair
  replay is already armed.

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

* fix(renderer): move active-runtime ref writes out of render

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 01:14:40 -07:00
Neil baeb1b3cc8 perf(editor): stop hidden panels duplicating remote reloads (#13634)
* perf(editor): park hidden external reloads

* fix(editor): sync content refs after commit

* fix(editor): close post-commit ref window

* test(editor): cover commit-time visibility

* fix(editor): keep invalidated content visible and stop redundant reads

- Mark invalidated file content stale instead of dropping it so a reveal swaps
  bytes in place; the read-generation fence already blocks stale write-backs.
- Skip the lazy read when the newest read for the tab is still outstanding, so
  a worktree flip-flop cannot double-fetch.
- Stop claiming Cmd/Ctrl+S outside the workspace view, where no mounted panel
  owns the request and the keystroke was silently swallowed.
2026-08-11 01:14:37 -07:00
NeilandOrca 8fad723f84 fix(worktree-poller): sample the scan gate before its listing (#13772)
A write landing during a full scan was recorded by the post-scan gate stat,
so the next tick saw a clean gate and the create/delete waited up to 15 ticks
(~30s) for the backstop. Sample each gate dir's signature before its listing
so a racing write reads as stale and forces one rescan on the next tick.

Also fixes the flaky 'retires stale marker probes' spec: a folder caught
mid-rm opened a pending-marker window that the swallowed gate change kept
alive for the whole backstop gap (43 probes vs the 30 budget).

Co-authored-by: Orca <help@stably.ai>
2026-08-11 01:14:28 -07:00
Jinjing 9b79cc1b9e Add copy button for quick command (#13768)
* Add copy button to quick commands with visual feedback

Quick command rows now display a copy button that copies the command body to clipboard. The button shows brief visual feedback ("Copied" or "Couldn't copy") and is disabled when the command body is empty. Includes desktop and mobile UI, tests, and full i18n support.

* fix(ci): unblock verify for quick-command copy button

Key feedback to the copied body so prop changes drop stale labels without
setState-in-effect, and mock expo-clipboard in the mobile list test.
2026-08-11 01:06:03 -07:00
Jinwoo HongandJinwoo-H 5e3a2d25f7 Filter remote workspaces by creating device (#13718)
* Filter remote workspaces by creating device

* Fix workspace origin filter reconnect behavior

* Shorten workspace origin filter label

* Refine remote workspace filter UX

---------

Co-authored-by: Jinwoo-H <Jinwoo-H@users.noreply.github.com>
2026-08-11 01:05:12 -07:00
NeilandOrca 21d5ca6db3 [perf-remote] perf(renderer): dedupe remote status hydration (#13705)
* perf(renderer): dedupe remote status hydration

* fix(runtime-status): re-list host catalog when the listing goes stale

Coverage matching cannot observe catalog edits made by another client or the
orca CLI, so gate hydration on catalog listing age too.

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

* test(runtime-status): reset the catalog listing clock between tests

The staleness guard keeps its last-listed timestamp in module scope, so the
TTL test left fake time behind and made every following test in the file
depend on its position. Add a reset hook, call it in beforeEach, and pin the
TTL invariant on an externally added host rather than the timer alone.

Also extracts the coverage predicate in fetchSettings and restores the WHY
comment about compat failures clearing on a reachable status.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 00:33:55 -07:00
NeilandOrca a639bd355e [perf-remote] perf(codex): skip migration scans for nonshared reattaches (#13654)
* perf(codex): skip migration scans for nonshared reattaches

* fix(codex): require provenance to skip migration scans and bound ignored launches

Drops the exit-match escape hatch that skipped a scan without route provenance, and ages out ignored reattach launches on the existing 60s/256 lease policy so a lost exit can no longer pin an active launch (and its completion marker) for the process lifetime.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 00:33:17 -07:00
NeilandOrca bb08b66b21 perf(runtime): avoid forced SSH hydration on project refresh (#13636)
* perf(runtime): avoid forced SSH hydration on project refresh

* fix(runtime): backfill SSH states for targets learned without a state read

A failed-connect resync labelled a target with no ssh.getState, and the new
metadata-refresh gates then skipped it forever: no SSH chip and every worktree
mutation to that host failed the connection-generation check.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 00:20:53 -07:00
Neil c578f4e4e2 fix(e2e): restore the helpers the macOS key-remap spec imports (#13758)
#13314 landed terminal-macos-system-key-remap.spec.ts but its final commit,
"chore: drop non-mergeable IME e2e scratch files", deleted the three modules it
imports. The spec survived; terminal-ime-pane-arena, terminal-ime-cdp-composition
and terminal-ime-platform-policy did not.

Playwright resolves every spec before running any of them, so the unresolved
import is fatal for the whole run, not just that file: `playwright test --list`
on main reports "Total: 0 tests in 0 files". All ten scheduled E2E shards have
been failing at collection since, and the macOS system-key-remap coverage the PR
was for has never run once.

No typecheck project includes tests/, which is why this stayed invisible outside
the E2E lane.

Restored from the commit before the drop. pane-arena and platform-policy come
back verbatim; cdp-composition keeps only the four entry points this spec uses,
since the rest served specs that were not merged. Its doc comment is retargeted
accordingly — the composition-session drivers are the part that went.

Collection is back to 528 tests in 222 files and all six remap tests pass.
2026-08-11 00:10:40 -07:00
NeilandOrca 200b3e53ae perf(renderer): keep the repos array identity across no-op refetches (#13744)
* perf(renderer): keep the repos array identity across no-op refetches

reconcileFetchedRepos deliberately returns the previous array when a refetch
changes nothing, so identity-keyed memos can skip work. Two later steps in the
same chain copied unconditionally and threw that identity away:

- reconcileReadoptedSshRepoRows spread the input on its no-prune path, which is
  the common case.
- applyManualRepoOrder allocated a fresh array even when the saved order moved
  nothing.

Both now return the input when they change nothing, so state.repos stays
referentially stable through fetchRepos, fetchRuntimeEnvironmentRepos,
fetchReposForAllHosts, and hydratePersistedUI.

Return type stays Repo[] with the same cast reconcileFetchedRepos already uses;
all four call sites only read the result.

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

* refactor(renderer): make the store repos array readonly at the type level

Preserving the repos array identity means handing callers the same array that
is live store state, which previously relied on `as Repo[]` casts to launder
readonly inputs back into a mutable field. A cast is a footgun: the next person
to add a .push or .sort corrupts store state with no type error.

Widen RepoSlice['repos'] to readonly Repo[] and propagate honestly. Consumers
that only read take readonly Repo[]; genuine local accumulators are annotated
Repo[] and built from copies.

Removes all four pre-existing `as Repo[]` casts in the reconcile chain
(repo-identity-reconcile, superseded-ssh-repo-rows, manual-repo-order x2) —
this lands with fewer casts than main has today.

Type-only change; no runtime behavior differs.

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

* fix(renderer): compare nested repo fields so reconciliation actually fires

Preserving the repos array identity was inert. reconcileFetchedRepos compares
repo fields with !==, but every repo the renderer receives carries nested
records that are new objects on every fetch:

- main's hydrateRepo unconditionally rebuilds hookSettings for every repo,
  even a pristine one (persistence.ts:5109)
- IPC structured-clone (and the JSON hop for SSH/runtime hosts) reclones
  gitRemoteIdentity, upstream, repoIcon, and the path arrays

So every repo compared unequal, `identical` went false on every refresh, and
the array was rebuilt regardless of the copies removed in the parent commit.

Compare nested plain records structurally instead. They are small sanitized
values; anything non-plain falls back to reference equality.

The end-to-end test previously passed for a fixture-only reason: its repo had
five scalar fields and the mock returned the same object both calls, the one
shape production never produces. It now uses a production-shaped repo and
fails without this change.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 00:08:19 -07:00
BingZandOrcaWin bdebe53568 fix(settings): paste bash-native skill setup under WSL PTY (#13710)
* fix(settings): paste bash-native skill setup under WSL PTY

WSL worktree setup terminals force wsl.exe even when shellOverride is
powershell.exe. Auto-pasting the PowerShell `& { wsl.exe ... }` wrapper
into bash fails with a leading-& syntax error (#13305). Rewrite that
wrapper to a bash login-shell script for setup-terminal paste only;
clipboard copy still keeps the PS host wrapper for manual use outside Orca.

* fix(settings): align skill paste with resolved PTY shell

* fix(onboarding): keep shell preparation out of render

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-08-11 00:07:49 -07:00
Brennan Benson 3ed4dc484f fix(native-chat): scope persisted options to chat launches (#13675)
* fix(native-chat): defer to Codex model picker defaults

* fix(native-chat): settle Codex picker ownership

* fix(native-chat): record typed options after submit

* fix(native-chat): verify typed option submission

* perf(native-chat): skip option probe for chat sends

* perf(native-chat): scope verified sends to Codex

* fix(native-chat): require standalone picker command

* fix(native-chat): scope launch options to chat view

* fix(native-chat): align smart folder launch mode
2026-08-10 23:51:18 -07:00
Brennan Benson 915ee50cc2 fix(ui): rename Caffeinate Auto mode to Agent (#13751)
* fix(ui): rename caffeinate auto mode to agent

* fix(ui): center caffeinate radio indicator

* fix(ui): center caffeinate indicator within option
2026-08-10 23:50:41 -07:00