Files
fusion/scripts/__tests__/check-lane-wiring.test.mjs
gsxdsm 5897d87e95 fix(gate): the lane census judged a call against a signature it never had (the false positive #3013's merge introduced) (#3021)
#3013's merge of same-named declarations fixed a false **negative** and
introduced a false **positive**.

`ModelSelectorTab` declares its own two-parameter
`resolveEffectiveExecutor(task, settings)` — a pass-through with nothing
lane-related — while an unrelated exported function of the same name in
`effective-model-resolution.ts` takes `columnFlags`. Both local calls
were reported unwired against a signature they have never had.

Only **exported** declarations enter the accepting map, so the rule is
exact: if the calling file declares the name itself and the map entry
came from a different file, the call resolves to the local declaration
and is not a lane call here.

## The version I did not ship

My first attempt re-ran the detector over the single calling file and
used that result. It scored *better* on this tree — **19 → 16** instead
of 19 → 17, also clearing `bucket-mapping.ts` — and I threw it away.

A single-file pass cannot resolve an **imported** options interface. A
locally-declared function with an imported context type would quietly
stop being lane-accepting, and every call to it would stop being
checked. That is a false negative, which is the one failure a ratchet
must not have; the better-looking number came from the gate seeing less.
The global pass still does all type resolution here — only the *choice*
of declaration is local.

## Measured

| | |
|---|---|
| new tests | 3 |
| against the old census | **1 of 3 fails** — the positive |
| baseline | **19 → 17**, exactly the two `ModelSelectorTab` sites |

Both negatives pass either way and they are the ones that matter: a file
declaring its **own** exported lane function is not shadowed by itself,
and a file declaring nothing is judged normally. Shadowing must not
become a way to disappear a genuine unwired call.

## Still flagged, honestly

`bucket-mapping.ts:75` stays in the baseline. `bucketForTask(task:
TaskItem)` is only lane-accepting because `TaskItem` *declares*
`columnFlags` — the lane data rides on the domain object, so passing
`task` forwards it inherently. That is a different limitation
(options-bag vs domain-entity parameters) and I have not tried to fix it
here; it accounts for 2 of the remaining 17 along with
`otherBucketSecondaryLabel`.

## Verification

`node --test scripts/__tests__/check-lane-wiring.test.mjs` **19 passed**
· `pnpm test:gate` 13 + 161 + 487 + 71 · lint · lifecycle census
`--strict` · lane-wiring · fnxc-dates (TZ=UTC) · changesets — green.
2026-07-31 01:03:24 -07:00

239 lines
10 KiB
JavaScript

// Unit coverage for the lane-wiring census's "is this argument actually supplied?" rules.
/*
FNXC:LaneWiring 2026-07-30-23:55:
THESE TWO RULES DECIDE WHETHER A SEAM COUNTS AS WIRED, and until now nothing tested them.
Both census arms used to ask whether the lane argument was PRESENT rather than whether it carried
anything, so `{ reviewColumns: undefined }` and a trailing positional `undefined` both read as wired
while the callee received nothing. That is the one failure mode a ratchet must not have: it reports
coverage it does not have.
The NEGATIVES are the load-bearing half. Shorthand (`{ reviewColumns }`) forwards a variable whose
value is not knowable from syntax, and treating it as unwired would flag every correct forwarding
wrapper in the tree — a false-positive wave is how a gate trains its readers to skip it. Only a
literal `undefined` / `void 0` is provably empty.
*/
import test from "node:test";
import assert from "node:assert/strict";
import ts from "typescript";
import { mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
suppliesAValue,
effectiveArgCount,
findLaneAcceptingFunctions,
findUnwiredCallSites,
} from "../lib/lane-wiring-census.mjs";
/** One throwaway .ts file, so the census runs end-to-end rather than on a hand-built node. */
function fixture(source) {
const file = join(mkdtempSync(join(tmpdir(), "lane-wiring-")), "f.ts");
writeFileSync(file, source);
return [file];
}
function firstObjectProperty(source) {
const sf = ts.createSourceFile("t.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
let found = null;
const visit = (node) => {
if (!found && ts.isObjectLiteralExpression(node) && node.properties.length > 0) found = node.properties[0];
ts.forEachChild(node, visit);
};
visit(sf);
return found;
}
function callArgs(source) {
const sf = ts.createSourceFile("t.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
let found = null;
const visit = (node) => {
if (!found && ts.isCallExpression(node)) found = node.arguments;
ts.forEachChild(node, visit);
};
visit(sf);
return found;
}
/** Run the whole census over one throwaway source and return its unwired sites. */
function findUnwiredCallSitesIn(source) {
const files = fixture(source);
return findUnwiredCallSites(files, findLaneAcceptingFunctions(files));
}
test("a property spelled `undefined` supplies nothing", () => {
assert.equal(suppliesAValue(firstObjectProperty("f({ reviewColumns: undefined });")), false);
});
test("`void 0` is the same omission spelled differently", () => {
assert.equal(suppliesAValue(firstObjectProperty("f({ reviewColumns: void 0 });")), false);
});
test("a real value supplies", () => {
assert.equal(suppliesAValue(firstObjectProperty("f({ reviewColumns: resolved });")), true);
});
test("SHORTHAND forwards a variable and must still count as supplied", () => {
/* Treating this as unwired would flag every correct forwarding wrapper in the tree. */
assert.equal(suppliesAValue(firstObjectProperty("f({ reviewColumns });")), true);
});
test("a call expression value supplies", () => {
assert.equal(suppliesAValue(firstObjectProperty("f({ reviewColumns: resolve(store) });")), true);
});
test("a trailing positional `undefined` supplies nothing", () => {
assert.equal(effectiveArgCount(callArgs("f(task, undefined);")), 1);
});
test("a real trailing positional argument counts", () => {
assert.equal(effectiveArgCount(callArgs("f(task, resolved);")), 2);
});
test("a MIDDLE undefined positions the argument after it, which is real", () => {
assert.equal(effectiveArgCount(callArgs("f(task, undefined, resolved);")), 3);
});
/*
FNXC:LaneWiring 2026-07-30-23:50 (rebase onto main): THE HELPERS ARE TESTED, THE WIRING WAS NOT.
Every case above calls `suppliesAValue` / `effectiveArgCount` directly. Deleting `&& suppliesAValue(p)`
from `findUnwiredCallSites` therefore left all of them GREEN while the fix did nothing — I found that
by mutating during the conflict resolution, not by reading.
That is the exact defect this gate exists to catch, one level up: a correct helper that nothing calls.
These two run the census END TO END so the call itself is covered.
*/
test("the census reports a call whose lane property is spelled `undefined`", () => {
const files = fixture(`
export function needsLanes(task: string, opts: { reviewColumns?: ReadonlySet<string> }): string { return task; }
export function caller(): string { return needsLanes("x", { reviewColumns: undefined }); }
`);
const unwired = findUnwiredCallSites(files, findLaneAcceptingFunctions(files));
assert.deepEqual(unwired.map((u) => u.fn), ["needsLanes"]);
});
test("the census does NOT report the same call once the property carries a value", () => {
/* Paired positive: the guard must not report every options-bag call as unwired. */
const files = fixture(`
export function needsLanes(task: string, opts: { reviewColumns?: ReadonlySet<string> }): string { return task; }
export function caller(): string { return needsLanes("x", { reviewColumns: new Set() }); }
`);
const unwired = findUnwiredCallSites(files, findLaneAcceptingFunctions(files));
assert.deepEqual(unwired.map((u) => u.fn), []);
});
/*
FNXC:LaneWiring 2026-07-31-01:15:
CONDITIONAL shapes and NAME COLLISIONS — the third and fourth ways a wired call site stayed invisible.
Both were found the same way the earlier holes were: by using the gate and noticing it disagreed with
what the code plainly said. Three call sites wired in #2990/#3004 still counted as unwired, and a
correctly-wired call in task-priority.ts started being reported as unwired the moment a second
same-named function entered the vocabulary.
Every positive below is paired with its NEGATIVE. A shape the census merely stops flagging is not
progress — the question is whether deleting the argument still fails.
*/
const LANE_FN = "export function f(t: unknown, o?: { reviewColumns?: ReadonlySet<string> }) { return [t, o]; }";
test("a lane passed only in a ternary's true branch counts as wired", () => {
const unwired = findUnwiredCallSitesIn(`${LANE_FN}\nf(1, cond ? { reviewColumns: r } : {});`);
assert.equal(unwired.length, 0);
});
test("...and a ternary supplying it in NEITHER branch is still unwired", () => {
const unwired = findUnwiredCallSitesIn(`${LANE_FN}\nf(1, cond ? { nowMs: 1 } : {});`);
assert.equal(unwired.length, 1);
});
test("a lane passed through a conditional spread counts as wired", () => {
const unwired = findUnwiredCallSitesIn(`${LANE_FN}\nf(1, { ...(cond ? { reviewColumns: r } : {}) });`);
assert.equal(unwired.length, 0);
});
test("...and a conditional spread carrying no lane is still unwired", () => {
const unwired = findUnwiredCallSitesIn(`${LANE_FN}\nf(1, { ...(cond ? { nowMs: 1 } : {}) });`);
assert.equal(unwired.length, 1);
});
test("two same-named lane functions MERGE rather than clobber", () => {
/*
The real pair: core's `computeBlockerFanoutMap(tasks, n, opts)` and the dashboard wrapper
`computeBlockerFanoutMap(tasks, opts)`. Their lane options sit at different indices, so the last
declaration parsed used to replace the first and every caller of the other shape was misreported.
*/
const source = [
"export function g(t: unknown, n: number, o?: { reviewColumns?: ReadonlySet<string> }) { return [t, n, o]; }",
"export function g(t: unknown, o?: { columnFlagsByTaskId?: ReadonlyMap<string, unknown> }) { return [t, o]; }",
"g(1, 2, { reviewColumns: r });",
"g(1, { columnFlagsByTaskId: m });",
].join("\n");
assert.equal(findUnwiredCallSitesIn(source).length, 0);
});
test("...and the merge does not excuse a call passing neither shape", () => {
const source = [
"export function g(t: unknown, n: number, o?: { reviewColumns?: ReadonlySet<string> }) { return [t, n, o]; }",
"export function g(t: unknown, o?: { columnFlagsByTaskId?: ReadonlyMap<string, unknown> }) { return [t, o]; }",
"g(1, 2, { nowMs: 1 });",
].join("\n");
assert.equal(findUnwiredCallSitesIn(source).length, 1);
});
/*
FNXC:LaneWiring 2026-07-31-09:35:
SHADOWING — a call means the declaration it can actually see.
Merging same-named declarations fixed a false negative and introduced a false positive: two unrelated
functions named `resolveEffectiveExecutor` exist, one of which takes a lane answer, so every call to
the OTHER was reported unwired against a signature it never had.
The negatives matter more than the positive here. Shadowing must not become a way to disappear a
genuine unwired call: a file that declares its own EXPORTED lane-accepting function is not shadowed
by itself, and a file that declares nothing is judged normally.
*/
function unwiredAcross(sources) {
const dir = mkdtempSync(join(tmpdir(), "lane-wiring-multi-"));
const files = sources.map((source, index) => {
const file = join(dir, `f${index}.ts`);
writeFileSync(file, source);
return file;
});
return findUnwiredCallSites(files, findLaneAcceptingFunctions(files));
}
test("a local declaration shadows an unrelated exported function of the same name", () => {
const unwired = unwiredAcross([
"export function resolveThing(t: unknown, o?: { reviewColumns?: ReadonlySet<string> }) { return [t, o]; }",
[
"function resolveThing(t: unknown, s?: { quiet?: boolean }) { return [t, s]; }",
"export function use() { return resolveThing(1, { quiet: true }); }",
].join("\n"),
]);
assert.equal(unwired.length, 0);
});
test("...but a file declaring its OWN exported lane function is not shadowed by itself", () => {
const unwired = unwiredAcross([
[
"export function resolveThing(t: unknown, o?: { reviewColumns?: ReadonlySet<string> }) { return [t, o]; }",
"export function use() { return resolveThing(1, { quiet: true }); }",
].join("\n"),
]);
assert.equal(unwired.length, 1);
});
test("...and a file declaring nothing is judged against the exported signature", () => {
const unwired = unwiredAcross([
"export function resolveThing(t: unknown, o?: { reviewColumns?: ReadonlySet<string> }) { return [t, o]; }",
"export function use() { return resolveThing(1, { quiet: true }); }",
]);
assert.equal(unwired.length, 1);
});