From 1dcedb635e2f449bc7fcae19f67dfc6e6f5b16dd Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Sun, 15 Feb 2026 16:37:47 -0600 Subject: [PATCH] feat(auto-advance): chain phase execution across full milestone Wire execute-phase to invoke transition.md inline when --auto flag or workflow.auto_advance config is set, propagate --auto through transition to next phase invocations, add config-get command to gsd-tools, and fix broken "config get" calls to use hyphenated "config-get" subcommand. Closes #344 Co-Authored-By: Claude Opus 4.6 --- get-shit-done/bin/gsd-tools.cjs | 41 ++++++++++++++++++++++++ get-shit-done/workflows/discuss-phase.md | 2 +- get-shit-done/workflows/execute-phase.md | 27 ++++++++++++++-- get-shit-done/workflows/plan-phase.md | 2 +- get-shit-done/workflows/transition.md | 4 +-- 5 files changed, 69 insertions(+), 7 deletions(-) diff --git a/get-shit-done/bin/gsd-tools.cjs b/get-shit-done/bin/gsd-tools.cjs index a4cabaaf0..9d1d5bda7 100755 --- a/get-shit-done/bin/gsd-tools.cjs +++ b/get-shit-done/bin/gsd-tools.cjs @@ -692,6 +692,42 @@ function cmdConfigSet(cwd, keyPath, value, raw) { } } +function cmdConfigGet(cwd, keyPath, raw) { + const configPath = path.join(cwd, '.planning', 'config.json'); + + if (!keyPath) { + error('Usage: config-get '); + } + + let config = {}; + try { + if (fs.existsSync(configPath)) { + config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); + } else { + error('No config.json found at ' + configPath); + } + } catch (err) { + if (err.message.startsWith('No config.json')) throw err; + error('Failed to read config.json: ' + err.message); + } + + // Traverse dot-notation path (e.g., "workflow.auto_advance") + const keys = keyPath.split('.'); + let current = config; + for (const key of keys) { + if (current === undefined || current === null || typeof current !== 'object') { + error(`Key not found: ${keyPath}`); + } + current = current[key]; + } + + if (current === undefined) { + error(`Key not found: ${keyPath}`); + } + + output(current, raw, String(current)); +} + function cmdHistoryDigest(cwd, raw) { const phasesDir = path.join(cwd, '.planning', 'phases'); const digest = { phases: {}, decisions: [], tech_stack: new Set() }; @@ -4999,6 +5035,11 @@ async function main() { break; } + case 'config-get': { + cmdConfigGet(cwd, args[1], raw); + break; + } + case 'history-digest': { cmdHistoryDigest(cwd, raw); break; diff --git a/get-shit-done/workflows/discuss-phase.md b/get-shit-done/workflows/discuss-phase.md index 4104f9aca..ea183a84e 100644 --- a/get-shit-done/workflows/discuss-phase.md +++ b/get-shit-done/workflows/discuss-phase.md @@ -417,7 +417,7 @@ Check for auto-advance trigger: 1. Parse `--auto` flag from $ARGUMENTS 2. Read `workflow.auto_advance` from config: ```bash - AUTO_CFG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs config get workflow.auto_advance 2>/dev/null || echo "false") + AUTO_CFG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs config-get workflow.auto_advance 2>/dev/null || echo "false") ``` **If `--auto` flag present OR `AUTO_CFG` is true:** diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md index 89a227434..274b25d3e 100644 --- a/get-shit-done/workflows/execute-phase.md +++ b/get-shit-done/workflows/execute-phase.md @@ -359,11 +359,32 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs(phase-{X}): complete -**Routing is handled by `transition.md`** — do NOT emit a separate "Next Up" block here. +**Exception:** If `gaps_found`, the `verify_phase_goal` step already presents the gap-closure path (`/gsd:plan-phase {X} --gaps`). No additional routing needed — skip auto-advance. -After `verify_phase_goal` passes (or human approves), the workflow ends. The user runs `/gsd:progress` or the transition workflow handles next-step routing. +**Auto-advance detection:** -**Exception:** If `gaps_found`, the `verify_phase_goal` step already presents the gap-closure path (`/gsd:plan-phase {X} --gaps`). No additional routing needed. +1. Parse `--auto` flag from $ARGUMENTS +2. Read `workflow.auto_advance` from config: + ```bash + AUTO_CFG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs config-get workflow.auto_advance 2>/dev/null || echo "false") + ``` + +**If `--auto` flag present OR `AUTO_CFG` is true (AND verification passed with no gaps):** + +``` +╔══════════════════════════════════════════╗ +║ AUTO-ADVANCING → TRANSITION ║ +║ Phase {X} verified, continuing chain ║ +╚══════════════════════════════════════════╝ +``` + +Execute the transition workflow inline (do NOT use Task — orchestrator context is ~10-15%, transition needs phase completion data already in context): + +Read and follow `~/.claude/get-shit-done/workflows/transition.md`, passing through the `--auto` flag so it propagates to the next phase invocation. + +**If neither `--auto` nor `AUTO_CFG` is true:** + +The workflow ends. The user runs `/gsd:progress` or invokes the transition workflow manually. diff --git a/get-shit-done/workflows/plan-phase.md b/get-shit-done/workflows/plan-phase.md index 930aac30a..f7e4644d0 100644 --- a/get-shit-done/workflows/plan-phase.md +++ b/get-shit-done/workflows/plan-phase.md @@ -336,7 +336,7 @@ Check for auto-advance trigger: 1. Parse `--auto` flag from $ARGUMENTS 2. Read `workflow.auto_advance` from config: ```bash - AUTO_CFG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs config get workflow.auto_advance 2>/dev/null || echo "false") + AUTO_CFG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs config-get workflow.auto_advance 2>/dev/null || echo "false") ``` **If `--auto` flag present OR `AUTO_CFG` is true:** diff --git a/get-shit-done/workflows/transition.md b/get-shit-done/workflows/transition.md index 9d7b6a205..ee23503ed 100644 --- a/get-shit-done/workflows/transition.md +++ b/get-shit-done/workflows/transition.md @@ -378,7 +378,7 @@ Next: Phase [X+1] — [Name] ⚡ Auto-continuing: Plan Phase [X+1] in detail ``` -Exit skill and invoke SlashCommand("/gsd:plan-phase [X+1]") +Exit skill and invoke SlashCommand("/gsd:plan-phase [X+1] --auto") **If CONTEXT.md does NOT exist:** @@ -390,7 +390,7 @@ Next: Phase [X+1] — [Name] ⚡ Auto-continuing: Discuss Phase [X+1] first ``` -Exit skill and invoke SlashCommand("/gsd:discuss-phase [X+1]") +Exit skill and invoke SlashCommand("/gsd:discuss-phase [X+1] --auto")