Программирование с ИИ
ENRU
4.9

Петля «починил одно — сломал другое»

почему она возникает и как из неё выйти

Что это

Знакомая картина: починили ошибку A — появилась B. Починили B — вернулась A. Третий круг, четвёртый, и кажется, что код сопротивляется.

Петля возникает не от невезения. У неё три причины, и все три устранимы.

Почему так происходит

Причина 1. ИИ не видит целого

Каждая правка делается локально: вот эта функция, вот эта ошибка. Что эта функция вызывается ещё в трёх местах с другими ожиданиями — ИИ не знает, если ему не показали.

Поэтому правка, верная сама по себе, ломает соседнее.

Причина 2. Чинится симптом

Если каждый раз править место падения, а не причину, ошибка никуда не девается — она переезжает. Выскакивает в другом месте, под другим именем, и выглядит как новая (статьи 2.12, 2.13).

Причина 3. Контекст сессии засорён

К пятому кругу в разговоре лежат три отменённых решения, два неверных предположения и куча кода, который уже не актуален. ИИ опирается на всё это и начинает противоречить сам себе.

Как выйти

Остановиться и записать

Первое и самое полезное — перестать просить правки и выписать, что известно. Пять строк обычного текста:

измерено
A: падает при пустом городе — чинили дважды
B: дублируются записи — появилось после первой починки A
Общее: обе про функцию save_sub
Не проверял: вызывается ли save_sub из двух мест

Часто на этом месте петля и кончается: становится видно общее звено.

Зафиксировать поведение тестом

Пока нет проверки, каждая правка — это обмен одной ошибки на другую вслепую. Два теста — на A и на B — превращают игру в угадайку в работу: теперь видно, когда починены оба.

Запрос
Напиши два теста: один воспроизводит A, второй B.
Оба должны падать на текущем коде. Код не чини.

Требование «оба должны падать» существенно — оно доказывает, что тесты действительно проверяют нужное (статья 4.6).

Сузить зону

Если правки трогают полпроекта, каждая задевает лишнее. Явные границы (статья 3.13) резко снижают число побочных поломок:

Запрос
Меняй только save_sub. Если задачу не решить, не трогая
остальное, — остановись и скажи, что ещё нужно менять.

Начать новую сессию

Если круг третий и ответы противоречат друг другу — дело в засорённом контексте. Новая сессия с внятно сформулированной задачей и свежим кодом почти всегда быстрее, чем шестой круг в старой.

Что перенести в новую сессию: текущий код, оба теста, записку из первого шага. Чего не переносить — историю неудачных попыток.

Как сказать ИИ

Когда подозреваешь, что правка заденет лишнее:

Запрос
Эта функция вызывается где-то ещё? Если да — что в тех
местах сломается от предложенной правки?

Когда петля уже закрутилась:

Запрос
Мы чиним это третий раз: сначала A, потом B, снова A.
Не предлагай правку. Скажи, что общего у этих двух ошибок
и какая может быть одна причина у обеих.

Запрет «не предлагай правку» нужен обязательно. Без него ИИ выдаст четвёртую версию кода вместо анализа.

На что смотреть

Каждая правка больше предыдущей. Первая — три строки, вторая — двадцать, третья — новый модуль. Признак, что чинится не то; размер растёт от попыток обойти, а не решить.

«Теперь точно работает». После третьего круга эта фраза ничего не значит, пока нет теста.

Ошибки меняются местами. A и B появляются по очереди, никогда вместе — почти наверняка у них одна причина и одно место.

Правки в разных файлах. Если одна ошибка чинится то здесь, то там, значит, причина не найдена ни разу.

Шпаргалка

  • Три причины: ИИ не видит целого · чинится симптом · контекст засорён.

  • Остановись и выпиши, что известно, — часто этого достаточно.

  • Два теста, оба падающие, превращают угадайку в работу.

  • Сузь зону правок явной границей.

  • Третий круг — повод начать новую сессию, перенеся код и тесты.

  • «Не предлагай правку, скажи, что общего у этих ошибок».