mcpskills.net
SkillsMCPsAgentsPrompts
mcpskills.net — A curated directory of AI agent Skills and MCP servers
TermsPrivacy
← Back to Skills
Development

Doubt-Driven Development

Subjects every non-trivial decision to a fresh-context adversarial review before it stands. Use when correctness matters more than speed.

by Addy OsmaniRepository →Source →

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:

  1. Contract misread — reviewer flagged because CONTRACT was unclear. Fix the contract first.
  2. Valid + actionable — real issue requiring a change. Change it, re-loop.
  3. Valid trade-off — issue is real but cost of fixing exceeds cost of accepting. Document explicitly.
  4. 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