diff --git a/get-shit-done/workflows/autonomous.md b/get-shit-done/workflows/autonomous.md index c6363a32f..88fdeba7e 100644 --- a/get-shit-done/workflows/autonomous.md +++ b/get-shit-done/workflows/autonomous.md @@ -230,6 +230,9 @@ Proceed to 3b. **If SKIP_DISCUSS is `false` (or unset):** Execute the smart_discuss step for this phase. +**IMPORTANT — Discuss must be single-pass in autonomous mode.** +The discuss step in `--auto` mode MUST NOT loop. If CONTEXT.md already exists after discuss completes, do NOT re-invoke discuss for the same phase. The `has_context` check below is authoritative — once true, discuss is done for this phase regardless of perceived "gaps" in the context file. + After smart_discuss completes, verify context was written: ```bash diff --git a/get-shit-done/workflows/discuss-phase.md b/get-shit-done/workflows/discuss-phase.md index aaf6839ed..90a9f84ae 100644 --- a/get-shit-done/workflows/discuss-phase.md +++ b/get-shit-done/workflows/discuss-phase.md @@ -665,6 +665,16 @@ Each answer (or answer set, in batch mode) should reveal the next question or ne ``` After all areas are auto-resolved, skip the "Explore more gray areas" prompt and proceed directly to write_context. +**CRITICAL — Auto-mode pass cap:** +In `--auto` mode, the discuss step MUST complete in a **single pass**. After writing CONTEXT.md once, you are DONE — proceed immediately to write_context and then auto_advance. Do NOT re-read your own CONTEXT.md to find "gaps", "undefined types", or "missing decisions" and run additional passes. This creates a self-feeding loop where each pass generates references that the next pass treats as gaps, consuming unbounded time and resources. + +Check the pass cap from config: +```bash +MAX_PASSES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.max_discuss_passes 2>/dev/null || echo "3") +``` + +If you have already written and committed CONTEXT.md, the discuss step is complete. Move on. + **Interactive mode (no `--auto`):** **For each area:** diff --git a/sdk/prompts/workflows/discuss-phase.md b/sdk/prompts/workflows/discuss-phase.md index 4db4cc5c6..8c6abe155 100644 --- a/sdk/prompts/workflows/discuss-phase.md +++ b/sdk/prompts/workflows/discuss-phase.md @@ -64,6 +64,19 @@ Analyze the phase to identify gray areas: 5. **Log each decision** with rationale + +**CRITICAL — Single-pass guard:** +This step MUST complete in ONE pass. After writing CONTEXT.md, you are DONE. Do NOT re-read your own CONTEXT.md to identify "gaps", "undefined types", or "missing references" and run additional passes. Each decision naturally references other types and interfaces — this is expected, not a gap. The planner and executor will handle implementation details. + +Self-referential gap-finding creates an infinite loop where: +1. Pass N creates decisions referencing types/interfaces +2. Pass N+1 "discovers" those references as "gaps" +3. Pass N+1 creates new decisions that reference more types +4. Repeat forever + +Write your decisions once, comprehensively, then stop. + + Create CONTEXT.md capturing decisions made: diff --git a/sdk/src/config.ts b/sdk/src/config.ts index 381e2120d..0ab7b7ff2 100644 --- a/sdk/src/config.ts +++ b/sdk/src/config.ts @@ -31,6 +31,8 @@ export interface WorkflowConfig { research_before_questions: boolean; discuss_mode: string; skip_discuss: boolean; + /** Maximum self-discuss passes in auto/headless mode before forcing proceed. Default: 3. */ + max_discuss_passes: number; } export interface HooksConfig { @@ -82,6 +84,7 @@ export const CONFIG_DEFAULTS: GSDConfig = { research_before_questions: false, discuss_mode: 'discuss', skip_discuss: false, + max_discuss_passes: 3, }, hooks: { context_warnings: true, diff --git a/sdk/src/phase-runner.ts b/sdk/src/phase-runner.ts index 2e78139e8..c38a9a2d1 100644 --- a/sdk/src/phase-runner.ts +++ b/sdk/src/phase-runner.ts @@ -419,8 +419,9 @@ export class PhaseRunner { const contextFiles = await this.contextEngine.resolveContextFiles(PhaseType.Discuss); let prompt = await this.promptFactory.buildPrompt(PhaseType.Discuss, null, contextFiles); - // Supplement with self-discuss instructions - prompt += '\n\n## Self-Discuss Mode\n\nYou are the AI discussing decisions with yourself. No human is present. Identify 3-5 gray areas in the project scope, reason through each one, make opinionated choices, and write CONTEXT.md with your decisions.'; + // Supplement with self-discuss instructions with pass cap + const maxPasses = this.config.workflow.max_discuss_passes ?? 3; + prompt += `\n\n## Self-Discuss Mode\n\nYou are the AI discussing decisions with yourself. No human is present. Identify 3-5 gray areas in the project scope, reason through each one, make opinionated choices, and write CONTEXT.md with your decisions.\n\n**CRITICAL: Single-pass only.** You MUST complete all decisions in ONE pass and write CONTEXT.md once. Do NOT re-read your own CONTEXT.md to find "gaps" and do additional passes. The maximum allowed passes is ${maxPasses} — if you have already written CONTEXT.md, you are DONE. Proceed to the next workflow step. Self-referential gap-finding loops waste resources without adding value.`; planResult = await runPhaseStepSession( prompt,