On Windows, pnpm shortens the virtual store directory to
@vscode+windows-process-tre_<hash>, cutting into the package name before
the @, so the @vscode+windows-process-tree@* glob matched nothing and the
addon recompiled on every Windows job. node-pty escapes this because its
truncation lands after node-pty@, which the glob still matches.
Widening the prefix to @vscode+windows-process-tre* matches both the full
name kept on macOS/Linux and the truncated Windows one.
The workspace link means pnpm never creates a .pnpm/@orca+windows-registry@*
entry, so all four native-cache blocks globbed a path that cannot exist and
the addon was recompiled on every Windows job.
Also hardens the addon itself: RegEnumValueW reports a byte count and the
registry does not enforce whole WCHARs for string types, so an odd count let
Napi's auto-length scan run past the value; and a value named __proto__ would
reassign the result object's prototype instead of becoming an entry.
* refactor(windows): vendor the registry addon as @orca/windows-registry
windows-native-registry@3.2.2 was last published in 2023 by a single
maintainer. Orca called two of its exports, both read-only, so the whole
dependency is replaced by a local N-API addon under native/.
The vendored addon is read-only by construction: setValue, createKey and
deleteKey are gone, so RegDeleteTreeW no longer ships in the app. Two
upstream defects are also fixed rather than carried over — the name/data
scratch buffers were file-scope statics that concurrent reads would
scribble over, and createKey/deleteKey called .c_str() on a temporary.
Build wiring keeps the existing shape: still an optionalDependency gated
to win32, still excluded from pnpm's allowBuilds so only Orca's own
Windows rebuild runs node-gyp for it, still copied into the packaged
resources. The CI native caches now key on the vendored sources so an
addon.cc edit cannot restore a stale .node.
* test(windows): check the vendored registry addon against reg.exe
The addon is vendored source, so no upstream release proves it still
decodes values the way Orca's PATH readers expect. reg.exe is the only
independent oracle on the box.
* ci(windows): register the registry addon test on the Windows runner
A Windows-gated file self-skips on ubuntu, so without both registrations
it reports success while running on no machine at all.
* fix(build): link the registry addon as a workspace package, not file:
As a `file:` dependency pnpm re-resolved and re-linked the package on
every install, including `--frozen-lockfile` (measured: "added 1" on a
repeat no-op install). That virtual-store churn ran concurrently with
node-gyp reading the same tree and cost @vscode/windows-process-tree its
binding.gyp mid-rebuild, failing package (windows) whenever the native
cache hit and only that module needed building. The linux packaging job
hit the same race from the other side, as a pnpm staging move failure.
A workspace link resolves once and leaves the store alone; repeat
installs are now 55ms no-ops. native/windows-registry is listed
explicitly so `packages:` still does not auto-discover mobile/.
* fix(build): stop tracking node-gyp output for the vendored addon
The build/ tree is generated per host and ABI; the committed copy was
macOS-specific gyp scaffolding from a local build and would have shipped
stale Makefiles to every checkout.
* chore: ignore the vendored addon's node-gyp bin output too
node-gyp also emits bin/<platform>-<abi>/ beside build/; both are per-host
generated output that must never be committed.
* feat(mobile): finalize structured native Codex chat
* fix(mobile): close structured chat lifecycle gaps
* wip(mobile): fence stale structured inventory and bound operation-id retention
Fence local structured-session inventory and subscription responses with a
sync generation so a toggle-off clear, reconnect restore, or retry cannot
apply a mirror from a superseded instance. Bound mobile ambiguous
operation-ID retention at 128 with unmount cleanup.
Staged on the reconcile branch only: the sync module is now 312 lines and
needs a real split before this can reach the PR head.
* fix(ci): split the structured session-tabs sync and give static analysis mobile types
The local structured session-tabs sync module outgrew the 300-line cap once it
took on generation fencing, so split it along its real seams instead of raising
the cap: the generation/cursor fence, snapshot projection, snapshot apply,
inventory refresh, and the subscription loop. The original path stays as a
barrel so no importer moves.
Repoint the host-session-mirror settle census at the apply module, which owns
two receipts now — the snapshot it mirrors in, and the toggle-off teardown that
retracts what it published. The teardown receipt is named rather than anonymous
so the pin says which direction it settles.
The changed-code quality gate lints mobile files and resolves their types from
mobile/node_modules, but mobile is a separate pnpm project that the root install
never populates, so every mobile type degraded to an `error` type and the gate
reported phantom findings. Install mobile dependencies in static analysis when
the diff touches mobile, gated on a new classifier output.
* fix(mobile): let a slow capability handshake still reach connected
The mobile capability update is an advisory whose result is discarded, yet an
unanswered one was fatal while an explicit rejection was tolerated. A 5s timeout
on the direct client force-closed the socket, and on the relay path it failed
`confirmResume` before `connected` was ever published, so a consistently slow
link redialled forever. Both paths now share one helper that settles every
ambiguous outcome (timeout, mid-flight drop) like a rejection and rejects only
when the frame never reached the wire — the one case nothing else recovers from,
since the socket's own desync force-close is gated on already being connected.
The generation guard still keeps a replaced session from connecting.
Retained structured-session operation ids were capped at 128 with oldest-first
eviction, but every retained id belongs to a send whose outcome is unknown, so
eviction turned a user's retry into a second message on the host. Bound the map
by expiry against the id's own embedded timestamp instead, mirroring the host's
operation ledger, so no id is released while the host would still honour it.
Also give the mobile CI install the root install's lockfile drift guard (mobile's
lockfile carries patchedDependencies a silent rewrite would drop), gate
mobile_dependencies on should_run, and key the pnpm store cache on both lockfiles.
* refactor(mobile): extract the relay pending-request registry
The merge composed two independently-sized changes — this branch's capability
handshake settle and main's dial-stage tracking — pushing the relay session file
to 304 lines against a 300 cap. Neither side broke it alone.
Move the in-flight request registry (id generation, tracking, settlement, and
reject-all with its delivery-ambiguity marking) into RelayPendingRequests,
matching the existing collaborator pattern alongside RelayDialStageTracker and
RpcSessionLivenessWatchdog. No behavior change.
---------
Co-authored-by: Merge Sim <sim@local>
* Speed up PR CI with per-job path skips and native caches
Skip git-compat, xterm, packaging, and shell jobs when their inputs are
unchanged, reuse the composite install action (including Windows node-pty
cache), skip compiling the Windows CLI launcher on a cache hit, and cut the
test matrix from 16x2 to 8x2 shards without dropping coverage.
* Widen PR job skip prefixes for orcad browser and live shells
Chrome session/tab modules and zsh/fish wrapper templates are inputs to
required jobs the classifier previously skipped. Include that implementation
graph so those jobs still run when the files they load change.
* Fix CI cache safety and required gates
* Build scriptless Windows addons explicitly
* Preserve node-pty Windows support prebuild
* Remove duplicated Windows launcher unit lane
None of these change what CI checks — they remove work the runners
repeated on every PR.
- install-node-dependencies installed with --no-frozen-lockfile, so every
job re-resolved the graph against the registry to recompute what the
lockfile already pins. Measured at ~62 MB of packument metadata per job;
the pnpm store cache does not cover the metadata cache, so this was paid
~39 times per run. The `git diff` guard that made the re-resolution
redundant stays.
- --ignore-scripts leaves node-pty with no build/Release, so
ensure-native-runtime node-gyp-compiled it in every job asking for a
runtime. Cache the build under an ABI-bound key (runtime, resolved Node
version, node-pty patch) with no restore-keys, since a partial match is
exactly the mismatched build that would be recompiled anyway.
- The four fetch-depth: 0 checkouts pulled full history including every
historical blob (blobs are ~89% of this repo's pack). They only need the
commit graph for a merge-base diff, so fetch them blobless. Measured
30-43s each today versus 8s for the shallow checkouts. One of them,
e2e-paths, gates the entire E2E chain.
- E2E jobs ordered setup-node before pnpm, which meant setup-node could not
find the store and no E2E job cached dependencies at all. Reorder and
cache; this sits on the critical path in both the build job and each
shard.
- git_compatibility rebuilt Git 2.25.5 from a pinned tarball on every PR.
Cache the build; the sha256 assertion still guards the miss path.
- typecheck ran three independent tsc passes back to back and discarded the
.tsbuildinfo each project already emits. Run them concurrently and cache
the incremental state.
- package (windows) built the electron-vite targets serially via
build:release. Use a :parallel variant that overlaps them, matching what
the Linux package job already packages and smoke-tests from.
Contract tests cover each new cache's ordering and key so none of them can
silently start serving a stale or ABI-mismatched artifact.