Skip to content

check-test-typecheck.mts offers a shrink-only debt-ledger entry as a co-equal remedy with no authority marker — the #8519 census missed it because it swept only scripts/*.mjs #8538

Description

@qq9340100

Filed by the dev seat implementing #8519 (PR to follow). Unassigned and unlabeled for triage. Same surface as #8519: the gate farm / developer ergonomics.

⚠️ No gate is asked to be weakened. The gate is correct. This is about which remedy its output teaches, exactly as #8435 and #8519 framed it.

The finding

#8519's census reported five live instances of the #8435 shape. Re-running that census from a clean worktree cut from origin/main reproduces all five — and finds a sixth:

scripts/check-test-typecheck.mts:147

`${file}: ${count} type error(s) in a file the ledger does not cover. Fix them — this file is
 inside the checked zone, which is the point of ${PROJECT}. (A deleted `@ts-expect-error`
 shows up exactly here, as TS2578/TS2694.) Only with a reason: add the file to ${LEDGER_NAME}.`

LEDGER_NAME is the per-package test-typecheck-debt.json. It is unambiguously a shrink-only debt ratchet, and this script says so itself in two places:

  • its own LEDGER_COMMENT (line 104): "EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted";
  • its own sibling message 12 lines below: "the ledger only ratchets down".

AGENTS.md calls the same file "the per-file, shrink-only <package>/test-typecheck-debt.json".

So Only with a reason: add the file to test-typecheck-debt.json is the co-equal weakening remedy, unmarked — precisely the #8435 shape.

Why the census missed it — a mechanism, not an oversight

#8519's sweep is stated on the card as covering "all 76 scripts/*.mjs". That count is exactly right and reproduces today. But scripts/ also holds two .mts files, which a *.mjs glob cannot reach:

$ ls scripts/*.mjs | wc -l   ->  76
$ ls scripts/*.mts | wc -l   ->  2

check-test-typecheck.mts is one of them. The miss is structural in the sweep's file filter, so any future census of this convention should glob scripts/*.{mjs,mts} — otherwise it will keep reporting a complete count that is short by whatever lives in the two .mts files.

Other instance kinds this gate has, deliberately NOT counted

For the same reason #8519 listed its exclusions — so a future sweep does not re-litigate them:

  • check-test-typecheck.mts:160"the debt SHRANK, which is the goal. Re-record it so the number stays true". Ratchet down; squarely the author's job.
  • check-test-typecheck.mts:175"it GRADUATED … Delete its entry". Ratchet tightening; the author's job.

Only the line-147 message expands the ledger.

Two borderline cases, recorded rather than counted

Both are exemption maps whose entries bless a violation rather than declare a legal answer, which is closer to the ratchet shape than to the declaration registries #8519 excluded. Neither is mechanically shrink-only (no count, no ratchet direction), and both are documented as Object.create(null) "empty by design", so calling them instances would be a judgment call rather than a measurement. Recording them so triage can rule, not folding them into the count:

  • scripts/check-meta-type-normalized.mjs:271"If a site genuinely must read the raw spelling, add it to EXEMPT".
  • scripts/check-tenant-chokepoint.mjs:544"If a door genuinely must build unscoped, add it to EXEMPT". Note this one blesses a read door that returns other tenants' data, so if any exemption map deserves the marker it is this.

Confirmed not instances on re-measurement (they refuse the weakening remedy outright, which is the stronger check-driver-memory-census.mjs precedent, or offer only the tightening direction): check-query-options-erasure-ratchet.mjs ("The grandfather list is not a mute button"), check-slot-lookup-ratchet.mjs ("the baseline never grows"), check-i18n-coverage.mjs (--update offered only for ratchet-down), check-startup-registry-verdict.mjs and check-durability-degradation.baseline.json's own path (stale-entry deletion only), check-osv-exemptions.mjs. Confirmed declaration registries, entry is the correct fix: check-error-code-casing.mjs EXEMPT_FILES, check-single-authz-resolver.mjs ALLOW, check-skill-compatibility-version.mjs EXEMPT.

Suggested shape (not decided here)

The same copyable block the other five now carry: the greppable ⛔ MAINTAINER-ONLY token on the ledger-expanding line, a detector regex, a pure ratchetRemedyCarriesAuthority() predicate, and non-overlapping self-test assertions. One wrinkle specific to this file: it is TypeScript, run through a different harness than the .mjs gates, so where its self-test assertions live needs checking rather than assuming.

Related: #8435 (established the convention), PR #8517 (covered 2), #8519 (covers 3). #8519 is not addressed here and remains open on its own three gates.


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions