* Revert "Show child workspace statuses in the children toggle (#32224)"
This reverts commit b4ee652bcf.
* Fix revert button styling and retire stale child-toggle translations
* Revert "fix(workspace): show launch actions in empty tab groups (#32182)"
This reverts commit afe62effd3.
* Retire empty-workspace translations removed by revert
Rolls in the 69 missing translations from #32017 by @lucasrbsouza, preserving the current catalog and his original translated values. Adapted from commits a103b8d7e1 and 81befb581a.
* ci: run relay integration on the Blacksmith x86 pool
* ci: use the validated Blacksmith pool for Linux packaging
* test: allow shared Linux download caches across validated runner pools
* perf(watch): stop watching all of userData and .git for a handful of files
On macOS a directory fs.watch is a recursive FSEvents stream. Two watches used
that to notice a few files:
- The Active Server preference watched the whole userData directory for
orca-environments.json, so Orca's own writes there (agent-hooks status,
terminal history, browser caches; ~10 events/s measured) were routed back
to it.
- The shallow git metadata watch ran fs.watch on each repo's whole common
.git dir (and .git/logs), receiving objects/, refs/, lfs/ and every linked
worktree's churn to see six files.
Both now watch the individual files (kqueue on macOS, no fseventsd) through a
new rebinding file watch: events and a 30s sweep re-stat the path, rebind when
a rename-replace or deletion moved it, and pick up files created later. Events
are confirmed by a stat (size/mtime/ctime/inode) because macOS raises an
attribute event for every mmap read of the index and packed-refs; the watch is
one-shot with a backing-off window so a file every git process maps costs about
one rebind a second instead of a wakeup per read. The registry path is
unchanged, so CLI/serve readers and older peers are unaffected. Linux and
Windows keep the non-recursive directory watch for shallow subscriptions.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(watch): don't hang unsubscribing an errored watcher; find late metadata files sooner
- Node closes an errored fs.watch handle without emitting 'close', and a later
close() is a no-op, so awaiting 'close' could hang a watcher-child unsubscribe
and every subscribe queued behind it. Errored watchers are now dropped without
a close, and closeFileSystemWatcher also settles on 'error' or after 1s.
Applies to both the macOS file watch and the Linux/Windows directory watch.
- Missing metadata files (packed-refs from pack-refs/gc) are re-statted every
2s instead of waiting for the 30s rebind sweep.
- On macOS the delivery probe watches a file, matching the kqueue path the
shallow subscriptions now use.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(editor): keep every view of a shared record on its text; ask before a lossy UTF-8 save
- A clean record's draft may reach a view's live model. Views of a record share one draft, so a
commit that reads clean (a rich-mode undo that differs from disk only in trailing whitespace)
is the record's text; refusing it left the source view showing undone text, and typing there
resurrected it.
- A rich view applies another view's text (or a reload) without an undo step, so its Cmd+Z no
longer reverts the source view's typing or re-applies text undone there.
- An outside change to a path (Source Control discard, watcher) now reaches views of the same
record in other workspaces' panels, not only the named workspace's, so their cached copy of the
discarded text is dropped and reloaded.
- Explicit saves send the lossless-UTF-8 precondition. A non-UTF-8 file asks for confirmation
(Save as UTF-8, destructive) before replacing characters that aren't valid UTF-8; declining
leaves the bytes alone. The autosave-paused notice no longer promises a lossless conversion.
- Dev builds resolve worker-thread entries from the main output folder when the caller was bundled
into a shared chunk (packaged builds resolve from resources and are unchanged).
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(editor): say why save-and-close refused a non-UTF-8 file
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(watcher): back off on system event stalls and let the crash fuse recover
The watcher child's canary treated any missed delivery as a native deadlock
and exited. When the OS event source itself is stalled (an overloaded macOS
file-event daemon), each restart recreated every stream, adding load, and
after three restarts in two minutes the crash fuse disabled native watching
until the app restarted.
- Before exiting on a starved canary, probe the same dir with an independent
fs.watch. If fs.watch delivers, it is a child deadlock: restart as before.
If both stay silent (and fs.watch was proven to work on this host), it is a
system stall: keep the child and its streams and back off the canary
(30 s doubling to 5 min) until delivery resumes.
- The crash fuse now half-opens after an exponential cooldown (5 min doubling
to 60 min) so native watching is retried; callers keep their polling
fallback while it is open. A trial crash reopens it immediately; a trial
that stays healthy for 10 min resets the escalation.
- Arm the canary while a native subscribe is pending: always on macOS (its
subscribe does not crawl), and after a 10 min grace on crawling backends,
so a subscribe stuck behind a deadlock no longer disables the check.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(watcher): bound stalls, keep callers fresh, and let the fuse reopen reach callers
Review follow-ups for the watcher stall/backoff change:
- fs.watch proof is no longer a cached startup probe. Any delivery in the
process (including the canary's own fs.watch) proves it; a failed shallow
probe is re-measured after 30 s instead of failing shallow subscribes forever.
- The canary keeps one long-lived fs.watch on its dir and checks whether it
delivered since the probe started, instead of opening one per probe (which
makes macOS rebuild the shared event stream).
- Any native callback in the child during the probe window counts as proof the
child is not deadlocked. A stall that lasts 15 min forces a restart, still
rate-limited by the crash fuse.
- The child reports delivery health (healthy/stalled) to the host. A stall that
outlasts one backoff period makes the host send an overflow (rescan) to every
subscription on that cadence, and once more on recovery.
- Roots that fail while the crash fuse is open are no longer cached as
unwatchable until shutdown, and the git-common narrow watch's polling
fallback retries native events every 5 min. Log wording no longer claims
every caller polls.
- Linux/Windows keep the canary disarmed during a pending crawl (huge or
network trees); macOS stays armed.
- Fuse escalation resets only after the trial child's canary has confirmed
delivery for 10 min, not merely after it survived 10 min.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(watcher): back off stall rescans and end stalls when the canary disarms
- Host rescans during a stall now back off with the canary (30 s doubling to
5 min) instead of every 30 s for the whole stall, and stop once no
subscription is live.
- A canary that disarms after a stall (no live roots, or a crawl on
Linux/Windows) reports 'unknown', which ends the host's stall mode with one
rescan; the stall is re-detected once the canary re-arms. The crash fuse
ignores 'unknown'.
- Health reports are ignored after supervisor disposal (they were already
limited to the current child).
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* test: remove redundant cases and repair behavioral assertions
* docs: reconcile audit records with current main
* fix(deps): apply security updates from #32101
Apply the six-file DOMPurify 3.4.17 and Next.js 16.4.1 patch from PR #32101 to resolve the dependency security gate for this test audit. Original patch by Brennan Benson.
* test: satisfy changed-line quality gates
Add required braces and replace filter indexing with find. Rerun both CI quality gates and the 27 affected relay tests; refresh audit hashes and record the corrections.
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* Use incremental tsrs for local typechecks
* Update pinned Bun to 1.4.4
* fix(deps): bump dompurify to 3.4.17 and docs next to 16.4.1 for security advisories
dompurify 3.4.17 patches GHSA-cg2g-xh64-v4q7, GHSA-mrv2-3pqr-j5jr and
GHSA-c6gr-qvv4-5v3f in the root and mobile lockfiles. next 16.4.1 patches
GHSA-2464-fhr4-w9xw, GHSA-673q-mjm6-r5xr and GHSA-p3m5-59mp-jv5r in the
docs site.
* Prepare mobile bundle for smoke benchmarks
* Give native compiler benchmarks a larger ARM runner
---------
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Settled reveal and every other atlas recovery forced the current xterm buffer
onto the screen even while a TUI held DEC 2026 synchronized output. Codex
erases rows inside each held redraw, so a reveal mid-redraw showed a blank
pane for a frame (#32198).
Viewport presents now have one mode: they keep the last coherent canvas and
let xterm present when the TUI closes the frame, bounded by xterm's 1s
synchronized-output safety timeout. Structural replay keeps its retained frame
up until an open synchronized frame closes, bounded by its existing hold cap.
Co-authored-by: YEONGUK LEE <contact@abruption.dev>
* fix(mobile): keep a terminal tab's chat identity while its handle is unchanged
A status frame that omits agentType or providerSession flipped chat back to the
terminal for tabs with no launchAgent (#31977), and left a launched tab with no
session to read (#32134). Mobile now remembers the last resolved agent and
session per tab and handle, so a missing field is treated as missing evidence.
* fix(mobile): keep remembered chat read-only and drop it on relaunch
A chat resolved only from this phone's memory may sit on a bare shell, so its
writes stay locked until live status confirms the agent. A live agent frame
without a session no longer inherits the previous conversation, and the
latest remembered agent outranks an older launch hint.
* fix(mobile): gate native-chat image sends on a confirmed live agent
An image send from a chat only this phone remembers could paste into a bare
shell; it now shares the confirmed-agent gate with text sends.
* fix(mobile): type remembered chat identity structurally
Importing MobileSessionTab into the eligibility module pulled React Native
globals into the e2e program through nested-agent-idle-session-owner.spec.ts,
retyping setTimeout as number there.