| name | mu-code |
| description | Use when you have an implementation plan ready to execute - supports subagent-driven and inline execution modes with TDD, worktree isolation, and review gates |
Code
Overview
Execute implementation plan task by task. Two modes: subagent-driven (recommended) or inline.
Core principle: Fresh subagent per task + two-stage review (spec then quality) = high quality, fast iteration
Announce at start: "I'm using the mu-code skill to implement this plan."
Process
digraph process_overview {
rankdir=TB;
"Read plan, extract tasks" [shape=box];
"Step 1: Worktree Setup" [shape=box style=filled fillcolor=lightyellow];
"Step 2: Select Execution Mode" [shape=diamond];
"Subagent-Driven Mode" [shape=box];
"Inline Mode" [shape=box];
"Parallel Dispatch" [shape=box];
"Per-task loop: implement → review → next" [shape=box];
"All tasks complete" [shape=diamond];
"Chain to mu-review" [shape=box style=filled fillcolor=lightgreen];
"Read plan, extract tasks" -> "Step 1: Worktree Setup";
"Step 1: Worktree Setup" -> "Step 2: Select Execution Mode";
"Step 2: Select Execution Mode" -> "Subagent-Driven Mode" [label="subagents available\n(recommended)"];
"Step 2: Select Execution Mode" -> "Inline Mode" [label="no subagents /\nparallel session"];
"Step 2: Select Execution Mode" -> "Parallel Dispatch" [label="multiple independent\nfailures/tasks"];
"Subagent-Driven Mode" -> "Per-task loop: implement → review → next";
"Inline Mode" -> "Per-task loop: implement → review → next";
"Parallel Dispatch" -> "Per-task loop: implement → review → next";
"Per-task loop: implement → review → next" -> "All tasks complete";
"All tasks complete" -> "Chain to mu-review" [label="yes"];
"All tasks complete" -> "Per-task loop: implement → review → next" [label="no - next task"];
}
Step 1: Worktree Setup
Git worktrees create isolated workspaces sharing the same repository, allowing work on multiple branches simultaneously without switching.
Core principle: Systematic directory selection + safety verification = reliable isolation.
Directory Selection Process
Follow this priority order:
1. Check Existing Directories
ls -d .worktrees 2>/dev/null
ls -d worktrees 2>/dev/null
If found: Use that directory. If both exist, .worktrees wins.
2. Check CLAUDE.md
grep -i "worktree.*director" CLAUDE.md 2>/dev/null
If preference specified: Use it without asking.
3. Ask User
If no directory exists and no CLAUDE.md preference:
No worktree directory found. Where should I create worktrees?
1. .worktrees/ (project-local, hidden)
2. ~/.config/devmuse/worktrees/<project-name>/ (global location)
Which would you prefer?
Safety Verification
For Project-Local Directories (.worktrees or worktrees)
MUST verify directory is ignored before creating worktree:
git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
If NOT ignored:
Per Jesse's rule "Fix broken things immediately":
- Add appropriate line to .gitignore
- Commit the change
- Proceed with worktree creation
Why critical: Prevents accidentally committing worktree contents to repository.
For Global Directory (~/.config/devmuse/worktrees)
No .gitignore verification needed - outside project entirely.
Creation Steps
1. Detect Project Name
project=$(basename "$(git rev-parse --show-toplevel)")
2. Create Worktree
case $LOCATION in
.worktrees|worktrees)
path="$LOCATION/$BRANCH_NAME"
;;
~/.config/devmuse/worktrees/*)
path="~/.config/devmuse/worktrees/$project/$BRANCH_NAME"
;;
esac
git worktree add "$path" -b "$BRANCH_NAME"
cd "$path"
3. Run Project Setup
Auto-detect and run appropriate setup:
if [ -f package.json ]; then npm install; fi
if [ -f Cargo.toml ]; then cargo build; fi
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f pyproject.toml ]; then poetry install; fi
if [ -f go.mod ]; then go mod download; fi
4. Verify Clean Baseline
Run tests to ensure worktree starts clean:
npm test
cargo test
pytest
go test ./...
If tests fail: Report failures, ask whether to proceed or investigate.
If tests pass: Report ready.
5. Report Location
Worktree ready at <full-path>
Tests passing (<N> tests, 0 failures)
Ready to implement <feature-name>
Worktree Quick Reference
| Situation | Action |
|---|
.worktrees/ exists | Use it (verify ignored) |
worktrees/ exists | Use it (verify ignored) |
| Both exist | Use .worktrees/ |
| Neither exists | Check CLAUDE.md → Ask user |
| Directory not ignored | Add to .gitignore + commit |
| Tests fail during baseline | Report failures + ask |
| No package.json/Cargo.toml | Skip dependency install |
Common Worktree Mistakes
Skipping ignore verification
- Problem: Worktree contents get tracked, pollute git status
- Fix: Always use
git check-ignore before creating project-local worktree
Assuming directory location
- Problem: Creates inconsistency, violates project conventions
- Fix: Follow priority: existing > CLAUDE.md > ask
Proceeding with failing tests
- Problem: Can't distinguish new bugs from pre-existing issues
- Fix: Report failures, get explicit permission to proceed
Hardcoding setup commands
- Problem: Breaks on projects using different tools
- Fix: Auto-detect from project files (package.json, etc.)
Step 2: Execution Mode Selection
digraph when_to_use {
"Have implementation plan?" [shape=diamond];
"Tasks mostly independent?" [shape=diamond];
"Subagents available?" [shape=diamond];
"Subagent-Driven Mode" [shape=box];
"Inline Mode" [shape=box];
"Manual execution or brainstorm first" [shape=box];
"Have implementation plan?" -> "Tasks mostly independent?" [label="yes"];
"Have implementation plan?" -> "Manual execution or brainstorm first" [label="no"];
"Tasks mostly independent?" -> "Subagents available?" [label="yes"];
"Tasks mostly independent?" -> "Manual execution or brainstorm first" [label="no - tightly coupled"];
"Subagents available?" -> "Subagent-Driven Mode" [label="yes (recommended)"];
"Subagents available?" -> "Inline Mode" [label="no / parallel session"];
}
Subagent-Driven Mode (Recommended)
Execute plan by dispatching fresh subagent per task, with two-stage review after each: spec compliance review first, then code quality review.
Why subagents: You delegate tasks to specialized agents with isolated context. By precisely crafting their instructions and context, you ensure they stay focused and succeed at their task. They should never inherit your session's context or history — you construct exactly what they need. This also preserves your own context for coordination work.
Per-Task Process
digraph process {
rankdir=TB;
subgraph cluster_per_task {
label="Per Task";
"Dispatch implementer subagent (@../../agents/mu-coder.md)" [shape=box];
"Implementer subagent asks questions?" [shape=diamond];
"Answer questions, provide context" [shape=box];
"Implementer subagent implements, tests, commits, self-reviews" [shape=box];
"Dispatch spec reviewer subagent (@../../agents/mu-reviewer.md review-compliance)" [shape=box];
"Spec reviewer subagent confirms code matches spec?" [shape=diamond];
"Implementer subagent fixes spec gaps" [shape=box];
"Dispatch code quality reviewer subagent (@../../agents/mu-reviewer.md review-code)" [shape=box];
"Code quality reviewer subagent approves?" [shape=diamond];
"Implementer subagent fixes quality issues" [shape=box];
"Mark task complete in TodoWrite" [shape=box];
}
"Read plan, extract all tasks with full text, note context, create TodoWrite" [shape=box];
"More tasks remain?" [shape=diamond];
"Chain to mu-review for final review" [shape=box style=filled fillcolor=lightgreen];
"Read plan, extract all tasks with full text, note context, create TodoWrite" -> "Dispatch implementer subagent (@../../agents/mu-coder.md)";
"Dispatch implementer subagent (@../../agents/mu-coder.md)" -> "Implementer subagent asks questions?";
"Implementer subagent asks questions?" -> "Answer questions, provide context" [label="yes"];
"Answer questions, provide context" -> "Dispatch implementer subagent (@../../agents/mu-coder.md)";
"Implementer subagent asks questions?" -> "Implementer subagent implements, tests, commits, self-reviews" [label="no"];
"Implementer subagent implements, tests, commits, self-reviews" -> "Dispatch spec reviewer subagent (@../../agents/mu-reviewer.md review-compliance)";
"Dispatch spec reviewer subagent (@../../agents/mu-reviewer.md review-compliance)" -> "Spec reviewer subagent confirms code matches spec?";
"Spec reviewer subagent confirms code matches spec?" -> "Implementer subagent fixes spec gaps" [label="no"];
"Implementer subagent fixes spec gaps" -> "Dispatch spec reviewer subagent (@../../agents/mu-reviewer.md review-compliance)" [label="re-review"];
"Spec reviewer subagent confirms code matches spec?" -> "Dispatch code quality reviewer subagent (@../../agents/mu-reviewer.md review-code)" [label="yes"];
"Dispatch code quality reviewer subagent (@../../agents/mu-reviewer.md review-code)" -> "Code quality reviewer subagent approves?";
"Code quality reviewer subagent approves?" -> "Implementer subagent fixes quality issues" [label="no"];
"Implementer subagent fixes quality issues" -> "Dispatch code quality reviewer subagent (@../../agents/mu-reviewer.md review-code)" [label="re-review"];
"Code quality reviewer subagent approves?" -> "Mark task complete in TodoWrite" [label="yes"];
"Mark task complete in TodoWrite" -> "More tasks remain?";
"More tasks remain?" -> "Dispatch implementer subagent (@../../agents/mu-coder.md)" [label="yes"];
"More tasks remain?" -> "Chain to mu-review for final review" [label="no"];
}
Model Selection
Choose between two tiers only. Do not use haiku — implementation and review quality suffers too much to be worth the savings.
Simple implementation tasks (isolated functions, clear specs, 1-2 files, mechanical edits): use sonnet.
Everything else (multi-file integration, judgment calls, debugging, architecture, design, review): use opus.
Task complexity signals:
- Touches 1-2 files with a complete, mechanical spec → sonnet
- Touches multiple files, requires integration/judgment → opus
- Requires design judgment or broad codebase understanding → opus
When in doubt, prefer opus. Never pass model: "haiku" when dispatching mu-coder or mu-reviewer.
Handling Implementer Status
Implementer subagents report one of four statuses. Handle each appropriately:
DONE: Proceed to spec compliance review.
DONE_WITH_CONCERNS: The implementer completed the work but flagged doubts. Read the concerns before proceeding. If the concerns are about correctness or scope, address them before review. If they're observations (e.g., "this file is getting large"), note them and proceed to review.
NEEDS_CONTEXT: The implementer needs information that wasn't provided. Provide the missing context and re-dispatch.
BLOCKED: The implementer cannot complete the task. Assess the blocker:
- If it's a context problem, provide more context and re-dispatch with the same model
- If the task requires more reasoning, re-dispatch with a more capable model
- If the task is too large, break it into smaller pieces
- If the plan itself is wrong, escalate to the human
Never ignore an escalation or force the same model to retry without changes. If the implementer said it's stuck, something needs to change.
Subagent-Driven Example Workflow
You: I'm using the mu-code skill to implement this plan.
[Read plan file once: docs/plans/feature-plan.md]
[Extract all 5 tasks with full text and context]
[Create TodoWrite with all tasks]
Task 1: Hook installation script
[Get Task 1 text and context (already extracted)]
[Dispatch implementation subagent with full task text + context]
Implementer: "Before I begin - should the hook be installed at user or system level?"
You: "User level (~/.config/devmuse/hooks/)"
Implementer: "Got it. Implementing now..."
[Later] Implementer:
- Implemented install-hook command
- Added tests, 5/5 passing
- Self-review: Found I missed --force flag, added it
- Committed
[Dispatch spec compliance reviewer]
Spec reviewer: ✅ Spec compliant - all requirements met, nothing extra
[Get git SHAs, dispatch code quality reviewer]
Code reviewer: Strengths: Good test coverage, clean. Issues: None. Approved.
[Mark Task 1 complete]
Task 2: Recovery modes
[Get Task 2 text and context (already extracted)]
[Dispatch implementation subagent with full task text + context]
Implementer: [No questions, proceeds]
Implementer:
- Added verify/repair modes
- 8/8 tests passing
- Self-review: All good
- Committed
[Dispatch spec compliance reviewer]
Spec reviewer: ❌ Issues:
- Missing: Progress reporting (spec says "report every 100 items")
- Extra: Added --json flag (not requested)
[Implementer fixes issues]
Implementer: Removed --json flag, added progress reporting
[Spec reviewer reviews again]
Spec reviewer: ✅ Spec compliant now
[Dispatch code quality reviewer]
Code reviewer: Strengths: Solid. Issues (Important): Magic number (100)
[Implementer fixes]
Implementer: Extracted PROGRESS_INTERVAL constant
[Code reviewer reviews again]
Code reviewer: ✅ Approved
[Mark Task 2 complete]
...
[After all tasks]
[Chain to mu-review for final review]
Final reviewer: All requirements met, ready to merge
Done!
Inline Mode
Load plan, review critically, execute all tasks directly without subagents, report when complete.
Note: If subagents are available, use Subagent-Driven Mode instead for significantly higher quality output.
Step 1: Load and Review Plan
- Read plan file
- Review critically - identify any questions or concerns about the plan
- If concerns: Raise them with your human partner before starting
- If no concerns: Create TodoWrite and proceed
Step 2: Execute Tasks
For each task:
- Mark as in_progress
- Follow each step exactly (plan has bite-sized steps)
- Run verifications as specified
- Mark as completed
Step 3: Complete Development
After all tasks complete and verified:
- Chain to mu-review for final review
- Follow that skill to verify tests, present options, execute choice
When to Stop and Ask for Help
STOP executing immediately when:
- Hit a blocker (missing dependency, test fails, instruction unclear)
- Plan has critical gaps preventing starting
- You don't understand an instruction
- Verification fails repeatedly
Ask for clarification rather than guessing.
When to Revisit Earlier Steps
Return to Review (Step 1) when:
- Partner updates the plan based on your feedback
- Fundamental approach needs rethinking
Don't force through blockers - stop and ask.
Inline Mode Reminders
- Review plan critically first
- Follow plan steps exactly
- Don't skip verifications
- Reference skills when plan says to
- Stop when blocked, don't guess
- Never start implementation on main/master branch without explicit user consent
- Before any branch operation (checkout, create, rebase), follow Git Safety Protocol (@../../knowledge/principles/git-safety.md): verify current state before acting
Parallel Dispatch
You delegate tasks to specialized agents with isolated context. By precisely crafting their instructions and context, you ensure they stay focused and succeed at their task. They should never inherit your session's context or history — you construct exactly what they need. This also preserves your own context for coordination work.
When you have multiple unrelated failures (different test files, different subsystems, different bugs), investigating them sequentially wastes time. Each investigation is independent and can happen in parallel.
Core principle: Dispatch one agent per independent problem domain. Let them work concurrently.
When to Use Parallel Dispatch
digraph when_to_use {
"Multiple failures?" [shape=diamond];
"Are they independent?" [shape=diamond];
"Single agent investigates all" [shape=box];
"One agent per problem domain" [shape=box];
"Can they work in parallel?" [shape=diamond];
"Sequential agents" [shape=box];
"Parallel dispatch" [shape=box];
"Multiple failures?" -> "Are they independent?" [label="yes"];
"Are they independent?" -> "Single agent investigates all" [label="no - related"];
"Are they independent?" -> "Can they work in parallel?" [label="yes"];
"Can they work in parallel?" -> "Parallel dispatch" [label="yes"];
"Can they work in parallel?" -> "Sequential agents" [label="no - shared state"];
}
Use when:
- 3+ test files failing with different root causes
- Multiple subsystems broken independently
- Each problem can be understood without context from others
- No shared state between investigations
Don't use when:
- Failures are related (fix one might fix others)
- Need to understand full system state
- Agents would interfere with each other
The Pattern
1. Identify Independent Domains
Group failures by what's broken:
- File A tests: Tool approval flow
- File B tests: Batch completion behavior
- File C tests: Abort functionality
Each domain is independent - fixing tool approval doesn't affect abort tests.
2. Create Focused Agent Tasks
Each agent gets:
- Specific scope: One test file or subsystem
- Clear goal: Make these tests pass
- Constraints: Don't change other code
- Expected output: Summary of what you found and fixed
3. Dispatch in Parallel
Task("Fix agent-tool-abort.test.ts failures")
Task("Fix batch-completion-behavior.test.ts failures")
Task("Fix tool-approval-race-conditions.test.ts failures")
4. Review and Integrate
When agents return:
- Read each summary
- Verify fixes don't conflict
- Run full test suite
- Integrate all changes
Agent Prompt Structure
Good agent prompts are:
- Focused - One clear problem domain
- Self-contained - All context needed to understand the problem
- Specific about output - What should the agent return?
Fix the 3 failing tests in src/agents/agent-tool-abort.test.ts:
1. "should abort tool with partial output capture" - expects 'interrupted at' in message
2. "should handle mixed completed and aborted tools" - fast tool aborted instead of completed
3. "should properly track pendingToolCount" - expects 3 results but gets 0
These are timing/race condition issues. Your task:
1. Read the test file and understand what each test verifies
2. Identify root cause - timing issues or actual bugs?
3. Fix by:
- Replacing arbitrary timeouts with event-based waiting
- Fixing bugs in abort implementation if found
- Adjusting test expectations if testing changed behavior
Do NOT just increase timeouts - find the real issue.
Return: Summary of what you found and what you fixed.
Common Parallel Dispatch Mistakes
Too broad: "Fix all the tests" - agent gets lost
Specific: "Fix agent-tool-abort.test.ts" - focused scope
No context: "Fix the race condition" - agent doesn't know where
Context: Paste the error messages and test names
No constraints: Agent might refactor everything
Constraints: "Do NOT change production code" or "Fix tests only"
Vague output: "Fix it" - you don't know what changed
Specific: "Return summary of root cause and changes"
When NOT to Use Parallel Dispatch
Related failures: Fixing one might fix others - investigate together first
Need full context: Understanding requires seeing entire system
Exploratory debugging: You don't know what's broken yet
Shared state: Agents would interfere (editing same files, using same resources)
Parallel Dispatch Verification
After agents return:
- Review each summary - Understand what changed
- Check for conflicts - Did agents edit same code?
- Run full suite - Verify all fixes work together
- Spot check - Agents can make systematic errors
Tidy First Discipline
Separate all changes into two distinct types:
- STRUCTURAL — Rearranging code without changing behavior
- BEHAVIORAL — Adding or modifying actual functionality
- Never mix structural and behavioral changes in the same commit
- Always make structural changes first when both are needed
- Commit messages must state whether the commit is structural or behavioral
- Before restructuring or removing existing code, apply Chesterton's Fence (@../../knowledge/principles/chestertons-fence.md): understand why the code exists before changing it
TDD Discipline
Write the test first. Watch it fail. Write minimal code to pass.
Core principle: If you didn't watch the test fail, you don't know if it tests the right thing.
Violating the letter of the rules is violating the spirit of the rules.
When to Use TDD
Always:
- New features
- Bug fixes
- Refactoring
- Behavior changes
Exceptions (ask your human partner):
- Throwaway prototypes
- Generated code
- Configuration files
Thinking "skip TDD just this once"? Stop. That's rationalization.
The Iron Law
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
Write code before the test? Delete it. Start over.
No exceptions:
- Don't keep it as "reference"
- Don't "adapt" it while writing tests
- Don't look at it
- Delete means delete
Implement fresh from tests. Period.
Red-Green-Refactor
digraph tdd_cycle {
rankdir=LR;
red [label="RED\nWrite failing test", shape=box, style=filled, fillcolor="#ffcccc"];
verify_red [label="Verify fails\ncorrectly", shape=diamond];
green [label="GREEN\nMinimal code", shape=box, style=filled, fillcolor="#ccffcc"];
verify_green [label="Verify passes\nAll green", shape=diamond];
refactor [label="REFACTOR\nClean up", shape=box, style=filled, fillcolor="#ccccff"];
next [label="Next", shape=ellipse];
red -> verify_red;
verify_red -> green [label="yes"];
verify_red -> red [label="wrong\nfailure"];
green -> verify_green;
verify_green -> refactor [label="yes"];
verify_green -> green [label="no"];
refactor -> verify_green [label="stay\ngreen"];
verify_green -> next;
next -> red;
}
RED - Write Failing Test
Write one minimal test showing what should happen.
```typescript
test('retries failed operations 3 times', async () => {
let attempts = 0;
const operation = () => {
attempts++;
if (attempts < 3) throw new Error('fail');
return 'success';
};
const result = await retryOperation(operation);
expect(result).toBe('success');
expect(attempts).toBe(3);
});
Clear name, tests real behavior, one thing
</Good>
<Bad>
```typescript
test('retry works', async () => {
const mock = jest.fn()
.mockRejectedValueOnce(new Error())
.mockRejectedValueOnce(new Error())
.mockResolvedValueOnce('success');
await retryOperation(mock);
expect(mock).toHaveBeenCalledTimes(3);
});
Vague name, tests mock not code
Requirements:
- One behavior
- Clear name
- Real code (no mocks unless unavoidable)
Verify RED - Watch It Fail
MANDATORY. Never skip.
npm test path/to/test.test.ts
Confirm:
- Test fails (not errors)
- Failure message is expected
- Fails because feature missing (not typos)
Test passes? You're testing existing behavior. Fix test.
Test errors? Fix error, re-run until it fails correctly.
GREEN - Minimal Code
Write simplest code to pass the test.
```typescript
async function retryOperation(fn: () => Promise): Promise {
for (let i = 0; i < 3; i++) {
try {
return await fn();
} catch (e) {
if (i === 2) throw e;
}
}
throw new Error('unreachable');
}
```
Just enough to pass
```typescript
async function retryOperation(
fn: () => Promise,
options?: {
maxRetries?: number;
backoff?: 'linear' | 'exponential';
onRetry?: (attempt: number) => void;
}
): Promise {
// YAGNI
}
```
Over-engineered
Don't add features, refactor other code, or "improve" beyond the test.
Verify GREEN - Watch It Pass
MANDATORY.
npm test path/to/test.test.ts
Confirm:
- Test passes
- Other tests still pass
- Output pristine (no errors, warnings)
Test fails? Fix code, not test.
Other tests fail? Fix now.
REFACTOR - Clean Up
After green only:
- Remove duplication
- Improve names
- Extract helpers
Keep tests green. Don't add behavior.
Repeat
Next failing test for next feature.
Good Tests
| Quality | Good | Bad |
|---|
| Minimal | One thing. "and" in name? Split it. | test('validates email and domain and whitespace') |
| Clear | Name describes behavior | test('test1') |
| Shows intent | Demonstrates desired API | Obscures what code should do |
UC-ID Traceability
When the plan includes Covers: UC-xxx per task, ensure the coder annotates tests with UC-ID comments. This enables the review-coverage mode to verify all use cases are implemented.
The coder agent handles this automatically when given the Covers: field — see @../../agents/mu-coder.md Test Traceability section.
Why Order Matters
"I'll write tests after to verify it works"
Tests written after code pass immediately. Passing immediately proves nothing:
- Might test wrong thing
- Might test implementation, not behavior
- Might miss edge cases you forgot
- You never saw it catch the bug
Test-first forces you to see the test fail, proving it actually tests something.
"I already manually tested all the edge cases"
Manual testing is ad-hoc. You think you tested everything but:
- No record of what you tested
- Can't re-run when code changes
- Easy to forget cases under pressure
- "It worked when I tried it" ≠ comprehensive
Automated tests are systematic. They run the same way every time.
"Deleting X hours of work is wasteful"
Sunk cost fallacy. The time is already gone. Your choice now:
- Delete and rewrite with TDD (X more hours, high confidence)
- Keep it and add tests after (30 min, low confidence, likely bugs)
The "waste" is keeping code you can't trust. Working code without real tests is technical debt.
"TDD is dogmatic, being pragmatic means adapting"
TDD IS pragmatic:
- Finds bugs before commit (faster than debugging after)
- Prevents regressions (tests catch breaks immediately)
- Documents behavior (tests show how to use code)
- Enables refactoring (change freely, tests catch breaks)
"Pragmatic" shortcuts = debugging in production = slower.
"Tests after achieve the same goals - it's spirit not ritual"
No. Tests-after answer "What does this do?" Tests-first answer "What should this do?"
Tests-after are biased by your implementation. You test what you built, not what's required. You verify remembered edge cases, not discovered ones.
Tests-first force edge case discovery before implementing. Tests-after verify you remembered everything (you didn't).
30 minutes of tests after ≠ TDD. You get coverage, lose proof tests work.
Common Rationalizations
| Excuse | Reality |
|---|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests passing immediately prove nothing. |
| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" |
| "Already manually tested" | Ad-hoc ≠ systematic. No record, can't re-run. |
| "Deleting X hours is wasteful" | Sunk cost fallacy. Keeping unverified code is technical debt. |
| "Keep as reference, write tests first" | You'll adapt it. That's testing after. Delete means delete. |
| "Need to explore first" | Fine. Throw away exploration, start with TDD. |
| "Test hard = design unclear" | Listen to test. Hard to test = hard to use. |
| "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. |
| "Manual test faster" | Manual doesn't prove edge cases. You'll re-test every change. |
| "Existing code has no tests" | You're improving it. Add tests for existing code. |
TDD Red Flags - STOP and Start Over
- Code before test
- Test after implementation
- Test passes immediately
- Can't explain why test failed
- Tests added "later"
- Rationalizing "just this once"
- "I already manually tested it"
- "Tests after achieve the same purpose"
- "It's about spirit not ritual"
- "Keep as reference" or "adapt existing code"
- "Already spent X hours, deleting is wasteful"
- "TDD is dogmatic, I'm being pragmatic"
- "This is different because..."
All of these mean: Delete code. Start over with TDD.
TDD Bug Fix Example
Bug: Empty email accepted
RED
test('rejects empty email', async () => {
const result = await submitForm({ email: '' });
expect(result.error).toBe('Email required');
});
Verify RED
$ npm test
FAIL: expected 'Email required', got undefined
GREEN
function submitForm(data: FormData) {
if (!data.email?.trim()) {
return { error: 'Email required' };
}
}
Verify GREEN
$ npm test
PASS
REFACTOR
Extract validation for multiple fields if needed.
TDD Verification Checklist
Before marking work complete:
Can't check all boxes? You skipped TDD. Start over.
When Stuck
| Problem | Solution |
|---|
| Don't know how to test | Write wished-for API. Write assertion first. Ask your human partner. |
| Test too complicated | Design too complicated. Simplify interface. |
| Must mock everything | Code too coupled. Use dependency injection. |
| Test setup huge | Extract helpers. Still complex? Simplify design. |
Debugging Integration
Bug found? Write failing test reproducing it. Follow TDD cycle. Test proves fix and prevents regression.
Never fix bugs without a test.
Testing Anti-Patterns
When adding mocks or test utilities, avoid these common pitfalls:
- Testing mock behavior instead of real behavior
- Adding test-only methods to production classes
- Mocking without understanding dependencies
TDD Final Rule
Production code → test exists and failed first
Otherwise → not TDD
No exceptions without your human partner's permission.
Review Gates
Two-stage review after each task ensures both correctness and quality.
Stage 1: Spec Compliance Review
Before dispatching: verify BASE_SHA and HEAD_SHA are set (git rev-parse).
If reviewer returns files in "NOT reviewed" list, re-dispatch for remaining files.
Dispatch reviewer using @../../agents/mu-reviewer.md review-compliance:
- Does the implementation match the task specification?
- Missing requirements?
- Extra features not requested?
If issues found: Implementer fixes, reviewer re-reviews. Repeat until approved.
Must pass before Stage 2. Starting code quality review before spec compliance is approved is wrong order.
Stage 2: Code Quality Review
Before dispatching: verify BASE_SHA and HEAD_SHA are set (git rev-parse).
If reviewer returns files in "NOT reviewed" list, re-dispatch for remaining files.
Dispatch reviewer using @../../agents/mu-reviewer.md review-code:
- Code quality, readability, maintainability
- Test quality and coverage
- Error handling, edge cases
If issues found: Implementer fixes, reviewer re-reviews. Repeat until approved.
Final Review
After all tasks complete, chain to mu-review for comprehensive review of entire implementation.
Red Flags
Never:
- Start implementation on main/master branch without explicit user consent
- Switch branches, create branches, or run destructive git commands without verifying current state first (@../../knowledge/principles/git-safety.md)
- Skip reviews (spec compliance OR code quality)
- Proceed with unfixed issues
- Dispatch multiple implementation subagents in parallel (conflicts)
- Make subagent read plan file (provide full text instead)
- Skip scene-setting context (subagent needs to understand where task fits)
- Ignore subagent questions (answer before letting them proceed)
- Accept "close enough" on spec compliance (spec reviewer found issues = not done)
- Skip review loops (reviewer found issues = implementer fixes = review again)
- Let implementer self-review replace actual review (both are needed)
- Start code quality review before spec compliance is approved (wrong order)
- Move to next task while either review has open issues
- Create worktree without verifying it's ignored (project-local)
- Skip baseline test verification
- Proceed with failing baseline tests without asking
- Assume worktree directory location when ambiguous
- Skip CLAUDE.md check for worktree preferences
- Write code before test (TDD violation)
- Write test after implementation (TDD violation)
- Keep code written without TDD as "reference" (delete means delete)
- Skip verifying test fails (RED) or passes (GREEN)
- Rationalize skipping TDD "just this once"
- Dispatch parallel agents for related/coupled failures
If subagent asks questions:
- Answer clearly and completely
- Provide additional context if needed
- Don't rush them into implementation
If reviewer finds issues:
- Implementer (same subagent) fixes them
- Reviewer reviews again
- Repeat until approved
- Don't skip the re-review
If subagent fails task:
- Dispatch fix subagent with specific instructions
- Don't try to fix manually (context pollution)
Integration
- mu-plan creates the plan this skill executes
- Chain to mu-review after all tasks complete
- Agent references: @../../agents/mu-coder.md, @../../agents/mu-reviewer.md