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:
| class | count | what it really is |
|---|
TS2554 | 14 | registry.registerObject(x) missing the required packageId — see #12623 |
TS18048 | 13 | getRoutes().find() is Route | undefined |
TS2345 | 5 | request literals missing IHttpRequest's required headers / path |
TS7006 | 4 | untyped mock.calls callback parameters |
TS6133 | 1 | an 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
Filed unassigned and ungraded while paying down
packages/rest's test-typecheck ledger (part of #12573). ⛔ Not graded, not routed. Measured onorigin/main@527e0505d.The fact
scripts/check-test-typecheck.mts:107builds the_commentevery ledger carries, interpolating the package name into an otherwise fixed string: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'sschemaparameter was annotatedServiceObject(thez.inferOUTPUT type) instead ofServiceObjectInput, so legal authored literals raisedTS2740. #5543 was closed as completed on 2026-08-08 by PR #6786, which dropped the 135as anythat 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:
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:
TS2554registry.registerObject(x)missing the requiredpackageId— see #12623TS18048getRoutes().find()isRoute | undefinedTS2345IHttpRequest's requiredheaders/pathTS7006mock.callscallback parametersTS6133packages/restonly.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:258rebuilds the object from the constant on every--update:So a corrected
_commentwritten intotest-typecheck-debt.jsonsurvives exactly until the nextgen: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
_commentis 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:
Options
LEDGER_COMMENTentirely. 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._commentwhen one is present, so a package can record what its own debt actually is and a regeneration preserves it.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
Refs
packages/rest's new 37-error test-typecheck ledger — 13 of them are one class in one file, and 14 more look like one call-signature story across five #12573 — the paydown card whose ruling 1 required testing this claim; 0 of 33 matchedSchemaRegistry.registerObjectrequirespackageIdwhile its siblingregisterItemdeclares it optional — 14 ledgered TS2554 in packages/rest and 68 identical call sites in packages no tsc program reads #12623 — what the largest remaining class actually is@ts-expect-error退役 pin 不再是幽灵检查 #5478 / objectqlregisterObject的参数标成 schema 的 OUTPUT 类型(z.infer),合法的作者态字面量一律 TS2740 —— 这是 spec/client 两份测试层欠账的同一根因 #5543 / PR #6786 — where the clause came from, and where its cause was fixed@ts-expect-error退役 pin 在packages/spec里是幽灵检查:tsconfig 把**/*.test.ts排除出唯一的tsc --noEmit#5286 /packages/resthas NO tsc program that compiles any test file — 149 test files unchecked, and AGENTS.md names this exact shape as how a@ts-expect-errorbecomes a phantom check #12542 / PR #12570 — the mechanism and this ledger's creation