Search/Fix a Bug by Reproducing It with a Failing Test First

Fix a Bug by Reproducing It with a Failing Test First

Use when a bug is reported. The AI sorts out where the bug belongs, reproduces what the user sees in a failing test, tracks down the real cause, makes the smallest fix, keeps the test to catch it coming back, and repeats the user's steps to confirm it is fixed.

To use this AI rule
## Sort Out Which Part of the System Owns the Bug Before Touching Code Start with the observable impact, not the file where the symptom appeared. A useful triage result tells the next investigator what failed, who or what is affected, and which component owns the behavior. ### Classify before acting - Classify the defect as core behavior, system or integration behavior, or host-environment behavior. - Separate the component that displays the symptom from the component that controls the failing behavior. - Route the work to the owning boundary when the evidence points outside the current component. ### Define the evidence boundary Record the triggering input, initial state, exact user actions, expected result, actual result, and relevant environment. List facts separately from hypotheses. Do not edit implementation code during triage; the next stage must first establish a reproducible failure. The classification is provisional. If later evidence contradicts it, return here, revise the boundary, and move the test to the layer that actually owns the behavior. ## Reproduce What the User Sees in a Test That Fails Turn the report into the shortest repeatable scenario that still matches what the user experiences. Preserve the meaningful input, state, sequence, and visible outcome; remove incidental setup that does not affect the failure. ### Choose the closest reliable test layer - Use a focused unit or component test for isolated logic. - Use an integration or system test when persistence, rendering, transport, or multiple components participate. - Use a browser or end-to-end test when the failure depends on real interaction, focus, timing, navigation, or visual state. Write the regression test before changing source code. Run it and confirm that it fails for the reported reason, not because of broken setup, stale assets, missing data, or an unrelated assertion. A test that has never been observed failing is not evidence of the defect. If the behavior cannot be automated, document why and capture the strongest repeatable alternative, such as a deterministic manual procedure, screenshot sequence, trace, or measured output. Keep implementation code unchanged until the failure evidence is trustworthy. ## Find the First Point Where Behavior Goes Wrong to Pin Down the Cause Investigate only after the failing reproduction is stable. Generate multiple plausible hypotheses and test them with targeted observations instead of changing several things at once. ### Trace the first divergence Follow the failing input through state changes, boundaries, and control flow. Compare a passing case with the failing case and find the earliest point where actual behavior diverges from expected behavior. Inspect generated artifacts, persisted values, integration responses, or timing only where the reproduction indicates they matter. For each hypothesis, predict what evidence would confirm or reject it, run the smallest discriminating check, and record the result. Distinguish the root cause from downstream damage and from conditions that merely make the bug easier to observe. Do not modify production logic while isolating the cause. If all hypotheses fail, loop back to the reproduction, verify its assumptions, refine the classification, and form a new evidence-backed hypothesis. ## Make the Smallest Fix and Keep the Test to Catch the Bug Coming Back Once the root cause is isolated, change the smallest surface that restores the intended behavior. Preserve public contracts and unrelated behavior, and avoid cleanup, redesign, or refactoring that is not required by the failing case. Run the original failing test first. It must now pass because the cause was removed, not because the assertion was weakened, the scenario was skipped, or the test fixture stopped exercising the bug. Keep the test as a permanent regression guard. Then run the directly affected test group and the relevant static checks, linters, or type checks. Expand to a broader suite only when the change crosses shared boundaries or the narrower evidence identifies wider risk. Treat every new failure as evidence: either fix a true regression or return to root-cause isolation if the proposed correction was incomplete. Review the final diff for accidental edits, duplicated logic, weakened validation, and missing edge cases. The fix is complete at this stage only when the targeted behavior and its directly affected neighbors are green. ## Repeat the User's Steps in a Real Environment Before Calling It Fixed Automated tests are necessary but do not replace confirmation of the actual user path. Repeat the original user-facing procedure in the representative runtime, using the same meaningful input and state that exposed the defect. Compare the before-and-after outcome at the visible boundary. When applicable, also confirm the persisted result, rendered output, emitted event, integration handoff, or rebuilt artifact that the user ultimately depends on. Record the environment, steps, and observed result so another person can verify the conclusion. If manual behavior still fails, differs from the automated result, or requires an undocumented workaround, do not declare the defect resolved. Return to classification or reproduction, update the test to cover the missed condition, and repeat the cause-fix-regression-validation loop. Close with a concise evidence report: defect class, confirmed reproduction, root cause, minimal change, regression coverage, directly affected checks, and real-flow result. Add a reusable prevention rule only when the defect reveals a recurring architectural family; leave one-off details in the test and change history.