
Если ИИ берёт за основу существующий код и предлагает на вид убедительный патч, но что-то не даёт покоя; если фраза «кодовая база всегда так делала» начинает вызывать подозрения; если подключение более мощной модели не спасает от повторения тех же ошибок — проблема не в интеллекте модели, а в структуре, которая принимает прецедент за истину.
Это произошло со мной лично. Точнее — это то, что ИИ, работавший вместе со мной, сделал с моим кодом. Я вмешался одной фразой — и именно то, что эта фраза разорвала, и составляет суть этой статьи.
Точка затора
Я строил генератор кода. Инструмент, который из одной декларативной спецификации (схемы) извлекает и бэкенд, и фронтенд. У этого инструмента было единственное ключевое обещание — «если верификация пройдена, сборка обязана успешно завершиться». Если валидатор зажигает зелёный, а компилятор — красный, это значит, что инструмент солгал.
Однажды конкретный тип (уникальный идентификатор, UUID) споткнулся о валидатор. Тот остановился с сообщением «ожидалась строка, получен другой тип». Я попросил ИИ разобраться. ИИ прошёлся по коду и вскоре нашёл кое-что знакомое.
«Похожий тип (временно́е значение) уже успешно обрабатывается в точно такой же ситуации. Там есть ветвление с особым маркером, которое заставляет валидатор пропускать его. Для UUID такого ветвления нет. Чистое упущение. Нужно просто восстановить симметрию — применить к UUID тот же подход, что и к временно́му значению. Это фундаментальное решение.»
Диагноз выглядел безупречно: «асимметрия», «восстановление симметрии», «фундаментальное решение». Слова звучали весомо. Был составлен план. Пойди он в дело — патч был бы влит.
Одна строка
Читая план, я остановился и спросил:
«Прецедент? А обработка временно́го значения — это действительно правильный подход? Проверь.»
Вот и всё. Я не знал правильного ответа. Не знал, как нужно обрабатывать UUID. Всё, что у меня было — это сомнение: «Тот ориентир, который ты собираешься скопировать, — он проверен?»
Эта одна строка принудительно переключила ИИ из режима «ссылаться на код» в режим «верифицировать поведение».
Рухнувшая предпосылка
Когда ИИ проверил реальный вывод — не структуру кода, а то, что инструмент на самом деле производит — вся предпосылка рухнула целиком.
- Ожидаемое значение, в которое верил валидатор («ожидается строка»), было ложью, расходившейся с реальным выводом. Настоящий генератор создаёт UUID как собственный тип, а временно́е значение — как тип времени. Ни то ни другое не является строкой.
- В обработке временно́го значения, которая «работала нормально», имелась та же самая дыра. Это было не правильное проектирование, а дефектная заплатка, способная пройти верификацию, но сломать сборку.
- А если бы эта латка была скопирована на UUID? Появился бы ещё один случай, прямо нарушающий ключевое обещание инструмента: валидатор зелёный, компилятор красный.
То, что ИИ назвал «фундаментальным решением», было ошибочным. Причём не просто ошибочным — оно копировало существующий дефект и одновременно заставляло валидатор закрывать глаза на новый дефект. Хуже, чем ничего.
Как это называть — error amplification
Дадим название тому, что произошло. Это error amplification (усиление ошибок) ИИ.
ИИ читает существующий код и точно схватывает его структуру. Но является ли это правильным проектированием или наспех вбитой заплаткой — то есть решением или долгом — по одному лишь коду различить невозможно. Поэтому и происходит следующее:
- Существующая реализация принимается за молчаливо подразумеваемый правильный ответ,
- в новую ситуацию под видом «согласованности» и «симметрии» копируется тот же паттерн,
- и чем больше копирований, тем больший ложный авторитет получает паттерн — «кодовая база уже делает так во многих местах».
Дефект не устраняется. Накапливается количество случаев, а с ним — видимость легитимности. Это и есть усиление. Одна заплатка становится двумя, а перед третьим копированием уже никто не сомневается: «кодовая база же всегда так делала».
Это не история из моего опыта с единственным выводом. В 2025 году исследователи измерили это явление и дали работе заголовок «LLMs are Bug Replicators» («LLM — это репликаторы багов»). (Pan et al., 2025, arXiv:2503.11082) Когда в окружающем коде были дефекты, значительная часть багов, созданных моделью, дословно совпадала с уже существующими — у GPT-4o этот показатель составил 82.6%, а в среднем по моделям 44.4% были полностью идентичны непатченной версии. Ещё холоднее другой факт: в дефектном контексте вероятность выдать правильный и неправильный код была почти 1:1. Модель не ошибается случайно. Она избирательно воспроизводит дефектные паттерны, залегающие в контексте.
Та же ловушка есть в праве. Один неверно вынесенный прецедент набирает авторитет по мере цитирования. Количество ссылок — не свидетельство правомерности, но мы снова и снова путаем одно с другим. И это болезнь, которую программная инженерия знала ещё до ИИ: клоны кода, созданные копипастом, тихо переносят баги оригинала. Одно эмпирическое исследование зафиксировало, что около 18% клонов, прошедших через исправление бага, несли распространённый таким образом баг, причём чем ближе клон к оригиналу в одном файле, тем выше вероятность распространения. (Mondal et al., ICSME 2017) Что в коде, что в праве — частота прецедента не есть его легитимность.
Почему так получилось
Не потому что ИИ тупой. Скорее наоборот — из осторожности он стремился к согласованности, а стремясь к согласованности, выровнялся по неверному ориентиру. Механизм распадается на четыре части.
- Источником авторитета стал код. «Код написан так — значит, так и правильно». Но код может быть не решением, а одноразовой проекцией решения. Или просто долгом. ИИ это различие не провёл. В когнитивной науке это называется якорным смещением (anchoring bias). В исследовании этого смещения применительно к LLM было показано, что модели не только сильно тяготеют к первоначально заданному значению, но и притягиваются к нему ещё сильнее, когда оно помечено как «экспертное» — и что промпты вроде «проигнорируй эту подсказку» или «рассуждай пошагово» слабо исправляют это смещение. (Nguyen et al., 2024, arXiv:2412.06593) Существующая реализация — самый авторитетный якорь, который предъявляет кодовая база.
- Согласованность была спутана с корректностью. «Восстановить симметрию с существующим» — была внутренняя логика, но соответствие этого ориентира внешней реальности (реальному выводу) никто не проверял. Самосогласованность — отдельное от точности свойство: модель способна наращивать беспочвенную уверенность на правдоподобных, но неверных самообъяснениях. (Chen et al., 2023, arXiv:2305.14279)
- Комментарий был принят за доказательство. Комментарий «этот тип намеренно сводится к строке» был воспринят как «свидетельство правильного проектирования». Комментарий — лишь намерение автора, но не доказательство правомерности.
- Долг был упакован в словарь уверенности. Слова «фундаментальное решение», «по инструкции» придали не проверенному предложению кредит доверия, повысив стоимость моей фильтрации. Модели, обученные на человеческих предпочтениях, склоняются к согласию и учтивости в ущерб точности — эта тенденция, называемая sycophancy, заставляет модель обёртывать свои предложения в мягкие и категоричные формулировки. (Sharma et al., ICLR 2024, arXiv:2310.13548)
Что разорвало цикл
Вот суть этой статьи. Ошибку разорвала не более мощная модель и не более долгое раздумье. Её разорвала одна строка сомнения от человека.
И это вмешательство было не «знать ответ». Я ответа не знал. Это было указание направления — «поставь предпосылку под сомнение». Одной строки хватило, чтобы ИИ сменил режим: руки, которые ссылались на код, стали руками, которые верифицируют поведение.
Примечательно, что одно исследование зафиксировало именно эту асимметрию. Исследователи DeepMind показали, что плохая способность LLM к самокоррекции обусловлена не отсутствием умения исправлять ошибки, а отсутствием умения их находить — стоило лишь указать извне на местонахождение ошибки, как модель справлялась с её исправлением. (Tyen et al., Google DeepMind, 2023, arXiv:2311.08516) Именно это я и сделал. Я не знал, как исправить UUID, но указал на место: «вот здесь — поставь этот прецедент под сомнение». Этого оказалось достаточно.
Это говорит кое-что о структуре совместной работы человека и ИИ. Ценность человека — не в том, чтобы знать больше и быстрее. В этом ИИ уже выигрывает. Ценность человека в том, что он способен занять позицию, с которой ставит под сомнение предпосылки, на которых стоит ИИ. Вопрос «это действительно правильно?» принадлежит не тому, кто знает ответ, а тому, кто умеет сомневаться в ответе.
Однако эта позиция не даётся даром. Одно пользовательское исследование из Стэнфорда зафиксировало неудобный факт: участники, пользовавшиеся помощью ИИ, писали менее безопасный код — и при этом верили, что их код безопаснее. Но в том же исследовании участники, которые меньше доверяли ИИ и больше подвергали его сомнению, в итоге писали более безопасный код. (Perry et al., Stanford, 2022, arXiv:2211.03622) Позиция сомнения — не настройка по умолчанию. Чем глубже доверие, тем пустее это место становится.
Как это предотвращать
Урок должен остаться не в виде утешения, а в виде проектного решения.
- Прецедент ≠ истина. Прежде чем расширять существующий паттерн, верифицируем не внутреннюю согласованность, а то, производит ли он правильный результат.
- Якорь — в реальности (ground truth). Критерий оценки — не «как выглядит код», а реальный вывод · поведение в runtime · тесты. В этом случае решающим была везде не структура кода, а вопрос «что на самом деле создаётся».
- Стараемся различать решения и латки — и признаём, что не всегда можем. Когда по коду и комментариям их не разделить, явно фиксируем неопределённость: «это следует прецеденту, а легитимность прецедента не проверена».
- Сдерживаем словарь уверенности. К непроверенным предложениям не прикрепляем слова «фундаментальный», «правильный», «по инструкции».
- В автоматизацию встраиваем контрольные точки. В решения, где агент расширяет существующую реализацию, нужны ворота, принудительно проверяющие: «легитимность этого прецедента верифицирована?»
В итоге — та же история
Я давно говорю одно и то же. raw code — не носитель, сохраняющий решения. Код не вмещает «почему сделано именно так». Поэтому git blame показывает кто и когда, но не что было решено.
Этот инцидент — наиболее острое доказательство этого тезиса. Речь не о том, что люди теряют решения. Речь о том, что даже тщательно спроектированный агент принимает латку за дизайн и распространяет её на новый код. Если решения не зафиксированы явно, интеллект — не решение. Напротив: чем выше интеллект, тем последовательнее и убедительнее он распространяет технический долг.
Поэтому я создаю спецификации. Вписываю решения в единственный авторитетный слой деклараций вне кода. Тот вопрос, который ставит под сомнение прецедент — человеческую строку — я стремлюсь сделать не тем, что каждый раз бросает человек, а тем, что бросает сам система.
Закон — не меч, а указатель. Хороший указатель заранее говорит заблудившемуся: «здесь — сомневайся». Эта статья — запись о том, как был поставлен один такой указатель. Начиная с одной строки сомнения.
Связанные статьи
- Чего не показывает git blame — Структура, из-за которой код не сохраняет «почему», и способ заполнить этот пробел
- Yongol: стена в 200 эндпоинтов — Реализация предписания: вписывать решения в единственный слой деклараций (SSOT)
- Sycophancy ИИ — это бизнес-фича — Корни тенденции упаковывать технический долг в словарь уверенности
- Почему кодинг-агенты работают и почему ломаются — Почему верификацию необходимо выносить за пределы LLM
Дополнительное чтение (внешнее)
- Generative AI and the End of Chesterton’s Fence — Reece. Принцип «не убирай забор, не понимая, зачем он поставлен», рушится перед кодом, порождённым вероятностно, без намерения. Точно перекликается с тезисом этой статьи: код не сохраняет стоящее за ним решение.
- Programming as Theory Building — Christian Ekrem. Опираясь на классику Питера Наура, доказывает: «программа — это не исходный код, а теория в голове человека». Теоретический корень того, почему ИИ, видя только код, не может отличить проектирование от долга.
- Vibe coding is not the same as AI-Assisted engineering — Addy Osmani. На реальных инцидентах разбирает, почему vibe coding, слепо доверяющий выводу ИИ, взрывается на продакшне, и предписывает рабочий процесс на основе спецификаций и верификации человеком.
- Cognitive Debt — Simon Willison (цитирует Storey). Чем быстрее ИИ штампует код, тем реальнее становится долг — уже не «дефект в коде», а «неспособность человека понять этот код». Концепция когнитивного долга.
- Overreliance on AI: Addressing Automation Bias — Lumenova AI. Механизмы, которыми автоматизационное смещение, якорное смещение и предвзятость подтверждения притупляют человеческое суждение, и решение в виде «когнитивных принудительных устройств» — психологическое обоснование ценности человека, спрашивающего «где усомниться».
Библиография
- Pan et al. “LLMs are Bug Replicators: An Empirical Study on LLMs’ Capability in Completing Bug-prone Code” (2025, arXiv:2503.11082)
- Mondal, Roy, Schneider. “Bug Propagation through Code Cloning: An Empirical Study” (ICSME 2017, link)
- Nguyen et al. “Anchoring Bias in Large Language Models: An Experimental Study” (2024, arXiv:2412.06593)
- Chen et al. “Two Failures of Self-Consistency in the Multi-Step Reasoning of LLMs” (2023, arXiv:2305.14279)
- Sharma et al. “Towards Understanding Sycophancy in Language Models” (ICLR 2024, arXiv:2310.13548)
- Tyen et al. (Google DeepMind). “LLMs cannot find reasoning errors, but can correct them given the error location” (2023, arXiv:2311.08516)
- Perry, Srivastava, Kumar, Boneh. “Do Users Write More Insecure Code with AI Assistants?” (Stanford, 2022, arXiv:2211.03622)
- Заглавное изображение: сгенерировано ИИ (Google Gemini)