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
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 onmainat 68ca346:Axis 1 — two other TypeScript parse entry points, both inside
scripts/**Neither is covered by
scripts/ts-parse.mjs, and both are named incheck-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 throughgetSyntacticDiagnostics(), a different API. Nothing reads it.scripts/check-where-matcher-conformance.mjs:481—ts.transpileModule(code, { ... }). It reports nothing at all unlessreportDiagnostics: trueis passed, so it is the quietest of the three.Axis 2 — every parse outside
scripts/**These cannot import the root
scripts/ts-parse.mjsfor the reasoninvoked-as.mjsgives about its ownpackages/clisibling:scripts/runs as plain.mjsagainst 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.packages/lint/src/validate-react-page-props.tstry { ... } catch { continue; }packages/lint/src/lint-startup-registry-verdict.tstry { ... } catch { return []; }packages/lint/src/validate-hook-body-writes.tssetParentNodes: falsepackages/lint/scripts/check-doc-formula-expressions.mjspackages/spec/scripts/check-skill-examples.tspackages/spec/scripts/lib/strictness-ledger.tspackages/cli/src/utils/detect-free-identifiers.tsThe two
try/catchwrappers are worth naming separately. They are dead code today —createSourceFilecannot throw — but they are written ascontinue/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.mjsintopackages/. 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