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:
gsxdsm
2026-07-31 09:13:21 -07:00
committed by GitHub
parent da10131d3f
commit f755f44734

View File

@@ -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);