feat: implement per-task atomic commits for better AI observability

- Each task commits immediately after completion (feat/fix/test/refactor)
- Plan completion commits metadata only (docs: SUMMARY + STATE + ROADMAP)
- Git history becomes primary context source for future Claude sessions
- Better bisect granularity, failure recovery, and revert capabilities

Changes:
- execute-phase.md: Added <task_commit> protocol and per-task commit flow
- execute-plan.md: Updated commit rules and success criteria
- git-integration.md: New task-completion format, strategy rationale
- tdd.md: Aligned TDD commits with standard task commit pattern
- summary.md: Added Task Commits section with commit hashes
- README.md: Rewrote git history section with atomic commit benefits
- scope-estimation.md: Clarified commit counts per plan
- principles.md: Added <atomic_commits> section explaining strategy

Each plan now produces 3-4 commits (2-3 task commits + 1 metadata commit)
instead of single monolithic commit. Optimizes observability for solo
developer + Claude Code workflow.
This commit is contained in:
Lex Christopherson
2026-01-05 16:09:14 -06:00
parent a6df00ab2a
commit 875ac900a2
8 changed files with 430 additions and 79 deletions

View File

@@ -171,9 +171,24 @@ GSD prevents this. Each plan is maximum 3 tasks. Each plan runs in a fresh subag
No degradation. Walk away, come back to completed work.
### Clean Git History
### Atomic Git Commits
Every task: atomic commit, clear message, summary documenting outcomes. Maintainable history you can trace.
Each task gets its own commit immediately after completion. Plans produce 2-4 commits total:
```bash
abc123f docs(08-02): complete user registration plan
def456g feat(08-02): add email confirmation flow
hij789k feat(08-02): implement password hashing
lmn012o feat(08-02): create registration endpoint
```
**Benefits:**
- Git bisect finds exact failing task
- Each task independently revertable
- Clear history for Claude in future sessions
- Better observability in AI-automated workflow
Every commit is surgical, traceable, and meaningful.
### Modular by Design

View File

@@ -14,10 +14,13 @@ allowed-tools:
---
<objective>
Execute a PLAN.md file, create SUMMARY.md, update project state, commit.
Execute a PLAN.md file with per-task atomic commits, create SUMMARY.md, update project state.
Commit strategy:
- Each task → 1 commit immediately after completion (feat/fix/test/refactor)
- Plan completion → 1 metadata commit (docs: SUMMARY + STATE + ROADMAP)
Uses intelligent segmentation:
- Plans without checkpoints → spawn subagent for full autonomous execution
- Plans with verify checkpoints → segment execution, pause at checkpoints
- Plans with decision checkpoints → execute in main context
@@ -88,23 +91,38 @@ Only rule 4 requires user intervention.
</deviation_rules>
<commit_rules>
**Critical: Stage only files this plan actually modified.**
**Per-Task Commits:**
NEVER use:
After each task completes:
1. Stage only files modified by that task
2. Commit with format: `{type}({phase}-{plan}): {task-name}`
3. Types: feat, fix, test, refactor, perf, chore
4. Record commit hash for SUMMARY.md
**Plan Metadata Commit:**
After all tasks complete:
1. Stage planning artifacts only: PLAN.md, SUMMARY.md, STATE.md, ROADMAP.md
2. Commit with format: `docs({phase}-{plan}): complete [plan-name] plan`
3. NO code files (already committed per-task)
**NEVER use:**
- `git add .`
- `git add -A`
- `git add src/` or any broad directory
Stage each file individually from the modified-files list.
**Always stage files individually.**
See ~/.claude/get-shit-done/references/git-integration.md for full commit strategy.
</commit_rules>
<success_criteria>
- [ ] All tasks executed
- [ ] SUMMARY.md created with substantive content
- [ ] Each task committed individually (feat/fix/test/refactor)
- [ ] SUMMARY.md created with substantive content and commit hashes
- [ ] STATE.md updated (position, decisions, issues, session)
- [ ] ROADMAP updated (plan count, phase status)
- [ ] Changes committed with feat({phase}-{plan}): [summary]
- [ ] Metadata committed with docs({phase}-{plan}): complete [plan-name] plan
- [ ] User informed of next steps
</success_criteria>

