Private
Public Access
0
0

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

This commit is contained in:
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 @@
# delete_means_delete_no_reference
## v1
**Why this iteration:** Lifted from the global Openpowers plugin (obra/superpowers) — `skills/test-driven-development/SKILL.md`. The directive encodes the Iron Law's "No exceptions: Don't keep it as 'reference', Don't 'adapt' it while writing tests, Don't look at it, Delete means delete" block at lines 31-46. Counterweight to the LLM default of "I'll just keep the function as a reference and write the test around it," which bends the test to match the implementation and breaks the proof of failure.
**Source:** superpowers plugin `skills/test-driven-development/SKILL.md:31-46` (The Iron Law + No exceptions block)
**Lifted:** 2026-07-04 (scavenge sweep: superpowers plugin directives)
@@ -0,0 +1,35 @@
# "Delete" means delete — never keep untested code as "reference" or "adapt it while writing tests"
## The rule
If the agent writes production code before writing the failing test (i.e., violates the TDD red-green order), the code is deleted. Not kept, not referenced, not "adapted while writing the test." The agent writes the test FIRST against the desired behavior, then writes the implementation from scratch. "Delete means delete."
Per `skills/test-driven-development/SKILL.md:31-46` (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.
## Why
Keeping the code as "reference" is a trap. The agent reads it back while writing the test, the test ends up matching the implementation rather than the desired behavior, and the test passes immediately because it has been bent to fit. This is testing-after in disguise; the same failure modes apply.
The only way out is cold: write the test against the desired behavior from memory, then write the implementation from the test. The sunk cost is real (the previous code is wasted), but the alternative (keeping it) is worse (the test is now contaminated).
## What this means in practice
- The agent writes the test BEFORE any implementation code touches disk.
- If the agent catches itself having written code first (e.g., a function shell), the agent deletes it (`rm <file>` or `edit_file` to remove the function definition).
- "I'll keep this as reference and write the test around it" is forbidden. The reference becomes the implementation; the test becomes the fitting exercise.
- "I already manually tested this and want to preserve the working code" is forbidden. Manual testing is not the test; the test is the test.
- The first commit on a feature is the failing test alone; the second commit is the implementation. Never reversed.
@@ -40,6 +40,7 @@ Read each file below before any action.
- core_value_read_first: conductor/directives/core_value_read_first/v1.md
- decompose_or_isolate_never_offload: conductor/directives/decompose_or_isolate_never_offload/v1.md
- decorator_orphan_pitfall: conductor/directives/decorator_orphan_pitfall/v1.md
- delete_means_delete_no_reference: conductor/directives/delete_means_delete_no_reference/v1.md
- defer_heavy_sdk_imports_to_subprocess: conductor/directives/defer_heavy_sdk_imports_to_subprocess/v1.md
- defer_not_catch_for_native_crashes: conductor/directives/defer_not_catch_for_native_crashes/v1.md
- deduction_loop_limit: conductor/directives/deduction_loop_limit/v1.md
@@ -63,6 +64,7 @@ Read each file below before any action.
- imscope_tuple_return_per_scope_override: conductor/directives/imscope_tuple_return_per_scope_override/v1.md
- inherited_cruft_ask_first: conductor/directives/inherited_cruft_ask_first/v1.md
- intent_signal_postfix_not_xml: conductor/directives/intent_signal_postfix_not_xml/v1.md
- reproduction_before_fix: conductor/directives/reproduction_before_fix/v1.md
- interceptor_activates_only_on_matching_shape: conductor/directives/interceptor_activates_only_on_matching_shape/v1.md
- knowledge_harvest_pattern: conductor/directives/knowledge_harvest_pattern/v1.md
- large_files_are_fine: conductor/directives/large_files_are_fine/v1.md
@@ -122,6 +124,7 @@ Read each file below before any action.
- scope_creep_track_doc_ban: conductor/directives/scope_creep_track_doc_ban/v1.md
- sdm_dependency_tags: conductor/directives/sdm_dependency_tags/v1.md
- search_all_call_sites_after_signature_change: conductor/directives/search_all_call_sites_after_signature_change/v1.md
- single_hypothesis_minimal_test: conductor/directives/single_hypothesis_minimal_test/v1.md
- state_visible_at_the_right_layer: conductor/directives/state_visible_at_the_right_layer/v1.md
- strict_state_management: conductor/directives/strict_state_management/v1.md
- stub_before_implement: conductor/directives/stub_before_implement/v1.md
@@ -137,6 +140,9 @@ Read each file below before any action.
- tier2_pre_flight_audit_gates: conductor/directives/tier2_pre_flight_audit_gates/v1.md
- worker_three_point_abort_check: conductor/directives/worker_three_point_abort_check/v1.md
- tdd_red_green_required: conductor/directives/tdd_red_green_required/v1.md
- test_must_fail_for_believed_reason: conductor/directives/test_must_fail_for_believed_reason/v1.md
- test_passing_immediately_proves_nothing: conductor/directives/test_passing_immediately_proves_nothing/v1.md
- three_fix_failures_question_architecture: conductor/directives/three_fix_failures_question_architecture/v1.md
- test_classification_via_import_presence: conductor/directives/test_classification_via_import_presence/v1.md
- test_instantiation_not_mock_away: conductor/directives/test_instantiation_not_mock_away/v1.md
- test_narrow_not_kitchen_sink: conductor/directives/test_narrow_not_kitchen_sink/v1.md
@@ -194,7 +200,12 @@ added 6 more (1 from using-superpowers Skill-Check-Iron-Rule, 3 from
brainstorming — lead-with-recommendation + even-simple-projects-get-designed +
spec-self-review-4-checks, 1 from dispatching-parallel-agents agent-prompt-
focused-on-one-domain, 1 from executing-plans review-plan-critically-first) for
a total of 142 — see HARVEST_SUMMARY.md for what was lifted in each pass).
a total of 142, and the 2026-07-04 superpowers scavenge (batch 2 of 5: TDD /
debugging) added 6 more (3 from test-driven-development — test-must-fail-for-
believed-reason + delete-means-delete-no-reference + test-passing-immediately-
proves-nothing; 3 from systematic-debugging — three-fix-failures-question-
architecture + single-hypothesis-minimal-test + reproduction-before-fix) for a
total of 148 — see HARVEST_SUMMARY.md for what was lifted in each pass).
No alternative encodings tested yet. This preset is the control group for
future experiments.
@@ -0,0 +1,8 @@
# reproduction_before_fix
## v1
**Why this iteration:** Lifted from the global OpenCode superpowers plugin (obra/superpowers) — `skills/systematic-debugging/SKILL.md`. The directive encodes Phase 1, step 2 (lines 60-64) "Reproduce Consistently - Can you trigger it reliably? If not reproducible → gather more data, don't guess." Counterweight to the LLM default of skipping reproduction and going straight to "I'll just change this and see if it helps."
**Source:** superpowers plugin `skills/systematic-debugging/SKILL.md:60-64` (Phase 1, step 2: Reproduce Consistently)
**Lifted:** 2026-07-04 (scavenge sweep: superpowers plugin directives)
@@ -0,0 +1,30 @@
# Reproduce the bug RELIABLY before attempting any fix — if the bug is not reproducible, gather data, do not guess
## The rule
Before changing any code to "fix" a bug, the agent MUST reproduce the bug deterministically. "I think this would have failed" is not reproduction; "I ran this exact reproduction 5 times and it failed 5/5" is. If the agent cannot reproduce the bug deterministically, the agent GATHERS MORE DATA (logs, traces, environment captures, environment diffs) rather than guessing at a fix.
Per `skills/systematic-debugging/SKILL.md:60-64` (Phase 1, step 2: Reproduce Consistently):
> 2. **Reproduce Consistently**
> - Can you trigger it reliably?
> - What are the exact steps?
> - Does it happen every time?
> - If not reproducible → gather more data, don't guess
## Why
A non-reproducible bug is a data-collection problem, not a code-fix problem. The agent does not have the information needed to fix; speculating a fix without the reproduction data is "decoration, not correction." The fix either does nothing or masks the bug temporarily.
Reliable reproduction is also the falsifiability requirement of a hypothesis. If the agent cannot reproduce, the agent cannot verify that a fix worked. "I changed code and the user says it works now" is not the same as "I changed code, re-ran the reproduction 10 times, observed 0/10 failures, then committed." Without the reproduction, the agent cannot tell whether the fix did anything.
## What this means in practice
- The agent documents the exact reproduction steps BEFORE attempting any fix:
1. Trigger: "Run X with these exact args"
2. Expected: "Y happens 100% of the time"
3. Actual: "Z happens (X% of the time)"
- If the reproduction is non-deterministic, the agent runs the reproduction N times and records the failure rate.
- The agent does NOT propose a fix until the reproduction rate matches the reported failure rate. (The agent's reproduction: 100% means "always fails"; user-reported: ~50% means the agent has more data to gather, not a fix to apply.)
- "While I gather data" can mean instrumentation (logs, traces, env captures) but the data is logged to a log file or `tests/artifacts/<name>.diag.log`, not as diagnostic stderr in production code (see `no_diagnostic_noise`).
- A fix attempt on a non-reproducible bug is a guess. The agent doesn't guess.
@@ -0,0 +1,8 @@
# single_hypothesis_minimal_test
## v1
**Why this iteration:** Lifted from the global OpenCode superpowers plugin (obra/superpowers) — `skills/systematic-debugging/SKILL.md`. The directive encodes Phase 3 (lines 145-163): Form Single Hypothesis + Test Minimally + Verify Before Continuing + Don't add more fixes on top. Counterweight to the LLM default of bundling multiple changes into one commit to "save time," which makes the outcome unauditable and slows diagnosis.
**Source:** superpowers plugin `skills/systematic-debugging/SKILL.md:145-163` (Phase 3: Hypothesis and Testing)
**Lifted:** 2026-07-04 (scavenge sweep: superpowers plugin directives)
@@ -0,0 +1,39 @@
# Form a SINGLE hypothesis, test it MINIMALLY — do not bundle multiple fix attempts into one change
## The rule
When debugging, the agent forms exactly one hypothesis at a time ("I think X is the root cause because Y"), states it explicitly, and tests it with the smallest possible change. The agent does not change multiple variables at once; the agent does not "fix several obvious problems" while in the debugging flow; the agent does not "while I'm here" improve unrelated code.
Per `skills/systematic-debugging/SKILL.md:145-163` (Phase 3: Hypothesis and Testing):
> **Scientific method:**
>
> 1. **Form Single Hypothesis**
> - State clearly: "I think X is the root cause because Y"
> - Write it down
> - Be specific, not vague
>
> 2. **Test Minimally**
> - Make the SMALLEST possible change to test hypothesis
> - One variable at a time
> - Don't fix multiple things at once
>
> 3. **Verify Before Continuing**
> - Did it work? Yes → Phase 4
> - Didn't work? Form NEW hypothesis
> - DON'T add more fixes on top
## Why
Bundled fixes are unauditable. If the test passes, the agent doesn't know WHICH of the bundled changes was responsible; if the test fails, the agent doesn't know which to revert. The next fix attempt becomes a search across multiple variables, which is exponentially slower than testing one at a time.
Stating the hypothesis explicitly is a discipline against "I just tried a bunch of things." If the agent cannot state the hypothesis in one sentence, the hypothesis is too vague to test — refine first, then test.
## What this means in practice
- Before each fix attempt, the agent writes: "I think [specific X] is the root cause because [specific Y]; I will test by [single change Z]."
- The change is single-line or single-parameter; not multi-file.
- If the change does not resolve the bug, the agent REVERTS the change (or notes it explicitly) and forms a new hypothesis. The revert is part of the protocol, not an option.
- "While I'm here" improvements are forbidden inside a debugging flow. The agent returns to the improvement in a separate commit after the bug is resolved.
- After three failed hypotheses (not three fix attempts in one commit; three SEPARATE hypotheses), the architecture question is reached (see `three_fix_failures_question_architecture`).
- The agent does not batch commits inside a debugging flow to "save time." Each hypothesis gets its own commit (atomic per hypothesis), with the test commit prepended when possible.
@@ -0,0 +1,8 @@
# test_must_fail_for_believed_reason
## v1
**Why this iteration:** Lifted from the global OpenCode superpowers plugin (obra/superpowers) — `skills/test-driven-development/SKILL.md`. The directive encodes the "Verify RED" step at lines 113-128: confirm the failure message is expected, not a typo or setup error. A test that fails for the wrong reason teaches nothing — the agent fixes the symptom and concludes the feature works. Counterweight to the LLM default of "test fails = feature missing" reasoning.
**Source:** superpowers plugin `skills/test-driven-development/SKILL.md:113-128` (Verify RED - Watch It Fail)
**Lifted:** 2026-07-04 (scavenge sweep: superpowers plugin directives)
@@ -0,0 +1,36 @@
# A test must fail for the reason you believe — if it fails for a different reason, your understanding of the system is wrong
## The rule
After writing a test, the agent MUST observe the failure message and confirm the failure matches the agent's claim about what is missing. If the test fails because of a typo, an import error, a missing fixture, or any reason OTHER than "the feature being tested doesn't exist yet," then the agent's understanding is wrong — the test is testing something else.
Per `skills/test-driven-development/SKILL.md:113-128` (Verify RED - Watch It Fail):
> **MANDATORY. Never skip.**
>
> ```bash
> npm test path/to/test.test.ts
> ```
>
> 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.
## Why
A test that fails for the wrong reason is worse than no test. If the test "fails" because of a typo, the agent fixes the typo (test now passes because the typo is gone), and concludes the feature works. The feature never ran. The next time the test would have caught a real regression, it now passes trivially.
The failure-mode observation is the only signal that distinguishes "test caught the missing feature" from "test caught a different bug that happens to make this assertion fail." Without the observation, the agent reasons about the wrong thing.
## What this means in practice
- The agent reads the FAIL message, not just the FAIL status.
- "Expected `5`, got `undefined`" with the new feature missing = good failure.
- "NameError: name 'submitForm' is not defined" (the agent forgot the import) = wrong failure; agent's understanding is broken; fix and re-run.
- If the failure is "expected feature was supposed to error on empty input but the test ran and returned a non-error" → the test ran the wrong function. The agent's mental model is wrong.
- The agent explicitly states the failure reason in the test output (e.g., "RED: function not defined as expected" or "RED: assertion failed because the function returns None instead of 'Email required'").
- A test that passes immediately is a test failure, not a test success.
@@ -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.
@@ -0,0 +1,8 @@
# three_fix_failures_question_architecture
## v1
**Why this iteration:** Lifted from the global OpenCode superpowers plugin (obra/superpowers) — `skills/systematic-debugging/SKILL.md`. The directive encodes Phase 4.5 (lines 199-213) plus the two red flags at lines 227-228. Counterweight to the LLM default of "one more fix attempt" past two failures, which is sunk-cost driven and signal-blind. After three failures, the architectural question is the right next step, not Fix #4.
**Source:** superpowers plugin `skills/systematic-debugging/SKILL.md:199-213` (Phase 4.5: If 3+ Fixes Failed) + `:227-228` (Red Flags)
**Lifted:** 2026-07-04 (scavenge sweep: superpowers plugin directives)
@@ -0,0 +1,45 @@
# After three failed fixes, stop and question the architecture — the pattern is wrong, not the line of code
## The rule
If three or more fix attempts have failed to resolve a bug (each fix revealing a new problem in a different place, each fix requiring "massive refactoring" to implement, each fix creating new symptoms elsewhere), the pattern is wrong, not the code. STOP attempting Fix #4 without architectural discussion.
Per `skills/systematic-debugging/SKILL.md:199-213` (Phase 4.5: If 3+ Fixes Failed):
> **Pattern indicating architectural problem:**
> - Each fix reveals new shared state/coupling/problem in different place
> - Fixes require "massive refactoring" to implement
> - Each fix creates new symptoms elsewhere
>
> **STOP and question fundamentals:**
> - Is this pattern fundamentally sound?
> - Are we "sticking with it through sheer inertia"?
> - Should we refactor architecture vs. continue fixing symptoms?
>
> **Discuss with your human partner before attempting more fixes**
>
> This is NOT a failed hypothesis - this is a wrong architecture.
## Why
A wrong architecture surfaces symptoms in many places. Each symptom fix touches one of those places, but the underlying architectural mistake generates the next symptom in a different place. The fix loop is unbounded; the architecture is the bug.
Continuing to attempt fixes past three is sunk-cost driven and signal-blind. The first fix was a hypothesis; by the third, the hypothesis domain has shifted from "this line is wrong" to "this design is wrong." The agent's tools (line-level edits) are mismatched to the new domain (architectural question).
## The three-failure red flags
Per `skills/systematic-debugging/SKILL.md:227-228`:
- "**One more fix attempt"** (when already tried 2+)
- **Each fix reveals new problem in different place**
If either flag is true, the agent has reached the architecture-question threshold. Stop.
## What this means in practice
- After failed Fix #1: form a new hypothesis, return to Phase 3 (Hypothesis and Testing).
- After failed Fix #2: return to Phase 1 (Root Cause Investigation) with the new information from the failed fixes.
- After failed Fix #3: STOP. The architecture is the bug. Write up the architectural question; surface the pattern of fixes; ask the user or Tier 2 whether to refactor or to try a different design entirely.
- The agent does NOT attempt Fix #4 without explicit user permission. The architectural question is a decision the user makes, not the agent.
- "Just one more fix" past three is a red flag, not a heuristic.
- A fix loop is not "progress because something changes" — it is "regression because each change creates a new symptom."