mirror of
https://github.com/mattpocock/skills.git
synced 2026-09-12 18:38:06 +07:00
docs: rewrite the remaining 18 pages to the four-section standard
One agent per page, each rewriting from its SKILL.md up and running its own evidence hunt across the wiki, the issue tracker and the unreleased changesets. Question counts track the evidence: wayfinder earns ten, resolving-merge-conflicts earns three. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
14780a1f8d
commit
c33ce1c187
+75
-12
@@ -1,35 +1,98 @@
|
||||
## What it does
|
||||
|
||||
`tdd` builds a feature or fixes a bug test-first, one behaviour at a time, driving the code out through a red-green loop.
|
||||
`tdd` builds a feature or fixes a bug test-first: one failing test, then just enough code to pass it, then the next behaviour. It carries the standards that make that loop produce tests worth keeping — what a good test is, where tests go, what mocks are for, and the three anti-patterns that quietly ruin a suite.
|
||||
|
||||
It will **not** write all the tests up front. Batching the tests first ("horizontal slicing") produces tests of _imagined_ behaviour — they check the shape of things and go numb to real changes. `tdd` instead takes vertical slices: one test, then just enough code to pass it, then the next test, each cycle informed by what the last one taught you. Tests target public interfaces only, so the implementation underneath can change without the tests moving.
|
||||
It writes no test at a seam you have not agreed to first. Before any test exists, it names the public boundaries it intends to test at and stops for your confirmation, because testing effort is finite and this is where you spend it on the critical paths instead of on every edge case. The other thing to know is that `tdd` is a **reference**, not a driver. Matt's own description of it is "just a reference on how to do TDD" — it holds the rules of the loop, and something else (you, or [implement](https://aihero.dev/skills-implement)) runs the session that applies them.
|
||||
|
||||
## When to reach for it
|
||||
|
||||
Type `/tdd`, or the agent reaches for it automatically when a task fits — building a feature or fixing a bug test-first, or when you say "red-green-refactor".
|
||||
|
||||
Reach for it when there's a concrete behaviour to build and you want tests that survive a refactor. If the behaviour isn't pinned down yet, settle the spec first — for that, use [to-spec](https://aihero.dev/skills-to-spec). When the work is really about the shape of the interface rather than the tests, use [codebase-design](https://aihero.dev/skills-codebase-design); `tdd` calls into it for the deep-module vocabulary during planning.
|
||||
Reach for it when there is a concrete behaviour to build, with an input and an observable output, and you want tests that survive a refactor.
|
||||
|
||||
## Red-green, one slice at a time
|
||||
| Your situation | Where to go |
|
||||
| --- | --- |
|
||||
| A behaviour with defined inputs and outputs — business logic, a request/response contract, a transformation, validation | `tdd` |
|
||||
| The behaviour isn't pinned down yet | [to-spec](https://aihero.dev/skills-to-spec), which also agrees the test seams before any code is written |
|
||||
| The question is really the shape of the interface, not the tests | [codebase-design](https://aihero.dev/skills-codebase-design) |
|
||||
| You have a spec or tickets and want the whole build run for you | [implement](https://aihero.dev/skills-implement), which drives `tdd` per ticket |
|
||||
| Config, wiring, glue, type annotations, straight CRUD delegation | Nothing here fits well — see the open gap below |
|
||||
|
||||
The leading idea is the **red-green loop**: write one failing test (red), add just enough code to pass it (green), then repeat for the next behaviour — each cycle informed by what the last one taught you. The very first cycle is a **tracer bullet**: one test that proves a single path works end-to-end, before you build outward from it. Because you just wrote the code, you know exactly which behaviour matters and how to verify it — you never outrun your headlights by committing to test structure you don't yet understand.
|
||||
That last row is a real hole, not a stylistic preference. The skill decides *where* the seams go; nothing in it decides *whether* a change is worth the loop at all. Run it on a change with no independent source of truth to assert against and you get a test that restates the implementation — the tautological anti-pattern the skill itself warns about, arrived at from the other direction. It is [issue #746](https://github.com/mattpocock/skills/issues/746) and it is open. Until it closes, that judgement is yours or your `CLAUDE.md`'s.
|
||||
|
||||
Two rules keep the tests honest. A good test reads like a specification ("user can checkout with valid cart") and exercises real code paths through the public API, so renaming an internal function never breaks it. And expected values come from an independent source of truth — a known-good literal, a worked example, the spec — never recomputed the way the code computes them, which is how a **tautological** test passes by construction and tells you nothing.
|
||||
## Prerequisites
|
||||
|
||||
Refactoring only happens once the suite is green; never while red.
|
||||
[codebase-design](https://aihero.dev/skills-codebase-design) needs to be installed. `tdd` used to carry its own deep-module and interface-design notes; in v1.0 those were deleted in favour of the shared skill, and `tdd` now leans on it for interface-design vocabulary. Nothing else — the skill is stateless and writes no files of its own.
|
||||
|
||||
## The loop, and the seam it runs at
|
||||
|
||||
Three words carry this skill.
|
||||
|
||||
**Red-green.** Write the failing test, then only enough code to pass it. No anticipating the test after next. There is no refactor phase: Matt dropped it in June 2026 because "my experience of using it was that it never, ever, ever did it," and because review and implementation work better as separate sessions. Refactoring belongs to [code-review](https://aihero.dev/skills-code-review).
|
||||
|
||||
**Vertical slice.** One seam, one test, one minimal implementation, then repeat — the first cycle being a **tracer bullet** that proves a single path end to end. The opposite is horizontal slicing: all the tests first, then all the code. Bulk tests verify *imagined* behaviour, they check the shape of things rather than what a user does, and they commit you to a test structure before you understand the implementation.
|
||||
|
||||
**Pre-agreed seam.** A seam is the public boundary you observe behaviour at without reaching inside. The rule is absolute: no test at an unconfirmed seam. In the full chain the seams are agreed earlier, during [to-spec](https://aihero.dev/skills-to-spec) — "`/tdd` is told to only work at pre-agreed test seams, `/code-review` checks that only agreed-upon test seams were used." Invoked on its own, `tdd` asks you directly.
|
||||
|
||||
The three anti-patterns it is written to prevent:
|
||||
|
||||
| Anti-pattern | The tell |
|
||||
| --- | --- |
|
||||
| Implementation-coupled | The test breaks when you rename an internal function, though behaviour did not change. Mocked internal collaborators, asserted call counts, database queries used to verify instead of the interface. |
|
||||
| Tautological | The expected value is computed the way the code computes it, so the test passes by construction. Expected values have to come from somewhere else — a known-good literal, a worked example, the spec. |
|
||||
| Horizontal slicing | A batch of tests landed before any implementation. |
|
||||
|
||||
Mocks are for system boundaries only — external APIs, time, randomness, sometimes the filesystem or the database. Not your own modules.
|
||||
|
||||
## Common questions
|
||||
|
||||
**Why doesn't it refactor? The description says "red-green-refactor".**
|
||||
|
||||
Because the refactor step was removed and the description was not. Matt dropped it deliberately: agents essentially never did it, and keeping implementation and review in separate sessions works better. Asked whether that is still TDD, his answer was "does it matter?" The mismatch between the trigger phrase and the body is filed as [issue #589](https://github.com/mattpocock/skills/issues/589) and is still open, so "red-green-refactor" continues to work as a phrase that fires the skill. What you get is red → green, and refactoring in [code-review](https://aihero.dev/skills-code-review).
|
||||
|
||||
**It asked me to choose a test seam and I had no idea which to pick.**
|
||||
|
||||
This is the most-reported friction with the skill ([issue #607](https://github.com/mattpocock/skills/issues/607)). The prompt lists candidate seams by name only, with nothing about what each one catches or misses, so you are choosing between labels. There is no fix shipped yet. The practical workaround is to ask the agent for the trade-offs before answering — what does the component-level seam miss that the integration seam catches, and how much slower is it. It is also why the chain agrees seams up front in `to-spec`, where you have the whole feature in view rather than one prompt.
|
||||
|
||||
**I ran `/implement` and it never invoked `/tdd`.**
|
||||
|
||||
Known and common. One user's estimate on [issue #479](https://github.com/mattpocock/skills/issues/479) is that `/implement` fails to trigger `/tdd` in about 80% of runs. Two structural reasons: `implement` says to use `tdd` "where possible, at pre-agreed seams", which is satisfied by doing TDD-shaped work without ever invoking the skill, and by the time implementation finishes the instruction is hundreds of lines back in the transcript. Naming it explicitly at the start of the run, or invoking `/tdd` yourself per slice, is the reliable path today.
|
||||
|
||||
**It wrote the implementation before the test, even though the skill says red first.**
|
||||
|
||||
It happens. One user pushed the model on it and got an unusually honest answer: "I knew the skill said 'one test at a time, watch it fail for the right reason' — I read it. I just defaulted to my normal habit." Matt's position is to live with it: "I've not managed to get agents to do anything 100% of the time. Being too forceful about this is also negative because we don't want to restrict an agent's creativity. So what I've done is I've just accepted that sometimes it will not follow TDD strictly. But overall I still get better results." If strict adherence matters for a particular slice, watch the run rather than trusting the skill to enforce it.
|
||||
|
||||
**Should it write browser or end-to-end tests first?**
|
||||
|
||||
Usually not, and the skill will not stop it. A user reported the agent writing a Playwright test first, then burning a long loop re-running it and concluding the *test* was broken for a feature that did not exist yet. Matt's answer: "I would configure this in your CLAUDE.md." Browser tests are slow enough that the red-green feedback loop stops paying for itself; declare in your repo's `CLAUDE.md` that they are written after the behaviour works.
|
||||
|
||||
**Does `/tdd` replace `/implement`, or the course's `/do-work`?**
|
||||
|
||||
No. `/tdd` documents the methodology; `/implement` is, in Matt's words, "a very simple work→feedback→commit loop" and is the direct stand-in for `/do-work`. The course's single `/do-work` step is now split across `/implement`, `/tdd` and `/code-review`. If you are asking which one to run against a ticket, the answer is almost always `/implement`.
|
||||
|
||||
**Where did the deep-modules and interface-design guidance go?**
|
||||
|
||||
Into [codebase-design](https://aihero.dev/skills-codebase-design) in v1.0, generalised so several skills share one vocabulary. `refactoring.md` left at the same time; refactoring is now [code-review](https://aihero.dev/skills-code-review)'s job, and that skill carries the Fowler smell baseline.
|
||||
|
||||
**Does it know about my other tickets?**
|
||||
|
||||
No. Run against one ticket, it will happily propose work that belongs to a sibling ticket, because it has no view of the rest of the issue graph ([issue #129](https://github.com/mattpocock/skills/issues/129)). Matt's position is that this is not `tdd`'s job. Passing the spec alongside the ticket helps; right-sizing the tickets in the first place helps more.
|
||||
|
||||
## It's working if
|
||||
|
||||
- It writes one test, gets it passing, and only then writes the next — not a batch of tests followed by a batch of code.
|
||||
- The tests name behaviours, not internals, and would survive an internal rename.
|
||||
- Expected values are literals from the spec, not figures derived the same way the code derives them.
|
||||
- It stops and names the seams it intends to test at, and waits, before any test file exists.
|
||||
- One test appears, goes red, gets just enough code to pass, and only then does the next test appear — not a batch of tests followed by a batch of code.
|
||||
- Test names read as capabilities ("user can checkout with valid cart"), not as internals ("checkout calls paymentService.process").
|
||||
- Expected values in assertions are literals you can trace to the spec, not values recomputed the way the code computes them.
|
||||
- Renaming an internal function breaks nothing in the suite.
|
||||
- Mocks appear only at external boundaries — the payment API, the clock — and never around your own modules.
|
||||
|
||||
## Where it fits
|
||||
|
||||
`tdd` is the red-green loop the main build chain runs to write code:
|
||||
`tdd` is the engine inside the build step of the main chain, rather than a step of its own:
|
||||
|
||||
```txt
|
||||
grill-with-docs → to-spec → to-tickets → implement → code-review
|
||||
```
|
||||
|
||||
[implement](https://aihero.dev/skills-implement) is the chain's build step, and it drives `tdd` internally to build each ticket test-first before handing off to [code-review](https://aihero.dev/skills-code-review) — so `tdd` is the engine inside that step rather than a step of its own. You can also reach for it directly, whenever there's a concrete behaviour to build without a full spec. Its other neighbour is [codebase-design](https://aihero.dev/skills-codebase-design), which it leans on to find deep-module seams worth testing at. When you're unsure which skill or flow fits, [ask-matt](https://aihero.dev/skills-ask-matt) routes you.
|
||||
[to-spec](https://aihero.dev/skills-to-spec) agrees the test seams up front, [implement](https://aihero.dev/skills-implement) drives `tdd` per ticket, and [code-review](https://aihero.dev/skills-code-review) checks afterwards that only the agreed seams were used — and owns the refactoring `tdd` no longer does. Its other neighbour is [codebase-design](https://aihero.dev/skills-codebase-design), the shared source of the seam and deep-module vocabulary `tdd` speaks. You can also reach for it on its own, whenever there is a concrete behaviour to build and no full spec in play. When you are unsure which skill fits your situation, [ask-matt](https://aihero.dev/skills-ask-matt) routes you.
|
||||
|
||||
Reference in New Issue
Block a user