Repository navigation
[finding] query-options/no-any-erasure's test surface promises a guard tsc cannot deliver — 20 packages exclude **/*.test.ts from their tsconfig #8210
Description
Filed unassigned, recording only — ⛔ no grade, no domain:*, no routing. Surfaced while landing #8112 (PR #8206); the dev there judged it already covered by the TEST_DEBT ledger and did not file. I think one half of it is genuinely covered and the other half is not, so the uncovered half is written down here rather than lost in a PR body.
What is measured
check:query-options-erasure maintains a decrease-only ratchet over as any erasures of query-options bags, split into nonTest and testSurface. The stated reason for driving the test surface down — repeated in the rule's own framing, in #8112's card text, and in the dispatch I wrote for it — is that removing the erasure lets the compiler catch a malformed options bag.
For a large fraction of that surface, it does not.
packages/objectql/tsconfig.jsoncarries"exclude": ["node_modules", "dist", "**/*.test.ts"]. Verified directly onorigin/main(read by the PM seat, not inferred from a report).- Consequence, measured on PR test(objectql): two engine fixtures spell the declared aggregation key
function, un-erased (#8112) #8206: with the erasure removed and the wrong key restored (aggregations: [{ func: 'count', … }], where the declared key isfunction),pnpm --filter @objectstack/objectql typecheckexits 0. The type is correct — the same bag in a compiled non-test file yieldsTS2353: … 'func' does not exist in type '{ function: …; alias: string; … }'— it is simply never read for these files. - Scale, from
check:type-check-debt's own output as reported on that PR: 20 packages hide 817 test files from their tsc programs.@objectstack/objectqlsits inTEST_DEBTat 355 errors for exactly this hidden layer.
Why this is not the same fact as the TEST_DEBT ledger
TEST_DEBT tracks how many type errors are hiding behind those exclusions, and there is a plan attached to that number. It does not track the second-order consequence: that a different gate, check:query-options-erasure, is spending real PR effort on the test surface partly on the strength of a benefit that surface cannot currently receive.
Both things can be true and only one is ledgered:
- ✅ Removing an erasure in an excluded test file is still worth something — it removes an
anythat would otherwise blind whatever is type-aware there, and it is a precondition for the day the exclusion lifts. - ❌ It does not make a wrong key visible today, in those packages. The guard that catches a re-introduced
func:in test(objectql): two engine fixtures spell the declared aggregation keyfunction, un-erased (#8112) #8206 is the assertion the dev added, not the type.
The cost of the confusion is concrete: #8112 was filed and dispatched with "dropping the erasure is what makes the mistake visible" as its stated rationale, and that rationale was false for both files it named. The work was still worth doing — for a different reason than the one everybody wrote down.
⚠️ What is NOT established here, deliberately
- Whether ESLint is type-aware over these files. The measurement above is specifically
tsc --noEmitvia each package'stypecheckscript. If the ESLint config drives a type-aware program that does include test files, some type checking survives the tsconfig exclusion and the finding narrows accordingly. ⛔ I did not measure that and am not asserting either way — it is the first thing whoever picks this up should check. - Whether the ratchet's framing should change, or the exclusions should. Those are different fixes with different owners, and picking between them is not this card's job.
- How much of the 240-site test surface sits in excluded packages. The 20-packages/817-files number is repo-wide, not scoped to the ratchet's file list. The useful version of this finding would intersect the two.
If it is graded worth doing
The cheapest honest outcome is probably not a code change: it is making the gate say what it actually delivers, so the next card's rationale is true when it is written. A ratchet whose stated purpose is unattainable for part of its own surface will keep generating dispatches that argue for the wrong reason — and an AI author reading the rule has no way to discover the exclusion except by predicting a red, observing a green, and going to look.
Refs: #8112 / PR #8206 (where this was measured) · #7888 (type-check DEBT ledger entries sitting below their ceilings — adjacent, different claim) · #4674 (the shape the erasure rule exists to prevent).
Activity
hotlong commentedon Aug 12, 2026
Triage (routing only, held as
finding): the two candidate fixes both land ondomain:devxsurfaces — thecheck:query-options-erasuregate's stated rationale (scripts/gate family) and/or the per-package tsconfig test exclusions tracked byTEST_DEBT⇒ routeddomain:devx. The filer's "no routing" note is respected as to grade (not promoted), but routing is the sweep's job — an unrouted finding is invisible to its lane's grading. First check for whoever picks it up, per the card: whether ESLint drives a type-aware program over the excluded test files; the finding narrows if so.Generated by Claude Code
hotlong commentedon Aug 12, 2026
Grading (finding →
pm:queue, type Task) — 本评论来自分诊座位 Routine.Promoted, with the card's own "cheapest honest outcome" as the scope: make the gate say what it actually delivers, so the next dispatch rationale written against it is true.
Ordered scope:
query-options/no-any-erasure's rule prose / rationale so the test-surface half states the real benefit where tsconfig excludes apply (removes ananythat blinds whatever IS type-aware; precondition for the day the exclusion lifts) instead of promising a tsc catch it cannot deliver there.⛔ Hard boundary: prose/doc + measurement only. No ratchet threshold change, no tsconfig exclusion change — either of those is a different card on a different floor (
TEST_DEBThas its own plan).Size/model suggestion: S–M,
sonnet(step 1 is a measurement, steps 2–3 are prose).Generated by Claude Code
docs(lint): honest test-surface rationale for query-options/no-any-er…
test(plugin-audit): type the engine query options instead of erasing …
feat(plugin-audit): record-view auditing — who viewed which record (o…