Skip to content

[finding] "no ledger entry is stale" in lint-startup-registry-verdict.corpus.test.ts is green by construction while LEDGER is empty — the one case in that file with no standing non-vacuity proof #10913

Description

@claude

The observation

packages/lint/src/lint-startup-registry-verdict.corpus.test.ts is explicit, in its own header, that a ratchet which has only ever been green cannot be told apart from a dead one (#4690), and it carries a standing proof for that: the sweep can still fire pushes a known-bad source through the same sweep function the corpus goes through.

That proof covers the sweep. It does not cover the file's second corpus case.

constLEDGER: Readonly<Record<string,string>>={};// deliberately empty
...
it('no ledger entry is stale',()=>{constlive=newSet(findings.map((f)=>`${f.path}::${f.rule}`));conststale=Object.keys(LEDGER).filter((key)=>!live.has(key));expect(stale, ...).toEqual([]);});

With LEDGER empty, Object.keys(LEDGER) is [] and stale is [] for every possible corpus and every possible findings set. The case cannot fail, and its verdict does not depend on the sweep at all — the value of live is never consulted. So of the two corpus cases in that file, one has a standing non-vacuity proof and the other is green by construction.

This is not an argument that the case is wrong. The empty ledger is deliberate and documented ("the non-vacuity proof is the the sweep can still fire case below, not the emptiness of this list") — that sentence is true of the sweep case and does not reach this one.

Evidence it can fire

Measured during the ablation for PR #10911: planting one LEDGER key that no live finding produces reds this case alone, with the intended message, while the other corpus case stays green.

× no ledger entry is stale
→ stale LEDGER entr(ies) — the site is fixed, delete the line:
packages/ablation/src/gone.ts:1::startup-open-vocabulary-verdict:
expected [ Array(1) ] to deeply equal []

That proof exists in a PR body. Nothing re-runs it, so it decays the moment the comparison changes shape.

Possible shapes (not prescribed)

  1. Give the staleness comparison the same treatment the sweep already has: lift it into a small pure function (stale(ledgerKeys, liveKeys)), have the real case call it, and add a non-vacuity case that pushes a known-stale pair through the same function. This mirrors the existing the sweep can still fire design exactly.
  2. Decide the case is acceptably vacuous while the ledger is empty and say so in the file, so the next reader does not have to re-derive it. This is a legitimate answer — it costs nothing and the case becomes live the moment anyone adds a ledger entry — but it should be a written decision rather than a silence.

Deliberately not proposed: adding a LEDGER entry to make it live. That list is shrink-only and hand-reviewed by design.

Scope

Filed unassigned per findings discipline. Not fixed in #10911 (the corpus-sweep cost and budget card): different defect class, and shape 1 vs 2 above is a decision rather than a mechanical repair. #10911 does make the case fail loudly if the shared sweep never runs, but that is a different invariant from the one described here.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions