From 89fe6c3bdb4f8303b45f7f96e3e00dfd583b30f9 Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Mon, 6 Apr 2026 18:51:49 -0700 Subject: [PATCH] fix(gsd): auto-remediate stale slice DB status when SUMMARY exists on disk When complete-slice unit fails after writing SUMMARY.md but before calling updateSliceStatus(), the DB stays out of sync. The post-unit check previously reported this as a "rogue" artifact, leading to infinite re-dispatch of the same complete-slice unit. Now auto-remediates by calling updateSliceStatus() to sync the DB when SUMMARY exists on disk but status != "complete". Falls back to rogue detection if the DB update fails. Closes #3633 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/resources/extensions/gsd/auto-post-unit.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/resources/extensions/gsd/auto-post-unit.ts b/src/resources/extensions/gsd/auto-post-unit.ts index 3bffee4b8..e0a10b4cd 100644 --- a/src/resources/extensions/gsd/auto-post-unit.ts +++ b/src/resources/extensions/gsd/auto-post-unit.ts @@ -39,7 +39,7 @@ import { } from "./auto-recovery.js"; import { regenerateIfMissing } from "./workflow-projections.js"; import { syncStateToProjectRoot } from "./auto-worktree.js"; -import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js"; +import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, updateSliceStatus, _getAdapter } from "./gsd-db.js"; import { renderPlanCheckboxes } from "./markdown-renderer.js"; import { consumeSignal } from "./session-status-io.js"; import { @@ -161,7 +161,14 @@ export function detectRogueFileWrites( const dbRow = getSlice(mid, sid); if (!dbRow || dbRow.status !== "complete") { - rogues.push({ path: summaryPath, unitType, unitId }); + // Auto-remediate: SUMMARY exists on disk but DB is stale — sync DB to + // match filesystem instead of reporting as rogue (#3633). + try { + updateSliceStatus(mid, sid, "complete", new Date().toISOString()); + } catch { + // If DB update fails, fall back to rogue detection so the issue is visible + rogues.push({ path: summaryPath, unitType, unitId }); + } } } else if (unitType === "plan-milestone") { if (!mid) return [];