Skip to content

[finding] query-options/no-any-erasure's test surface promises a guard tsc cannot deliver — 20 packages exclude **/*.test.ts from their tsconfig #8210

Closed

Description

@os-zhuang

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.

  1. packages/objectql/tsconfig.json carries "exclude": ["node_modules", "dist", "**/*.test.ts"]. Verified directly on origin/main (read by the PM seat, not inferred from a report).
  2. 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 is function), pnpm --filter @objectstack/objectql typecheck exits 0. The type is correct — the same bag in a compiled non-test file yields TS2353: … 'func' does not exist in type '{ function: …; alias: string; … }' — it is simply never read for these files.
  3. 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/objectql sits in TEST_DEBT at 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:

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 --noEmit via each package's typecheck script. 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

  1. hotlong commented on Aug 12, 2026

    @hotlong
    Contributor

    Triage (routing only, held as finding): the two candidate fixes both land on domain:devx surfaces — the check:query-options-erasure gate's stated rationale (scripts/ gate family) and/or the per-package tsconfig test exclusions tracked by TEST_DEBT ⇒ routed domain: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

  2. added theissue type on Aug 12, 2026
  3. hotlong commented on Aug 12, 2026

    @hotlong
    Contributor

    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:

    1. Measure the ESLint question first (the card's flagged unknown): is a type-aware ESLint program checking the excluded test files? The finding narrows or widens on that answer — report the reading either way.
    2. Update query-options/no-any-erasure's rule prose / rationale so the test-surface half states the real benefit where tsconfig excludes apply (removes an any that blinds whatever IS type-aware; precondition for the day the exclusion lifts) instead of promising a tsc catch it cannot deliver there.
    3. Optionally intersect the ratchet's file list with the 20 excluded packages and record the split in the rule doc — that makes the gap inspectable instead of rediscoverable.

    ⛔ 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_DEBT has its own plan).

    Size/model suggestion: S–M, sonnet (step 1 is a measurement, steps 2–3 are prose).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions