Commit Graph
604 Commits
Author SHA1 Message Date
NeilandOrca 25ea2bbfd1 onboarding: seamless macOS notification permission step with live state detection (#7684)
* feat(onboarding): state-aware macOS notification permission step

The Set up notifications step showed a one-size-fits-all 'Open Mac
Settings' button that simultaneously fired the macOS permission prompt
and opened System Settings — two competing system UIs, with System
Settings unnecessary for the common fresh-install case.

Electron exposes no API to read macOS notification authorization, but
scheduling outcomes do reveal it: a silent probe notification's 'show'
event means permission is granted, 'failed' means delivery is blocked.
A new notifications:probeDelivery IPC runs that probe (cached via
passive delivery evidence and a persisted confirmation flag), and the
onboarding card now renders the real state:

- fresh install: the probe itself pops the native Allow dialog the
  moment the step opens; the card flips to 'Notifications are enabled'
  automatically when the user clicks Allow (silent 2.5s re-probes)
- blocked: amber card with an Open System Settings deep-link, which
  also self-heals once the user flips the toggle
- granted: green confirmation card

The test-notification button now feeds the same card instead of the
ambiguous 'if no banner appeared…' toast during onboarding.

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

* fix: don't log expected probe rejections while polling for permission

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

* fix: amber warning styling + single stable dev bundle id for notifications

- Blocked card now uses the app's shipped amber idiom (tinted surface with
  amber title/body) instead of white-on-amber-wash, which read muddy in
  dark mode; macOS permission card split into its own module to stay under
  the max-lines budget.
- Dev instances previously minted a unique macOS bundle id per
  branch x Electron version, registering a new Notification Settings entry
  every time ('Orca: <branch>' rows piling up forever) and pointing the
  settings deep-link at ids System Settings can't resolve. All dev
  instances now share com.stablyai.orca.dev: one Notification Center
  entry, one permission grant covering every dev build.

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

* fix: tighten macOS permission card copy

Body copy was one long sentence; now a single short instruction with
'Updates automatically.' as a separate dimmer line. Also repairs locale
catalog parity for keys introduced by commits rebased into this branch.

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

* fix: drop 'Updates automatically.' line; ad-hoc sign dev app copies

The extra line read as confusing filler — the cards now carry one short
instruction each.

Dev Electron copies had broken code signatures (the Info.plist identity
edits invalidate the ad-hoc seal), which macOS punishes by refusing
Notification Center registration outright: every dev notification failed
with UNErrorDomain error 1, the app never appeared in System Settings >
Notifications, and the settings deep-link had nothing to land on. The dev
runner now ad-hoc re-signs the copied bundle after the plist edits
(bundleLayoutVersion bumped so stale unsigned copies are recreated).
Verified end-to-end: runner-built copy passes codesign --verify --deep,
probe delivery returns delivered, the onboarding card flips green in dev,
and the deep link opens the dev app's own notifications pane.

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

* fix: drop confusing copy line; session-only permission evidence

Removes the 'Updates automatically.' line from both permission cards.

Also drops the persisted notificationDeliveryConfirmed flag: OS-level
permission changes between sessions, and a stale positive rendered a
false green card. Delivery evidence is now session-scoped only.

Documented detection ceiling (verified empirically on macOS 26): while
the permission dialog is unanswered — and when notifications are toggled
off in System Settings after being authorized — macOS accepts requests
and silently swallows them, with no public API (Notification Center
delivered-history and legacy ncprefs both included) able to distinguish
that from real delivery. 'failed' remains definitive for unsigned builds
and dialog-level denials.

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

* feat: real macOS notification permission readout via native helper

Electron has no API for UNUserNotificationCenter authorization, and every
observable fallback lies: scheduling succeeds (and getHistory lists the
notification) even while macOS silently swallows display because the
permission dialog is unanswered or notifications were toggled off in
System Settings. The onboarding card therefore showed 'enabled' after the
user disabled notifications.

Adds native/notification-status-macos: a tiny Swift binary that prints
the app's real authorization status. It runs from inside the app bundle
(NSBundle resolves the bundle by walking up from the executable) and
embeds the app's CFBundleIdentifier in a __TEXT,__info_plist section so
every codesign --force pass — electron-builder's signing or the dev
runner's ad-hoc deep sign — derives the identifier macOS keys
notification records to. Spawning it from the app returns authorized /
denied / not-determined exactly matching System Settings.

