diff --git a/get-shit-done/bin/lib/config.cjs b/get-shit-done/bin/lib/config.cjs index 67fe5a6b9..9cfb7dc9f 100644 --- a/get-shit-done/bin/lib/config.cjs +++ b/get-shit-done/bin/lib/config.cjs @@ -22,6 +22,7 @@ const VALID_CONFIG_KEYS = new Set([ 'workflow.discuss_mode', 'workflow.skip_discuss', 'workflow._auto_chain_active', + 'workflow.use_worktrees', 'git.branching_strategy', 'git.phase_branch_template', 'git.milestone_branch_template', 'git.quick_branch_template', 'planning.commit_docs', 'planning.search_gitignored', 'hooks.context_warnings', diff --git a/get-shit-done/references/planning-config.md b/get-shit-done/references/planning-config.md index f8276c761..20ee56f37 100644 --- a/get-shit-done/references/planning-config.md +++ b/get-shit-done/references/planning-config.md @@ -24,6 +24,7 @@ Configuration options for `.planning/` directory behavior. | `git.phase_branch_template` | `"gsd/phase-{phase}-{slug}"` | Branch template for phase strategy | | `git.milestone_branch_template` | `"gsd/{milestone}-{slug}"` | Branch template for milestone strategy | | `git.quick_branch_template` | `null` | Optional branch template for quick-task runs | +| `workflow.use_worktrees` | `true` | Whether executor agents run in isolated git worktrees. Set to `false` to disable worktrees — agents execute sequentially on the main working tree instead. Recommended for solo developers or when worktree merges cause issues. | diff --git a/get-shit-done/workflows/diagnose-issues.md b/get-shit-done/workflows/diagnose-issues.md index ea53fe26e..47f3e09d6 100644 --- a/get-shit-done/workflows/diagnose-issues.md +++ b/get-shit-done/workflows/diagnose-issues.md @@ -55,6 +55,12 @@ gaps = [ +**Read worktree config:** + +```bash +USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.use_worktrees 2>/dev/null || echo "true") +``` + **Report diagnosis plan to user:** ``` @@ -92,7 +98,7 @@ For each gap, fill the debug-subagent-prompt template and spawn: Task( prompt=filled_debug_subagent_prompt + "\n\n\n- {phase_dir}/{phase_num}-UAT.md\n- .planning/STATE.md\n\n${AGENT_SKILLS_DEBUGGER}", subagent_type="gsd-debugger", - isolation="worktree", + ${USE_WORKTREES !== "false" ? 'isolation="worktree",' : ''} description="Debug: {truth_short}" ) ``` diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md index 0bdb11174..f403da146 100644 --- a/get-shit-done/workflows/execute-phase.md +++ b/get-shit-done/workflows/execute-phase.md @@ -68,6 +68,14 @@ AGENT_SKILLS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills Parse JSON for: `executor_model`, `verifier_model`, `commit_docs`, `parallelization`, `branching_strategy`, `branch_name`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `plans`, `incomplete_plans`, `plan_count`, `incomplete_count`, `state_exists`, `roadmap_exists`, `phase_req_ids`. +Read worktree config: + +```bash +USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.use_worktrees 2>/dev/null || echo "true") +``` + +When `USE_WORKTREES` is `false`, all executor agents run without `isolation="worktree"` — they execute sequentially on the main working tree instead of in parallel worktrees. + **If `phase_found` is false:** Error — phase directory not found. **If `plan_count` is 0:** Error — no plans found in phase. **If `state_exists` is false but `.planning/` exists:** Offer reconstruct or continue. @@ -223,6 +231,8 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT For 200k models, this keeps orchestrator context lean (~10-15%). For 1M+ models (Opus 4.6, Sonnet 4.6), richer context can be passed directly. + **Worktree mode** (`USE_WORKTREES` is not `false`): + ``` Task( subagent_type="gsd-executor", @@ -279,6 +289,19 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT ) ``` + **Sequential mode** (`USE_WORKTREES` is `false`): + + Omit `isolation="worktree"` from the Task call. Replace the `` block with: + + ``` + + You are running as a SEQUENTIAL executor agent on the main working tree. + Use normal git commits (with hooks). Do NOT use --no-verify. + + ``` + + When worktrees are disabled, execute plans **one at a time within each wave** (sequential) regardless of the `PARALLELIZATION` setting — multiple agents writing to the same working tree concurrently would cause conflicts. + 3. **Wait for all agents in wave to complete.** **Completion signal fallback (Copilot and runtimes where Task() may not return):** diff --git a/get-shit-done/workflows/execute-plan.md b/get-shit-done/workflows/execute-plan.md index cbbf71330..920e92ab9 100644 --- a/get-shit-done/workflows/execute-plan.md +++ b/get-shit-done/workflows/execute-plan.md @@ -72,7 +72,7 @@ grep -n "type=\"checkpoint" .planning/phases/XX-name/{phase}-{plan}-PLAN.md | Verify-only | B (segmented) | Segments between checkpoints. After none/human-verify → SUBAGENT. After decision/human-action → MAIN | | Decision | C (main) | Execute entirely in main context | -**Pattern A:** init_agent_tracking → spawn Task(subagent_type="gsd-executor", model=executor_model, isolation="worktree") with prompt: execute plan at [path], autonomous, all tasks + SUMMARY + commit, follow deviation/auth rules, report: plan name, tasks, SUMMARY path, commit hash → track agent_id → wait → update tracking → report. +**Pattern A:** init_agent_tracking → spawn Task(subagent_type="gsd-executor", model=executor_model) with prompt: execute plan at [path], autonomous, all tasks + SUMMARY + commit, follow deviation/auth rules, report: plan name, tasks, SUMMARY path, commit hash → track agent_id → wait → update tracking → report. **Include `isolation="worktree"` only if `workflow.use_worktrees` is not `false`** (read via `config-get workflow.use_worktrees`). **Pattern B:** Execute segment-by-segment. Autonomous segments: spawn subagent for assigned tasks only (no SUMMARY/commit). Checkpoints: main context. After all segments: aggregate, create SUMMARY, commit. See segment_execution. diff --git a/get-shit-done/workflows/quick.md b/get-shit-done/workflows/quick.md index 89441f965..bfd46f718 100644 --- a/get-shit-done/workflows/quick.md +++ b/get-shit-done/workflows/quick.md @@ -126,6 +126,10 @@ AGENT_SKILLS_VERIFIER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" age Parse JSON for: `planner_model`, `executor_model`, `checker_model`, `verifier_model`, `commit_docs`, `branch_name`, `quick_id`, `slug`, `date`, `timestamp`, `quick_dir`, `task_dir`, `roadmap_exists`, `planning_exists`. +```bash +USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.use_worktrees 2>/dev/null || echo "true") +``` + **If `roadmap_exists` is false:** Error — Quick mode requires an active project with ROADMAP.md. Run `/gsd:new-project` first. Quick tasks can run mid-phase - validation only checks ROADMAP.md exists, not phase status. @@ -559,7 +563,7 @@ ${AGENT_SKILLS_EXECUTOR} ", subagent_type="gsd-executor", model="{executor_model}", - isolation="worktree", + ${USE_WORKTREES !== "false" ? 'isolation="worktree",' : ''} description="Execute: ${DESCRIPTION}" ) ``` diff --git a/tests/config.test.cjs b/tests/config.test.cjs index 31a2da656..74fa46852 100644 --- a/tests/config.test.cjs +++ b/tests/config.test.cjs @@ -232,6 +232,16 @@ describe('config-set command', () => { assert.strictEqual(config.workflow.text_mode, true); }); + test('sets workflow.use_worktrees to disable worktree isolation', () => { + writeConfig(tmpDir, {}); + + const result = runGsdTools('config-set workflow.use_worktrees false', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const config = readConfig(tmpDir); + assert.strictEqual(config.workflow.use_worktrees, false); + }); + test('errors when no key path provided', () => { const result = runGsdTools('config-set', tmpDir); assert.strictEqual(result.success, false); diff --git a/tests/execute-phase-wave.test.cjs b/tests/execute-phase-wave.test.cjs index 871e9904c..d00b453db 100644 --- a/tests/execute-phase-wave.test.cjs +++ b/tests/execute-phase-wave.test.cjs @@ -105,4 +105,20 @@ describe('execute-phase docs: user-facing wave flag', () => { 'help.md should include wave-filter usage' ); }); + + test('workflow supports use_worktrees config toggle', () => { + const content = fs.readFileSync(WORKFLOW_PATH, 'utf-8'); + assert.ok( + content.includes('USE_WORKTREES'), + 'workflow should reference USE_WORKTREES variable' + ); + assert.ok( + content.includes('config-get workflow.use_worktrees'), + 'workflow should read use_worktrees from config' + ); + assert.ok( + content.includes('Sequential mode'), + 'workflow should document sequential mode when worktrees disabled' + ); + }); });