@@ -2703,6 +2703,71 @@ export function coveringJobFilter(entry, inputPath) {
27032703 * still matches through that constant while a card editing the GATE FILE
27042704 * matches through identity. They answer different inputs.
27052705 *
2706+ * ## The FIFTH key this file measured and REFUSED: the module a gate IMPORTS (#13126)
2707+ *
2708+ * `firstPartyImportTargets` already follows a gate's `./sibling.mjs` import —
2709+ * but only to inherit that module's HINTS, which answers "what population does
2710+ * this gate watch, once you count what its helper watches". The same edge
2711+ * answers a second question, and it is identity-shaped: *if I edit this helper,
2712+ * which gate can I break?* None of the four keys above reaches it. A module is
2713+ * not the family's own file, not a `paths:` pattern, not a job filter, and its
2714+ * own path is not a literal the gate spells.
2715+ *
2716+ * The gap is real and was measured over the live tree, 183 families x 7347
2717+ * tracked files:
2718+ *
2719+ * (family, imported module) pairs 273
2720+ * ...another key already answers 41 15%, mostly a `scripts/**` hint
2721+ * a gate declares for other reasons
2722+ * ...NOVEL, no key reaches them 232 swept over the whole corpus with
2723+ * the candidate key consulted LAST:
2724+ * ADDED 232, RE-ATTRIBUTED 0, LOST 0
2725+ *
2726+ * So the key would be additive by construction, the way #13000's is, and it is
2727+ * still refused. The reason is PRECISION and the numbers are not close. #13000
2728+ * bought its class for 5 novel leads on this same corpus; this one costs 232,
2729+ * and 201 of the 232 (87%) land on five shared utilities that nearly every gate
2730+ * links:
2731+ *
2732+ * scripts/invoked-as.mjs a card that names 14 families names 118
2733+ * scripts/import-prerequisite.mjs 14 -> 55
2734+ * scripts/ts-parse.mjs 13 -> 37
2735+ * scripts/js-comment-mask.mjs 17 -> 38
2736+ * scripts/workspace-enumerator.mjs 12 -> 23
2737+ *
2738+ * Every one of those leads is TRUE — editing `invoked-as.mjs` really can turn
2739+ * all 118 red. A 118-gate list is still the failure this file's header names:
2740+ * the dev who gets one stops reading it, which ends exactly where a list that
2741+ * omits the one gate that matters ends. The tail is the opposite shape and is
2742+ * the half worth having — 21 modules carrying 31 pairs, the median card moving
2743+ * from 14 families to 15 — and the ONLY property separating the two halves is
2744+ * fan-in. This file draws its lines on provenance rather than on volume
2745+ * (`firstPartyImportTargets` says so where it refuses an imported gate file),
2746+ * and a fan-in cut has no provenance to state: `invoked-as.mjs` and
2747+ * `dispatch-gates.mjs` are the same KIND of edge, one link apart.
2748+ *
2749+ * Two narrowings were measured and neither earns it either:
2750+ *
2751+ * importer is a `--self-test` family 12 novel pairs, but 8 of the 12 are
2752+ * `<- invoked-as.mjs`, and the line is
2753+ * the INHERITANCE narrowing borrowed for
2754+ * the question #11556 / #11511 settled
2755+ * separately — identity is not that
2756+ * target is not itself a gate file 63 novel pairs, and it still takes an
2757+ * `import-prerequisite.mjs` card to 55
2758+ *
2759+ * What the refusal COSTS is a live missing lead, and it is named rather than
2760+ * implied: `scripts/pm/bare-root-worklist.mjs --self-test` statically imports
2761+ * THIS file, and a card editing this file derives 14 families without naming
2762+ * it. That gate gets run by hand. The miss costs one CI round, which is the
2763+ * side this file's header errs on everywhere, and it is a far smaller cost than
2764+ * the 118-lead card the general key prints for the module all 118 import.
2765+ *
2766+ * Two shapes make 232 a LOWER bound rather than an exact size, both already
2767+ * refused upstream for their own measured reasons: a dynamic `import()` of a
2768+ * `scripts/` module (3 live family-module pairs) and a relative target outside
2769+ * `scripts/` (3, all `eslint.config.mjs`).
2770+ *
27062771 * Returns `{ key, via }` — `via` is the provenance label the output prints, so
27072772 * a lead can never be read as the wrong kind of claim.
27082773 */
@@ -6760,6 +6825,80 @@ function selfTest() {
67606825 subtracted.length === 0,
67616826 );
67626827
6828+ // ── The refused fifth key, kept honest (#13126) ────────────────────────────
6829+ // `coveringKey`'s docblock refuses an IDENTITY key over these same import
6830+ // edges, and that refusal is a MEASUREMENT rather than a preference: it holds
6831+ // only while the class stays concentrated in the shared utilities nearly
6832+ // every gate links. Prose cannot notice the tree flattening under it, so the
6833+ // price is re-derived here on every run and asserted. A red in this block is
6834+ // not a broken derivation — it says the refusal is due a re-pricing.
6835+ const importClassFamilies = [...discoverFamilies().byCheck];
6836+ const importClassEdges = new Map();
6837+ for (const [check, e] of importClassFamilies) {
6838+ const edges = new Set();
6839+ for (const f of e.files ?? []) {
6840+ if (!existsSync(join(ROOT, f))) continue;
6841+ for (const mod of firstPartyImportTargets(f, readFileSync(join(ROOT, f), 'utf8'))) {
6842+ if ((e.files ?? []).includes(mod)) continue;
6843+ edges.add(mod);
6844+ }
6845+ }
6846+ importClassEdges.set(check, edges);
6847+ }
6848+ const importNovel = [];
6849+ let importCoveredElsewhere = 0;
6850+ for (const [check, e] of importClassFamilies) {
6851+ for (const mod of importClassEdges.get(check) ?? []) {
6852+ if (coveringKey(e, mod)) importCoveredElsewhere++;
6853+ else importNovel.push([check, mod]);
6854+ }
6855+ }
6856+ t(
6857+ `the refused import-edge class is real and NOVEL — ${importNovel.length} (family, imported module)`
6858+ + ` pair(s) no key reaches, of ${importNovel.length + importCoveredElsewhere}`,
6859+ importNovel.length > 0,
6860+ );
6861+ t(
6862+ `…and the split the refusal quotes is not invented: ${importCoveredElsewhere} pair(s) another key`
6863+ + ' already answers, so the novel half is a measurement and not the raw count',
6864+ importCoveredElsewhere > 0,
6865+ );
6866+ // The card's own witness, and the single lead this refusal is KNOWN to cost.
6867+ // Asserted in both halves: the import edge exists, and no key names it.
6868+ const bareRootKey = 'scripts/pm/bare-root-worklist.mjs --self-test';
6869+ const bareRootImportFamily = importClassFamilies.find(([c]) => c === bareRootKey)?.[1];
6870+ t(
6871+ 'the witness holds — bare-root-worklist --self-test imports THIS file, and no key names that'
6872+ + ' family for a card editing it',
6873+ (importClassEdges.get(bareRootKey)?.has('scripts/pm/dispatch-gates.mjs') ?? false)
6874+ && !!bareRootImportFamily
6875+ && coveringKey(bareRootImportFamily, 'scripts/pm/dispatch-gates.mjs') === null,
6876+ );
6877+ // Why it is refused, re-derived rather than recalled: the worst module would
6878+ // print a list nobody reads. The bound is the header's own "22 leads is the
6879+ // same as none", doubled — green through ordinary drift, red only if the
6880+ // concentration genuinely collapses and the class is worth re-pricing.
6881+ const importAddPerModule = new Map();
6882+ for (const [, mod] of importNovel) importAddPerModule.set(mod, (importAddPerModule.get(mod) ?? 0) + 1);
6883+ const importWorst = [...importAddPerModule]
6884+ .map(([mod, add]) => ({
6885+ mod,
6886+ add,
6887+ after: add + importClassFamilies.filter(([, e]) => coveringKey(e, mod)).length,
6888+ }))
6889+ .sort((a, b) => b.after - a.after);
6890+ t(
6891+ `the refusal is still earned — a card editing ${importWorst[0]?.mod} would name`
6892+ + ` ${importWorst[0]?.after} families under the refused key`,
6893+ (importWorst[0]?.after ?? 0) > 44,
6894+ );
6895+ const importTop5 = importWorst.slice(0, 5).reduce((s, r) => s + r.add, 0);
6896+ t(
6897+ `…and the class is still concentrated: ${importTop5} of ${importNovel.length} novel pair(s) land`
6898+ + ` on ${Math.min(5, importWorst.length)} module(s)`,
6899+ importTop5 * 2 > importNovel.length,
6900+ );
6901+
67636902 // #12107, the live half — three claims about THIS tree, each one a thing the
67646903 // fix buys that a fixture cannot show.
67656904 const tsLiveFamilies = [...discoverFamilies().byCheck];
0 commit comments