notifications:probeDelivery now prefers this readout (authoritative,
silent), firing at most one dialog-trigger probe per session while the
decision is pending, and falls back to the previous delivery-probe
heuristics when the helper is unavailable. The card polls the readout
silently in every state, so toggling Allow notifications in System
Settings flips the card within a poll — both directions, verified live.
Test notifications also consult the readout so 'delivered' is no longer
claimed for swallowed notifications.

Packaged builds ship the helper via extraResources and sign it in
afterPack like the computer-use helper; dev copies compile it on demand
(swiftc, non-fatal when missing) with the shared dev bundle id.

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

* feat: in-app fallback for swallowed notifications + permission card in Settings

- Dispatch now consults the authorization readout before creating a
  native notification: when macOS would silently swallow it (denied or
  prompt unanswered) it returns reason 'blocked-by-system' instead of
  piling invisible notifications into Notification Center. The terminal
  notification path surfaces that as a once-per-session in-app toast
  with an Open System Settings action. Mobile fan-out is unaffected.
- Settings > Notifications now shows the same live permission card as
  onboarding (moved to components/notifications/), polling the readout
  so System Settings changes reflect within seconds, and the test
  button updates it inline.
- Test sends that are blocked at the OS level now show the
  settings-pointing failure toast instead of a generic error.

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

* fix: hide macOS permission card while Orca notifications are disabled

