feat(directives): scavenge superpowers plugin (test-driven-development, systematic-debugging): 6 directives

This commit is contained in:
ed
2026-07-04 12:31:40 -04:00
parent 19738b52e7
commit 2a1b1698b9
13 changed files with 286 additions and 1 deletions
@@ -0,0 +1,8 @@
# test_passing_immediately_proves_nothing
## v1
**Why this iteration:** Lifted from the global OpenCode superpowers plugin (obra/superpowers) — `skills/test-driven-development/SKILL.md`. The directive encodes the "Why Order Matters" block at lines 206-217 (tests-after pass immediately, proving nothing) plus the Rationalizations table at lines 256-263. Counterweight to the LLM default of "I'll test after to verify it works," which produces tests bent to match the implementation rather than the user's needed behavior.
**Source:** superpowers plugin `skills/test-driven-development/SKILL.md:206-217` (Why Order Matters) + `:256-263` (Rationalizations table)
**Lifted:** 2026-07-04 (scavenge sweep: superpowers plugin directives)
@@ -0,0 +1,41 @@
# Tests written after implementation pass immediately — a test that passes immediately proves nothing
## The rule
A test written after the implementation already exists will pass on the first run, because the test is shaped to match what the code does (not what it should do). Passing immediately is the diagnostic signal that the test was written after, and the test teaches nothing about behavior the agent hadn't already encoded in the implementation.
Per `skills/test-driven-development/SKILL.md:206-217` (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.
And the Rationalizations table at lines 256-263:
> | Excuse | Reality |
> |--------|---------|
> | "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?" |
## Why
Tests-first answer "what should this do?" — the agent reasons about the behavior the user needs, then encodes that reasoning as an assertion. The assertion is the spec; the implementation makes the spec pass.
Tests-after answer "what does this do?" — the agent looks at the code, sees what it does, and writes an assertion that matches. The assertion captures the agent's memory of the implementation, not the user's needs. Any edge case the agent forgot in implementation is also missing from the test, by construction.
The proof that a test catches the bug is observing the test fail when the bug is present. A test that has never failed has never caught anything.
## What this means in practice
- If a test passes on the first run, the agent pauses and asks: "Did I write this BEFORE the implementation?"
- The pause is mandatory, not optional. A passing test without a prior failing observation is a process violation.
- The fix is to revert the implementation, re-run the test, observe the failure (it should fail for the missing-feature reason), then re-implement. This proves the test catches the missing feature.
- A test that passes immediately is rewritten before continuing. The agent does not "accept the passes" and move on.
- New codebases / new features: there is no excuse — write the test first, see it fail, implement, see it pass.
- Existing codebases: when adding tests to existing code, the "failing then passing" cycle is reproduced by temporarily removing the code path under test, not by re-typing the test from scratch.