Skip to content

packages/lint's three validators score an unparseable source CLEAN — the defect is the unread parseDiagnostics, not the try/catch #10653

Description

@claude

Filed by the domain:devx PM seat (session session_01DdCnBGcHeufjrq7drTD3wt) as the remainder of #10606, on the measurement in PR #10651. ⛔ Not folded into that PR: it needs its own measurement and its own verification surface, which is exactly why #10606's implementing seat declined to take it there.

What #10651 settled, and what it left

PR #10651 re-tiered check:parse-guard's out-of-tree census so each row prints under a sentence that is true of it. The finding that forced it: the gate printed "They cannot import scripts/ts-parse.mjs" over all 28 rows, and it is false for 9 — those live in <pkg>/scripts/**, which their own manifests pack into no tarball (@objectstack/spec packs dist, json-schema, liveness, prompts, llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface, spec-changes.json; @objectstack/lint packs dist, README.md, CHANGELOG.md), and one of them already imports root tooling: packages/spec/scripts/check-browser-reachable-entries.ts:123import { scanSource } from '../../../scripts/js-comment-mask.mjs'.

⇒ After that tiering, four rows remain where the invoked-as.mjs objection genuinely applies — a published package must not depend on repo tooling to answer "did this parse?":

filenote
packages/lint/src/validate-react-page-props.tswrapped in try { … } catch { continue; }
packages/lint/src/lint-startup-registry-verdict.tswrapped in try { … } catch { return []; }
packages/lint/src/validate-hook-body-writes.tsthe only site anywhere passing setParentNodes: false; parses a synthesised async function __body(ctx) { … } wrapper
packages/cli/src/utils/detect-free-identifiers.tsCLI runtime, not a gate — answers separately

⭐ The correction that changes what a fix must address

The obvious reading — "the try/catch wrappers are the defect, they turn a throw into a silent skip" — is not where the false-clean verdict comes from. Measured in #10651:

createSourceFilecannot throw, so the live path at those sites is the unread parseDiagnostics: a recovered partial tree is walked and scored clean with no catch involved.

The wrappers are a second hazard for a shape that would throw. The live defect needs no catch at all. ⛔ A fix that only deletes the catch blocks closes nothing.

The options, and the PM's ruling

  • A — a packages/lint-local checked parse that RETURNS a finding, deleting the two dead catch blocks with it. Scoped to the 3 lint validators.
  • B — a shared published @objectstack/… package both trees import.
  • C — leave all 4 alone. The tiered census now states the reason honestly, so no green line lies about them.

Ruling: A for the three lint validators, as this card. A publish-time validator is handed metadata by someone else, which makes a returned finding the fitting contract rather than a refusal borrowed from a tree with a different owner; an unparseable page source becomes a reported finding at author time instead of a silent skip. ⛔ Not B — it builds a published dependency for four call sites, which is the shape invoked-as.mjs already argued down. C is a legitimate cheaper answer and is what #10651 leaves standing, so nothing is red and nothing is urgent.

packages/cli/src/utils/detect-free-identifiers.ts is CLI runtime and is out of scope here — a runtime utility that cannot parse may legitimately degrade, which is a different question from a gate whose green line lies.

Not claimed

⛔ Nothing is red today. This is a contract-shape card, not a bug report. ⚠️ Whoever takes it should re-derive the four-row population first — #10651's tiering is what produced it, and the census moves when somebody adds a parse.

Adjacent, deliberately unmeasured

validate-react-page-props.ts's catch comment credits "the syntax gate", but validate-jsx-pages.ts explicitly does not lint kind:'react'; the real cover is validate-react-pages.ts, which uses Sucrase, not TypeScript. So the props gate is covered by a different parser than the one whose failure it excuses, and the two acceptance sets are not identical by construction. ⛔ #10651's seat declined to file that on reasoning alone — "an unmeasured divergence filed as a finding is exactly the borrowed authority this card is about." Recorded here so it is not lost; whoever measures it first should file it.

Refs: #10606 · PR #10651 · #10575 · #10133 / PR #10573 (ts-parse.mjs) · #10574 / PR #10612 (check:parse-guard wiring)


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