Merge pull request #1307 from gsd-build/feat/workflow-skip-discuss-1304

feat: add workflow.skip_discuss setting to bypass discuss-phase
This commit is contained in:
Tom Boucher
2026-03-21 18:30:27 -04:00
committed by GitHub
4 changed files with 165 additions and 4 deletions

View File

@@ -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,

View File

@@ -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)
<domain>
## Phase Boundary
{goal from ROADMAP phase description}
</domain>
<decisions>
## 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.
</decisions>
<code_context>
## Existing Code Insights
Codebase context will be gathered during plan-phase research.
</code_context>
<specifics>
## Specific Ideas
No specific requirements — discuss phase skipped. Refer to ROADMAP phase description and success criteria.
</specifics>
<deferred>
## Deferred Ideas
None — discuss phase skipped.
</deferred>
```
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:

View File

@@ -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": <current>,
"nyquist_validation": <current>,
"ui_phase": <current>,
"ui_safety_gate": <current>
"ui_safety_gate": <current>,
"skip_discuss": <current>
}
}
```
@@ -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:
<success_criteria>
- [ ] 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

View File

@@ -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);
});
});