perf(ci): isolate the transform corpus from coverage

This commit is contained in:
Tianyi Cui
2026-08-22 20:10:54 +08:00
parent ea6f61f144
commit 4edf6400ff
4 changed files with 18 additions and 2 deletions
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-31-coverage-exempt-heavy-suites.md
2026-07-31-coverage-exempt-heavy-suites.md: 1f468a69321b451593a9279cfebc1b457fb08a47
2026-07-31-coverage-exempt-heavy-suites.zh.md: 7e519f44c8321b6b99c04c6af56c4cfa5b641663
2026-07-31-coverage-exempt-heavy-suites.md: 69b2e9a1c98e3b2975f95f7020b602aca513397a
2026-07-31-coverage-exempt-heavy-suites.zh.md: 58e7489deec50d2088ccca3b2e4a35aeba9cb104
@@ -10,6 +10,8 @@ The CI coverage lane (`check:ci:coverage`) had its wall clock pinned by a handfu
The decisive waste: the instrumentation tax these suites paid contributed **nothing** to the per-file 100% thresholds — the measured code they execute in-process is either outside the threshold scope already or independently fully covered by other suites. Running them instrumented traded lane time for zero information.
The Web Worker transform corpus exposed the same waste on native Windows: `transform-corpus.spec.ts` spent 279 seconds inside one 442-second coverage partition while the other seven partitions settled in 110161 seconds. Its real checker runs package source only in a spawned Node process, outside the parent Vitest worker's v8 coverage session, so the slow partition produced no threshold data from that work.
## Decision
The `ci-coverage` aggregate splits into two parallel gates; every test still runs, and only the heavy suites stop paying the instrumentation tax:
@@ -30,6 +32,7 @@ A suite contributes to coverage exactly when it executes measured files in-proce
| All 6 typert generator specs | The generator's own src | Generator src is threshold-excluded as a package (`vitest.config.ts`) — outside the threshold scope to begin with |
| tools-catalog.spec additionally imports | `typert-registry` and `tool-cordis` src | Each package's own tests cover them fully (verified with focused coverage runs, zero threshold errors) |
| `scripts/install-lefthook.spec.ts`, `scripts/oxlint-contract.spec.ts`, `scripts/change-scope.spec.ts`, `scripts/translation-pairing-merge.spec.ts` | None — they test `scripts/` sources (never in `coverage.include`) and work by spawning child processes | Nothing to carry |
| `packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts` | None — its package-source imports and the complete bundle sweep run in a spawned Node process | The Web Worker runtime's in-process unit suites carry its source coverage |
### Membership contract
@@ -55,6 +58,8 @@ Coverage-result invariance therefore does not rest on humans maintaining the ros
Measured on CI (16-core runner): the gate segment went from 424 seconds to the two gates in parallel — `test:coverage` 95.9 s + `test:coverage-exempt-heavy` 71.1 s — with the lane converging on the slower at about 96 seconds; the instrumented gate reported zero threshold errors both before and after the split. `vitest list` verifies the env toggle adds and removes exactly the exempt set; `run-gates.spec.ts` covers the aggregate graph construction.
The Web Worker corpus entry is pinned by an eight-partition aggregate that runs all 15,250 tests and reports 100% for 45,959 statements, 28,116 branches, 9,781 functions, and 40,550 lines. A focused instrumented corpus run records no package source from its child process; the paired list check proves the spec is absent from the instrumented inventory and present in the uninstrumented inventory.
## Consequences
- The exempt suites execute without adding instrumentation cost to the thresholded gate; partitioned wall-clock measurements belong to the [in-job partitioning decision](2026-08-18-in-job-partitioned-coverage.md).
@@ -10,6 +10,8 @@ CI 覆盖率 lane`check:ci:coverage`)的墙钟被少数几个重型测试
关键的浪费在于:这些套件缴纳的插桩税对 per-file 100% 阈值**没有任何贡献**——它们进程内执行的被度量代码,要么本来就不在阈值口径内,要么已由其他套件独立满覆盖。继续在插桩下运行它们,纯粹是用 lane 时长换零信息。
Web Worker 转换语料库在原生 Windows 上暴露了同一类浪费:`transform-corpus.spec.ts` 在一个 442 秒的覆盖率分区中占用 279 秒,而其余七个分区在 110–161 秒内完成。它的真实检查器只在 spawn 的 Node 子进程中运行包源码,处于父 Vitest worker 的 v8 覆盖率会话之外,因此这个慢分区没有从该工作中产生任何阈值数据。
## Decision
`ci-coverage` 聚合拆成两个并行 gate,全部测试仍然执行,只有重型套件不再交插桩税:
@@ -30,6 +32,7 @@ Linux 覆盖率 CI 与原生 Windows CI 在插桩门禁内部使用 [job 内分
| typert generator 全部 6 个 spec | generator 自身 src | generator src 已整包 threshold-excluded`vitest.config.ts`),本不在阈值口径内 |
| 其中 tools-catalog.spec 额外 import | `typert-registry``tool-cordis` 的 src | 两包各自的测试独立满覆盖(focused coverage 实测无阈值错误) |
| `scripts/install-lefthook.spec.ts``scripts/oxlint-contract.spec.ts``scripts/change-scope.spec.ts``scripts/translation-pairing-merge.spec.ts` | 无——被测对象是 `scripts/` 源码(从不在 coverage.include),执行方式是 spawn 子进程 | 无需接 |
| `packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts` | 无——包源码 import 与完整 bundle 扫描都在 spawn 的 Node 子进程中运行 | Web Worker runtime 的进程内单元套件承担其源码覆盖率 |
### 成员资格约定
@@ -55,6 +58,8 @@ per-file 100% 阈值本身就是豁免名单的守卫,名单错误无法静默
CI 实测(16 核 runner):拆分前 gate 段 424 秒,拆分后两 gate 并行 `test:coverage` 95.9 秒 + `test:coverage-exempt-heavy` 71.1 秒,lane 收敛于较慢者约 96 秒;拆分前后插桩 gate 阈值错误均为零。`vitest list` 验证 env 开关两态恰好增删豁免集;`run-gates.spec.ts` 覆盖聚合图构造。
Web Worker 语料库条目由八分区聚合固定:它执行全部 15,250 个测试,并对 45,959 条语句、28,116 个分支、9,781 个函数和 40,550 行报告 100%。聚焦的插桩语料库运行不会记录其子进程中的包源码;配对名单检查证明该 spec 不在插桩清单中,但存在于无插桩清单中。
## Consequences
- 豁免套件在执行时不会向阈值门禁叠加插桩开销;分区墙钟数据由 [job 内分区决策](2026-08-18-in-job-partitioned-coverage.zh.md)负责记录。
+6
View File
@@ -39,4 +39,10 @@ export const coverageExemptHeavySuites: readonly CoverageExemptSuite[] = [
{ filter: 'scripts/oxlint-contract.spec.ts', exclude: 'scripts/oxlint-contract.spec.ts' },
{ filter: 'scripts/change-scope.spec.ts', exclude: 'scripts/change-scope.spec.ts' },
{ filter: 'scripts/translation-pairing-merge.spec.ts', exclude: 'scripts/translation-pairing-merge.spec.ts' },
// The real corpus transform runs package src only in a spawned Node process,
// outside the parent Vitest worker's v8 coverage session.
{
filter: 'packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts',
exclude: 'packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts',
},
]