View File

@@ -11,14 +11,15 @@ The git log should read like a changelog of what shipped, not a diary of plannin
<commit_points>
| Event | Commit? | Why |
| ----------------------- | ------- | ------------------------------------- |
| BRIEF + ROADMAP created | YES | Project initialization |
| PLAN.md created | NO | Intermediate - commit with completion |
| RESEARCH.md created | NO | Intermediate |
| DISCOVERY.md created | NO | Intermediate |
| **Phase completed** | YES | Actual code shipped |
| Handoff created | YES | WIP state preserved |
| Event | Commit? | Why |
| ----------------------- | ------- | ------------------------------------------------ |
| BRIEF + ROADMAP created | YES | Project initialization |
| PLAN.md created | NO | Intermediate - commit with plan completion |
| RESEARCH.md created | NO | Intermediate |
| DISCOVERY.md created | NO | Intermediate |
| **Task completed** | YES | Atomic unit of work (1 commit per task) |
| **Plan completed** | YES | Metadata commit (SUMMARY + STATE + ROADMAP) |
| Handoff created | YES | WIP state preserved |
</commit_points>
@@ -56,30 +57,88 @@ git commit
</format>
<format name="phase-completion">
## Phase Completion
<format name="task-completion">
## Task Completion (During Plan Execution)
Each task gets its own commit immediately after completion.
```
feat([domain]): [one-liner from SUMMARY.md]
{type}({phase}-{plan}): {task-name}
- [Key accomplishment 1]
- [Key accomplishment 2]
- [Key accomplishment 3]
[If issues encountered:]
Note: [issue and resolution]
- [Key change 1]
- [Key change 2]
- [Key change 3]
```
Use `fix([domain])` for bug fix phases.
**Commit types:**
- `feat` - New feature/functionality
- `fix` - Bug fix
- `test` - Test-only (TDD RED phase)
- `refactor` - Code cleanup (TDD REFACTOR phase)
- `perf` - Performance improvement
- `chore` - Dependencies, config, tooling
**Examples:**
```bash
# Standard task
git add src/api/auth.ts src/types/user.ts
git commit -m "feat(08-02): create user registration endpoint
- POST /auth/register validates email and password
- Checks for duplicate users
- Returns JWT token on success
"
# TDD task - RED phase
git add src/__tests__/jwt.test.ts
git commit -m "test(07-02): add failing test for JWT generation
- Tests token contains user ID claim
- Tests token expires in 1 hour
- Tests signature verification
"
# TDD task - GREEN phase
git add src/utils/jwt.ts
git commit -m "feat(07-02): implement JWT generation
- Uses jose library for signing
- Includes user ID and expiry claims
- Signs with HS256 algorithm
"
```
</format>
<format name="plan-completion">
## Plan Completion (After All Tasks Done)
After all tasks committed, one final metadata commit captures plan completion.
```
docs({phase}-{plan}): complete [plan-name] plan
Tasks completed: [N]/[N]
- [Task 1 name]
- [Task 2 name]
- [Task 3 name]
SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
```
What to commit:
```bash
git add .planning/phases/XX-name/ # PLAN.md + SUMMARY.md
git add src/ # Actual code created
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
```
**Note:** Code files NOT included - already committed per-task.
</format>
<format name="handoff">
@@ -104,23 +163,92 @@ git commit
<example_log>
**Old approach (per-plan commits):**
```
a]7f2d1 feat(checkout): Stripe payments with webhook verification
b]3e9c4 feat(products): catalog with search, filters, and pagination
c]8a1b2 feat(auth): JWT with refresh rotation using jose
d]5c3d7 feat(foundation): Next.js 15 + Prisma + Tailwind scaffold
e]2f4a8 docs: initialize ecommerce-app (5 phases)
a7f2d1 feat(checkout): Stripe payments with webhook verification
3e9c4b feat(products): catalog with search, filters, and pagination
8a1b2c feat(auth): JWT with refresh rotation using jose
5c3d7e feat(foundation): Next.js 15 + Prisma + Tailwind scaffold
2f4a8d docs: initialize ecommerce-app (5 phases)
```
**New approach (per-task commits):**
```
# Phase 04 - Checkout
1a2b3c docs(04-01): complete checkout flow plan
4d5e6f feat(04-01): add webhook signature verification
7g8h9i feat(04-01): implement payment session creation
0j1k2l feat(04-01): create checkout page component
# Phase 03 - Products
3m4n5o docs(03-02): complete product listing plan
6p7q8r feat(03-02): add pagination controls
9s0t1u feat(03-02): implement search and filters
2v3w4x feat(03-01): create product catalog schema
# Phase 02 - Auth
5y6z7a docs(02-02): complete token refresh plan
8b9c0d feat(02-02): implement refresh token rotation
1e2f3g test(02-02): add failing test for token refresh
4h5i6j docs(02-01): complete JWT setup plan
7k8l9m feat(02-01): add JWT generation and validation
0n1o2p chore(02-01): install jose library
# Phase 01 - Foundation
3q4r5s docs(01-01): complete scaffold plan
6t7u8v feat(01-01): configure Tailwind and globals
9w0x1y feat(01-01): set up Prisma with database
2z3a4b feat(01-01): create Next.js 15 project
# Initialization
5c6d7e docs: initialize ecommerce-app (5 phases)
```
Each plan produces 2-4 commits (tasks + metadata). Clear, granular, bisectable.
</example_log>
<anti_patterns>
- PLAN.md creation (wait for phase completion)
**Still don't commit (intermediate artifacts):**
- PLAN.md creation (commit with plan completion)
- RESEARCH.md (intermediate)
- DISCOVERY.md (intermediate)
- Minor planning tweaks
- "Fixed typo in roadmap"
These create noise. Commit outcomes, not process.
**Do commit (outcomes):**
- Each task completion (feat/fix/test/refactor)
- Plan completion metadata (docs)
- Project initialization (docs)
**Key principle:** Commit working code and shipped outcomes, not planning process.
</anti_patterns>
<commit_strategy_rationale>
## Why Per-Task Commits?
**Context engineering for AI:**
- Git history becomes primary context source for future Claude sessions
- `git log --grep="{phase}-{plan}"` shows all work for a plan
- `git diff <hash>^..<hash>` shows exact changes per task
- Less reliance on parsing SUMMARY.md = more context for actual work
**Failure recovery:**
- Task 1 committed ✅, Task 2 failed ❌
- Claude in next session: sees task 1 complete, can retry task 2
- Can `git reset --hard` to last successful task
**Debugging:**
- `git bisect` finds exact failing task, not just failing plan
- `git blame` traces line to specific task context
- Each commit is independently revertable
**Observability:**
- Solo developer + Claude workflow benefits from granular attribution
- Atomic commits are git best practice
- "Commit noise" irrelevant when consumer is Claude, not humans
</commit_strategy_rationale>

