Doubt-Driven Development
Subjects every non-trivial decision to a fresh-context adversarial review before it stands. Use when correctness matters more than speed.
A confident answer is not a correct one. Doubt-driven development materializes a fresh-context reviewer biased to disprove before any non-trivial output stands.
When to Use
A decision is non-trivial when at least one of these is true:
- It introduces or modifies branching logic
- It crosses a module or service boundary
- It asserts a property the type system cannot verify
- Its correctness depends on context the future reader cannot see
- Its blast radius is irreversible (production deploy, data migration, public API)
The Process
Doubt cycle:
- [ ] Step 1: CLAIM — wrote the claim + why-it-matters
- [ ] Step 2: EXTRACT — isolated artifact + contract, stripped reasoning
- [ ] Step 3: DOUBT — invoked fresh-context reviewer with adversarial prompt
- [ ] Step 4: RECONCILE — classified every finding against the artifact text
- [ ] Step 5: STOP — met stop condition
Step 1: CLAIM
Name the decision in two or three lines:
CLAIM: "The new caching layer is thread-safe under the
read-heavy workload described in the spec."
WHY THIS MATTERS: a race here corrupts user data and is
hard to detect in QA.
Step 2: EXTRACT
A fresh-context reviewer needs the artifact and the contract, not the journey.
- Code: the diff or the function — not the whole file
- Decision: the proposal in 3–5 sentences plus constraints
- Assertion: the claim plus the evidence
Strip your reasoning. If you hand over conclusions, you'll get back validation of your conclusions.
Step 3: DOUBT
The reviewer's prompt must be adversarial:
Adversarial review. Find what is wrong with this artifact.
Assume the author is overconfident. Look for:
- Unstated assumptions
- Edge cases not handled
- Hidden coupling or shared state
- Ways the contract could be violated
- Existing conventions this might break
- Failure modes under unexpected input
Do NOT validate. Do NOT summarize. Find issues, or state
explicitly that you cannot find any after thorough examination.
ARTIFACT: <paste artifact>
CONTRACT: <paste contract>
Pass ARTIFACT + CONTRACT only. Do NOT pass the CLAIM. Handing the reviewer your conclusion biases it toward agreement.
Step 4: RECONCILE
For each finding, classify in this precedence order:
- Contract misread — reviewer flagged because CONTRACT was unclear. Fix the contract first.
- Valid + actionable — real issue requiring a change. Change it, re-loop.
- Valid trade-off — issue is real but cost of fixing exceeds cost of accepting. Document explicitly.
- Noise — reviewer flagged something actually correct under context it didn't have.
Step 5: STOP
Stop when:
- Next iteration returns only trivial or already-considered findings, or
- 3 cycles completed (escalate to user), or
- User explicitly says "ship it"
Verification
After applying doubt-driven development:
- Every non-trivial decision was named explicitly as a CLAIM
- At least one fresh-context review per non-trivial artifact
- The reviewer received ARTIFACT + CONTRACT — NOT the CLAIM
- The reviewer's prompt was adversarial ("find issues")
- Findings were classified against the artifact text
- A stop condition was met (trivial findings, 3 cycles, or user override)
- In interactive mode, cross-model was explicitly offered