# A systematic procedure

The following is intended as a sequentially ordered schematic rather than a script to be followed strictly in every situation. (If a close-reading of a stack trace immediately indicates that a problem is limited in scope and simple to fix, for example, obviously just go fix the problem immediately.) Experience—both general and domain-specific—develops the intuition for what point in the script at which to enter for systematic debugging.

1. Tighten the feedback loop
• Automate reproduction
2. Isolate suspect code / component
• RTFEM
• Bisection: statically (in code), dynamically (in control flow), diachronically (in change history)
• Automate bisection and reproduction together if cost-effective and feasible (git bisect run)
3. Precisely identify the elements of state that violate expectations
• Inspect local state: Inputs and any proximate modifications
• Inspect non-local state: object state, function preconditions, compiler flags, data shape, dependency versions, language / framework magic, etc.
• Compare to a reference implementation (another component, same component elsewhere in time)
4. Perform retrograde analysis to identify root causes and permissive background conditions

# Mixed strategies

Systematic application of unsystematic modifications to implementation, state, execution order, or execution form, in order to provoke the system into revealing more of itself (when used as a disclosure stratagem: see “Beat the grass to startle the snake”) and/or catalyze lateral thinking (when used as an oblique strategy: see “Steelmanning divination”). Sometimes referred to as “banging at it”.