Repository navigation
Commit de3fafc
test(cli): budget the six remaining cli test files from 13 s up; spawn the source entry with node in three (#28616)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XE1ashwufQRjetDvaJEkX2H)_
Part of #23181 (slice 28). The card stays open for later slices: this
one takes only the six remaining `packages/cli` files at 13 s and over
in slice 23's table.
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:`packages/cli` 里 CI 读数 13 s 以上、还没有预算头的 6 个测试文件,每个在第 2 行加一行
`// test-budget:` 头(metadata-type-schema-gate 30 s,其余 5 个 20 s)。其中 3
个文件原来经 `node_modules/.bin/tsx` 包装层起 CLI 源码入口,现在改成直接用 `process.execPath`
起同一个 `bin/run-dev.js`,与 metadata-type-schema-gate 已有写法一致。
- **为什么改**:卡 #23181 的测试提速职责:超过 10 s 的测试文件要么提速,要么按裁决 6181973363 B
声明预算。逐个文件数过:每次 spawn 都是不同的(命令、参数、夹具)组合,没有可合并的重复;schema-migration-plugins
没有 spawn,地板是冷导入 `@objectstack/runtime`(本地约 9.9 s)。所以都走预算头,能省的只有 tsx 包装层。
- **风险与回滚**:只改测试文件,不发布任何东西(cli 的 `files[]` 只有
dist、README、CHANGELOG);没有删、没有放宽任何断言,用例名和数量不变;回滚即 revert。
-
**先看**:`packages/cli/test/validate-lint-mapping-connector-source.test.ts`
与 `packages/cli/test/info-detail-package-fold.test.ts`(tsx →
`process.execPath`);`packages/cli/test/emit-json-pipe.test.ts`(只改了末尾那一次
CLI spawn,四个 harness 和对照仍走 tsx)。
- **两分钟验证**:`pnpm --filter @objectstack/cli exec vitest run
test/validate-lint-mapping-connector-source.test.ts
test/info-detail-package-fold.test.ts` → 10/10 通过。
- **需要你做的**:无,席位落地。
## What changes
The six files and their slowest reading over the five scheduled `ci.yml`
runs `41199450735`, `41217827347`, `41237094739`, `41255489006`,
`41271604267` (slice 23's offender table, default reporter's per-file
module line in the Test Core shard logs):
| file | CI max | tests | spawns / boots | distinct triples | cause |
fix |
|:--|--:|--:|:--|--:|:--|:--|
| `test/metadata-type-schema-gate.test.ts` | 16.1 s (41217827347) | 8 |
4 source-CLI spawns, already on `process.execPath` | 4 | one spawn per
(command, fixture): `os validate` on the control, planted-key and `lg`
stacks, `os build` on the planted key (its no-artifact claim). About 2.6
s each locally; the in-process cases take under 0.2 s together | header
30 |
| `src/utils/schema-migration-plugins.test.ts` | 15.9 s (41271604267) |
52 | no spawn, no boot | n/a | a cold import: the composition imports
`@objectstack/runtime` for the AppPlugin it composes, as `os serve`
does. A probe timed it at 9.86 s under this package's vitest config,
plus 3.94 s for the module under test, 1.21 s for plugin-auth (aliased
to its src) and 0.45 s for service-automation. Each lands on whichever
case triggers it first (the "host config LOADS" case reads 9.9 s); no
case repeats it | header 20 |
| `test/validate-lint-mapping-connector-source.test.ts` | 15.7 s
(41217827347) | 3 | 3 source-CLI spawns through the `tsx` wrapper | 3 |
`os validate --json` and `os lint --json` on the card stack, `os lint
--json` on the control stack. The wrapper adds about 1.3 s per spawn |
spawn with `process.execPath`; header 20 |
| `test/scaffold-test-script-passes.test.ts` | 14.9 s (41217827347) | 9
| 8 spawns of the emitted projects' own scripts | 8 | five vitest `test`
runs (init plugin, its empty-suite control, create plugin fresh, after
`build`, its empty-suite control) and three tsc runs (`build`,
`typecheck` clean, `typecheck` with the planted error). Each runs on its
own fixture state | header 20 |
| `test/info-detail-package-fold.test.ts` | 14.8 s (41217827347) | 7 | 6
source-CLI spawns through the `tsx` wrapper, already in one `beforeAll`
| 6 | `os info --json` and `os info` on the option-B, top-level and
two-package projects | spawn with `process.execPath`; header 20 |
| `test/emit-json-pipe.test.ts` | 13.5 s (41271604267) | 7 | 6 children:
4 tsx harnesses, the tsx `console.log` control, 1 source-CLI `os
validate --json` through the wrapper | 6 | each harness writes through
`emitJson` and ends a different way; the in-process `isExitSignal` case
pays the cold import of `format.ts` and the spec barrel (about 2.3 s) |
the CLI spawn uses `process.execPath`; header 20 |
**Why the floor is distinct real work.** No file repeats a (command,
flags, fixture) triple, and the two that spawn the most already share
their setup (`info-detail` in one `beforeAll`; `scaffold` materialises
each fixture once per case, from in-process renderers). Nothing reads a
file through a child that could become an in-process read. So every file
takes the ruling 6181973363 letter B header: N = the slowest CI reading
× 1.25, rounded up to 10 s (16.1 → 30; 15.9, 15.7, 14.9, 14.8, 13.5 →
20). Class `spawns the real producer once per single-cause fixture` for
the five spawning files, `whole-package import` for
`schema-migration-plugins` (the precedent is the lint headers that name
a cold barrel import as that class). All six parse with `readTestBudget`
(`scripts/measure-test-shard-timings.mjs`): line 2, the class and
seconds above.
**The one lever inside the floor.** Three files spawned `bin/run-dev.js`
through `node_modules/.bin/tsx`. `metadata-type-schema-gate`,
`authoring-rule-command-parity` and `format-zod-union` already run the
same entry with `process.execPath`: same entry file, same `src/`, same
`childEnv()`, same arguments. The three now do the same.
`emit-json-pipe`'s four harnesses and its control keep `tsx`: they
import `src/utils/format.ts` directly and need its loader, and the pipe
they pin is the one the tsx child writes to.
Not changed: no assertion, case name, case count, timeout, tier, project
or helper. No source file.
## Tests
- **A/B** for the three files whose code changed. Base copied beside
head as `zzbase.*` (`git show c658320:…`), one box, one lock hold, N=3.
Each side ran in its own vitest invocation (the three files together,
`--maxWorkers=1`) so neither side inherits the other's transform cache,
and the order alternated (head first, base first, head first). Reading:
the default reporter's per-file line. Copies deleted before the gate
run.
| file | base (s) | head (s) | change |
|:--|:--|:--|--:|
| `validate-lint-mapping-connector-source` | 11.44, 12.11, 11.09 | 8.47,
8.53, 8.61 | −26.1% (mean 11.55 → 8.54) |
| `info-detail-package-fold` | 10.73, 10.96, 10.69 | 7.75, 8.08, 7.99 |
−26.4% (mean 10.79 → 7.94) |
| `emit-json-pipe` | 12.72, 13.36, 12.76 | 11.94, 13.23, 12.11 | −4.0%
(mean 12.95 → 12.43), within the run-to-run spread |
Every run exit 0, 17/17 tests per side, same names. `emit-json-pipe`
moved one spawn of six, and it runs first in its invocation, so it pays
the cold transform of the spec graph; its header carries it.
- **All six on head**, one run with
`test/vitest-tiers-partition.test.ts`: 7 files, 108/108 passed. Case
counts are the same as the base run (8, 52, 3, 9, 7, 7), and the tier
partition pin is green, so the three edited files stay in `integration`.
- **Header-only files** (`metadata-type-schema-gate`,
`schema-migration-plugins`, `scaffold-test-script-passes`): no A/B, per
the order.
- `pnpm --filter @objectstack/cli typecheck` (tsc and
`check:test-typecheck`) exit 0, with
`NODE_OPTIONS=--max-old-space-size=4096`.
- No ablation: no tested behaviour changed (test-only).
## Acceptance notes
- **`schema-migration-plugins`' 9.9 s is a config cost, not a test
cost.** `@objectstack/runtime` resolves to its `dist/`, but this
package's `vitest.config.ts` aliases several packages that the runtime
graph reaches to their `src/`, so vite transforms them on the first
import. The lever is that shared config, which every cli file reads. It
is outside this slice's file surface; noted, not filed. Carrier: none.
- **`skip-changeset`.** Test-only. `@objectstack/cli`'s `files[]` is
`dist`, `README.md`, `CHANGELOG.md`; its build emits no `*.test.ts` into
`dist/`. No `files[]` content changes.
## Verification
All readings on head `2af0e899`: the fix commit `ea81aa2f` plus one
merge of `origin/main` after slice 23 (#28581) landed, as the order
asks. The A/B and the six-file run above were taken on `ea81aa2f`; the
merge touches none of the six files.
- **Derived gate families:** `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack` → 52 families, each run
with its exit code captured before any pipe, after a full `pnpm exec
turbo run build --concurrency=2` (118 tasks, exit 0). All 52 exit 0.
`--ran` reconciliation: `✓ dispatch-gates --ran: 52 derived famil(ies)
accounted for — 52 run, 0 NOT-MEASURED`. On the pre-merge head, before
the full build, `check:dual-build-cjs-loads` and `check:i18n-coverage`
read exit 3 (no full build, a container prerequisite) and the other 50
exit 0.
- **cli unit tier** (`pnpm --filter @objectstack/cli exec vitest run
--project unit`): 362/362 files, 5155/5155 tests.
- **Hand gates:** `pnpm exec eslint --no-inline-config` over the six
files exit 0 (`@objectstack/cli` has no `lint` script; the repo-wide
`pnpm lint` is CI's); `node scripts/check-commit-card-trailers.mjs
--range origin/main..HEAD` exit 0; `node scripts/check-nul-bytes.mjs`
exit 0.
- **CI** families (Test Core with the cli integration tier, lint farm,
type-check lanes) are read off this PR's check-runs by the seat.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5pfFsY9QCnzGXyBnPP
Co-authored-by: Claude <noreply@anthropic.com>1 parent 0c03ce2 commit de3fafc
6 files changed
Lines changed: 20 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
201 | 202 | | |
202 | 203 | | |
203 | 204 | | |
204 | | - | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
205 | 208 | | |
206 | 209 | | |
207 | 210 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
64 | 65 | | |
65 | 66 | | |
66 | 67 | | |
67 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
68 | 73 | | |
69 | | - | |
70 | 74 | | |
71 | 75 | | |
72 | 76 | | |
| |||
172 | 176 | | |
173 | 177 | | |
174 | 178 | | |
175 | | - | |
| 179 | + | |
176 | 180 | | |
177 | 181 | | |
178 | 182 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
25 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
26 | 29 | | |
27 | 30 | | |
28 | 31 | | |
| |||
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
41 | | - | |
42 | | - | |
| 44 | + | |
43 | 45 | | |
44 | 46 | | |
45 | 47 | | |
| |||
54 | 56 | | |
55 | 57 | | |
56 | 58 | | |
57 | | - | |
| 59 | + | |
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
| |||
0 commit comments