test(engine): pin the completion fan-out's review dependent bucket (16th resolver) (#3190)
Sixteenth resolver from the coverage map on #3115. `completedReviewColumns` reads the **dependents** resting in review when a blocker completes. No case in this file put a dependent in a renamed review lane, so blinding it left all 13 tests green. ## What the literal costs A dependent sitting in review is never read, so its `blockedBy` is never cleared when the blocker finishes. **It stays blocked by work that is already done** — the most visible form of this class, because the board simply stops moving. ## Measured 14 pass; blinding `completedReviewColumns` fails exactly this case. ## Note for anyone continuing the map `completedHoldColumns` in this same sweep measured as **already covered**, so only the review bucket was owed. Three buckets, three resolvers, covered independently — the same per-resolver granularity that found the missing halves in #3138 and #3186, where my own earlier tests pinned one resolver of a pair and I had recorded the sweep as done. **16 of 26 pinned** across 15 merged PRs. ## Verification `self-healing-completion-fanout` **14 passed** · `pnpm test:gate` full pass · lint — green. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed task completion reconciliation for workflows with renamed lanes. * Dependent tasks in review lanes are now correctly unblocked when their blocker moves to a custom completion lane. * **Tests** * Added regression coverage for custom workflow lane configurations. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -260,6 +260,33 @@ describe("the task:moved fan-out resolves the board's own lanes", () => {
|
||||
mgr.stop();
|
||||
});
|
||||
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-19:30:
|
||||
`completedReviewColumns` was UNCOVERED on the #3115 map. It reads the DEPENDENTS resting in review
|
||||
when a blocker completes; no case here put a dependent in a renamed review lane, so blinding it left
|
||||
the file green.
|
||||
|
||||
What the literal costs: a dependent sitting in review is never read, so its `blockedBy` is never
|
||||
cleared when the blocker finishes. It stays blocked by work that is already done — the most visible
|
||||
form of this class, because the board simply stops moving.
|
||||
*/
|
||||
it("clears blockedBy for a dependent resting in the board's own review lane", async () => {
|
||||
const blocker = makeTask("FN-BLOCKER", { column: "shipped" });
|
||||
const dependent = makeTask("FN-DEP", { column: "checking", blockedBy: "FN-BLOCKER", status: "queued" });
|
||||
const store = createStore([blocker, dependent]) as unknown as TaskStore & EventEmitter;
|
||||
(store as unknown as { listWorkflowDefinitions: unknown }).listWorkflowDefinitions =
|
||||
vi.fn(async () => [{ id: "wf-renamed", ir: RENAMED_IR }]);
|
||||
const mgr = new SelfHealingManager(store, { rootDir: "/repo" });
|
||||
|
||||
await mgr.reconcileCompletedTask("FN-BLOCKER");
|
||||
|
||||
expect(store.updateTask).toHaveBeenCalledWith(
|
||||
"FN-DEP",
|
||||
expect.objectContaining({ blockedBy: null }),
|
||||
);
|
||||
mgr.stop();
|
||||
});
|
||||
|
||||
it("rebinds the branch on a move into the board's own review lane", async () => {
|
||||
const t = makeTask("FN-R2", { column: "checking" });
|
||||
const store = renamedStore(t);
|
||||
|
||||
Reference in New Issue
Block a user