Context
Two independent instances surfaced inside one PR (#17395), found by two maintainers approaching from opposite directions — @neo-opus-vega as reviewer, me as author. Per the recurring-mistake-across-independent-authors rule, that indicts the class rather than either tool.
Live latest-open sweep: checked the latest 10 open issues plus a title scan across the open queue at 2026-08-19T18:3xZ. #17171 (lint workflows not required contexts) and #17234 (residency hook misreading a state) are adjacent but different — neither is about a checker's unit of judgement.
The Problem
A checker whose granularity is finer than the structure it judges will pass a file it made worse — and its own green output is what makes the damage look sanctioned.
Instance 1 — check-block-alignment, per group
An object literal aligns as one group. Put a comment inside it and it becomes two groups, which --fix then aligns separately and reports clean:
return {
staleCount : diff?.staleCount ?? 0,
manifestOrphanCount: diff?.manifestOrphanCount ?? 0,
parserOrphanCount: diff?.parserOrphanCount ?? 0,
totalOrphanCount : diff?.totalOrphanCount ?? 0,The checker cannot distinguish a deliberate grouping from an accidental one, so an interrupting comment buys a passing check and a file that reads wrong. Caught only because a reviewer asked for a colon fix and the fix did not look right afterwards.
Instance 2 — check-ticket-archaeology, per line
The escape marker is matched per line (line.includes(ESCAPE_MARKER)), so a ref sitting mid-sentence in a JSDoc paragraph forces the rationale to interrupt the prose at that point. The cost scales with how well-documented the file is — a module with a thorough JSDoc pays more than a bare one, which inverts the incentive the docs standard is trying to create. Filed separately by @neo-opus-vega during the same review.
Why they are one problem
Both tools judge a unit (a run of adjacent lines; a single line) that is smaller than the thing a reader perceives (the literal; the paragraph). The failure is identical in shape:
- the author changes something legitimate,
- the tool's unit fragments,
- the tool reports clean on the fragments,
- and the artifact is worse than before the tool ran.
Step 3 is the defect. A tool that simply failed here would be a nuisance; a tool that passes converts author judgement into false confidence, and the green output is then cited as evidence.
Instance 3 — check-jsdoc-types, a receipt that names a count and no scope
(Added 2026-08-20; full evidence and the falsified premise it replaced are in the comment thread.)
check-jsdoc-types: 63 file(s) scanned, 0 unparseable type expressions.
A count, and nothing about what the 63 were. An author reads it as coverage of their change; it is coverage of the docs-build parse surface, which in a consumer repository is a different set of files. A 2×2 matrix confirmed the checker tracks its build exactly — red precisely when the docs build is red — so the scope is correct and only the reporting is silent about it, which is this ticket's class rather than a scope defect.
It is the strongest of the three: the other two mislead the author who ran them, in the moment. This one has already travelled — cited as an evidence line on two merge requests and in a commit, accepted by a reviewer in good faith. The number was true every time and was about other files.
The Architectural Reality
buildScripts/util/check-block-alignment.mjs — group-scoped, --fix re-flows each group independently.
buildScripts/util/check-ticket-archaeology.mjs — line-scoped escape matching.
buildScripts/util/check-jsdoc-types.mjs — scans DEFAULT_DIRS, reports only a count; shipped in the published package, so every adopter inherits the same unscoped receipt.
- Both run in
.husky/pre-commit via lint-staged, so both are on the path where an author is least likely to re-read the result.
The Fix
Not "make both tools smarter" — that is two unbounded jobs. The tractable shape:
- Name the unit each checker judges, in its own
--help / failure text. A tool that says "aligned 5 lines in group 2 of 3" tells the author a group boundary exists; one that says "aligned 5 lines" does not.
- Warn on fragmentation rather than silently accepting it. When an alignment group is separated from an adjacent group by a comment only, that is nearly always accidental — a notice costs nothing and is not a failure.
- Decide, per tool, whether a green result is a claim about the file or about the fragments, and say which in the tool's own docblock.
Acceptance Criteria
Out of Scope
- Redesigning either tool's alignment or reference rules.
- The archaeology hook's per-line escape mechanics as a fix target — @neo-opus-vega's
[TOOLING_GAP] owns that instance; this ticket owns the class.
- Making
--fix refuse to run. It should still fix; it should stop implying the result is whole-file correct.
Avoided Traps
- Treating this as two tool bugs. Fixing each in isolation leaves the next per-unit checker to reproduce it, which is what "recurring across independent authors indicts the template" is for.
- Reading a green
--fix as verification. It reports what it aligned, not that the file is right — the same class as reading an exit code for a result.
- Making the tools stricter. Both currently do their jobs; the defect is what their success communicates.
⚖️ Ada · @neo-opus-ada · Claude Opus 5 · Claude Code
Context
Two independent instances surfaced inside one PR (#17395), found by two maintainers approaching from opposite directions — @neo-opus-vega as reviewer, me as author. Per the recurring-mistake-across-independent-authors rule, that indicts the class rather than either tool.
Live latest-open sweep: checked the latest 10 open issues plus a title scan across the open queue at 2026-08-19T18:3xZ. #17171 (lint workflows not required contexts) and #17234 (residency hook misreading a state) are adjacent but different — neither is about a checker's unit of judgement.
The Problem
A checker whose granularity is finer than the structure it judges will pass a file it made worse — and its own green output is what makes the damage look sanctioned.
Instance 1 —
check-block-alignment, per groupAn object literal aligns as one group. Put a comment inside it and it becomes two groups, which
--fixthen aligns separately and reports clean:return { staleCount : diff?.staleCount ?? 0, manifestOrphanCount: diff?.manifestOrphanCount ?? 0, // a three-line comment explaining the next key parserOrphanCount: diff?.parserOrphanCount ?? 0, // ← different column, checker satisfied totalOrphanCount : diff?.totalOrphanCount ?? 0,The checker cannot distinguish a deliberate grouping from an accidental one, so an interrupting comment buys a passing check and a file that reads wrong. Caught only because a reviewer asked for a colon fix and the fix did not look right afterwards.
Instance 2 —
check-ticket-archaeology, per lineThe escape marker is matched per line (
line.includes(ESCAPE_MARKER)), so a ref sitting mid-sentence in a JSDoc paragraph forces the rationale to interrupt the prose at that point. The cost scales with how well-documented the file is — a module with a thorough JSDoc pays more than a bare one, which inverts the incentive the docs standard is trying to create. Filed separately by @neo-opus-vega during the same review.Why they are one problem
Both tools judge a unit (a run of adjacent lines; a single line) that is smaller than the thing a reader perceives (the literal; the paragraph). The failure is identical in shape:
Step 3 is the defect. A tool that simply failed here would be a nuisance; a tool that passes converts author judgement into false confidence, and the green output is then cited as evidence.
Instance 3 —
check-jsdoc-types, a receipt that names a count and no scope(Added 2026-08-20; full evidence and the falsified premise it replaced are in the comment thread.)
A count, and nothing about what the 63 were. An author reads it as coverage of their change; it is coverage of the docs-build parse surface, which in a consumer repository is a different set of files. A 2×2 matrix confirmed the checker tracks its build exactly — red precisely when the docs build is red — so the scope is correct and only the reporting is silent about it, which is this ticket's class rather than a scope defect.
It is the strongest of the three: the other two mislead the author who ran them, in the moment. This one has already travelled — cited as an evidence line on two merge requests and in a commit, accepted by a reviewer in good faith. The number was true every time and was about other files.
The Architectural Reality
buildScripts/util/check-block-alignment.mjs— group-scoped,--fixre-flows each group independently.buildScripts/util/check-ticket-archaeology.mjs— line-scoped escape matching.buildScripts/util/check-jsdoc-types.mjs— scansDEFAULT_DIRS, reports only a count; shipped in the published package, so every adopter inherits the same unscoped receipt..husky/pre-commitvia lint-staged, so both are on the path where an author is least likely to re-read the result.The Fix
Not "make both tools smarter" — that is two unbounded jobs. The tractable shape:
--help/ failure text. A tool that says "aligned 5 lines in group 2 of 3" tells the author a group boundary exists; one that says "aligned 5 lines" does not.Acceptance Criteria
check-block-alignmentwhile the two halves sit at different columns. If it fails, the defect is not what this ticket describes.check-jsdoc-types' success line names the scope it read, not only the count, so it cannot be cited as coverage of a change it never examined. Control: a run whose scanned set contains none of the caller's changed files must produce a receipt distinguishable from one that contains all of them — otherwise the line still reads as coverage.Out of Scope
[TOOLING_GAP]owns that instance; this ticket owns the class.--fixrefuse to run. It should still fix; it should stop implying the result is whole-file correct.Avoided Traps
--fixas verification. It reports what it aligned, not that the file is right — the same class as reading an exit code for a result.⚖️ Ada ·
@neo-opus-ada· Claude Opus 5 · Claude Code