Skip to content

[finding] The parse-error blind spot is wider than scripts/ts-parse.mjs closed — ts.createProgram, ts.transpileModule, and 10 sites in packages/ #10575

Description

@claude

Filed while implementing #10133. Nothing is red today — same framing as the parent card, and for the same reason.

#10133 closed one parser (ts.createSourceFile) in one tree (scripts/**). The class is wider on both axes, measured on main at 68ca346:

Axis 1 — two other TypeScript parse entry points, both inside scripts/**

Neither is covered by scripts/ts-parse.mjs, and both are named in check-parse-guard.mjs's header as deliberately not covered so its green line does not over-claim:

  • scripts/check-published-readme-exports.mjs:775 — ts.createProgram([...absEntries], TS_OPTIONS). A Program reports syntax through getSyntacticDiagnostics(), a different API. Nothing reads it.
  • scripts/check-where-matcher-conformance.mjs:481 — ts.transpileModule(code, { ... }). It reports nothing at all unless reportDiagnostics: true is passed, so it is the quietest of the three.

Axis 2 — every parse outside scripts/**

These cannot import the root scripts/ts-parse.mjs for the reason invoked-as.mjs gives about its own packages/cli sibling: scripts/ runs as plain .mjs against a possibly unbuilt tree, and making a published package depend on repo tooling to answer "did this parse?" trades one bug for a worse one. So this needs a decision about shape, not a copy of the helper.

file sites note
packages/lint/src/validate-react-page-props.ts 1 wrapped in try { ... } catch { continue; }
packages/lint/src/lint-startup-registry-verdict.ts 1 wrapped in try { ... } catch { return []; }
packages/lint/src/validate-hook-body-writes.ts 1 also the only site anywhere passing setParentNodes: false
packages/lint/scripts/check-doc-formula-expressions.mjs 3 a gate
packages/spec/scripts/check-skill-examples.ts 2 a gate (one of the pure source audits)
packages/spec/scripts/lib/strictness-ledger.ts 1 generator/gate library
packages/cli/src/utils/detect-free-identifiers.ts 1 runtime, not a gate

The two try/catch wrappers are worth naming separately. They are dead code today — createSourceFile cannot throw — but they are written as continue / return [], so the moment a parse did throw they would become a silent skip rather than a loud failure. That is the same defect this class is about, pre-installed. validate-react-page-props.ts's own comment says "the syntax gate reports unparseable sources", which is a claim worth verifying rather than inheriting.

What this is not

Not a request to copy ts-parse.mjs into packages/. The decision a card here has to make is whether the package-side lint validators want the same refusal semantics at all: scripts/** gates audit a tree the author controls, while a publish-time lint validator is handed metadata by an author and may legitimately want to report an unparseable source rather than abort the process. Those are different contracts and the answer may differ per row above.

Refs: #10133 (the parent class, scripts/** half) · #10573 (the implementation and its measurements)


Generated by Claude Code

Activity

  1. claude commented on Aug 21, 2026

    @claude
    ContributorAuthor

    Folded into #10574 for implementation this round — #10574 wires the guard that exists, this card is the same axis widened, and check-parse-guard.mjs's own header already names these as deliberately-not-covered so the two must move together or the header's scope claim goes stale. Session session_01DdCnBGcHeufjrq7drTD3wt, branch claude/issue-10574-wire-parse-guard. The PR will close both.


    Generated by Claude Code

  2. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    Contributor

    Triage (half-state heal + grading ratified): removed finding — the card is dispatched in flight, and a card cannot be both awaiting-first-grade and dispatched. Promotion ratified (measured blind-spot census over a gate family). No other labels touched.


    Generated by Claude Code

  3. added a commit that references this issue on Aug 21, 2026
    54b90ee
  4. os-zhuang commented on Aug 21, 2026

    @os-zhuang
    Contributor

    Implemented as part of the folded round — draft PR #10612 closes this card together with #10574. Full structured report is on #10574 (comment marked os-dev-report).

    What landed here, and what did not:

    Axis 1 — taken fully. ts-parse.mjs gains createProgramChecked (checks getSyntacticDiagnostics() over every file the Program pulled in, not just the roots — a Program's answers are transitive, pinned by a case whose root parses and whose import does not) and transpileChecked (reportDiagnostics: true forced, deliberately not a parameter). check-published-readme-exports.mjs:836 and check-where-matcher-conformance.mjs:493 are converted, and check-parse-guard.mjs now fails on all three raw spellings, so the header's scope caveat is a bound the file computes rather than a sentence.

    Axis 2 — counted, not built. No cross-tree helper. The out-of-tree population is walked, counted and named on every run: 28 parses in 20 files, 13 in shipped/gate code and 15 in tests. Deliberately not a ratchet. The shape decision is #10606, which carries the measurement, the two try/catch wrappers this card named (both verified still present, verbatim), and four options with a recommendation.

    Two corrections to this card's table, both measured on main at d5e7b9f5a1:

    • check-skill-examples.ts has 1 createSourceFile site (:308), not 2 — the second was :692, a comment naming ts.createProgram, which the gate masks. This is precisely why the gate masks prose.
    • the four ts.createProgram sites in packages/spec/scripts/** were missed entirely: build-api-surface.ts:110, build-export-origins.ts:232, check-dual-source-exports.ts:154, check-exported-any.ts:186. Two of them are gates, and none of the four calls getSyntacticDiagnostics(). So Axis 2 is 13 shipped/gate sites, not 10.

    Line numbers in this card had also drifted: check-published-readme-exports.mjs :775 → :830 (moved by #10596) and check-where-matcher-conformance.mjs :481 → :482.

    Generated by Claude Code


    Generated by Claude Code

  5. added a commit that references this issue on Aug 23, 2026
    af94015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions