test(engine): memoize corpus scans in lifecycle-column gate tests

Both gate-admitted census tests re-scanned the whole ~1200-file corpus
redundantly: legacy-column-literal-census ran census() twice in full
(~900ms each) and no-legacy-move-targets re-read the entire tree a second
time in its anti-vacuity case. Memoize the census result and share a
comment-stripped read cache so each tree is scanned once per run.

Fusion-Task-Id: none
This commit is contained in:
gsxdsm
2026-08-04 17:03:44 -07:00
parent 5dbfef7b64
commit 71b13e7888
2 changed files with 36 additions and 15 deletions

View File

@@ -196,7 +196,18 @@ function productionSources(): string[] {
.filter((f) => !f.includes("__tests__") && !/\.(test|spec)\.tsx?$/.test(f));
}
/*
FNXC:LegacyColumnCensus 2026-08-05-00:02 (gate cost):
MEMOISED, for the same reason its sibling no-legacy-move-targets.test.ts memoises countByFile().
census() re-read and re-scanned the whole ~1200-file corpus, and two cases each call it in full
("never grows" and "reports when the count has fallen") — so the heaviest scan in this suite ran
twice for one tree, ~900ms each, buying nothing because the tree cannot change mid-run. A guard that
is gratuitously slow is a guard someone eventually moves back out of the gate.
*/
let censusCache: { total: number; byFile: Map<string, number> } | undefined;
function census(): { total: number; byFile: Map<string, number> } {
if (censusCache) return censusCache;
const byFile = new Map<string, number>();
let total = 0;
for (const file of productionSources()) {
@@ -221,7 +232,8 @@ function census(): { total: number; byFile: Map<string, number> } {
total += n;
}
}
return { total, byFile };
censusCache = { total, byFile };
return censusCache;
}
describe("legacy column-literal census — the unconverted lifecycle surface", () => {

View File

@@ -72,6 +72,27 @@ function stripComments(source: string): string {
.replace(/\/\/[^\n]*/g, "");
}
/*
FNXC:WorkflowResolvedColumns 2026-08-05-00:02 (gate cost):
SHARED comment-stripped read cache. countByFile() already memoised its scan, but the anti-vacuity
case ("scans a real corpus") re-read the ENTIRE corpus a second time with its own readFileSync loop
to find moveTask( callers — measured ~270ms of a second full pass over the same unchanging tree. Both
consumers want the same comment-stripped source, so read+strip each file once and share it.
*/
const strippedSourceCache = new Map<string, string>();
function strippedSource(file: string): string {
const cached = strippedSourceCache.get(file);
if (cached !== undefined) return cached;
let stripped: string;
try {
stripped = stripComments(readFileSync(resolve(REPO_ROOT, file), "utf8"));
} catch {
stripped = "";
}
strippedSourceCache.set(file, stripped);
return stripped;
}
/*
FNXC:WorkflowResolvedColumns 2026-07-31-23:59:
MEMOISED for gate admission. Each case called this independently and every call re-read the whole
@@ -87,13 +108,7 @@ function countByFile(): Record<string, number> {
if (countsCache) return countsCache;
const counts: Record<string, number> = {};
for (const file of sourceFiles()) {
let source: string;
try {
source = readFileSync(resolve(REPO_ROOT, file), "utf8");
} catch {
continue;
}
const hits = stripComments(source).match(MOVE_TARGET);
const hits = strippedSource(file).match(MOVE_TARGET);
if (hits && hits.length > 0) counts[file] = hits.length;
}
countsCache = counts;
@@ -115,13 +130,7 @@ describe("moveTask targets resolve the board's own lane", () => {
const files = sourceFiles();
expect(files.length).toBeGreaterThan(200);
const callers = files.filter((file) => {
try {
return /moveTask\s*\(/.test(stripComments(readFileSync(resolve(REPO_ROOT, file), "utf8")));
} catch {
return false;
}
});
const callers = files.filter((file) => /moveTask\s*\(/.test(strippedSource(file)));
expect(callers.length).toBeGreaterThan(5);
expect(callers).toContain("packages/engine/src/self-healing.ts");
});