A green 'Notifications are enabled' card next to a disabled Enable
Notifications toggle read as a contradiction — the card now renders (and
the readout polls) only while Orca's own notifications setting is on.
Also single-flights the authorization helper so simultaneous agent
completions share one readout process.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-08 22:21:40 -07:00
Jinwoo Hong 20832ef36f ci(daemon): fail builds, packaging, and CI when the terminal daemon cannot start — and stop failing silently (#7849) 2026-07-08 19:46:14 -04:00
Jinwoo Hong 685418d8e4 fix(daemon): daemon cannot start in 1.4.129-rc.1 — electron require leaked into daemon-entry chunk (#7844) 2026-07-08 19:41:09 -04:00
NeilandOrca 4a6d12959f fix: recover fresh local terminal spawns from a deleted saved cwd (#7847)
After #7750 removed the containment guard, the residual #7239 failure mode
is a persisted/inherited startupCwd whose directory no longer exists: every
spawn dies with the provider's missing-directory error. Fresh local renderer
spawns now opt in (cwdFallback: 'worktree') to recover at the workspace root
with a generic in-terminal notice; reattach, SSH, remote-runtime, runtime/API
and mobile callers keep exact cwd semantics, and existing directories —
including outside the worktree (#7685) — spawn as requested.

Co-authored-by: Orca <help@stably.ai>
2026-07-08 16:33:58 -07:00
Jinwoo HongandOrca 8368e946df Fix orchestration agent prompt injection (#7758)
Co-authored-by: Orca <help@stably.ai>
2026-07-07 19:50:57 -07:00
Jinwoo Hong dfc12f2cf6 fix(watcher): isolate @parcel/watcher in a forked process so native crashes can't kill the app (#7547) (#7757) 2026-07-07 22:10:22 -04:00
Jinwoo Hong c256a5a417 Windows terminal update-survival (single consolidated PR) (#7538) 2026-07-07 19:21:07 -04:00
bea9b38544 Fix OMP worktree title identity flicker
* Fix OMP worktree title identity flicker

* Add headless fresh pairing server script

* Harden fresh pairing server script startup

* Default fresh pairing server to reachable address

* review: harden OMP tab identity validation

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

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-07 13:51:25 -07:00
JinjingandOrca 544bca5202 fix: terminal IME candidate selection and text commit on Linux (#7634)
* fix terminal IME candidate selection and text commit on Linux

Sogou Pinyin and fcitx on Linux failed in Orca's terminal because bare
229 keydowns were swallowed, and empty composition updates prematurely
deactivated tracking. This led to dropped Chinese text or leaked Space/digit
candidate-selection keys reaching the PTY.

- Allow bare 229 keydowns to bypass suppression on Linux so xterm can diff
  and commit text.
- Prevent empty compositionupdate events from prematurely deactivating
  the composition tracker.
- Suppress and preventDefault candidate-selection keys (Space and digits)
  during active composition and a brief post-composition window.
- Add comprehensive unit tests and an Electron CDP-driven E2E repro.

* fix: register IME gate command as direct spec-file invocation

The reliability-gate checker rejects --grep title selectors and requires
every evidenceRun command to match a gate command. Drop the --grep from
the e2e gate command and its evidence run, and remove the stale 3-file
evidence run superseded by the full 7-file run.

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

* Guard overlapping and post-composition Linux IME candidate keys

- Track pending candidate key releases in a Map instead of a single
  slot to support overlapping selector key events without stranding.
- Apply the candidate selection guard to post-composition key releases
  that arrive after compositionend, preventing digits/Space from
  leaking into the PTY.
- Restrict the Linux/Sogou candidate selection guard to Linux to
  prevent interference on macOS and Windows.
- Exclude Shift+Space from candidate selection key checks.

* Guard held-key IME candidate repeats and scope policy to desktop Linux

- Keep auto-repeat keydowns for a candidate key suppressed past the
  250ms guard window until its corresponding keyup event is received.
- Clear stale pending releases on fresh non-repeat keydowns to avoid
  guarding the wrong key events.
- Exclude Android and ChromeOS user agents from desktop Linux-specific
  IME candidate key suppression behaviors.
- Ensure the composition tracker is activated unconditionally on
  compositionupdate events.

* Clean up IME reference and extract shared test event fixture

- Remove the obsolete Linux Sogou Pinyin IME reference document.
- Extract the fully-defaulted XtermBypassEvent helper into a shared
  fixture file to keep the policy test suites in sync.
- Add a test verifying that Shift+Space (fcitx full-/half-width toggle)
  is not suppressed as an IME candidate key.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-06 22:03:39 -07:00
NeilandOrca f311307560 Add max-lines ratchet CI gate to block new line-limit bypasses (#7608)
oxlint already fails any file over max-lines that is not suppressed, so the
only way to grow past the budget is to add an eslint/oxlint-disable max-lines
comment or a per-file max-lines bump in mobile/.oxlintrc.json. This adds a CI
gate that freezes the current set of suppressions (config/max-lines-baseline.txt,
355 grandfathered entries) and fails the build when a NEW one appears — with a
loud, actionable message pointing at 'split the file'. Existing oversized files
are untouched; the baseline may only shrink (pnpm check:max-lines-ratchet --prune).

Wired into the root lint script and as a dedicated pr.yml step. Unit-tested
(15 cases) and verified against all three failure paths + clean-tree pass.

Co-authored-by: Orca <help@stably.ai>
2026-07-06 17:12:27 -07:00
Brennan BensonandOrca 28fe4df817 Preserve terminal scrollbar position after tab switches (#7472)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 01:33:05 -07:00
Jinjing 3dd3cc9f68 Clarify Orca orchestration tool boundary and sidebar lineage (#7522)
* Clarify Orca orchestration tool boundary and sidebar lineage

Add a "Tool Boundary" section to the orchestration skill, requiring
explicit Orca runtime state instead of generic subagent tools or
chat-only parallel workers. Also add tests to verify the tool boundary
and clarify sidebar lineage for same-worktree workers.

* Clarify worktree lineage guidance and parent-child boundaries

Update orchestration guidance and tests to clarify when to use child versus
top-level worktree lineages, and when to prefer same-worktree workers.

* Require stating the desired Orca lineage before creating a worktree from
  an active feature branch.
* Limit child worktrees to conceptually stacked or dependent tasks.
* Prefer same-worktree workers unless isolated checkouts are explicitly
  needed and do not require uncommitted changes.
2026-07-06 00:05:49 -07:00
Neil ce687221d3 lint(unicorn): enable prefer-number-properties, prefer-array-find, prefer-array-index-of (#7516)
Enable three unicorn rules — one correctness, two performance — and fix every
existing violation repo-wide so the rules pass as errors.

prefer-number-properties (76 sites)
- parseInt/parseFloat/NaN -> Number.* : safe aliases (autofixed).
- isNaN -> Number.isNaN (12 sites, hand-converted): global isNaN coerces its
  argument, Number.isNaN does not. Verified every call site already passes a
  number (Number.parseInt results, number-typed fields, Date.getTime()), so the
  conversion is behavior-preserving today and guards against a future non-numeric
  argument silently coercing.

prefer-array-find (26 sites)
- .filter(pred)[0] -> .find(pred); .filter(pred).at(-1) / .pop() -> .findLast(pred).
  Drops the intermediate array and short-circuits.

prefer-array-index-of (5 sites)
- .findIndex(x => x === v) -> .indexOf(v).

Verified: typecheck (node/cli/web) clean, 53 affected suites pass (1679 tests),
oxlint clean repo-wide. mobile/ uses findLast safely (already ships ES2023
.toReversed()); config scripts and e2e helpers run on Node 24.
2026-07-05 23:56:37 -07:00
Jinjing c97d3a4977 Replace post-worker_done polling with idle behavior (#7509)
- Instruct workers to stop and idle or exit immediately after sending
  `worker_done`, rather than running a 10-minute polling loop.
- Distinguish instructions based on worker kind: prompt-returning
  agents should remain idle for re-engagement, while bare-shell
  workers should exit.
- Prevent infinite polling overhead since the coordinator re-engages
  workers via fresh terminal input instead of inbox polling.
2026-07-05 23:10:20 -07:00
Jinwoo Hong 6a4b89785c revert: back out the Windows terminal update-survival chain (#7421→#7499) (#7505)
* Revert "Preload the daemon windowsHide shim via --require; wrap promisify custom (#7499)"

This reverts commit 8f396badaf.

* Revert "Hide console windows for children of the node.exe-hosted daemon (#7486)"

This reverts commit f0fdd3a716.

* Revert "fix(daemon): relocate daemon host image out of the install-dir kill zone (#7473)"

This reverts commit f4faafa987.

* Revert "fix(pty): keep runtime dirs a surviving daemon still uses (#7463)"

This reverts commit 3cd23a13a1.

* Revert "Relocate node-pty ConPTY runtime outside the Windows install dir (fixes update-time terminal loss) (#7421)"

This reverts commit 509c41e2bf.
2026-07-05 22:50:48 -07:00
Jinwoo Hong f0fdd3a716 Hide console windows for children of the node.exe-hosted daemon (#7486)
Since #7473 the terminal daemon runs under a standalone node.exe.
Electron's bundled Node defaults windowsHide to true; plain node.exe
defaults it to false, so every child_process call in the daemon that
does not pass the flag - the periodic PowerShell CIM process probes,
node-pty's kill-path conpty_console_list_agent fork - now allocates a
visible console, which opens and closes a Windows Terminal window on
the user's screen every few seconds.

Fix: daemon-entry installs a child_process shim (first import, before
any module captures bindings like promisify(execFile)) that defaults
windowsHide: true across spawn/exec/execFile/fork and their sync
variants, restoring the Electron default the daemon has always relied
on. Explicit windowsHide from a caller still wins. Also adds
windowsHide to node-pty's console-list agent fork in the existing
patch as defense in depth.

Verified on Windows: reproduced the flash with the rc.5 production
daemon (WindowsTerminal windows, ~3s cadence matching the CIM probe
interval, conhost spawned visible-capable "0x4"); with the shim, a
node.exe-hosted daemon's children (OpenConsole, powershell, node
helpers) all run without a visible-capable console and session kill
still works end to end.
2026-07-05 21:26:30 -07:00
f4faafa987 fix(daemon): relocate daemon host image out of the install-dir kill zone (#7473)
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
2026-07-05 19:52:06 -07:00
Jinwoo Hong 509c41e2bf Relocate node-pty ConPTY runtime outside the Windows install dir (fixes update-time terminal loss) (#7421) 2026-07-05 12:50:27 -07:00
Bevis a3e34b66b8 fix(pet): stop i18n from corrupting CSS keyframes
Keep PetOverlay runtime keyframes out of localization so translated locales cannot invalidate sprite or bob animations.\n\nAlso adds regression coverage for translated-locale keyframe CSS and removes the stale generated locale entries.
2026-07-04 14:43:57 -07:00
Neil bec4392d87 cleanup(main): defer serve-sim materialization, dedupe reload flags, guard gate validators (#7321)
Quality pass on main-process/build PRs merged 2026-07-03:

- ios-emulator-backend: resolve the serve-sim executable via a lazily-cached getter
  instead of eagerly in the constructor. The bridge is built before the main window
  is shown, so the one-time recursive copy + xattr subprocess (first launch after each
  version bump) no longer blocks macOS startup for a feature that may go unused (#7174).
- index: collapse the two near-identical `{webContentsId, until}` reload flags
  (expectedRendererReload / recoveryReloadInFlight) into one `createWebContentsTimedFlag`
  primitive; behavior preserved, including consume-on-read for the recovery reload (#7290).
- check-reliability-gates: coerce gate.commands/testFiles/platforms/providers with an
  `asArray` helper before `.includes`, so a hand-edited manifest with a missing/mistyped
  field reports a validation failure instead of throwing an uncaught TypeError; extract
  `hasCompleteRedGreenEvidence` for the duplicated status check (#7295).
- claude-pty: derive FABLE_WEEKLY_LABEL_RE from WEEKLY_RE.source so a future weekly-
  wording change stays in one place and can't reopen the parsing gap it just closed.
- macos-tcc-login-shell: trim the 30-line flag-by-flag JSDoc to the two non-obvious whys
  (TCC identity, env(1) SHELL re-assertion) per the repo comment guidance (#7003).

Typecheck, oxlint, oxfmt, `check:reliability-gates`, and touched unit suites all pass.
2026-07-03 22:32:11 -07:00
Jinjing b2fcbdbc73 fix: bound release notes by published releases (#7311) 2026-07-03 20:53:16 -07:00
5b5ce6cef8 Harden reliability gate policy and register merged terminal regression tests as gates (#7295)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: brennanb2025 <delta-eng@stably.ai>
2026-07-03 19:58:07 -07:00
Brennan BensonandOrca 1282f5c2da Add reliability gate manifest (#7001)
Co-authored-by: Orca <help@stably.ai>
2026-07-03 19:26:00 -07:00
Alexander 99d61b13b2 Bound generated release notes by previous tag (#5649)
Fixes #5579. Pass previous_tag_name to GitHub generate-notes so draft-release notes stop accumulating across releases; omit it safely on first release. Adds tag parse/compare + paginated tag fetch and regression tests.
2026-07-03 14:22:47 -07:00
Brennan Benson 087ad66aa2 Revert "Ship serve-sim camera dylib as data and materialize it at runtime" (#7172) 2026-07-02 18:46:00 -07:00
Brennan BensonandOrca f44cb3059b Ship serve-sim camera dylib as data and materialize it at runtime (#7168)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 18:24:23 -07:00
Brennan Benson d6fb8e04f9 Revert "Notarize serve-sim camera dylibs in macOS releases" (#7165) 2026-07-02 18:05:50 -07:00
Brennan BensonandNeil 99bc693cd5 Fix Codex config paths in managed runtime home (#7157)
* Fix mirrored Codex relative config paths

Orca mirrors ~/.codex/config.toml into a managed CODEX_HOME before launching Codex. Relative path-valued Codex settings were then resolved from the runtime home instead of the user's real Codex home, which made config loading fail in Orca while the same CLI worked in a normal terminal. Rewrite known relative path settings to absolute paths rooted at the system Codex home while preserving runtime-owned trust sections.

* Dedupe Codex TOML line scanner and include path rewrite in CLI tsconfig

* Harden Codex config path rewrite and cover managed account homes

- Track multiline arrays in the shared TOML line scanner so array lines
  are never mistaken for table headers or path keys
- Escape control characters and reject lone-surrogate unicode escapes so
  the rewritten runtime config always stays valid TOML
- Extend the rewrite allowlist with profiles.* file settings and
  debug.config_lockfile.* (both can abort Codex config loading)
- Rewrite relative paths when mirroring the canonical config into
  managed account homes (codex login CODEX_HOMEs), anchoring WSL
  accounts to the Linux-side ~/.codex with posix join semantics

---------

Co-authored-by: Neil <neil@stably.ai>
2026-07-02 17:01:41 -07:00
Brennan BensonandOrca ee8bdf1aac Notarize serve-sim camera dylibs in macOS releases (#7077)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 16:42:56 -07:00
Jinwoo Hong 2ce9314acb Improve Windows terminal performance: retain WebGL contexts, warm first ConPTY (#7085) 2026-07-02 18:41:23 -04:00
Brennan BensonandNeil 49a8e80526 Temporarily bypass Windows inner signature gate (#7137)
Co-authored-by: Neil <neil@stably.ai>
2026-07-02 12:34:35 -07:00
Brennan BensonandNeil d2d3e90c96 Fix Windows inner signature PowerShell path (#7136)
Co-authored-by: Neil <neil@stably.ai>
2026-07-02 12:11:58 -07:00
Brennan BensonandNeil fc17c57b6b Fix Windows SignPath PSGallery preflight (#7135)
* Verify Windows app executable signing

* Isolate Windows signing verifier tests

* Handle direct Windows installer extraction

* Fix SignPath PowerShell gallery preflight

---------

Co-authored-by: Neil <neil@stably.ai>
2026-07-02 11:42:44 -07:00
Brennan BensonandNeil 85cec26773 Prevent unsigned Windows app releases (#6806)
* Verify Windows app executable signing

* Isolate Windows signing verifier tests

* Handle direct Windows installer extraction

---------

Co-authored-by: Neil <neil@stably.ai>
2026-07-02 10:54:19 -07:00
Brennan BensonandOrca df6e5d56a7 Test arm64 ConPTY payload packaging (#6970)
Co-authored-by: Orca <help@stably.ai>
2026-06-30 18:22:08 -07:00
Brennan BensonandOrca 22db5b78d6 Fix Windows bundled ConPTY packaging (#6968)
Co-authored-by: Orca <help@stably.ai>
2026-06-30 18:05:38 -07:00
Neil 7cfae28115 ci: isolate Blacksmith mac release build (#6962) 2026-06-30 16:36:59 -07:00
Brennan BensonandOrca 9408cadb80 ci: keep release workflow GitHub-hosted for SignPath (#6946)
Co-authored-by: Orca <help@stably.ai>
2026-06-30 14:58:43 -07:00
Brennan BensonandOrca 16de859fdf ci: isolate mac release build from SignPath matrix (#6937)
Co-authored-by: Orca <help@stably.ai>
2026-06-30 13:55:48 -07:00
Brennan BensonandOrca 22e9c4f4bb ci: pin Windows release runner to VS 2022 (#6932)
Co-authored-by: Orca <help@stably.ai>
2026-06-30 13:21:32 -07:00
JinjingandOrca d4084ba982 fix(terminal): force model clear when webgl texture atlas is reset (#6868)
Patch @xterm/addon-webgl so clearTexture() and page merge/delete operations
request a model clear and bump a generation counter. Without this, the renderer
keeps drawing glyphs against a stale atlas after the texture is reset, leaving
garbled or blank cells until the next full repaint.

Co-authored-by: Orca <help@stably.ai>
2026-06-30 01:06:45 -07:00
Neil f9e18910ae chore(lint): adopt unicorn/prefer-import-meta-properties (error) (#6847)
Migrate fileURLToPath(import.meta.url) / dirname(...) boilerplate to the
native import.meta.dirname / import.meta.filename, then enable the rule
at error so new code stays on the native form.

The oxlint autofix rewrites the expression but leaves the now-unused
node:url / node:path imports behind (which the already-enabled
no-unused-vars=error would then flag), so this commit also removes those
34 orphaned imports — trimming the named import where other names are
still used, deleting the line where it was the sole import.

Scope is build scripts + Node-env tests only (config/scripts, tools/
benchmarks, *.test.{ts,mjs}, vitest configs); zero shipped runtime code.
The native properties are exact equivalents (Node >= 20.11; repo is on
24), so behavior is unchanged.

Verified: oxlint 0 errors tree-wide (root + mobile), oxfmt clean,
typecheck (node+cli+web) + mobile tsc pass, root vitest 22825 passed /
0 failed, mobile vitest 1018 passed. Exercised the rewritten scripts
directly: build:relay (6 targets), ensure-native-runtime,
verify-macos-entitlements all run correctly with import.meta.dirname.
2026-06-29 23:37:30 -07:00
NeilandOrca 46646d7ff1 chore(lint): upgrade oxlint to 1.71 + enable 7 new rules (autofixed backlog) (#6841)
* chore(lint): upgrade oxlint to 1.71 and enable 7 new rules

Upgrade oxlint 1.67.0 -> 1.71.0 (1.72 was blocked by the repo's 3-day
minimum-release-age supply-chain guard; nothing here needs it). The
bump is a no-op on the existing config.

Enable 3 error rules (backlog autofixed to zero in this commit) and
4 warn rules (surface signal without gating CI):

error (autofixed, behavior-preserving):
- unicorn/prefer-node-protocol        (~1531 sites: bare builtin -> node:)
- typescript/no-import-type-side-effects (~36: all-inline-type -> import type)
- unicorn/no-array-reverse            (19: copy-then-reverse -> toReversed)

warn (real signal, current fires are test-only/correct):
- unicorn/no-array-fill-with-reference-type  (aliasing footgun guard)
- typescript/no-unsafe-function-type         (bans bare Function type)
- unicorn/prefer-array-flat-map              (map().flat() -> flatMap())
- unicorn/prefer-regexp-test                 (.match() in bool ctx -> .test())

mobile/.oxlintrc.json extends root, so it inherits all 7; the autofix
ran from root and covered mobile/ too.

Verification (all green): oxlint 0 errors (root+mobile+aux configs),
oxfmt clean, typecheck (node+cli+web), vitest 22795 passed / 0 failed,
builds (electron-vite + web + cli) succeed. node: rewrites confirmed to
skip embedded SSH/CLI string payloads (AST-only); all toReversed sites
verified to operate on fresh copies or write-once locals.

* chore(lint): bump mobile oxlint to 1.71 so inherited rules parse

mobile/ is a standalone pnpm project pinning its own oxlint@1.67, which
lacks unicorn/no-array-fill-with-reference-type (needs >=1.70). Since
mobile/.oxlintrc.json extends the root config, mobile CI's 'cd mobile &&
oxlint' failed to parse the new rule. Bump mobile to match root (1.71).

Verified in mobile/: oxlint 0 errors, oxfmt --check clean, tsc --noEmit
pass, vitest 978 passed / 0 failed.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-29 22:38:29 -07:00
Neil 61503b7666 refactor(command-code): split managed hook script (#6807)
* refactor(command-code): split managed hook script

* fix(command-code): include split script in cli typecheck
2026-06-29 18:13:45 -07:00
Miguel Echávarri cd03928e94 fix(i18n): correct Spanish "PR" mistranslated as "relaciones públicas" (#6749)
Machine translation rendered the abbreviation "PR" (pull request) as "relaciones públicas" (public relations) across 32 Spanish UI strings — e.g. "Reabrir relaciones públicas" (Reopen PR), "Crear relaciones públicas" (Create PR), "Abrir cheques de relaciones públicas" (Open PR checks).

Adds the missing `es` rule to LOCALE_PHRASE_FIXES. Because "relaciones públicas" is a real Spanish phrase (unlike the CJK-only ko/zh patterns 홍보/公关), the rule guards on the actual `PR`/`PRs` token via a new optional `whenEnMatches` RegExp guard in applyPhraseFixes, so it never fires on unrelated English that merely contains a "pr" substring (approve, preview, press). `whenEnMatches` is backward compatible — existing `whenEnIncludes` rules are unchanged.

Regenerates the 32 affected es.json leaves. Adds a vitest spec covering the rewrites and a negative case proving the token guard ignores genuine "public relations" strings.
2026-06-29 11:56:26 -07:00
NeilandOrca 9f94ccdb8f perf(emulator): prune serve-sim dedupe keys on worktree forget (#6708)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 23:41:14 -07:00
NeilandOrca c96d8e3b5a perf(emulator): return MJPEG frames as views instead of per-frame copies (#6707)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 23:40:55 -07:00
mehmet turac 19eeacfad3 fix: pin CLI build output to CommonJS (#6656) 2026-06-28 22:58:27 -07:00
NeilandOrca ad87bb0123 perf(editor): skip markdown TOC parse while the panel is closed (#6695)
The rich markdown editor rebuilt the entire Table-of-Contents outline on
every content change by running a full-document remark parse
(buildMarkdownTableOfContents), then discarded the result whenever the TOC
panel was closed — which is the default state. The parse is driven by the
300ms-debounced serialize path, so it fired ~3x/sec during sustained typing,
with cost scaling linearly with document size.

Gate the memo on showTableOfContents so the parse only runs when the panel is
actually open. Including showTableOfContents in the deps rebuilds the outline
the moment the panel opens, so there is no stale TOC.

Benchmark (config/scripts/markdown-toc-parse-benchmark.mjs), per content
change while typing:
  175 KiB doc / 200 headings -> ~65 ms median  (13.2 s cumulative over a
                                                 ~1 min typing burst)
  351 KiB doc / 400 headings -> ~138 ms median (27.8 s cumulative)
With the fix this drops to ~0 ms while the panel is closed.

Adds a unit test proving the parse is skipped (and a stable empty-array
reference returned) while closed, and still runs when open.

Co-authored-by: Orca <help@stably.ai>
2026-06-28 21:19:10 -07:00
NeilandOrca 5db5b23257 perf(renderer): drop per-tick matchMedia alloc + purge hibernation epoch map (#6696)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 21:16:02 -07:00