test(engine): pin the temp-merge sweep's terminal grace (17th resolver) (#3192)

Seventeenth resolver from the coverage map on #3115. The two cases
around this one use `done` and `archived` — **the ids** — so blinding
`mergeTempTerminalColumns` left all 21 tests green.

## What the literal costs

The terminal check selects the **shorter grace**: a finished task's temp
merge worktree is reaped after `DONE_TASK_TEMP_WORKTREE_GRACE_MS`
instead of the full stale window. Keyed on the ids, a card in a renamed
completion lane never qualified, so its worktree lingered for the long
window — **disk held by work that already finished**.

## The second cost, which is why this asserts on the audit reason

Without the resolver the sweep eventually acts, but records `reason:
"stale"` instead of `"done-task-stale"`. So its own trail
**misattributes why it acted**.

A sweep that does roughly the right thing under the wrong label is the
kind of defect nobody notices until they are reading audit events during
an incident — and then the record actively misleads. Asserting only on
the file being gone would have passed either way.

## Measured

22 pass; blinding `mergeTempTerminalColumns` fails exactly this case.

**17 of 26 pinned** across 16 merged PRs. Also re-measured this turn:
`wsDoneColumns` and `doneMetaColumns` have gone green independently, so
the map keeps drifting as the fleet adds coverage — re-run before
picking the next entry.

## Verification

`self-healing-tempdir-sweep` **22 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 stale-task handling for tasks in terminal columns of custom
workflows.
* These tasks now correctly follow the done-task grace period and record
the appropriate audit reason.

* **Tests**
  * Added regression coverage to verify the corrected behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
gsxdsm
2026-07-31 09:24:35 -07:00
committed by GitHub
parent f755f44734
commit c8268a6454

View File

@@ -319,6 +319,44 @@ describe("SelfHealingManager temp-dir AI merge worktree sweep", () => {
]));
});
/*
FNXC:WorkflowResolvedColumns 2026-07-31-20:10:
`mergeTempTerminalColumns` was UNCOVERED on the #3115 map. The two cases around this one use `done`
and `archived` — the ids — so blinding the resolver leaves them green.
The terminal check picks the SHORTER grace: a finished task's temp merge worktree is reaped after
DONE_TASK_TEMP_WORKTREE_GRACE_MS instead of the full stale window. Keyed on the ids, a card in a
renamed completion lane never qualified, so its worktree lingered for the long window — disk held
by work that finished, and the audit reason reads "stale" rather than "done-task-stale", so the
sweep's own record misattributes why it eventually acted.
*/
it("uses the done-task grace for a task in a RENAMED terminal lane", async () => {
const stale = tempMergeDir("fusion-ai-merge-fn-999-renamedterminal");
makeDoneTaskStale(stale);
const { manager, audits } = makeManager({}, taskWithColumn("shipped"));
(manager as unknown as { store: Record<string, unknown> }).store.listWorkflowDefinitions =
vi.fn(async () => [{
id: "custom:renamed",
ir: {
version: "v2",
id: "custom:renamed",
nodes: [],
edges: [],
columns: [
{ id: "building", name: "building", traits: [{ trait: "wip", config: { limitSetting: "maxConcurrent" } }] },
{ id: "shipped", name: "shipped", traits: [{ trait: "complete" }] },
],
},
}]);
await expect(sweep(manager)).resolves.toBe(1);
expect(existsSync(stale)).toBe(false);
expect(sweepAudits(audits)).toEqual(expect.arrayContaining([
expect.objectContaining({ metadata: expect.objectContaining({ success: true, reason: "done-task-stale" }) }),
]));
});
it("removes worktree for archived task after grace period", async () => {
const stale = tempMergeDir("fusion-ai-merge-fn-999-archivedtask");
makeDoneTaskStale(stale);