From 236e9f136740af72cdf33ca631d286f413624c4f Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Mon, 6 Apr 2026 18:35:59 -0700 Subject: [PATCH] fix(gsd): exclude closed slices from findMissingSummaries check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip slices with status skipped/complete/done when checking for missing SUMMARY files. Skipped slices never produce SUMMARYs by design, and legacy-complete slices may lack them after worktree merge failures. The DB status is authoritative — missing SUMMARY is a cosmetic gap, not evidence the slice was incomplete. Fixes #3620 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/resources/extensions/gsd/auto-dispatch.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/resources/extensions/gsd/auto-dispatch.ts b/src/resources/extensions/gsd/auto-dispatch.ts index ccc3921e6..a03d0d043 100644 --- a/src/resources/extensions/gsd/auto-dispatch.ts +++ b/src/resources/extensions/gsd/auto-dispatch.ts @@ -93,14 +93,22 @@ function missingSliceStop(mid: string, phase: string): DispatchAction { /** * Check for milestone slices missing SUMMARY files. * Returns array of missing slice IDs, or empty array if all present or DB unavailable. + * + * Excludes skipped slices (intentionally summary-less) and legacy-complete + * slices whose DB status is authoritative even without on-disk SUMMARY (#3620). */ function findMissingSummaries(basePath: string, mid: string): string[] { if (!isDbAvailable()) return []; - const sliceIds = getMilestoneSlices(mid).map(s => s.id); - return sliceIds.filter(sid => { - const summaryPath = resolveSliceFile(basePath, mid, sid, "SUMMARY"); - return !summaryPath || !existsSync(summaryPath); - }); + const slices = getMilestoneSlices(mid); + // Skipped slices never produce SUMMARYs; legacy-complete slices may lack them + const CLOSED_STATUSES = new Set(["skipped", "complete", "done"]); + return slices + .filter(s => !CLOSED_STATUSES.has(s.status)) + .filter(s => { + const summaryPath = resolveSliceFile(basePath, mid, s.id, "SUMMARY"); + return !summaryPath || !existsSync(summaryPath); + }) + .map(s => s.id); } // ─── Rewrite Circuit Breaker ──────────────────────────────────────────────