Skip to content

resolveCheckToFiles matches only .mjs|.cjs|.js|.sh, so all 23 TypeScript-authored gates resolve to ZERO gate files and contribute ZERO watch hints #12107

Description

@yinlianghui

Found while wiring the new check:exported-any-returns gate for #11927 — the new gate landed
invisible, and checking why turned up 22 existing families in the same state.

Measured at 0e0bf8049 plus that card's branch.

The rule

scripts/pm/dispatch-gates.mjs:

exportfunctionresolveCheckToFiles(checkName,scriptsMap){constcmd=scriptsMap[checkName];if(!cmd)return[];return[...newSet([...cmd.matchAll(/(scripts\/[\w./-]+\.(?:mjs|cjs|js|sh))/g)].map((m)=>m[1]))];}

A gate whose npm script names a .ts / .mts / .cts file matches nothing. entry.files stays
empty, so discoverFamilies never opens the source — and everything downstream of opening it is
therefore also empty: no watch hints, no first-party import following, no no-population
marker read, and no entry in the gateFiles set.

The consequence, in the derivation's own terms

Such a family can never be matched for any card. It scores undetermined ("its sources name no
path at all") for every PR in the tree — but the reason is not that its author declined to declare
a population. It is that the declaration was never read. The two are indistinguishable in the
output, which is the same conflation scripts/pm/bare-root-worklist.mjs was built to report on one
level down.

It also silently voids the bare-root sweep for these files: that sweep walks the gate sources
discoverFamilies resolves, so a TypeScript gate is never swept, and --self-test reporting
"none missing" says nothing about it either way.

The 23

Verified by resolving each zero-file family's command back to its script:

gatesource it names
check:generatedscripts/check-generated.ts
check:api-surfacescripts/build-api-surface.ts
check:exported-anypackages/spec/scripts/check-exported-any.ts
check:dual-source-exportspackages/spec/scripts/check-dual-source-exports.ts
check:browser-reachable-entriespackages/spec/scripts/check-browser-reachable-entries.ts
check:skill-examplespackages/spec/scripts/check-skill-examples.ts
check:authorable-surfacescripts/build-schemas.ts
check:docsscripts/build-docs.ts
check:skill-docsscripts/build-skill-docs.ts
check:skill-refsscripts/build-skill-references.ts
check:meta-url-spellingscripts/build-meta-url-spelling.ts
check:spec-changesscripts/build-spec-changes.ts
check:upgrade-guidescripts/build-upgrade-guide.ts
check:export-originsscripts/build-export-origins.ts
check:react-blocksscripts/build-react-blocks-contract.ts
check:template-manifestsscripts/check-template-manifests.ts
check:objectui-pin-citationsscripts/check-objectui-pin-citations.ts
check:llms-txtscripts/check-llms-txt.ts
check:livenessscripts/liveness/check-liveness.mts
check:empty-statescripts/liveness/check-empty-state.mts
check:variant-docsscripts/check-variant-docs.mts
check:strictness-ledgerscripts/check-strictness-ledger.mts
check:exported-any-returnsscripts/check-exported-any-returns.mts (#11927, this card's trigger)

Reproducer:

import{discoverFamilies}from'./scripts/pm/dispatch-gates.mjs';const{ byCheck }=discoverFamilies();console.log([...byCheck].filter(([,e])=>!e.files.length).length,'of',byCheck.size);// → 24 of 166 (23 above + one family whose script is a `pnpm -r` composite)

Two further wrinkles the fix has to decide, not just the extension list

  1. The path is relative to the PACKAGE, not the repo.packages/client's alias reads
    tsx ../../scripts/check-exported-any-returns.mts …, and the package-filter branch of
    discoverFamilies prepends the package's own directory prefix to whatever
    resolveCheckToFiles returns — which would produce packages/client/../../scripts/…. That
    resolves on disk but is not a tracked-path spelling, so it would match nothing in hintCovers
    without a normalisation step. The existing .mjs callers never hit this because they all live
    in the package they serve.
  2. It is a widening, and this repo prices widenings.firstPartyImportTargets' docblock
    measures its own at +893 pairs and states the zero-loss property explicitly. Admitting 23 gate
    sources adds hints AND adds them to gateFiles (which suppresses import-following into those
    files) — a subtraction direction that has to be measured, not argued, the way that docblock
    does it.

⛔ Deliberately not fixed inside #11927: the hint sets are fleet-wide, so re-attributing 23
families' matched lists is a change every open dispatch brief reads, not a rider on a card about
one package's return types.


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