From 5635d71ed1aa4e7b39c0c0863e1e65a1c0173179 Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Mon, 30 Mar 2026 20:23:29 -0700 Subject: [PATCH] fix(quick): enforce commit boundary between executor and orchestrator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Executor constraints now prohibit committing docs artifacts (SUMMARY.md, STATE.md, PLAN.md) — these are the orchestrator's responsibility in Step 8. Step 8 now explicitly stages all artifacts with git add before calling gsd-tools commit, and documents that it must always run even if the executor already committed some files. This prevents PLAN.md from being left untracked when the executor runs without worktree isolation (e.g. local repos with no remote, or when workflow.use_worktrees is false). Closes #1503 Co-Authored-By: Claude Opus 4.6 (1M context) --- get-shit-done/workflows/quick.md | 8 +++-- tests/quick-commit-boundary.test.cjs | 53 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/quick-commit-boundary.test.cjs diff --git a/get-shit-done/workflows/quick.md b/get-shit-done/workflows/quick.md index 89441f965..3aba0b0f5 100644 --- a/get-shit-done/workflows/quick.md +++ b/get-shit-done/workflows/quick.md @@ -552,8 +552,9 @@ ${AGENT_SKILLS_EXECUTOR} - Execute all tasks in the plan -- Commit each task atomically +- Commit each task atomically (code changes only) - Create summary at: ${QUICK_DIR}/${quick_id}-SUMMARY.md +- Do NOT commit docs artifacts (SUMMARY.md, STATE.md, PLAN.md) — the orchestrator handles the docs commit in Step 8 - Do NOT update ROADMAP.md (quick tasks are separate from planned phases) ", @@ -681,7 +682,7 @@ Use Edit tool to make these changes atomically **Step 8: Final commit and completion** -Stage and commit quick task artifacts: +Stage and commit quick task artifacts. This step MUST always run — even if the executor already committed some files (e.g. when running without worktree isolation). The `gsd-tools commit` command handles already-committed files gracefully. Build file list: - `${QUICK_DIR}/${quick_id}-PLAN.md` @@ -692,6 +693,9 @@ Build file list: - If `$FULL_MODE` and verification file exists: `${QUICK_DIR}/${quick_id}-VERIFICATION.md` ```bash +# Explicitly stage all artifacts before commit — PLAN.md may be untracked +# if the executor ran without worktree isolation and committed docs early +git add ${file_list} 2>/dev/null node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(quick-${quick_id}): ${DESCRIPTION}" --files ${file_list} ``` diff --git a/tests/quick-commit-boundary.test.cjs b/tests/quick-commit-boundary.test.cjs new file mode 100644 index 000000000..401b6398c --- /dev/null +++ b/tests/quick-commit-boundary.test.cjs @@ -0,0 +1,53 @@ +/** + * GSD Quick Workflow — Commit Boundary Tests (#1503) + * + * Validates that the quick workflow correctly separates executor + * responsibilities (code commits) from orchestrator responsibilities + * (docs artifact commit), preventing PLAN.md from being left untracked + * when the executor runs without worktree isolation. + */ + +const { test, describe } = require('node:test'); +const assert = require('node:assert'); +const fs = require('fs'); +const path = require('path'); + +const WORKFLOWS_DIR = path.join(__dirname, '..', 'get-shit-done', 'workflows'); + +describe('quick workflow commit boundary (#1503)', () => { + const quickPath = path.join(WORKFLOWS_DIR, 'quick.md'); + let content; + + test('quick.md exists', () => { + assert.ok(fs.existsSync(quickPath), 'workflows/quick.md should exist'); + content = fs.readFileSync(quickPath, 'utf-8'); + }); + + test('executor constraints prohibit committing docs artifacts', () => { + assert.ok( + content.includes('Do NOT commit docs artifacts'), + 'executor constraints should prohibit committing SUMMARY.md, STATE.md, PLAN.md' + ); + }); + + test('Step 8 explicitly stages artifacts with git add before commit', () => { + assert.ok( + content.includes('git add ${file_list}'), + 'Step 8 should explicitly git add the file list before gsd-tools commit' + ); + }); + + test('Step 8 includes PLAN.md in file list', () => { + assert.ok( + content.includes('${QUICK_DIR}/${quick_id}-PLAN.md'), + 'Step 8 file list must include PLAN.md' + ); + }); + + test('Step 8 runs unconditionally', () => { + assert.ok( + content.includes('MUST always run'), + 'Step 8 should state it must always run regardless of executor commits' + ); + }); +});