git:20260502.ad239a0 to git:20260606.0acd84f

29 added, 21 removed. Audit A to A.

---
name: test-driven-development
description: Use when implementing any feature or bugfix, before writing implementation code
---
# Test-Driven Development (TDD)
## Overview
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
**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
- ```dot
- 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];
+ ```mermaid
+ graph LR
+ red["RED<br/>Write failing test"]
+ style red fill:#ffcccc
+ verify_red{"Verify fails<br/>correctly"}
+ green["GREEN<br/>Minimal code"]
+ style green fill:#ccffcc
+ verify_green{"Verify passes<br/>All green"}
+ refactor["REFACTOR<br/>Clean up"]
+ style refactor fill:#ccccff
+ next_step(["Next"])
- 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 --> verify_red
+ verify_red -->|yes| green
+ verify_red -->|"wrong<br/>failure"| red
+ green --> verify_green
+ verify_green -->|yes| refactor
+ verify_green -->|no| green
+ refactor -->|"stay<br/>green"| verify_green
+ verify_green --> next_step
+ next_step --> red
```
### RED - Write Failing Test
Write one minimal test showing what should happen.
**Requirements:**
+
- One behavior
- Clear name
- Real code (no mocks unless unavoidable)
### Verify RED - Watch It Fail
**MANDATORY. Never skip.**
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. Don't add features, refactor other code, or "improve" beyond the test.
### Verify GREEN - Watch It Pass
**MANDATORY.**
Confirm:
+
- Test passes
- Other tests still pass
- Output pristine (no errors, warnings)
**Test fails?** Fix code, not test.
### 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.
## Why Order Matters
**"I'll write tests after to verify it works"**
Tests written after code pass immediately — proving nothing. You never saw the test catch the bug.
**"I already manually tested all the edge cases"**
Manual testing is ad-hoc. No record, can't re-run, easy to forget cases under pressure.
**"Deleting X hours of work is wasteful"**
Sunk cost fallacy. Working code without real tests is technical debt.
## 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. |
| "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. |
## Red Flags - STOP and Start Over
- Code before test
- Test after implementation
- Test passes immediately
- Can't explain why test failed
- "Already manually tested it"
- "Tests after achieve the same purpose"
- "This is different because..."
**All of these mean: Delete code. Start over with TDD.**
## Verification Checklist
Before marking work complete:
- [ ] Every new function/method has a test
- [ ] Watched each test fail before implementing
- [ ] Each test failed for expected reason (feature missing, not typo)
- [ ] Wrote minimal code to pass each test
- [ ] All tests pass
- [ ] Output pristine (no errors, warnings)
- [ ] Tests use real code (mocks only if unavoidable)
- [ ] Edge cases and errors covered
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.
## Final Rule
```
Production code → test exists and failed first
Otherwise → not TDD
```
No exceptions without your human partner's permission.