diff --git a/packages/engine/src/__tests__/scheduler-load-lane-union.test.ts b/packages/engine/src/__tests__/scheduler-load-lane-union.test.ts index 3b4703327c..47e79e9ee2 100644 --- a/packages/engine/src/__tests__/scheduler-load-lane-union.test.ts +++ b/packages/engine/src/__tests__/scheduler-load-lane-union.test.ts @@ -62,12 +62,82 @@ describe("the scheduler's load-lane union covers every legacy role", () => { expect(loadLanes(RENAMED_IR).has("shipped")).toBe(false); }); - it("the scheduler builds this same union", () => { - // Guards the mirror above against drift: if scheduler.ts stops unioning a role, this fails. + it("the scheduler builds this same union", async () => { + /* + FNXC:WorkflowLifecycleColumns 2026-07-31-04:20: + AST, NOT A SOURCE-TEXT MATCH — the previous form hardcoded a local VARIABLE NAME. + + It asserted `source.toContain('...columnsWithFlag(loadLaneIr, "")')`. #2796 resolves + assignment load per task and renamed that local from `loadLaneIr` to `ir`; the union it builds is + unchanged (scheduler.ts, the `columnsWithFlag(ir, ...)` spread), but the literal stopped matching + and this failed. Neither PR's CI could see it — the test landed on main via #2787 after #2796 was + cut, and #2796 does not touch this file, so it only breaks in the merged state. + + A guard that fails on a rename, a reformat, or a line wrap while the behaviour is untouched costs + more than it protects: it reports drift that did not happen, and the reflex fix is to edit the + string, which teaches nobody anything. + + So: parse `scheduler.ts` and collect the string literal passed as the SECOND argument to every + `columnsWithFlag(...)` call, whatever the first argument is called. The invariant — every legacy + role is unioned somewhere in the scheduler — is preserved and is what actually gets checked. + + Still a structural assertion rather than a behavioural one, for the reason the file header gives: + the call site sits inside a dispatch path a unit test has no business standing up. The three + cases above cover the resolver's behaviour; this one covers the wiring. + */ + const ts = await import("typescript"); const source = readFileSync(new URL("../scheduler.ts", import.meta.url), "utf8"); + const sf = ts.createSourceFile("scheduler.ts", source, ts.ScriptTarget.Latest, true); + + /* + FNXC:WorkflowResolvedColumns 2026-07-30-16:45 (#2804 review — greptile): + SCOPED TO `resolveLoadLanes`, not the whole file. + + The first version collected EVERY `columnsWithFlag` call in scheduler.ts. `resolveDependencySatisfactionColumns` + in the same file passes `mergeBlocker` and `humanReview` for its own, unrelated question — so + deleting either from the load-lane union left them in the set anyway and every assertion below + still passed. The test could not fail for the regression it exists to catch. + + Scoping means two things have to be sanity-checked, not one: that the function was FOUND, and that + it contained calls. Either being false is a silent pass, which is the failure mode this whole + exercise keeps producing. + */ + const flagsPassed = new Set(); + let loadLaneFnFound = false; + + const collectWithin = (node: import("typescript").Node): void => { + if (ts.isCallExpression(node) + && ts.isIdentifier(node.expression) + && node.expression.text === "columnsWithFlag" + && node.arguments.length >= 2 + && ts.isStringLiteral(node.arguments[1])) { + flagsPassed.add(node.arguments[1].text); + } + ts.forEachChild(node, collectWithin); + }; + + const findLoadLaneFn = (node: import("typescript").Node): void => { + if (ts.isVariableDeclaration(node) + && ts.isIdentifier(node.name) + && node.name.text === "resolveLoadLanes" + && node.initializer) { + loadLaneFnFound = true; + collectWithin(node.initializer); + return; + } + ts.forEachChild(node, findLoadLaneFn); + }; + findLoadLaneFn(sf); + + /* + Both sanity checks are load-bearing. A rename of `resolveLoadLanes` would otherwise leave the set + empty and the loop below would assert nothing — the exact vacuity this scoping was meant to remove. + */ + expect(loadLaneFnFound, "scheduler.ts no longer declares resolveLoadLanes — this test is scoped to it").toBe(true); + expect(flagsPassed.size).toBeGreaterThan(0); for (const flag of ["intake", "hold", "countsTowardWip", "mergeOrchestration", "mergeBlocker", "humanReview"]) { - expect(source).toContain(`...columnsWithFlag(loadLaneIr, "${flag}")`); + expect(flagsPassed, `scheduler.ts no longer passes "${flag}" to columnsWithFlag`).toContain(flag); } }); });