← All craftbooks

Reproduce-Then-Fix a Bug

Build: software and codeevalv2.0.2released 2026-09-05workflow: build-loop

Fix a bug the disciplined way, with proof at every step: a failing test that reproduces it (verified red by a real test run), the smallest change at the real defect site, a green suite afterwards, and an enforced independent review of the fix.

Steps

Entry step: reproduce. Each step names the specialist role it wants; the full working prompt is expandable.

  1. Reproduce with a failing testdebugging engineerentry

    Establish the failure on the real code, as a running test that fails for the right reason.

    Show working prompt
    The bug to fix: {{scope}}
    
    Establish the failure on the REAL code before changing anything. Read the bug description and the involved source. Find how this project runs its tests (`list_package_scripts`, then read the existing test layout). Write ONE focused test that captures the exact wrong behavior, in the project's real test layout and style — never a scratch file like `src/bug.test.js`. Then run the suite with `run_package_script` (`test`) and confirm it FAILS because of your new test, for the right reason — quote the failing assertion. If the command needs first-use approval, say so and wait rather than guessing. If you cannot reproduce the bug at all, record every attempt honestly; do not invent a cause.
    
    Write `{{workPath}}/repro.md` with exactly these sections: `## Symptom` (what the user sees, in their words), `## Repro command` (the exact command you ran), `## Expected`, `## Actual`, `## Red evidence` (the failing test's path and the quoted failing output from the real run). Cite the real files involved with backtick paths.
    
    Observable handoff: write the completed result to `{{workPath}}/repro.md` in the project's artifacts drawer with `write_artifact`. Do not merely describe what the file would contain. Re-read it with `read_artifact` before finishing this phase and repair any incomplete sections.
  2. Locate the defectroot-cause analyst

    Name the defect site and the causal chain from it to the symptom. No source edits.

    Show working prompt
    Read `{{workPath}}/repro.md`, then trace the failure to its source. Name the defect site precisely: file, symbol, and the first place state or logic goes wrong. Explain the causal chain from that site to the observed symptom, step by step. Check sibling cases: does the same defect pattern appear in neighboring code paths that just have no test yet? Do not edit any source in this phase.
    
    Write `{{workPath}}/diagnosis.md` with exactly these sections: `## Defect site` (the file and symbol, with backtick paths), `## Causal chain`, `## Siblings checked` (which neighboring paths you inspected and what you found). Every path you cite must be real. Before working, open `{{workPath}}/repro.md` with `read_artifact`.
    
    Observable handoff: write the completed result to `{{workPath}}/diagnosis.md` in the project's artifacts drawer with `write_artifact`. Do not merely describe what the file would contain. Re-read it with `read_artifact` before finishing this phase and repair any incomplete sections.
  3. Make the smallest fixsoftware engineer

    Change the real defect site, minimally, keeping the new test as a regression guard.

    Show working prompt
    Read `{{workPath}}/diagnosis.md` and make the SMALLEST correct change at the defect site it names. There is no prescribed output path for source changes — edit the actual files from the diagnosis with `read_file` plus `write_file`/`replace_in_file`. Never special-case the reproduction's exact input just to silence the test; fix the cause. Cover the sibling cases the diagnosis flagged, and keep (or strengthen) the reproduction test so it becomes the permanent regression guard. Re-run the focused test while you work.
    
    Then write `{{workPath}}/fix-notes.md` with exactly these sections: `## Problem` (one paragraph), `## Change` (what you altered and why it breaks the causal chain), `## Files touched` (backtick path per line), `## Regression coverage` (which test now guards this), `## Risk` (what could still go wrong; be honest about anything unverified), `## How to verify` (the exact commands a person runs to confirm). Before working, open `{{workPath}}/diagnosis.md` with `read_artifact`.
    
    Observable handoff: write the completed result to `{{workPath}}/fix-notes.md` in the project's artifacts drawer with `write_artifact`. Do not merely describe what the file would contain. Re-read it with `read_artifact` before finishing this phase and repair any incomplete sections.
  4. Validate red-to-greensoftware engineer

    Re-run the original reproduction and the whole suite; record the real results.

    Show working prompt
    Prove the fix with fresh eyes. Read `{{workPath}}/repro.md` and re-run the EXACT reproduction command it records with `run_package_script` (the suite runs ONLY through `run_package_script` with script name "test"; `run_installed_script` is for named ops scripts and is NOT the test runner) — the previously failing test must now pass, and the whole suite must be green. Anything you could not actually run gets labeled unverified, never claimed. If something regressed, your fix was too broad — go back and narrow it before validating again.
    
    Write `{{workPath}}/validation.md` with exactly these sections: `## Repro re-run` (the command and what happened to the once-failing test), `## Suite` (the full-suite result), `## Result` (red-to-green confirmed, or what remains unverified and why). Before working, open `{{workPath}}/repro.md` with `read_artifact`.
    
    Observable handoff: write the completed result to `{{workPath}}/validation.md` in the project's artifacts drawer with `write_artifact`. Do not merely describe what the file would contain. Re-read it with `read_artifact` before finishing this phase and repair any incomplete sections.
  5. Evaluate the deliverabledebugging reviewer

    Independently grade the observable deliverable and route it to finish, repair, or user escalation.

    Show working prompt
    Review `{{workPath}}/validation.md`, `{{workPath}}/repro.md`, `{{workPath}}/diagnosis.md`, `{{workPath}}/fix-notes.md` against every criterion below. Inspect the underlying evidence files named by the workflow; do not grade from the author's summary alone.
    
    1. The failure was reproduced with recorded red evidence: repro.md quotes a real failing run of a test that lives in the project's actual test layout, or the run stopped honestly at needs-user.
    2. diagnosis.md names a defect site that exists in this codebase and a causal chain that actually explains the symptom.
    3. The change is at that defect site, is minimal, and covers the sibling cases the diagnosis flagged — open the touched files and check; do not grade from fix-notes.md alone.
    4. validation.md re-ran the original reproduction command and the once-failing test now passes with the whole suite green — judged from the recorded runs, not the author's summary.
    5. The reproduction test survives as a permanent regression guard: it exists in the test layout and would fail again if the fix were reverted.
    6. fix-notes.md names every touched file (paths that exist), states residual risk honestly, and gives runnable verification steps.
    
    Open `{{workPath}}/validation.md`, `{{workPath}}/repro.md`, `{{workPath}}/diagnosis.md`, `{{workPath}}/fix-notes.md` with `read_artifact`. Write the evidence-backed review to `{{workPath}}/review.md` in the artifacts drawer with `write_artifact`.
    
    List the findings as a markdown table with columns `| Severity | File | Line | Problem | Fix |` (severities: critical/major/minor/nit; empty table only on PASS). Give each criterion a PASS or FAIL with a concrete path, excerpt, measurement, or observed behavior. End with exactly `Verdict: PASS` or `Verdict: REVISE`. The gate ENFORCES the verdict: a well-formed REVISE is rejected and routed back to `repair` automatically, carrying your findings — so list every finding in the table with a concrete fix. On PASS, `advance_task_step` to `finish`. Never write PASS while a criterion is unmet.
  6. Finishproject lead

    All deterministic and reviewer criteria passed.

    Show working prompt
    The independent review passed. Read `{{workPath}}/review.md` with `read_artifact`, then use `write_task_note` to record a concise DONE summary with the final deliverable paths (`{{workPath}}/validation.md`, `{{workPath}}/repro.md`, `{{workPath}}/diagnosis.md`, `{{workPath}}/fix-notes.md`) and the evidence that each acceptance criterion passed. Report DONE without starting new work.
  7. Repair the deliverablesoftware engineer

    Fix only the concrete gaps from the latest independent review.

    Show working prompt
    Read `{{workPath}}/review.md` with `read_artifact` and repair every failed criterion in `{{workPath}}/validation.md`, `{{workPath}}/repro.md`, `{{workPath}}/diagnosis.md`, `{{workPath}}/fix-notes.md`. Make changes on each file's declared surface (`write_artifact` for artifact inputs, `write_file` for workspace inputs), not in task notes or a reply. Preserve evidence that already passed. Re-run or re-check anything the reviewer found unproven. Ensure `{{workPath}}/validation.md` is genuinely updated this turn so the repair is observable, then hand it back for independent evaluation.
  8. Escalate unresolved concernsproject lead

    The bounded repair loop ended without a defensible pass.

    Show working prompt
    The deliverable did not pass after 3 review rounds. Do not claim success. Read `{{workPath}}/review.md` with `read_artifact`, then use `write_task_note` to record DONE_WITH_CONCERNS: the unmet criteria, what was attempted, the affected paths, and the smallest user decision or missing input needed to continue.

Triggers

Phrases that suggest this craftbook to a crew.

Source

View this craftbook on GitHub · MIT license