A bug provokes an almost reflexive urge - to fix it at once. There is a symptom, there is a suspicion, there is an agent ready to write code: the temptation to jump from the complaint to the edit, skipping everything in between, is strong. It is exactly this jump that spawns a second wave of bugs - when what gets fixed is not the cause but what resembles it, and the symptom leaves only to return from the side.
The naive move is understandable: an edit feels like progress, while diagnosis feels like a delay. It seems the experienced agent "already sees" what the matter is, and asking it to reproduce the problem is a superfluous step. Behind this is the belief that the cause is obvious from the symptom. But a symptom is most often compatible with several causes, and choosing among them by eye is a bet, not a diagnosis.
It breaks at the very first step that people tend to skip - reproduction. Until the bug is reproduced stably and the environment in which it appears is fixed, there is no subject of work: any edit is checked by the feeling that "it seems not to happen anymore". A stable reproduction is not bureaucracy but the turning of a vague complaint into an observable fact that can be refuted or confirmed. Fixing the environment also cuts off a whole class of false trails: a bug that lives only on a certain version, dataset or configuration stops looking random the moment the conditions of its appearance are named explicitly.
Hence the order of debugging, the reverse of the naive one. First fix the minimal reproduction and the environment. Then ask the agent to name two or three hypotheses about the cause and, more importantly, for each - an observation that would refute it. Next add diagnostics or a narrow test without touching production code. Change the code only after the cause is confirmed. And at the end remove the temporary logging and leave a regression test that locks in that the bug will not return unnoticed.
The center of this order is hypotheses with refuting observations, and this is not a formality. The demand to name what exactly would refute a guess cuts off confirmation thinking: the agent stops looking for arguments in favor of the first version and starts testing it. A good hypothesis is one that can be killed by an observation; if no observation refutes it, it is not a hypothesis but a belief, and it is too early to change code by it.
This order is conveniently pinned as a short durable contract for the agent, so as not to spell it out every time. It fits in a few lines: reproduce without changing production code, show the causal chain from the entry to the failure, name a refuting observation for each hypothesis and only then propose a minimal patch and a regression test. Such a contract keeps debugging in the right sequence even under the pressure of "let's just fix it faster".
The cost of a broken order is asymmetric and insidious. An edit made before the cause is confirmed sometimes "works" - the symptom disappears - and that is a worse outcome than an outright failure: the cause remains, and the signal about it you have just silenced. The bug will return in another place, under another symptom, and it will be hard to link it to this edit. The time saved on diagnosis returns with interest as a floating defect. This hits autonomous work especially hard: an agent allowed to fix the symptom will confidently close the task as done, and the chain of consequences surfaces later without it and without the context in which it was easy to untangle.
This does not mean every typo must be carried through the full protocol. For a defect with an obvious, single cause the reproduction and the edit converge into one step. The protocol pays off where the symptom is unstable, the causes may be several, or the bug floats between runs: the less obvious the cause, the more expensive it is to guess and the cheaper it is to reproduce first.
You should check not only the disappearance of the symptom but the quality of the proof of the cause. The right check is a regression test that failed before the edit and passes after: it shows that you addressed the cause itself rather than masked the symptom. If such a test cannot be built, the cause is most likely not confirmed - you are observing a coincidence, not an established link, and it is too early to rejoice at the green screen. A useful control question before closing: can I name the cause in one phrase and show the observation that confirmed it. No such phrase means you saw the symptom disappear, not the cause removed.
The typical failures repeat the skipped steps. No reproduction - the fix is made by description and misses. No refuting observations - the first hypothesis is clung to and confirmed by oneself. No regression test - the same bug returns a month later as new. The sign of all of them is the same: the code was changed before the cause was named and confirmed. Reproduction and cause first, then the edit; otherwise you treat not the disease but its shadow.
Воспроизведи ошибку без изменения production-кода.
Покажи причинную цепочку от входа до сбоя.
Для каждой гипотезы назови наблюдение, которое её опровергнет.
После подтверждения предложи минимальный patch и regression test.