Skip to content

finding(tooling): every generated test-typecheck ledger states a cause that #5543 fixed 18 days ago, and --update overwrites any correction written into the file #12624

Description

@os-litant

Filed unassigned and ungraded while paying down packages/rest's test-typecheck ledger (part of #12573). ⛔ Not graded, not routed. Measured on origin/main @ 527e0505d.

The fact

scripts/check-test-typecheck.mts:107 builds the _comment every ledger carries, interpolating the package name into an otherwise fixed string:

constLEDGER_COMMENT=`Per-file tsc error debt of the ${PKG_NAME} TEST layer (#5286). `+// …'and every file below still carries errors from before that gate existed, '+'almost all of them fixture literals annotated with a schema OUTPUT type (`z.infer`) while holding '+'an authored INPUT literal. EXACT ratchet, …';

Two things follow, and the second is what makes the first hard to notice.

1 · The stated cause is a fossil

That clause is the finding from #5478 / #5543: registerObject's schema parameter was annotated ServiceObject (the z.inferOUTPUT type) instead of ServiceObjectInput, so legal authored literals raised TS2740. #5543 was closed as completed on 2026-08-08 by PR #6786, which dropped the 135 as any that had been dodging it.

packages/rest's ledger was created 18 days later, by PR #12570 on 2026-08-26 — and was stamped with the fixed cause as though it were present tense.

Measured against the ledger's own 12 non-fenced files:

z.infer occurrences: 0 0 0 0 0 0 0 0 0 0 0 0 (all 12 ledgered files)
positive control: 65 `expect` in export-integration.test.ts, 95 in import-integration.test.ts

The zero is a reading, not a broken grep. The 37 errors that ledger actually recorded are four unrelated stories, none of them the named one:

classcountwhat it really is
TS255414registry.registerObject(x) missing the required packageId — see #12623
TS1804813getRoutes().find() is Route | undefined
TS23455request literals missing IHttpRequest's required headers / path
TS70064untyped mock.calls callback parameters
TS61331an unused import

⚠️ I measured this for packages/rest only. packages/spec's 55 entries were not checked against the claim — for that package the clause may well still be accurate, since #5478 is where the wording came from.

2 · The ledger cannot correct itself

check-test-typecheck.mts:258 rebuilds the object from the constant on every --update:

constledger: Ledger={_comment: LEDGER_COMMENT, entries };

So a corrected _comment written into test-typecheck-debt.json survives exactly until the next gen:test-typecheck-debt — which the ratchet requires a dev to run on every repair (a file that loses errors is red until its number is re-recorded). I hit this directly: corrected the prose, re-ran the regenerator, and the refuted claim came back. The one workflow that guarantees the ledger's numbers are honest also guarantees its stated cause cannot be.

Why it is worth fixing rather than shrugging at

The _comment is the first thing a dev picking up a paydown card reads, and it is load-bearing: #12573's dispatch made "test the ledger's own hypothesis before repairing anything" its first ruling precisely because a wrong cause sends the reader file-by-file down the wrong shape. Here it also points at a resolved issue, so a reader who follows it finds a closed card and no obvious next step.

packages/client's ledger is the sharpest case — 0 entries, and it still asserts a cause for the debt it does not have.

Three ledgers carry the identical clause today:

packages/client/test-typecheck-debt.json claim present | entries: 0
packages/rest/test-typecheck-debt.json claim present | entries: 9
packages/spec/test-typecheck-debt.json claim present | entries: 55

Options

  • A. Drop the causal clause from LEDGER_COMMENT entirely. The mechanism sentences (EXACT ratchet, the three red directions, the regenerate command) are the part that is true for every package; the cause never was.
  • B. Keep a causal note but make it per-package — read from the ledger file's existing _comment when one is present, so a package can record what its own debt actually is and a regeneration preserves it.
  • C. Leave it and rely on readers distrusting it. ⛔ Not recommended: the regenerator actively restores it over corrections.

No urgency claimed — no gate reads _comment, so nothing is red and nothing regresses. This is about the prose the ratchet hands its next reader.

Re-check

sed -n '107,116p' scripts/check-test-typecheck.mts
sed -n '255,260p' scripts/check-test-typecheck.mts
for f in packages/*/test-typecheck-debt.json; do echo "$f"; done

Refs

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