From 01c9115f3a72ac402c03882708a8c16d5b471980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=82CHES?= Date: Sun, 8 Feb 2026 08:09:03 -0600 Subject: [PATCH] fix(#478): respect commit_docs=false in all .planning commit paths (#482) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(execute-phase): pass file paths to subagents instead of content The --include flag added in fa81821 caused orchestrator context bloat by reading STATE, config, and plan files into the orchestrator's context, then embedding all content in Task() prompts. With multiple plans, this consumed 50-60%+ of context before execution. Fix: Pass file paths only. Subagents read files themselves in their fresh 200k context. Orchestrator stays lean (~10-15% as intended). Fixes #479 Co-Authored-By: Claude Opus 4.5 * fix: respect commit_docs=false in execute-plan and debugger workflows Two code paths bypassed the commit_docs configuration check, causing .planning files to be intermittently committed when commit_docs=false: 1. execute-plan.md: update_codebase_map step ran `git add .planning/codebase/*.md` unconditionally — now gated behind commit_docs check 2. gsd-debugger.md: used `git add -A` which stages .planning/ files — replaced with explicit individual file staging and proper commit_docs conditional Fixes #478 https://claude.ai/code/session_013yS1F2VR3Jn2pdwqr5NuDo * fix: route all .planning commits through gsd-tools.js CLI Instead of wrapping direct git commands in markdown conditionals, both bypass paths now use gsd-tools.js commit which has the commit_docs check built in: 1. execute-plan.md: uses `gsd-tools.js commit --amend` for codebase map updates (new --amend flag added to CLI) 2. gsd-debugger.md: code commit uses direct git (no .planning files), planning docs commit uses gsd-tools.js commit Also added --amend support to gsd-tools.js commit command so the execute-plan codebase map step can amend the previous metadata commit. Fixes #478 https://claude.ai/code/session_013yS1F2VR3Jn2pdwqr5NuDo * docs: update reference docs to use gsd-tools.js CLI for all .planning commits Reference documentation showed direct git add/commit patterns for .planning files, which agents copy-paste and bypass the commit_docs check. Updated all three reference files to show gsd-tools.js commit as the canonical pattern: - git-planning-commit.md: replaced manual bash conditionals with CLI - git-integration.md: replaced direct git add/commit in initialization, plan-completion, and handoff examples - planning-config.md: replaced conditional git example with CLI call https://claude.ai/code/session_013yS1F2VR3Jn2pdwqr5NuDo --------- Co-authored-by: Claude Opus 4.5 --- agents/gsd-debugger.md | 21 +++++------ get-shit-done/bin/gsd-tools.js | 14 ++++---- get-shit-done/references/git-integration.md | 12 ++----- .../references/git-planning-commit.md | 30 +++++----------- get-shit-done/references/planning-config.md | 9 +++-- get-shit-done/workflows/execute-phase.md | 35 ++++++------------- get-shit-done/workflows/execute-plan.md | 2 +- 7 files changed, 44 insertions(+), 79 deletions(-) diff --git a/agents/gsd-debugger.md b/agents/gsd-debugger.md index 66c485c89..db354673b 100644 --- a/agents/gsd-debugger.md +++ b/agents/gsd-debugger.md @@ -988,25 +988,20 @@ INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js state load) **Commit the fix:** -If `COMMIT_PLANNING_DOCS=true` (default): +Stage and commit code changes (NEVER `git add -A` or `git add .`): ```bash -git add -A -git commit -m "fix: {brief description} - -Root cause: {root_cause} -Debug session: .planning/debug/resolved/{slug}.md" -``` - -If `COMMIT_PLANNING_DOCS=false`: -```bash -# Only commit code changes, exclude .planning/ -git add -A -git reset .planning/ +git add src/path/to/fixed-file.ts +git add src/path/to/other-file.ts git commit -m "fix: {brief description} Root cause: {root_cause}" ``` +Then commit planning docs via CLI (respects `commit_docs` config automatically): +```bash +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs: resolve debug {slug}" --files .planning/debug/resolved/{slug}.md +``` + Report completion and offer next steps. diff --git a/get-shit-done/bin/gsd-tools.js b/get-shit-done/bin/gsd-tools.js index fd339f1dd..65243c745 100755 --- a/get-shit-done/bin/gsd-tools.js +++ b/get-shit-done/bin/gsd-tools.js @@ -865,8 +865,8 @@ function cmdFindPhase(cwd, phase, raw) { } } -function cmdCommit(cwd, message, files, raw) { - if (!message) { +function cmdCommit(cwd, message, files, raw, amend) { + if (!message && !amend) { error('commit message required'); } @@ -893,7 +893,8 @@ function cmdCommit(cwd, message, files, raw) { } // Commit - const commitResult = execGit(cwd, ['commit', '-m', message]); + const commitArgs = amend ? ['commit', '--amend', '--no-edit'] : ['commit', '-m', message]; + const commitResult = execGit(cwd, commitArgs); if (commitResult.exitCode !== 0) { if (commitResult.stdout.includes('nothing to commit') || commitResult.stderr.includes('nothing to commit')) { const result = { committed: false, hash: null, reason: 'nothing_to_commit' }; @@ -2095,11 +2096,12 @@ function main() { } case 'commit': { + const amend = args.includes('--amend'); const message = args[1]; - // Parse --files flag + // Parse --files flag (collect args after --files, stopping at other flags) const filesIndex = args.indexOf('--files'); - const files = filesIndex !== -1 ? args.slice(filesIndex + 1) : []; - cmdCommit(cwd, message, files, raw); + const files = filesIndex !== -1 ? args.slice(filesIndex + 1).filter(a => !a.startsWith('--')) : []; + cmdCommit(cwd, message, files, raw, amend); break; } diff --git a/get-shit-done/references/git-integration.md b/get-shit-done/references/git-integration.md index 2c554470a..44e2164ee 100644 --- a/get-shit-done/references/git-integration.md +++ b/get-shit-done/references/git-integration.md @@ -51,8 +51,7 @@ Phases: What to commit: ```bash -git add .planning/ -git commit +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs: initialize [project-name] ([N] phases)" --files .planning/ ``` @@ -130,11 +129,7 @@ SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md What to commit: ```bash -git add .planning/phases/XX-name/{phase}-{plan}-PLAN.md -git add .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md -git add .planning/STATE.md -git add .planning/ROADMAP.md -git commit +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md ``` **Note:** Code files NOT included - already committed per-task. @@ -154,8 +149,7 @@ Current: [task name] What to commit: ```bash -git add .planning/ -git commit +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/ ``` diff --git a/get-shit-done/references/git-planning-commit.md b/get-shit-done/references/git-planning-commit.md index e53584de5..11c19e3b2 100644 --- a/get-shit-done/references/git-planning-commit.md +++ b/get-shit-done/references/git-planning-commit.md @@ -1,35 +1,23 @@ # Git Planning Commit -Check whether to commit planning artifacts, then commit if enabled. +Commit planning artifacts using the gsd-tools CLI, which automatically checks `commit_docs` config and gitignore status. -## Check Configuration +## Commit via CLI + +Always use `gsd-tools.js commit` for `.planning/` files — it handles `commit_docs` and gitignore checks automatically: ```bash -# Check config.json first -COMMIT_PLANNING_DOCS=$(cat .planning/config.json 2>/dev/null | grep -o '"commit_docs"[[:space:]]*:[[:space:]]*[^,}]*' | grep -o 'true\|false' || echo "true") - -# Auto-detect gitignored (overrides config) -git check-ignore -q .planning 2>/dev/null && COMMIT_PLANNING_DOCS=false +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs({scope}): {description}" --files .planning/STATE.md .planning/ROADMAP.md ``` -Default: `true` if not set or config missing. +The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.planning/` is gitignored. No manual conditional checks needed. -## Conditional Commit +## Amend previous commit -Only run git operations if `COMMIT_PLANNING_DOCS=true`: +To fold `.planning/` file changes into the previous commit: ```bash -if [ "$COMMIT_PLANNING_DOCS" = "true" ]; then - git add .planning/STATE.md .planning/ROADMAP.md - git commit -m "$(cat <<'EOF' -docs({scope}): {description} - -{optional body} - -Co-Authored-By: Claude -EOF -)" -fi +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "" --files .planning/codebase/*.md --amend ``` ## Commit Message Patterns diff --git a/get-shit-done/references/planning-config.md b/get-shit-done/references/planning-config.md index a91495278..a7f09b26d 100644 --- a/get-shit-done/references/planning-config.md +++ b/get-shit-done/references/planning-config.md @@ -53,15 +53,14 @@ INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js init execute-phase "1") **Auto-detection:** If `.planning/` is gitignored, `commit_docs` is automatically `false` regardless of config.json. This prevents git errors when users have `.planning/` in `.gitignore`. -**Conditional git operations:** +**Commit via CLI (handles checks automatically):** ```bash -if [ "$COMMIT_DOCS" = "true" ]; then - git add .planning/STATE.md - git commit -m "docs: update state" -fi +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "docs: update state" --files .planning/STATE.md ``` +The CLI checks `commit_docs` config and gitignore status internally — no manual conditionals needed. + diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md index 0a44315ac..1db8ea5a6 100644 --- a/get-shit-done/workflows/execute-phase.md +++ b/get-shit-done/workflows/execute-phase.md @@ -13,16 +13,14 @@ Read STATE.md before any operation to load project context. -Load all context in one call (include file contents to avoid redundant reads): +Load all context in one call: ```bash -INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js init execute-phase "${PHASE_ARG}" --include state,config) +INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js init execute-phase "${PHASE_ARG}") ``` 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`. -**File contents (from --include):** `state_content`, `config_content`. These are null if files don't exist. - **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. @@ -96,17 +94,10 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true` - Bad: "Executing terrain generation plan" - Good: "Procedural terrain generator using Perlin noise — creates height maps, biome zones, and collision meshes. Required before vehicle physics can interact with ground." -2. **Read files and spawn agents:** +2. **Spawn agents with file paths (not content):** - Content must be inlined — `@` syntax doesn't work across Task() boundaries. - STATE and CONFIG are already loaded via `--include` in initialize step. - - ```bash - PLAN_CONTENT=$(cat "{plan_path}") - # Use state_content and config_content from INIT (no need to re-read) - STATE_CONTENT=$(echo "$INIT" | jq -r '.state_content // empty') - CONFIG_CONTENT=$(echo "$INIT" | jq -r '.config_content // empty') - ``` + Pass paths only — executors read files themselves with their fresh 200k context. + This keeps orchestrator context lean (~10-15%). Each agent prompt: @@ -123,16 +114,12 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true` @~/.claude/get-shit-done/references/tdd.md - - Plan: - {plan_content} - - Project state: - {state_content} - - Config (if exists): - {config_content} - + + Read these files at execution start using the Read tool: + - Plan: {phase_dir}/{plan_file} + - State: .planning/STATE.md + - Config: .planning/config.json (if exists) + - [ ] All tasks executed diff --git a/get-shit-done/workflows/execute-plan.md b/get-shit-done/workflows/execute-plan.md index bdaf124b7..9a92a9e05 100644 --- a/get-shit-done/workflows/execute-plan.md +++ b/get-shit-done/workflows/execute-plan.md @@ -365,7 +365,7 @@ git diff --name-only ${FIRST_TASK}^..HEAD 2>/dev/null Update only structural changes: new src/ dir → STRUCTURE.md | deps → STACK.md | file pattern → CONVENTIONS.md | API client → INTEGRATIONS.md | config → STACK.md | renamed → update paths. Skip code-only/bugfix/content changes. ```bash -git add .planning/codebase/*.md && git commit --amend --no-edit +node ~/.claude/get-shit-done/bin/gsd-tools.js commit "" --files .planning/codebase/*.md --amend ```