Twelve prose violations to zero. Eight files split into per-topic subdirectories with the original left as an index; both SKILL.md files keep their frontmatter so discovery still works, with detail moved to references/. Deleted docs/cleanup-2026-05/ (7 files) and linux_configuration/docs/ VERIFICATION.md on the user's ruling: unreferenced records of finished work whose rules are now enforced by the polling, shellcheck and shfmt hooks. PACMAN_WRAPPER_SECURITY.md was split instead - unlike those, it documents live guarantees. Every split verified by a sorted diff against HEAD: zero content lines lost, only the new headings and index links added. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
4.0 KiB
| name | description |
|---|---|
| test-driven-development | Drives development with tests. Use when implementing any logic, fixing any bug, or changing any behavior. Use when you need to prove that code works, when a bug report arrives, or when you're about to modify existing functionality. |
Test-Driven Development
Overview
Write a failing test before writing the code that makes it pass. For bug fixes, reproduce the bug with a test before attempting a fix. Tests are proof — "seems right" is not done. A codebase with good tests is an AI agent's superpower; a codebase without tests is a liability.
When to Use
- Implementing any new logic or behavior
- Fixing any bug (the Prove-It Pattern)
- Modifying existing functionality
- Adding edge case handling
- Any change that could break existing behavior
When NOT to use: Pure configuration changes, documentation updates, or static content changes that have no behavioral impact.
Related: For browser-based changes, combine TDD with runtime verification using Chrome DevTools MCP — see the Browser Testing section below.
The TDD Cycle
RED GREEN REFACTOR
Write a test Write minimal code Clean up the
that fails ──→ to make it pass ──→ implementation ──→ (repeat)
│ │ │
▼ ▼ ▼
Test FAILS Test PASSES Tests still PASS
Step 1: RED — Write a Failing Test
Write the test first. It must fail. A test that passes immediately proves nothing.
// RED: This test fails because createTask doesn't exist yet
describe("TaskService", () => {
it("creates a task with title and default status", async () => {
const task = await taskService.createTask({ title: "Buy groceries" });
expect(task.id).toBeDefined();
expect(task.title).toBe("Buy groceries");
expect(task.status).toBe("pending");
expect(task.createdAt).toBeInstanceOf(Date);
});
});
Step 2: GREEN — Make It Pass
Write the minimum code to make the test pass. Don't over-engineer:
// GREEN: Minimal implementation
export async function createTask(input: { title: string }): Promise<Task> {
const task = {
id: generateId(),
title: input.title,
status: "pending" as const,
createdAt: new Date(),
};
await db.tasks.insert(task);
return task;
}
Step 3: REFACTOR — Clean Up
With tests green, improve the code without changing behavior:
- Extract shared logic
- Improve naming
- Remove duplication
- Optimize if necessary
Run tests after every refactor step to confirm nothing broke.
The Prove-It Pattern (Bug Fixes)
When a bug is reported, do not start by trying to fix it. Start by writing a test that reproduces it.
Bug report arrives
│
▼
Write a test that demonstrates the bug
│
▼
Test FAILS (confirming the bug exists)
│
▼
Implement the fix
│
▼
Test PASSES (proving the fix works)
│
▼
Run full test suite (no regressions)
Example:
// Bug: "Completing a task doesn't update the completedAt timestamp"
// Step 1: Write the reproduction test (it should FAIL)
it("sets completedAt when task is completed", async () => {
const task = await taskService.createTask({ title: "Test" });
const completed = await taskService.completeTask(task.id);
expect(completed.status).toBe("completed");
expect(completed.completedAt).toBeInstanceOf(Date); // This fails → bug confirmed
});
// Step 2: Fix the bug
export async function completeTask(id: string): Promise<Task> {
return db.tasks.update(id, {
status: "completed",
completedAt: new Date(), // This was missing
});
}
// Step 3: Test passes → bug fixed, regression guarded
Further reading
Split out to keep this file under the 250-line cap.