Its three parallel real-Git lanes, two of them through Docker, push
git-binary-compatibility.test.ts past the 30s test timeout on the 4-vCPU
hosted runner (64s file time vs 14s), failing PR #34600 twice after #34566.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Keep preflight and the unit-test matrix (the PR critical path) on Blacksmith; move routing, aggregation, contract, packaging and mobile checks to hosted standard runners, which are free for public repos under Enterprise concurrency.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(browser): focus newly opened image tabs
Focus the window before the webview so Command+W closes the new
image tab instead of the original tab after a plain image click.
Add tests for focus order, image loading, and close-shortcut forwarding.
Fixes#34114
* test(browser): verify image tab focus with native keyboard input
* refactor(ci): keep browser E2E routes within registry size limit
* fix(ci): enable background launch for native browser regression
* test(ci): include browser routes in isolated detector fixture
---------
Co-authored-by: Neil <neil@stably.ai>
lint:ast-grep and check-flaky-test-pattern-ratchet each parsed the whole tree.
ast-grep-gates.mjs scans once; the lint gate re-runs ast-grep only on files with
warning-or-error findings (ast-grep's own report and exit code), and the flaky
ratchet counts test-* matches from the shared scan.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
- Plan unit selection starts after setup (overlaps lint) instead of last.
- Localization extraction starts with the typecheck; test-file-runners is background.
- run-ratchets.mjs runs ratchets in a pool (19s serial -> 8s locally).
- pnpm lint uses CI's single-parse check-import-boundaries.mjs.
- ORCA_UNIT_FULL_SHARD_COUNT accepts 2-10 (default stays 5).
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Reverts #29133 except its daemon async-I/O stall telemetry, so we can measure how often stalls happen on official Node before committing to a patched runtime. The macOS terminal host goes back to the official Node 24.22.1 download and the daemon protocol back to v51; no release or hourly build published v52.
Builds the macOS terminal host's Node 24.22.1 from pinned source with a libuv patch: idle threadpool workers recheck for queued work every 30 s instead of waiting forever, so a lost Darwin condition-variable wake-up (libuv #5280) no longer strands terminal I/O. Bumps the daemon protocol to v52 so new terminals start on the patched runtime right after an update; older daemons stay attachable. Adds stalled/recovered daemon async-I/O telemetry, and lets release workflows rebuild older refs that predate the source build.
Fixes STA-11709, #31926.
* perf(lint): keep JS plugins out of default oxlint and adopt ast-grep
Any jsPlugin makes Oxlint hand every file's AST to Node, so the seven custom
plugins cost the default `oxlint` run several times its native time.
- Move app-store-performance, quadratic-buffer-concat, renderer-scrollbar-style
and ime-enter-guard (scope- or dataflow-aware) to config/oxlint-js-plugins.json,
run by `pnpm lint:js-plugins`, CI, lint-staged and the changed-lines gate.
- Port sort-comparator-performance, mobile-pairing and native-chat-design-tokens
to ast-grep rules with rule tests, and delete the plugins.
- Add @ast-grep/cli, config/sgconfig.yml, `pnpm lint:ast-grep` / `test:ast-grep`,
a CI step, and an ast-grep pass in check-changed-code-quality.
- Add flaky-test rules (wall-clock reads, real-time waits, polling loops,
unquarantined skips, unexplained timeout bumps), baselined by a count ratchet.
* Enforce flaky-test ratchet on changed files; refresh baseline
* docs(agents): keep custom-rule details out of AGENTS.md
* Resolve ast-grep from the repo so gate scans of other roots work
* ci: fail when a checked-in test file has no runner
Two node:test files under .github/actions lost their runner when #31792
trimmed cloud pretest, and the two monaco .bench.ts budgets were never run
by any CI job. Wire both back in and add a static check that every
test-like file is collected by a declared runner or imported by a
collected entry (the src .spec.* suite-module convention).
* ci: ignore type-only imports and quote the lease glob for cmd.exe
* ci: parse type-only imports, cover UNIT_EXCLUDE, route cloud runner edits
Type-only imports are now dropped with the TypeScript parser, so a type
alias before a runtime re-export no longer hides it. UNIT_EXCLUDE files
must be named by a pr.yml or unit-tests.yml step. A cloud-only diff that
adds a test or edits a runner config now runs the static job. The monaco
benchmarks stay manual (pnpm test:perf:benchmarks) until a CI runner
proves their wall-clock budgets.
* ci: require UNIT_INCLUDE names in dedicated jobs and erase typeof import()
* ci: resolve each runtime import to the one file Vite loads
The unit dependency graph keeps every plausible candidate so it can
invalidate conservatively, which cannot prove a suite runs: an import of
./case.spec counted both case.spec.ts and case.spec.tsx. Resolve with
Vite's extension order instead.
* ci: take runtime imports from transpiled output
Imports used only as types are erased without a type modifier, so
parsing for type-only syntax still followed them. Derive edges from
ts.transpileModule output, which erases what Vitest's transform erases,
and only transpile files that can reach an uncollected candidate.
* ci: fix the agent-status benchmark config and route all cloud code
The agent-status benchmark config inherited the unit projects, whose
includes override its own, so it ran the whole unit suite and never the
benchmark. Clear projects as the performance config does. Route every
cloud code file to the static job, since content-detected tests can have
any name.
* ci: move routine checks and unsigned builds to Blacksmith
* ci: retain GitHub Mac images for isolated SSH fixtures
* ci: keep shared terminal perf preparation on Blacksmith
* test: allow encrypted slow-link fixture to finish on ARM CI
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* 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
* fix(ci): recover verified pnpm setup from registry metadata outages
* fix(ci): prepare native pnpm shims after fallback verification
* fix(ci): provide Node for pnpm fallback in bare containers
* ci: install fish 4 from its GitHub release when the Launchpad PPA is down
* TEMP: skip the fish PPA to prove the GitHub release fallback (revert)
* Revert "TEMP: skip the fish PPA to prove the GitHub release fallback (revert)"
This reverts commit 58ba0c5074.
* ci: install pinned fish directly from its verified release
* ci: isolate standalone fish from runner resources
* ci: one list for Windows boundary tests and one step for ratchets
The Windows boundary step's 74 test paths were hand-listed in pr.yml and
again in WINDOWS_PACKAGE_TESTS, and the copies had drifted: six files ran
in the step but could not trigger the job. The step now prints
WINDOWS_BOUNDARY_TESTS, which WINDOWS_PACKAGE_TESTS spreads.
The ten per-ratchet preflight steps and the eight lint entries become one
run-ratchets.mjs that runs every check-*-ratchet(s).mjs it finds.
* fix(ci): preserve existing local lint ratchet scope
* fix(deps): root and mobile resolve one zod, and CI fails if they drift
Mobile type-checks src/shared zod schemas. With mobile on zod 4.6.5 and the
root on 4.6.7, TypeScript treated them as unrelated packages, so wrapped
schemas inferred {} (tests/e2e/helpers/phone-feed-list.ts:154) whenever a
job installed mobile deps.
* fix(deps): guard every package mobile's tsconfig remaps, not only zod
* test(ci): pin the shared-dependency version check to the static phase
* fix(process-host): let a slow Windows taskkill finish instead of orphaning the grandchild
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(process-host): abandon taskkill shortly after the root exits so it cannot walk a reissued pid
Co-Authored-By: Claude <noreply@anthropic.com>
* test(process-host): log the taskkill outcome and caller settle time under load
Co-Authored-By: Claude <noreply@anthropic.com>
* ci: register the late-taskkill Windows test in the package-windows path list
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(process-host): release the git admission slot on root close again; cap the background taskkill at 30 s
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat(ci): ratchet raw repo connectionId host reads; one drop-in resolver
Codex review 6 class fix (#4/#6/#7): host decisions read off a repo row's
legacy connectionId miss rows that name SSH only as executionHostId.
- getRepoRoutingConnectionId (shared/execution-host.ts): drop-in for a raw
repo.connectionId routing check that also finds executionHostId-only SSH.
- check-repo-host-read-ratchet: per-file count of raw repo connectionId
reads in src/main, src/shared, src/cli; counts may only shrink.
- Migrated 66 cheap reads: runtime GitHub/GitLab commands, PR/MR head ref
fetches, preserved-branch cleanup, ref queries, base-ref IPC, worktree
preparation, trash sweep, scan cache TTL, usage metadata.
* fix(ipc): PR base IPC routes executionHostId-only SSH rows; ratchet is a stated lower bound
Review follow-up (Opus on #31096):
- worktrees:resolvePrBase decided git/gh routing on the raw connectionId while
its head-ref fetches already used the resolver; one resolved connectionId
now drives all of it (test fails on main).
- getRepoRoutingConnectionId's contract is stated exactly: never local when the
raw field is set; on a contradictory ssh row executionHostId wins.
- The ratchet regex no longer matches report.connectionId; header and docs
say it is a lower bound.
- Regression tests for a runtime GitHub and GitLab command site.
* test(ci): pin the repo host-read ratchet step to the static phase
* fix(ci): repo host-read ratchet skips verbatim field copies into projected rows
A copy of connectionId into a projected row decides nothing; migrating it to
the resolver would change what the projection publishes. The sidebar feed
catalog's copy (added after the baseline) and two older projections no longer
count; baseline pruned to 91.
* ci: fail the static job on unformatted files
Runs oxfmt --check over the same tree pnpm format writes (~2s), and makes the
pre-commit hook format markdown and YAML so it covers what CI now checks.
* ci: route docs-only and workflow-only diffs through the formatting check
The format check reads the whole tree, so a diff that skipped the static job
could land drift that fails every later PR. Any changed file oxfmt formats now
selects static analysis (not typecheck or units), like the mobile-only route.
The path detector checks out .oxfmtrc.json for its ignores. The hook no longer
fails a commit whose only matches oxfmt ignores (lockfiles).
* fix(renderer): list a pane main holds before the window mounts it, so a tab close by a split's handle finds it (dark, layout-owner build only)
Co-Authored-By: Claude <noreply@anthropic.com>
* test(e2e): the split-close spec polls through the host's "can't answer yet" terminal list
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(runtime): a pane the window lists before main binds its terminal keeps main's terminal (dark, layout-owner build only)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(runtime): a tab close by a main-side split's handle stands on main's own record of the pane (dark, layout-owner build only)
Replaces the window-side listing and the binding fill: the window's list lags main in three
ways (built before main wrote the pane, from it before the binding, or before the window mounts
it), and only main's own layout answers all three.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(runtime): main's relisting for a close tells no clients (dark, layout-owner build only)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: E2E Test <e2e@test.local>
Co-authored-by: Claude <noreply@anthropic.com>
* fix(terminal): a pane main first sees at its binding goes where the window split it (dark, layout-owner build only)
* fix(terminal): keep main's divider positions when taking the window's split tree
* test(terminal): main's divider above the window's new split is kept
* ci: the layout-owner switch-on job runs the hidden-terminal load spec that caught the split graft
* test(terminal): type the side-by-side fixture as a split so ratio spreads typecheck
---------
Co-authored-by: E2E Test <e2e@test.local>
* fix(ci): background steps are single run steps, so no JavaScript action reads the event payload while the runner rewrites it
* test(ci): guard the background slot cap and pin the payload-free allowlist
* fix(persistence): repo-row store writes take the row, not the id; ratchet the rest (R4-2a)
* fix(persistence): host-filter the runtime nested import; widen the id-only write ratchet (review)
* fix(runtime): nested import keeps matching runtime-stamped native rows on a paired host
* fix(persistence): class-scope the ratchet param exemptions; update a new main test to the target shape
* fix(ipc): fence a project-group move by the resolved twin host, so an SSH twin is not WSL-fenced
* test(ci): pin the id-only store write ratchet step to the static phase
* refactor(pty): every PTY retirement names its exit proof; ratchet the unproven ones
* refactor(pty): count raw ownership drops, route an abandoned relay stop to unverifiable, honest proof labels
* ci: run the layout-owner switch-on specs as an advisory PR job
Build the e2e app with ORCA_LAYOUT_OWNER=main through the existing e2e.yml
(new layout_owner input, read only by the app and orcad builds), run the
layout oracle, its positive control and the layout-owner acceptance specs
with the save-divergence log on, and upload a summary by kind and spec.
Not in the PR aggregate's needs.
* ci: summarize divergence logs without a test report, and drop file-path ids from kinds
* ci: switch-on job adds the stream-loss spec and the managed-SSH Docker lane, drops diff-word-wrap (fails switch off), and names each looped test in the summary
* test(e2e): editor-model-host-isolation opens both files through the store's open action, so a layout-owner build's main holds the tabs
* ci: the divergence summary skips a cut-short test report instead of failing
* ci: re-run PR checks on a merge ref that includes the main typecheck repair (#30680)
* refactor(terminal): one PTY attribution for teardown, close and identity; delete the deprecated resolver pair
- strict ssh: route: a proven direct listing beats a same-id server proxy; other contradictions refuse
- terminal spawn's git branch takes the strict route when a host is named (rivals refuse)
- resolveTerminalPtyOwner + isUnattributedTwinWorktree replace resolveRuntimeOwnerForWorktree in
shutdown, pane and agent hibernation, and PTY identity; close logs unroutable runtime ids
- delete getRuntimeEnvironmentIdForWorktree/resolveRuntimeOwnerForWorktree (legacy branch moved
into the adapter), the alias golden test, the importer ratchet, its baseline and pr.yml step
- hasHostEvidence reads the owner indexes instead of scanning repos and groups
* fix(terminal): close and identity read spawn's attribution for unscoped remote ids (Opus P2)
- an unattributed twin's unscoped remote: id is skipped and logged on close, never closed locally
- setup terminals: identity and close follow spawn's runtime; raw-id teardown stays local
- drop the last stale getRuntimeEnvironmentIdForWorktree mock (tests/e2e unit suite)
* refactor(terminal): one ownership read in resolveTerminalPtyOwner
* test(terminal): pin the close-path twin skip and the two-proxy direct listing (Opus P3)
* test(terminal): keep the close-provider owner fixture's full union type (Codex P1)
* test(browser): expose native popup admission blockers with faithful app events
* test(browser): probe Electron popup identity and inherited sandbox API limits
* test(browser): handle requests without associated contents in popup probe
* docs(browser): record blocked Electron popup compatibility gates and test routing
* docs(browser): keep popup evidence in PR
* build: share one pnpm virtual store across worktrees, off under CI
Each worktree carried a full node_modules; the global virtual store links
one slot per package version instead. pnpm keeps an explicit setting on
under CI, so a pnpmfile hook turns it off there: CI packages from,
caches and verifies a project-local node_modules.
* fix(build): keep shared electron and windows-process-tree dirs untouched under GVS
Every worktree runs Electron from the one shared electron package, so the
per-repo dist cache must not swap that dist and a foreign-arch install must
not land in it. The relay addon builder now repairs and compiles a private
copy instead of the shared windows-process-tree dir.
* fix(build): accept CLI runtime imports reached through an in-artifact store link
Under the global virtual store node_modules/<pkg> realpaths into a store
outside the repo. The check still rejects anything not reached through a
node_modules link inside the artifact, such as a stray ~/node_modules.
* docs: explain the global virtual store layout and the ~/node_modules hazard
* test: compare CLI closure paths with POSIX separators so the suite passes on Windows
* build: keep Windows on the normal pnpm layout unless ORCA_PNPM_GLOBAL_VIRTUAL_STORE=1
Store links are true symlinks on Windows, and installs without admin or
Developer Mode are unverified; CI still forces the normal layout first.
* fix(build): close the remaining shared-slot gaps under the global virtual store
- verify-skills-cli-runtime resolves each import from the importer's realpath,
as Node does, so an artifact-local copy can't mask a ~/node_modules load.
- A concurrent sibling install of the shared Electron dist is kept, not swapped out.
- rebuild:node goes through ensure-native-runtime, which builds a shared
node-pty beside the slot instead of node-gyp cleaning its build/ dir.
* fix(build): keep pnpm rebuild:node a forced rebuild
It replaced pnpm rebuild node-pty, which always rebuilt; without --force it
only rebuilt a node-pty that failed to load.
* docs: note that the store switches must stay set, since pnpm run relinks
* build: move the pnpmfile under config/ to keep the repo root allowlisted
pnpm-workspace.yaml points pnpm at it; the lockfile checksum is unchanged
because the content is.
* fix(build): enable the global virtual store from the pnpmfile, not the workspace file
pnpm exec derives NODE_PATH from the file setting, so even with the store
forced off under CI every child process got the root node_modules on its
NODE_PATH; a Windows rebuild fixture then resolved the real
@orca/windows-registry it deliberately omits. The hook now sets the store
both ways, and ORCA_PNPM_GLOBAL_VIRTUAL_STORE=0/1 is the one switch.
* test(pty): keep F3's concurrent spawns on the node-pty mock
Two concurrent first import('node-pty') calls race vitest's mock registry
and the loser loads the real addon under the mocked linux platform. It
passed only where a platform-agnostic build/Release happened to exist,
so it failed on every shared-store worktree.
* ci: fail PRs whose packages need a dependency they never declared
A new dependency_isolation job installs with the global virtual store
forced on (ORCA_PNPM_FORCE_GLOBAL_VIRTUAL_STORE_IN_CI), HOME and the store
in an empty temp dir, then runs pnpm tc and the undeclared-dependency test.
Postinstall now warns when a node_modules above the shared store, such as
~/node_modules, would mask the same class of bug locally.
* ci: set the isolation job's HOME and store through GITHUB_ENV
Job-level env cannot read the runner context, which made pr.yml invalid.
orcad-remote-*, remote-install-*, remote-node-runtime-store-*, remote-versioned-install and
remote-deploy-timing leave src/main/ssh. git mv plus import and path-literal rewrites; one e2e route
regex learns the new folder. orcad-remote-deploy and orcad-remote-node-runtime-report stay for now
because open PRs #29834 and #29829 edit them.
tests/ is typechecked by nothing in CI, so the Windows CLI matrix spec imported a helper that never existed (#30231). Per-file error counts under tests/ (tsc -p config/tsconfig.e2e.json) may now only go down.
Worktree ids built as `${repo.id}::${path}` by hand are how one worktree got two
spellings (#30150). New code composes them through src/shared/worktree/id.ts; the
ratchet counts the remaining hand-built ids per file (18) and may only go down. Six
byte-identical `${repo.id}::${repo.path}` sites move to getRepoMainWorktreeId.
* ci: ratchet src/ path literals in CI config, workflows and e2e code that name no file
* ci(path-literal): resolve relative imports exactly
* ci(path-literal): resolve against tracked files only; read ./src imports
* ci(path-literal): scan src/packages and src/types references too
* ci(path-literal): skip paths quoted in comments
* ci(path-literal): keep a recursive glob's boundary
* ci(path-literal): strip comments with a string-aware scan; any import occurrence is exact
* ci(path-literal): imports need a module or index; relative globs and folders stay prefixes
* chore(ci): ratchet renderer importers of the deprecated runtime-owner resolvers
getRuntimeEnvironmentIdForWorktree and resolveRuntimeOwnerForWorktree read a
worktree two hosts publish as not-a-runtime, which callers treat as local. The
62 renderer files importing them are grandfathered; the list may only shrink.
* ci: register the deprecated runtime-owner ratchet step in the preflight phase map