From c8268a6454aa238b02a7fd3b6afe3f7cb561e67e Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Fri, 31 Jul 2026 09:24:35 -0700 Subject: [PATCH] test(engine): pin the temp-merge sweep's terminal grace (17th resolver) (#3192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. ## 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. --- .../self-healing-tempdir-sweep.test.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/engine/src/__tests__/self-healing-tempdir-sweep.test.ts b/packages/engine/src/__tests__/self-healing-tempdir-sweep.test.ts index b705784d53..8e59d5f30c 100644 --- a/packages/engine/src/__tests__/self-healing-tempdir-sweep.test.ts +++ b/packages/engine/src/__tests__/self-healing-tempdir-sweep.test.ts @@ -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 }).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);