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:
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user