diff --git a/src/resources/extensions/gsd/doctor.ts b/src/resources/extensions/gsd/doctor.ts index 7ffb29830..a11490545 100644 --- a/src/resources/extensions/gsd/doctor.ts +++ b/src/resources/extensions/gsd/doctor.ts @@ -1144,8 +1144,31 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean; unitId: taskUnitId, message: `Task ${task.id} is marked done but summary is missing`, file: relTaskFile(basePath, milestoneId, slice.id, task.id, "SUMMARY"), - fixable: false, + fixable: true, }); + // Write a stub summary so validate-milestone can proceed. + // This prevents infinite skip loops when tasks are marked done + // without summaries (#820). + if (shouldFix("task_done_missing_summary")) { + const stubPath = join( + basePath, ".gsd", "milestones", milestoneId, "slices", slice.id, "tasks", + `${task.id}-SUMMARY.md`, + ); + const stubContent = [ + `---`, + `status: done`, + `result: unknown`, + `doctor_generated: true`, + `---`, + ``, + `# ${task.id}: ${task.title || "Unknown"}`, + ``, + `Summary stub generated by \`/gsd doctor\` — task was marked done but no summary existed.`, + ``, + ].join("\n"); + await saveFile(stubPath, stubContent); + fixesApplied.push(`created stub summary for ${taskUnitId}`); + } } if (!task.done && hasSummary) {