diff --git a/get-shit-done/bin/lib/config.cjs b/get-shit-done/bin/lib/config.cjs index 1570e29ae..252a6e446 100644 --- a/get-shit-done/bin/lib/config.cjs +++ b/get-shit-done/bin/lib/config.cjs @@ -20,6 +20,7 @@ const VALID_CONFIG_KEYS = new Set([ 'workflow.text_mode', 'workflow.research_before_questions', 'workflow.discuss_mode', + 'workflow.skip_discuss', 'workflow._auto_chain_active', 'git.branching_strategy', 'git.phase_branch_template', 'git.milestone_branch_template', 'git.quick_branch_template', 'planning.commit_docs', 'planning.search_gitignored', @@ -114,6 +115,7 @@ function buildNewProjectConfig(userChoices) { text_mode: false, research_before_questions: false, discuss_mode: 'discuss', + skip_discuss: false, }, hooks: { context_warnings: true, diff --git a/get-shit-done/workflows/autonomous.md b/get-shit-done/workflows/autonomous.md index 4d4a96eb5..f293c8323 100644 --- a/get-shit-done/workflows/autonomous.md +++ b/get-shit-done/workflows/autonomous.md @@ -136,7 +136,79 @@ Phase ${PHASE_NUM}: Context exists — skipping discuss. Proceed to 3b. -**If has_context is false:** Execute the smart_discuss step for this phase. +**If has_context is false:** Check if discuss is disabled via settings: + +```bash +SKIP_DISCUSS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.skip_discuss 2>/dev/null || echo "false") +``` + +**If SKIP_DISCUSS is `true`:** Skip discuss entirely — the ROADMAP phase description is the spec. Display: + +``` +Phase ${PHASE_NUM}: Discuss skipped (workflow.skip_discuss=true) — using ROADMAP phase goal as spec. +``` + +Write a minimal CONTEXT.md so downstream plan-phase has valid input. Get phase details: + +```bash +DETAIL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase ${PHASE_NUM}) +``` + +Extract `goal` and `requirements` from JSON. Write `${phase_dir}/${padded_phase}-CONTEXT.md` with: + +```markdown +# Phase {PHASE_NUM}: {Phase Name} - Context + +**Gathered:** {date} +**Status:** Ready for planning +**Mode:** Auto-generated (discuss skipped via workflow.skip_discuss) + + +## Phase Boundary + +{goal from ROADMAP phase description} + + + + +## Implementation Decisions + +### Claude's Discretion +All implementation choices are at Claude's discretion — discuss phase was skipped per user setting. Use ROADMAP phase goal, success criteria, and codebase conventions to guide decisions. + + + + +## Existing Code Insights + +Codebase context will be gathered during plan-phase research. + + + + +## Specific Ideas + +No specific requirements — discuss phase skipped. Refer to ROADMAP phase description and success criteria. + + + + +## Deferred Ideas + +None — discuss phase skipped. + + +``` + +Commit the minimal context: + +```bash +node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${PADDED_PHASE}): auto-generated context (discuss skipped)" --files "${phase_dir}/${padded_phase}-CONTEXT.md" +``` + +Proceed to 3b. + +**If SKIP_DISCUSS is `false` (or unset):** Execute the smart_discuss step for this phase. After smart_discuss completes, verify context was written: diff --git a/get-shit-done/workflows/settings.md b/get-shit-done/workflows/settings.md index 0ddcaa1e1..17c1bd593 100644 --- a/get-shit-done/workflows/settings.md +++ b/get-shit-done/workflows/settings.md @@ -144,6 +144,15 @@ AskUserQuestion([ { label: "No (Recommended)", description: "Ask questions directly. Faster, uses fewer tokens." }, { label: "Yes", description: "Search web for best practices before each question group. More informed questions but uses more tokens." } ] + }, + { + question: "Skip discuss-phase in autonomous mode? (use ROADMAP phase goals as spec)", + header: "Skip Discuss", + multiSelect: false, + options: [ + { label: "No (Recommended)", description: "Run smart discuss before each phase — surfaces gray areas and captures decisions." }, + { label: "Yes", description: "Skip discuss in /gsd:autonomous — chain directly to plan. Best for backend/pipeline work where phase descriptions are the spec." } + ] } ]) ``` @@ -166,7 +175,8 @@ Merge new settings into existing config.json: "ui_safety_gate": true/false, "text_mode": true/false, "research_before_questions": true/false, - "discuss_mode": "discuss" | "assumptions" + "discuss_mode": "discuss" | "assumptions", + "skip_discuss": true/false }, "git": { "branching_strategy": "none" | "phase" | "milestone", @@ -222,7 +232,8 @@ Write `~/.gsd/defaults.json` with: "auto_advance": , "nyquist_validation": , "ui_phase": , - "ui_safety_gate": + "ui_safety_gate": , + "skip_discuss": } } ``` @@ -247,6 +258,7 @@ Display: | UI Phase | {On/Off} | | UI Safety Gate | {On/Off} | | Git Branching | {None/Per Phase/Per Milestone} | +| Skip Discuss | {On/Off} | | Context Warnings | {On/Off} | | Saved as Defaults | {Yes/No} | @@ -264,7 +276,7 @@ Quick commands: - [ ] Current config read -- [ ] User presented with 9 settings (profile + 7 workflow toggles + git branching) +- [ ] User presented with 10 settings (profile + 8 workflow toggles + git branching) - [ ] Config updated with model_profile, workflow, and git sections - [ ] User offered to save as global defaults (~/.gsd/defaults.json) - [ ] Changes confirmed to user diff --git a/tests/config.test.cjs b/tests/config.test.cjs index 1a3255323..9671dbc0e 100644 --- a/tests/config.test.cjs +++ b/tests/config.test.cjs @@ -674,3 +674,78 @@ describe('config-set-model-profile command', () => { } }); }); + +// ─── config-set (workflow.skip_discuss) ─────────────────────────────────────── + +describe('config-set workflow.skip_discuss', () => { + let tmpDir; + + beforeEach(() => { + tmpDir = createTempProject(); + runGsdTools('config-ensure-section', tmpDir); + }); + + afterEach(() => { + cleanup(tmpDir); + }); + + test('workflow.skip_discuss is a valid config key', () => { + const result = runGsdTools('config-set workflow.skip_discuss true', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.skip_discuss, true); + }); + + test('skip_discuss defaults to false in new configs', () => { + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.skip_discuss, false); + }); + + test('skip_discuss can be toggled back to false', () => { + runGsdTools('config-set workflow.skip_discuss true', tmpDir); + const result = runGsdTools('config-set workflow.skip_discuss false', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.skip_discuss, false); + }); + + test('skip_discuss is present in config-new-project output', () => { + const emptyDir = createTempProject(); + try { + const result = runGsdTools(['config-new-project', '{}'], emptyDir, { HOME: emptyDir, USERPROFILE: emptyDir }); + assert.ok(result.success, `Command failed: ${result.error}`); + + const config = readConfig(emptyDir); + assert.strictEqual(config.workflow.skip_discuss, false, 'skip_discuss should default to false'); + } finally { + cleanup(emptyDir); + } + }); + + test('skip_discuss can be set via config-new-project choices', () => { + const emptyDir = createTempProject(); + try { + const choices = JSON.stringify({ + workflow: { skip_discuss: true }, + }); + const result = runGsdTools(['config-new-project', choices], emptyDir, { HOME: emptyDir, USERPROFILE: emptyDir }); + assert.ok(result.success, `Command failed: ${result.error}`); + + const config = readConfig(emptyDir); + assert.strictEqual(config.workflow.skip_discuss, true); + } finally { + cleanup(emptyDir); + } + }); + + test('config-get workflow.skip_discuss returns the set value', () => { + runGsdTools('config-set workflow.skip_discuss true', tmpDir); + const result = runGsdTools('config-get workflow.skip_discuss', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const output = JSON.parse(result.output); + assert.strictEqual(output, true); + }); +});