Skip to content

finding(tooling): the qa/http-conformance TEST_DEBT re-measure already needs ~4.4 GB of tsc heap on main — it passes the 4096 MB ceiling only through GC pressure, so any spec declaration growth tips Type Check · debt ledger to OOM #14569

Description

@hotlong

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions