#6478·gsd-2

Regression: regenerateIfMissing(PLAN) no-op when task plans missing → plan-slice stuck loop

Author: waja1n0zCreated Jun 27, 2026Updated Jun 27, 2026

Problem

Auto-mode stuck-loops on plan-slice when any tasks/T##-PLAN.md is missing from disk, even though the slice was successfully planned in the DB. The artifact-verification recovery path (regenerateIfMissing(..., "PLAN")) is a no-op for this exact failure mode. This is a regression of #6146 / #6343.

Root Cause

workflow-projections.js:385-464 (the regenerateIfMissing function) has two defects in the "PLAN" branch:

  1. Early-return ignores task plans. At workflow-projections.js:441:

    javascript
    if (existsSync(filePath)) {       // filePath = ${sliceId}-PLAN.md only
        return false;
    }

    If the slice plan exists but any tasks/T##-PLAN.md is missing (the verifier's actual failure), the function bails before checking task plans.

  2. Fallback uses legacy non-DB renderer. At workflow-projections.js:450:

    javascript
    case "PLAN":
        renderPlanProjection(basePath, milestoneId, sliceId);  // legacy, slice only
        return existsSync(filePath);

    renderPlanProjection never emits tasks/T##-PLAN.md files and omits the ## Files Likely Touched section — matching the two verifier messages: task plan missing and Slice plan missing 'Files Likely Touched' section.

A correct "TASK_PLAN" branch was added at lines 401-420 that calls renderTaskPlanFromDb per task, but the sole caller (auto-post-unit.js:929) only passes "PLAN", never "TASK_PLAN", so that branch is unreachable from the recovery path.

Net effect: post-unit verification fails → regenerateIfMissing("PLAN") returns false (early-return) or returns true with the legacy renderer that still doesn't write task plans → re-verify fails → dispatch repeats → stuck-stop after 3 iterations.

Expected Behavior

The "PLAN" branch should be authoritative for the slice's planning artifacts: use the DB-driven renderPlanFromDb for the slice file, AND iterate every task row to render any missing tasks/T##-PLAN.md via renderTaskPlanFromDb. Do not early-return on the slice file alone.

Suggested fix (applied locally):

javascript
if (fileType === "PLAN") {
    let regenerated = 0;
    if (!existsSync(filePath)) {
        try {
            await renderPlanFromDb(basePath, milestoneId, sliceId);
            if (existsSync(filePath)) regenerated++;
        } catch (err) { logWarning(...); }
    }
    const taskRows = getSliceTasks(milestoneId, sliceId);
    for (const task of taskRows) {
        const planPath = join(basePath, ".gsd", "milestones", milestoneId,
            "slices", sliceId, "tasks", `${task.id}-PLAN.md`);
        if (!existsSync(planPath)) {
            try {
                await renderTaskPlanFromDb(basePath, milestoneId, sliceId, task.id);
                if (existsSync(planPath)) regenerated++;
            } catch (err) { logWarning(...); }
        }
    }
    return regenerated > 0;
}

Environment

  • GSD version: 3.0.0
  • Model: claude-opus-4-7
  • Unit: plan-slice/M001/S04 (also affected: S01, S02, S03)

Reproduction Context

Plan-slice phase. gsd_plan_slice succeeds (DB write OK, activity log: "Slice S04 planned."). Post-unit artifact verification then fails because tasks/T01-PLAN.md is missing on disk. Recovery via regenerateIfMissing(..., "PLAN") is a no-op. Auto-mode re-dispatches the same unit 3 times and stops with Stuck: plan-slice/M001/S04 derived 3 consecutive times without progress.

Forensic Evidence

Stuck-loop anomalies on every plan-slice unit in the session:

  • plan-slice/M001/S01 dispatched 3×
  • plan-slice/M001/S02 dispatched 3×
  • plan-slice/M001/S03 dispatched 3×
  • plan-slice/M001/S04 dispatched 3× → terminal

Verifier warnings (verbatim):

  • verify-fail plan-slice M001/S04: task plan missing .gsd/milestones/M001/slices/S04/tasks/T01-PLAN.md
  • Slice plan missing 'Files Likely Touched' section

Journal pattern (S04, abridged):

[dispatch-match] rule="executing → execute-task (recover missing task plan → plan-slice)" unit=M001/S04
[unit-end] unit=M001/S04
[artifact-verification-retry] unit=M001/S04
[iteration-end]
... (repeats 3x) ...
[auto-exit] flow=64c318d0

Related

  • #6146
  • #6343

Auto-generated by /gsd forensics