View File

@@ -115,6 +115,29 @@ Plan → Execute → Ship → Learn → Repeat
Milestones mark shipped versions (v1.0 → v1.1 → v2.0).
</ship_fast>
<atomic_commits>
**Git commits = context engineering for Claude.**
Each task gets its own commit immediately after completion:
- Format: `{type}({phase}-{plan}): {task-description}`
- Types: feat, fix, test, refactor, perf, chore, docs
- One final metadata commit per plan: `docs({phase}-{plan}): complete [plan-name]`
**Why per-task commits:**
- Git history becomes primary context source for future Claude sessions
- `git bisect` finds exact failing task, not just failing plan
- Each task independently revertable
- Better failure recovery (task 1 committed ✅, retry task 2)
- Observability optimized for AI workflow, not human browsing
**Plans produce 3-4 commits total:**
- 2-3 task commits (working code)
- 1 metadata commit (SUMMARY + STATE + ROADMAP)
See `~/.claude/get-shit-done/references/git-integration.md` for complete strategy.
</atomic_commits>
<anti_enterprise>
NEVER include:

View File

@@ -80,7 +80,7 @@ Plan 1: "Auth Database Models" (2 tasks)
Plan 2: "Auth API Core" (3 tasks)
Plan 3: "Auth API Protection" (2 tasks)
Plan 4: "Auth UI Components" (2 tasks)
Each: 30-40% context, peak quality, focused commits
Each: 30-40% context, peak quality, atomic commits (2-3 task commits + 1 metadata commit)
```
</anti_patterns>
@@ -137,7 +137,7 @@ Each plan: fresh context, peak quality. More plans = more thoroughness, same qua
<summary>
**2-3 tasks, 50% context target:**
- All tasks: Peak quality
- Git: Atomic, surgical commits
- Git: Atomic per-task commits (each task = 1 commit, plan = 1 metadata commit)
- Autonomous plans: Subagent execution (fresh context)
**The principle:** Aggressive atomicity. More plans, smaller scope, consistent quality.
@@ -145,5 +145,7 @@ Each plan: fresh context, peak quality. More plans = more thoroughness, same qua
**The rule:** If in doubt, split. Quality over consolidation. Always.
**Depth rule:** Depth increases plan COUNT, never plan SIZE.
**Commit rule:** Each plan produces 3-4 commits total (2-3 task commits + 1 docs commit). More granular history = better observability for Claude.
</summary>
</scope_estimation>

View File

@@ -151,18 +151,37 @@ Follow project conventions for test location:
<commit_pattern>
## Commit Pattern for TDD Tasks
Each TDD task produces atomic commits:
TDD tasks produce 2-3 atomic commits (one per TDD phase):
```
test: add failing test for email validation
test({phase}-{plan}): add failing test for email validation
feat: implement email validation
- Tests valid email formats accepted
- Tests invalid formats rejected
- Tests empty input handling
refactor: extract regex to constant (optional)
feat({phase}-{plan}): implement email validation
- Regex pattern matches RFC 5322
- Returns boolean for validity
- Handles edge cases (empty, null)
refactor({phase}-{plan}): extract regex to constant (optional)
- Moved pattern to EMAIL_REGEX constant
- No behavior changes
- Tests still pass
```
This pattern:
- Creates clean git history
- Each commit is independently revertable
- Shows TDD discipline in commit log
**This aligns with the standard task commit pattern:**
- Non-TDD tasks: 1 commit per task (feat/fix)
- TDD tasks: 2-3 commits per task (test/feat/refactor)
Both follow same format: `{type}({phase}-{plan}): {description}`
**Benefits:**
- Each commit independently revertable
- Git bisect works at commit level (not just task level)
- Clear history showing TDD discipline
- Consistent with overall commit strategy
</commit_pattern>

View File

@@ -62,6 +62,18 @@ completed: YYYY-MM-DD
- [Second key accomplishment]
- [Third if applicable]
## Task Commits
Each task was committed atomically:
1. **Task 1: [task name]** - `abc123f` (feat/fix/test/refactor)
2. **Task 2: [task name]** - `def456g` (feat/fix/test/refactor)
3. **Task 3: [task name]** - `hij789k` (feat/fix/test/refactor)
**Plan metadata:** `lmn012o` (docs: complete plan)
_Note: TDD tasks may have multiple commits (test → feat → refactor)_
## Files Created/Modified
- `path/to/file.ts` - What it does
- `path/to/another.ts` - What it does
@@ -83,7 +95,7 @@ completed: YYYY-MM-DD
- **Fix:** [What was done]
- **Files modified:** [file paths]
- **Verification:** [How it was verified]
- **Commit:** [hash]
- **Committed in:** [hash] (part of task commit)
[... repeat for each auto-fix ...]
@@ -189,7 +201,7 @@ The one-liner should tell someone what actually shipped.
- **Fix:** Added bcrypt hashing on registration, comparison on login with salt rounds 10
- **Files modified:** src/app/api/auth/login/route.ts, src/lib/auth.ts
- **Verification:** Password hash test passes, plaintext never stored
- **Commit:** abc123f
- **Committed in:** abc123f (Task 2 commit)
**2. [Rule 3 - Blocking] Installed missing jose dependency**
- **Found during:** Task 4 (JWT token generation)
@@ -197,7 +209,7 @@ The one-liner should tell someone what actually shipped.
- **Fix:** Ran `npm install jose`
- **Files modified:** package.json, package-lock.json
- **Verification:** Import succeeds, build passes
- **Commit:** def456g
- **Committed in:** def456g (Task 4 commit)
### Deferred Enhancements

View File

@@ -440,8 +440,8 @@ Execute each task in the prompt. **Deviations are normal** - handle them automat
**If `type="auto"`:**
**Before executing:** Check if task has `tdd="true"` attribute:
- If yes: Follow TDD execution flow (see `<tdd_execution>`) - RED → GREEN → REFACTOR cycle with multiple atomic commits
- If no: Standard implementation with single commit
- If yes: Follow TDD execution flow (see `<tdd_execution>`) - RED → GREEN → REFACTOR cycle with atomic commits per stage
- If no: Standard implementation
- Work toward task completion
- **If CLI/API returns authentication error:** Handle as authentication gate (see below)
@@ -449,7 +449,8 @@ Execute each task in the prompt. **Deviations are normal** - handle them automat
- Continue implementing, applying rules as needed
- Run the verification
- Confirm done criteria met
- Track any deviations for Summary documentation
- **Commit the task** (see `<task_commit>` below)
- Track task completion and commit hash for Summary documentation
- Continue to next task
**If `type="checkpoint:*"`:**
@@ -860,8 +861,118 @@ After TDD task completion, ensure:
- All tests pass
- Test coverage for the new behavior exists
- No unrelated tests broken
**Note:** TDD tasks produce 2-3 commits (test/feat/refactor). Non-TDD tasks produce 1 commit after task completion.
</tdd_execution>
<task_commit>
## Task Commit Protocol
After each task completes (verification passed, done criteria met), commit immediately:
**1. Identify modified files:**
Track files changed during this specific task (not the entire plan):
```bash
git status --short
```
**2. Stage only task-related files:**
Stage each file individually (NEVER use `git add .` or `git add -A`):
```bash
# Example - adjust to actual files modified by this task
git add src/api/auth.ts
git add src/types/user.ts
```
**3. Determine commit type:**
| Type | When to Use | Example |
|------|-------------|---------|
| `feat` | New feature, endpoint, component, functionality | feat(08-02): create user registration endpoint |
| `fix` | Bug fix, error correction | fix(08-02): correct email validation regex |
| `test` | Test-only changes (TDD RED phase) | test(08-02): add failing test for password hashing |
| `refactor` | Code cleanup, no behavior change (TDD REFACTOR phase) | refactor(08-02): extract validation to helper |
| `perf` | Performance improvement | perf(08-02): add database index for user lookups |
| `docs` | Documentation changes | docs(08-02): add API endpoint documentation |
| `style` | Formatting, linting fixes | style(08-02): format auth module |
| `chore` | Config, tooling, dependencies | chore(08-02): add bcrypt dependency |
**4. Craft commit message:**
Format: `{type}({phase}-{plan}): {task-name-or-description}`
```bash
git commit -m "{type}({phase}-{plan}): {concise task description}
- {key change 1}
- {key change 2}
- {key change 3}
"
```
**Examples:**
```bash
# Non-TDD task
git commit -m "feat(08-02): create user registration endpoint
- POST /auth/register validates email and password
- Checks for duplicate users
- Returns JWT token on success
"
# TDD task - RED phase
git commit -m "test(07-02): add failing test for JWT generation
- Tests token contains user ID claim
- Tests token expires in 1 hour
- Tests signature verification
"
# TDD task - GREEN phase
git commit -m "feat(07-02): implement JWT generation
- Uses jose library for signing
- Includes user ID and expiry claims
- Signs with HS256 algorithm
"
# TDD task - REFACTOR phase
git commit -m "refactor(07-02): extract JWT config to constants
- Moved expiry time to constant
- Centralized algorithm selection
- No behavior changes
"
```
**5. Record commit hash:**
After committing, capture hash for SUMMARY.md:
```bash
TASK_COMMIT=$(git rev-parse --short HEAD)
echo "Task ${TASK_NUM} committed: ${TASK_COMMIT}"
```
Store in array or list for SUMMARY generation:
```bash
TASK_COMMITS+=("Task ${TASK_NUM}: ${TASK_COMMIT}")
```
**Atomic commit benefits:**
- Each task independently revertable
- Git bisect finds exact failing task
- Git blame traces line to specific task context
- Clear history for Claude in future sessions
- Better observability for AI-automated workflow
</task_commit>
<step name="checkpoint_protocol">
When encountering `type="checkpoint:*"`:
@@ -1181,16 +1292,11 @@ ROADMAP_FILE=".planning/ROADMAP.md"
- Add completion date
</step>
<step name="git_commit_plan">
Commit plan completion (SUMMARY + PROJECT-STATE + ROADMAP + modified code files):
<step name="git_commit_metadata">
Commit plan metadata (SUMMARY + STATE + ROADMAP):
**Critical: Stage only files this plan actually modified.**
NEVER use:
- `git add .`
- `git add -A`
- `git add src/` or any broad directory add
**Note:** All task code has already been committed during execution (one commit per task).
This final commit captures plan completion metadata only.
**1. Stage planning artifacts:**
@@ -1203,45 +1309,73 @@ git add .planning/STATE.md
**2. Stage roadmap file:**
```bash
if [ -f .planning/ROADMAP.md ]; then
git add .planning/ROADMAP.md
else
git add .planning/ROADMAP.md
fi
git add .planning/ROADMAP.md
```
**3. Stage only code files from the modified-files list**
**4. Verify staging before commit:**
**3. Verify staging:**
```bash
git status
# Confirm only expected files are staged
# Should show only planning artifacts, no code files
```
**5. Commit:**
**4. Commit metadata:**
```bash
git commit -m "$(cat <<'EOF'
feat({phase}-{plan}): [one-liner from SUMMARY.md]
docs({phase}-{plan}): complete [plan-name] plan
- [Key accomplishment 1]
- [Key accomplishment 2]
- [Key accomplishment 3]
Tasks completed: [N]/[N]
- [Task 1 name]
- [Task 2 name]
- [Task 3 name]
SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
EOF
)"
```
For commit message conventions and git workflow patterns, see ~/.claude/get-shit-done/references/git-integration.md
**Example:**
```bash
git commit -m "$(cat <<'EOF'
docs(08-02): complete user registration plan
Tasks completed: 3/3
- User registration endpoint
- Password hashing with bcrypt
- Email confirmation flow
SUMMARY: .planning/phases/08-user-auth/08-02-registration-SUMMARY.md
EOF
)"
```
**Git log after plan execution:**
```
abc123f docs(08-02): complete user registration plan
def456g feat(08-02): add email confirmation flow
hij789k feat(08-02): implement password hashing with bcrypt
lmn012o feat(08-02): create user registration endpoint
```
Each task has its own commit, followed by one metadata commit documenting plan completion.
For commit message conventions, see ~/.claude/get-shit-done/references/git-integration.md
</step>
<step name="update_codebase_map">
**If .planning/codebase/ exists:**
Check what changed in this plan:
Check what changed across all task commits in this plan:
```bash
git diff --name-only HEAD~1 2>/dev/null
# Find first task commit (right after previous plan's docs commit)
FIRST_TASK=$(git log --oneline --grep="feat({phase}-{plan}):" --grep="fix({phase}-{plan}):" --grep="test({phase}-{plan}):" --reverse | head -1 | cut -d' ' -f1)
# Get all changes from first task through now
git diff --name-only ${FIRST_TASK}^..HEAD 2>/dev/null
```
**Update only if structural changes occurred:**
@@ -1265,7 +1399,7 @@ Make single targeted edits - add a bullet point, update a path, or remove a stal
```bash
git add .planning/codebase/*.md
git commit --amend --no-edit # Include in plan commit
git commit --amend --no-edit # Include in metadata commit
```
**If .planning/codebase/ doesn't exist:**