|
97 | 97 | // |
98 | 98 | // The cost is test-body work, and it is concentrated, not uniform: median file |
99 | 99 | // 0.03s, 105 of 137 files under 2s, top 20 files = 87.7% of the wall. The 20 |
100 | | -// files that spawn the real CLI as a subprocess (`bin/run-dev.js` through |
101 | | -// `tsx`, against a `mkdtemp` project) are 56.1% of the file wall (300.1s) while |
102 | | -// carrying 177 of 1498 tests. Each spawn re-executes the CLI's module graph in |
103 | | -// a COLD process, which is the standing theory after all — relocated out of |
104 | | -// vitest's worker, where neither its transform cache nor its module registry |
105 | | -// can reach it. Floor per spawn, doing nothing but printing a version: |
106 | | -// |
107 | | -// tsx bin/run-dev.js --version 6.5-6.8s (the source entry these use) |
| 100 | +// files that spawned the real CLI as a subprocess (all 20 of them |
| 101 | +// `bin/run-dev.js` through `tsx` on that date, against a `mkdtemp` project) |
| 102 | +// were 56.1% of the file wall (300.1s) while carrying 177 of 1498 tests — |
| 103 | +// three have since moved to the built entry (#11707; last section of this |
| 104 | +// header) and the split has not been re-measured. Each spawn re-executes the |
| 105 | +// CLI's module graph in a COLD process, which is the standing theory after |
| 106 | +// all — relocated out of vitest's worker, where neither its transform cache |
| 107 | +// nor its module registry can reach it. Floor per spawn, doing nothing but |
| 108 | +// printing a version: |
| 109 | +// |
| 110 | +// tsx bin/run-dev.js --version 6.5-6.8s (the source entry all 20 used) |
108 | 111 | // node bin/run.js --version 2.9-3.2s (the built entry) |
109 | 112 | // node -e 0 0.031s (process floor) |
110 | 113 | // |
|
173 | 176 | // `packages/cli` has no `vi.mock` of `@objectstack/types` (its only mock targets |
174 | 177 | // are `../utils/optional-package.js`, `node:fs/promises` and |
175 | 178 | // `@objectstack/cloud-connection`) — but neither is free, and a package added |
176 | | -// here later must be re-checked for both. Swapping the spawns to |
177 | | -// the built entry would halve per-spawn boot and is exactly the source-vs-dist |
178 | | -// trade `scripts/check-test-source-alias.mjs` exists to refuse — see the note |
179 | | -// above on why a test that passes GREEN against a stale artifact is the |
180 | | -// dangerous outcome. Before adding a `test` block for speed, re-measure: if |
181 | | -// `tests` is still the dominant term, the block is not the lever. |
| 179 | +// here later must be re-checked for both. |
| 180 | +// |
| 181 | +// ## WHY THE SPAWN SWAP IS NOT THIS GATE'S TRADE TO REFUSE (#11707, #12460) |
| 182 | +// |
| 183 | +// This file used to close by calling a swap of the spawns to the built entry |
| 184 | +// “exactly the source-vs-dist trade `scripts/check-test-source-alias.mjs` |
| 185 | +// exists to refuse”. It is not one, and naming a gate for a verdict it never |
| 186 | +// reaches reads as verification while verifying nothing. What that gate does |
| 187 | +// measure: the specifiers written in `import` / `export … from` / `import()` / |
| 188 | +// `require()` statements reachable from a package's test files, kept when they |
| 189 | +// name a workspace dep whose own entry point resolves under `dist/`, then |
| 190 | +// resolved through THIS config's `resolve.alias` table. That is a verdict about |
| 191 | +// IN-PROCESS import resolution. It says nothing about which entry a test hands |
| 192 | +// to `spawn()`, and its own header signs that second axis over to a different |
| 193 | +// mechanism (“A SECOND resolution hazard, which this gate does NOT cover”, |
| 194 | +// #11412). The `plugin-auth` entry below is this file's worked example: it |
| 195 | +// satisfies the gate while being inert for the child, whose own `exports` |
| 196 | +// lookup reaches `dist/` either way. |
| 197 | +// |
| 198 | +// So the swap was available, and #11707 took it — 2.06x faster in test time, |
| 199 | +// measured there. Four files in `test/` consume `packages/cli/dist` today: |
| 200 | +// `serve-node-env-production-default` (since #11113) and the three spawners |
| 201 | +// #11707 moved onto `node bin/run.js` with `NODE_ENV` unset |
| 202 | +// (`serve-mcp-stdio-answers`, `serve-mcp-capability-collision`, |
| 203 | +// `serve-stdio-stdout-purity`). Re-running this gate on that commit and on its |
| 204 | +// parent returns a byte-identical verdict AND a byte-identical measured |
| 205 | +// population: it did not see the swap. |
| 206 | +// |
| 207 | +// What keeps those four honest is a declaration, not this gate. `turbo.json` |
| 208 | +// declares `@objectstack/cli#test` `dependsOn: ["build"]` (#11268), so CI |
| 209 | +// builds `dist/` before the suite runs, and each of the four refuses an unbuilt |
| 210 | +// tree in a sentence of its own. The residual — a `dist/` merely BEHIND its |
| 211 | +// source — is real, and those files state it. An in-process import has no such |
| 212 | +// declaration standing behind it, which is why the alias entries above exist |
| 213 | +// and why the gate does refuse THAT trade — see the note above on why a test |
| 214 | +// that passes GREEN against a stale artifact is the dangerous outcome. |
| 215 | +// |
| 216 | +// Before adding a `test` block for speed, re-measure: if `tests` is still the |
| 217 | +// dominant term, the block is not the lever. |
182 | 218 | import { defineConfig } from 'vitest/config'; |
183 | 219 | import path from 'path'; |
184 | 220 |
|
|
0 commit comments