AIs have a lazy instinct: produce code that runs, then produce a test that agrees with it. A test written after the code can pass by construction — we shipped weeks on "all green" dashboards where the tests had been quietly molded to fit broken behavior. Fake green is worse than red: red tells the truth.
For what makes a test worth keeping (boundaries, stubbing rules, the three test smells), see what-good-tests-look-like.md.
The loop
- Write the test first, asserting the behavior the user actually asked for — through the public interface, not internal details.
- Run it. Watch it fail. The red light proves the test can catch the problem. No red, no proof — a test you never saw fail is a decoration.
- Write the minimum code that turns it green. No speculative extras.
- Re-run everything. Your change must not flip other lights.
Hard rules
- Never weaken, skip, or rewrite a failing test to make it pass. A failing test is information about the code, not an obstacle. If the test itself is genuinely wrong, say so out loud and justify it against the spec before touching it.
- One test → one implementation → repeat. Don't write twenty tests up front against imagined behavior.
- Hostile input is a first-class test case. Garbage dates, wrong types, negatives, empty files — a founder's users will type them, so your tests type them first. (Our own A/B run shipped a bug where an invalid date silently swallowed an expense — the missing test was exactly this one.)
- Expected values come from an independent source (the spec, a worked example) — never computed the same way the code computes them.
The writer never grades its own test
A model cannot find the bug it was blind to while writing it. Grading your own paper with the same answer key is not verification.
Change the brain. The agent that writes the implementation and the agent that writes or runs the verification must be a different model family or a different tier. Failure modes inside one model are tightly correlated: the boundary it never considered while implementing is the boundary it will not consider while testing. Same weights, same blind spot — effort does not fix it.
Starve the verifier of the writer's story. It gets the requirement, the artifact, and a reproducible command with its real output. It does not get the writer's reasoning, its notes, or its defense of the tricky part. Hand over that narrative and the fresh model walks straight into the hole the first one dug.
Never verify below the difficulty of the code. The rule is swap family or swap tier, with capability at or above the job — top-tier writes, flagship verifies, or the reverse. Pointing the smallest model at complex logic is not a check, it is a rubber stamp with extra steps. Cheap tiers earn their keep on mechanical work: does the command run, does the output match the expected string, is every item on the checklist accounted for.
Make it the default staffing, not a thing you remember. If your standing roster already builds on one strong model and verifies on a different one, the swap above happens by configuration — nothing to recall at 2am under a deadline. A roster where one model does both has the verification silently removed.
Which tier to staff each role with: model-tiering. The same rule from the review side: two-axis-review.
Success criteria
Every new behavior has a test that was seen red before it went green. No agent verified its own implementation. Zero tests were modified to accommodate broken code.
1---2name: red-light-first3description: Write the failing test before the fix or feature — never trust a green light you didn't first see red. Use when building any feature or fixing any bug.4---56AIs have a lazy instinct: produce code that *runs*, then produce a test that *agrees with it*. A test written after the code can pass by construction — we shipped weeks on "all green" dashboards where the tests had been quietly molded to fit broken behavior. Fake green is worse than red: red tells the truth.78For what makes a test worth keeping (boundaries, stubbing rules, the three test smells), see [what-good-tests-look-like.md](what-good-tests-look-like.md).910## The loop11121. **Write the test first**, asserting the behavior the user actually asked for — through the public interface, not internal details.132. **Run it. Watch it fail.** The red light proves the test can catch the problem. No red, no proof — a test you never saw fail is a decoration.143. **Write the minimum code** that turns it green. No speculative extras.154. **Re-run everything.** Your change must not flip other lights.1617## Hard rules1819- Never weaken, skip, or rewrite a failing test to make it pass. A failing test is information about the code, not an obstacle. If the test itself is genuinely wrong, say so out loud and justify it against the spec before touching it.20- One test → one implementation → repeat. Don't write twenty tests up front against imagined behavior.21- **Hostile input is a first-class test case.** Garbage dates, wrong types, negatives, empty files — a founder's users will type them, so your tests type them first. (Our own A/B run shipped a bug where an invalid date silently swallowed an expense — the missing test was exactly this one.)22- Expected values come from an independent source (the spec, a worked example) — never computed the same way the code computes them.2324## The writer never grades its own test2526A model cannot find the bug it was blind to while writing it. Grading your own paper with the same answer key is not verification.2728- **Change the brain.** The agent that writes the implementation and the agent that writes or runs the verification must be a different model family or a different tier. Failure modes inside one model are tightly correlated: the boundary it never considered while implementing is the boundary it will not consider while testing. Same weights, same blind spot — effort does not fix it.29- **Starve the verifier of the writer's story.** It gets the requirement, the artifact, and a reproducible command with its real output. It does not get the writer's reasoning, its notes, or its defense of the tricky part. Hand over that narrative and the fresh model walks straight into the hole the first one dug.30- **Never verify below the difficulty of the code.** The rule is swap family or swap tier, with capability at or above the job — top-tier writes, flagship verifies, or the reverse. Pointing the smallest model at complex logic is not a check, it is a rubber stamp with extra steps. Cheap tiers earn their keep on mechanical work: does the command run, does the output match the expected string, is every item on the checklist accounted for.3132- **Make it the default staffing, not a thing you remember.** If your standing roster already builds on one strong model and verifies on a different one, the swap above happens by configuration — nothing to recall at 2am under a deadline. A roster where one model does both has the verification silently removed.3334Which tier to staff each role with: `model-tiering`. The same rule from the review side: `two-axis-review`.3536## Success criteria3738Every new behavior has a test that was seen red before it went green. No agent verified its own implementation. Zero tests were modified to accommodate broken code.