From a1ef04a5f3814682b4a05f9f17e4e63d3d2c13f3 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Wed, 18 Mar 2026 12:06:48 -0400 Subject: [PATCH] fix: route needs-discussion phase to interactive flow instead of stopping (#1175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a milestone has CONTEXT-DRAFT.md (phase: needs-discussion), the dispatch table returned 'stop' — which made auto-mode exit. Running /gsd again would re-enter auto → dispatch → stop → loop indefinitely. The guided-flow already has a complete interactive handler for needs-discussion (discuss from draft / start fresh / skip), but it was never reached from the auto-mode entry path. Added an early check in dispatchNextUnit: if phase is needs-discussion, stop auto-mode gracefully and route to showSmartEntry() which handles the discussion flow correctly. Fixes #1170 --- src/resources/extensions/gsd/auto.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/resources/extensions/gsd/auto.ts b/src/resources/extensions/gsd/auto.ts index 4acc369a7..4afa7370f 100644 --- a/src/resources/extensions/gsd/auto.ts +++ b/src/resources/extensions/gsd/auto.ts @@ -1439,6 +1439,23 @@ async function dispatchNextUnit( await runSecretsGate(); + // ── Interactive discussion gate ── + // If the active milestone needs discussion (has CONTEXT-DRAFT.md but no roadmap), + // stop auto-mode and route to the interactive discussion flow. The guided-flow + // handles needs-discussion correctly — it just needs to be called instead of + // letting the dispatch table fire "needs-discussion → stop" (#1170). + if (state.phase === "needs-discussion") { + if (s.currentUnit) { + await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id)); + } + const cmdCtx = s.cmdCtx!; + const basePath = s.basePath; + await stopAuto(ctx, pi, `${mid}: ${midTitle} needs discussion before planning.`); + const { showSmartEntry } = await import("./guided-flow.js"); + await showSmartEntry(cmdCtx, pi, basePath); + return; + } + // ── Dispatch table ── const dispatchResult = await resolveDispatch({ basePath: s.basePath, mid, midTitle: midTitle!, state, prefs, });