|
|
@@ -14,9 +14,11 @@ The coverage audit found that PR #499 had restored deterministic native-Windows
|
|
|
|
|
|
The required `windows` job in [ci.yml](../../../../.github/workflows/ci.yml) remains `windows node 24 / wine blocking` on `ubuntu-latest`. It retains the checksum-verified Windows Node, Wine apt and pnpm caches, a hoisted install confined to a workspace snapshot, and the [shared Wine gate script](../../../../scripts/wine-windows-gates.sh) that run the workspace build and production site. The stable `windows` job id remains a dependency of `all checks passed`. The [archived Wine experiment](../../archived/process/2026-07-27-wine-windows-gates-experiment.md) preserves its measured trade-offs, while this note owns the current dual topology.
|
|
|
|
|
|
-Every pull request also starts an independent `windows-native` job named `windows node 24 / native complete` on GitHub's standard `windows-2025` image. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete` under native PowerShell. The job is deliberately absent from `all-checks-passed.needs`: the aggregate neither waits for it nor changes conclusion because of it, while the native job retains its own unmasked success or failure result.
|
|
|
+Every pull request also starts an independent `windows-native` job named `windows node 24 / native complete` on the organization-owned `dsh-windows-2025-16core` runner. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete` under native PowerShell. The job is deliberately absent from `all-checks-passed.needs`: the aggregate neither waits for it nor changes conclusion because of it, while the native job retains its own unmasked success or failure result.
|
|
|
|
|
|
-Inside `windows-native`, workspace build, production-site, and 100%-per-file coverage failures make that job fail, while the broader static, documentation, package, and built-artifact portability inventory remains observational. Coverage has a one-worker budget, and gate concurrency remains one so the instrumented and exempt-heavy suites do not overlap; one runner shares installation and build outputs across those gates, and serial gate and publint worker bounds keep the standard image within a predictable resource envelope. Linux remains the owner of duplicate lint and snapshot enforcement.
|
|
|
+Inside `windows-native`, workspace build, production-site, and 100%-per-file coverage failures make that job fail, while the broader static, documentation, package, and built-artifact portability inventory remains observational. The 16-core lane gives coverage a six-worker budget, split into four instrumented workers and two exempt-heavy workers, runs two top-level gates concurrently, and allows eight publint workers. Every Vitest project uses forked workers because Node 24's CJS lexer fatal has reproduced in shared worker threads on Windows as well as POSIX; the two-gate schedule also prevents the exempt-heavy Oxlint probe from racing the workspace build over its temporary contract files. Two asynchronous fixtures whose real process or lazy grammar startup can exceed Vitest's default polling window use explicit five-second waits without changing their asserted outcomes. Linux remains the owner of duplicate lint and snapshot enforcement.
|
|
|
+
|
|
|
+The 16-core allocation is the measured stable point for this inventory. Relative to the previous two-core serial job, the complete native lane fell from 32 minutes 11 seconds to 6 minutes 27 seconds while all 41 gates and the unchanged per-file coverage threshold passed. A 32-core run reduced aggregate gate time by only 1.47 seconds and still triggered the same CJS-lexer fatal inside a fork worker, so additional cores did not provide a reliable wall-clock improvement.
|
|
|
|
|
|
The first native run exposed two failures hidden by the compatibility lane. Documentation projection tests derived an image basename by splitting only on `/`; they now use Node's platform basename. Chokidar consumers received `%TEMP%` through the `C:\\Users\\RUNNER~1` 8.3 alias while libuv returned the long directory name, tripping its Windows event-path assertion. Shared settings and credentials watchers, plus Cordis module and exact-config HMR, now canonicalize the existing native watch base or deepest existing ancestor before opening the watcher and preserve a missing suffix, while file access and diagnostics retain the configured path.
|
|
|
|
|
|
@@ -40,7 +42,7 @@ The subsequent exact hosted run isolated seven other fixture contracts. The Powe
|
|
|
|
|
|
That run also made syntax highlighting sensitive to runner contention rather than source text. Shiki's JavaScript engine deferred TextMate regexes longer than 3,000 characters until their first match, while Shiki counted that compilation against its 500 ms per-line tokenization budget. A busy Windows coverage worker could therefore stop the first TypeScript line after the `const` match and return the remainder under the same keyword style. The client now uses Shiki's default regex translation with lazy compilation disabled and tokenizes one representative sample for each boot grammar without a startup cutoff while constructing the singleton. Scanner creation and pattern compilation therefore finish before user content enters the unchanged 500 ms per-line budget. The token-boundary and Markdown DOM fixtures continue to require the complete highlighted result rather than accepting the partial stream.
|
|
|
|
|
|
-The same exact hosted run showed that three concurrent instrumented Vitest workers were an unsafe budget for the standard Windows image: otherwise independent Git-merge and JSON-RPC HTTP integration cases reached the default five-second ceiling together. The native lane now gives Vitest one worker, while the real Git subprocess suite and the two real HTTP composition cases have explicit fifteen-second integration budgets without changing their workloads or assertions. The translation merge fixture also preserves `import.meta.resolve('tsx/esm')` as a `file:` URL when passing it to Node's `--import`; converting it to a drive-letter path had failed before the driver could print its owned recovery guidance. After the latest package regrouping, the fork-isolated JSONL suite's inventory follows its new `packages/session/` location rather than silently returning that process-bound suite to the shared thread pool.
|
|
|
+The same exact hosted run showed that three concurrent instrumented Vitest workers were an unsafe budget for the standard Windows image: otherwise independent Git-merge and JSON-RPC HTTP integration cases reached the default five-second ceiling together. At that stage the native lane temporarily gave Vitest one worker, while the real Git subprocess suite and the two real HTTP composition cases received explicit fifteen-second integration budgets without changing their workloads or assertions. The translation merge fixture also preserves `import.meta.resolve('tsx/esm')` as a `file:` URL when passing it to Node's `--import`; converting it to a drive-letter path had failed before the driver could print its owned recovery guidance. After the latest package regrouping, the fork-isolated JSONL suite's inventory follows its new `packages/session/` location rather than silently returning that process-bound suite to the shared thread pool.
|
|
|
|
|
|
The project-skill composition fixture had one separate eventual-consistency race: on a contended host the agent could begin its next model step after `write` returned but before Chokidar invalidated the skill catalog, moving the replacement catalog behind the subsequent `skill` call. The fixture now holds that post-write tool boundary until the real registry observes `hot-skill`, then retains its strict request-order and durable-transcript assertions. Production code remains asynchronous; the test explicitly waits for the watcher contract it intends to exercise instead of relying on scheduler timing or accepting a different request index.
|
|
|
|
|
|
@@ -64,7 +66,9 @@ POSIX mode bits, chmod-based unreadability, and chmod-based writer-lock refusal
|
|
|
|
|
|
**Run native Windows only after merge.** A post-merge reference diagnoses portability regressions after they enter `master`; it does not give reviewers an exact-head native result.
|
|
|
|
|
|
-**Use an organization-owned larger Windows runner.** Larger images can reduce wall clock, but the diagnostic path would then depend on repository-external labels and allocation. Standard `windows-2025` is portable; larger runners remain benchmark targets.
|
|
|
+**Keep GitHub's standard `windows-2025` runner.** That portable two-core image completed the exact inventory reliably, but its 32-minute serial result made the automatic native signal substantially less useful than the selected 16-core runner.
|
|
|
+
|
|
|
+**Use a 32-core or larger runner.** The 32-core comparison improved aggregate gate time by only 1.47 seconds over 16 cores and failed in Node's CJS lexer; earlier high-concurrency 32-core and 64-core trials failed in the same class. More capacity therefore added allocation cost without a stable end-to-end gain.
|
|
|
|
|
|
## Consequences
|
|
|
|