Skip to content

Recipe: Bug Fix with SDD

This recipe shows how to use SpecForge to document, scope, and resolve a bug in a way that creates a lasting spec — so the same class of bug never ships again.

Why Document Bugs as Specs?

Most bugs recur because the correct behavior was never formally specified. Fixing a bug without a spec means:

  • The fix has no acceptance criteria (how do you know it's fixed?)
  • The regression test has no traceability
  • The same pattern can reappear in related code

SDD treats bugs as missing or incorrect specs. Fixing the bug means writing the spec that should have existed, then implementing to match it.


Scenario

Users report that placing two orders simultaneously sometimes results in duplicate charges. This is a concurrency bug in the order placement flow.


Step 1 — Clarify the Bug

Prompt:

Use specforge to clarify requirements for a bug fix:
duplicate charges when placing simultaneous orders in project proj_abc123

SpecForge will ask:

  • Where does the duplication occur — API layer, payment processor, or DB?
  • Is this reproducible under specific conditions (load, network delay)?
  • What's the expected behavior — exactly one charge per order, always?
  • Are there existing tests that should have caught this?

Step 2 — Create a Bug Fix Spec

Prompt:

Create a spec for fixing duplicate charge bug in order placement for project proj_abc123.
Root cause: race condition in OrderService.placeOrder — no idempotency key on Stripe call.
Expected: exactly one charge per order regardless of concurrent requests.

What the spec will contain:

markdown
## Acceptance Criteria

1. Placing the same order twice concurrently results in exactly one Stripe charge
2. The second concurrent request receives a 409 Conflict response with order ID
3. Idempotency key is derived from orderId and stored in orders table
4. Existing orders cannot be modified after payment is initiated
5. Integration test covers concurrent order placement with 10 simultaneous requests
6. Unit test covers idempotency key generation edge cases (UUID v4, collision resistance)

Step 3 — Challenge the Fix Design

Prompt:

Challenge spec SPEC-BUG-001 for project proj_abc123

SpecForge will probe:

  • What if the idempotency key generation itself has a race condition?
  • What if the first request fails mid-flight — does the second one succeed?
  • What's the expiry policy for idempotency keys?
  • Does the fix handle the case where the payment succeeds but the DB write fails?

Step 4 — Security Check

Prompt:

Run a security check on spec SPEC-BUG-001 for project proj_abc123

Concurrent payment bugs often have security implications — ensure the fix doesn't introduce a TOCTOU vulnerability.


Step 5 — Reverse Engineer Existing Code

Document what the current (broken) code actually does:

Prompt:

Reverse engineer the code at /Users/me/my-app/src/orders/OrderService.ts for project proj_abc123

This creates a spec of the current behavior — useful for understanding exactly where the spec and the implementation diverged.


Step 6 — Generate Tests First (TDD approach)

Prompt:

Generate tests for spec SPEC-BUG-001 in project proj_abc123

Write the regression tests before touching the implementation. This ensures:

  • The bug is reproducible with a test (red)
  • The fix makes the test pass (green)
  • The test stays in the suite forever (regression protection)

Step 7 — Generate Execution Plan

Prompt:

Generate an execution plan for spec SPEC-BUG-001 in project proj_abc123

For a bug fix, the plan typically looks like:

markdown
## Phase 1: Reproduce
- [ ] Write failing integration test that triggers duplicate charge (RED)
- [ ] Confirm test fails against current implementation

## Phase 2: Fix
- [ ] Add idempotency_key column to orders table (migration)
- [ ] Generate idempotency key in OrderService before Stripe call
- [ ] Store key atomically with order creation (transaction)
- [ ] Handle 409 from Stripe idempotency endpoint

## Phase 3: Verify
- [ ] Run integration test (GREEN)
- [ ] Run full test suite
- [ ] Manual test with Stripe test mode concurrent requests

Step 8 — Implement and Validate

After implementing the fix:

Prompt:

Validate spec SPEC-BUG-001 against the code at /Users/me/my-app/src for project proj_abc123

Ensure all 6 acceptance criteria are covered by the implementation and tests.


Step 9 — Detect Drift from Original Spec

If there's an existing SPEC for the order placement flow, check if the bug fix introduced drift:

Prompt:

Detect drift in spec SPEC-002 (order placement) for project proj_abc123

The fix may need to be reflected in the original spec as a new criterion: "The system must use idempotency keys for all Stripe API calls."


Step 10 — Capture the Learning

Prompt:

Capture learning: payment provider API calls must always include idempotency keys derived from the business entity ID, never from request-generated UUIDs

This pattern is now stored and will influence future specs that involve payment API calls.


Output of This Recipe

By the end:

  • A bug fix spec (SPEC-BUG-001) with full acceptance criteria
  • Regression tests with traceability to each criterion
  • The original spec updated to reflect the correct behavior
  • A captured learning that prevents the pattern from recurring
  • An audit trail: when the bug was found, what the fix was, why it was the right fix