Found while driving PR #14513 (#14439) to green. Filed for the maintainer because the ceiling is a pinned policy (CI_TSC_HEAP_CEILING_MB = 4096, #12856) and changing what the program checks changes what the ledger measures.
Measured
scripts/check-type-check-coverage.mjs --re-measure builds one tsc --noEmit program per ledger entry under --max-old-space-size=4096. For the packages/qa/http-conformance TEST_DEBT entry (8 source files, 5 of them tests, but importing @objectstack/core, @objectstack/objectql, @objectstack/runtime, @objectstack/plugin-hono-server, @objectstack/driver-sqlite-wasm, @objectstack/spec), the same program shape run with an 8 GB cap and --extendedDiagnostics:
| main @ 53d36892 (base worktree, closure built) |
|---|
| Files | 906 |
| Lines of Definitions | 691,580 |
| Types | 1,801,110 |
| Instantiations | 7,342,314 |
| Memory used (tsc's own count) | 4,473,321 K |
| Check time | 68.9 s |
Under the 4096 MB ceiling the program still completes on main (merge-queue Lint & Type Check runs are green through 53d36892 and later), but only because V8 collects harder near the limit: a local run on a main-based worktree peaked at 3,961 MB RSS and spent minutes in GC before finishing. The headroom is therefore a few percent, not a margin.
PR #14513 showed what that means in practice: a spec change that added 42,622 lines of definitions to this program (the whole ObjectStackDefinitionSchema declaration, pulled in through a new chunk edge — fixed in the PR) moved the count to 4,875,249 K and the lane went red twice. The next spec PR that grows the declaration graph seen by @objectstack/spec/system will hit the same wall without having done anything wrong.
Options
| Option | Cost | Note |
|---|
| A | Raise CI_TSC_HEAP_CEILING_MB to 6144 for the re-measure | Policy change; the file's own comment says 4096 is pinned to the CI runner's measured old-space and "if 4096 is wrong, it is wrong DOWNWARD" — ubuntu-latest has 7 GB, so 6144 needs a measurement of what else runs in that job | Restores headroom without changing what is measured |
| B | Shrink the program: skipLibCheck: true in the re-measure project only | Changes the measurement semantics of every TEST_DEBT number (declaration files stop being checked); the frozen numbers would need a wholesale re-measure | Large heap win (declaration files dominate: 691k lines of definitions vs 17k of TypeScript) |
| C | Shrink the program's inputs: have http-conformance type its tests against narrower entries (it imports whole packages for a handful of names) | Per-package edit; recurs for the next heavy entry | Local, no policy change |
| D | Leave as is; treat each OOM as the offending PR's to fix | Every spec PR pays a debugging cycle for a ceiling it did not set | What happened on #14513 |
Not decided here. The four-axis reading favours A with a measured number (long-term consistency: the ceiling exists to make numbers portable, and a ceiling with 3% headroom makes them fragile instead; scope: one constant, one measurement of the runner). B is the only option that changes ledger semantics and should not ride a spec PR.
Found while driving PR #14513 (#14439) to green. Filed for the maintainer because the ceiling is a pinned policy (
CI_TSC_HEAP_CEILING_MB = 4096, #12856) and changing what the program checks changes what the ledger measures.Measured
scripts/check-type-check-coverage.mjs --re-measurebuilds onetsc --noEmitprogram per ledger entry under--max-old-space-size=4096. For thepackages/qa/http-conformanceTEST_DEBT entry (8 source files, 5 of them tests, but importing@objectstack/core,@objectstack/objectql,@objectstack/runtime,@objectstack/plugin-hono-server,@objectstack/driver-sqlite-wasm,@objectstack/spec), the same program shape run with an 8 GB cap and--extendedDiagnostics:main@53d36892(base worktree, closure built)Under the 4096 MB ceiling the program still completes on
main(merge-queueLint & Type Checkruns are green through53d36892and later), but only because V8 collects harder near the limit: a local run on amain-based worktree peaked at 3,961 MB RSS and spent minutes in GC before finishing. The headroom is therefore a few percent, not a margin.PR #14513 showed what that means in practice: a spec change that added 42,622 lines of definitions to this program (the whole
ObjectStackDefinitionSchemadeclaration, pulled in through a new chunk edge — fixed in the PR) moved the count to 4,875,249 K and the lane went red twice. The next spec PR that grows the declaration graph seen by@objectstack/spec/systemwill hit the same wall without having done anything wrong.Options
CI_TSC_HEAP_CEILING_MBto 6144 for the re-measureubuntu-latesthas 7 GB, so 6144 needs a measurement of what else runs in that jobskipLibCheck: truein the re-measure project onlyhttp-conformancetype its tests against narrower entries (it imports whole packages for a handful of names)Not decided here. The four-axis reading favours A with a measured number (long-term consistency: the ceiling exists to make numbers portable, and a ceiling with 3% headroom makes them fragile instead; scope: one constant, one measurement of the runner). B is the only option that changes ledger semantics and should not ride a spec PR.