Код‑ревью в эпоху ИИ: 7 ошибок, ведущих к инцидентам. ai code review.. ai code review. llm.. ai code review. llm. pull request.. ai code review. llm. pull request. автоматизация ревью.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект. качество кода.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект. качество кода. код-ревью.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект. качество кода. код-ревью. контроль качества.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект. качество кода. код-ревью. контроль качества. Программирование.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект. качество кода. код-ревью. контроль качества. Программирование. технический долг.. ai code review. llm. pull request. автоматизация ревью. Блог компании OTUS. ИИ в разработке. ии-агенты. искусственный интеллект. качество кода. код-ревью. контроль качества. Программирование. технический долг. Управление разработкой.

Материал подготовлен в преддверии старта курса «ИИ для разработчиков».

Всем привет, меня зовут Сергей Прощаев и в этой статье расскажу про ревью кода, созданного ИИ, и про то, почему AI Code Review так часто не спасает. Я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech & E‑commerce, преподаю на курсах разработки и архитектуры в ОТУС.

Типичный сценарий, который я всё чаще вижу в командах, выглядит так. Разработчик ставит задачу агенту, тот за несколько минут собирает патч на 600 строк, гоняет тесты, отчитывается об успехе.

Открывается pull request, в нём уже сидит AI‑ревьюер и оставил девять комментариев:

  • три про именование;

  • два про отсутствующий docstring;

  • один про потенциальный NPE, остальные про стиль.

Автор поправил, бот пометил замечания устранёнными, CI зелёный. Человек открывает diff, видит восемь файлов, аккуратный код и закрытые замечания — и ставит апрув.

Через неделю приходит расхождение по балансам, и на разборе выясняется, что изменение сломало контракт, которого в diff вообще не было.

Рис. 1. Зелёный pull request и то, что он не показывает

Рис. 1. Зелёный pull request и то, что он не показывает

Сразу разведу два понятия.

  • AI Code Review — автоматическая проверка pull request моделью или агентом.

  • ИИ‑код — код, который агент написал или существенно изменил. Это независимые понятия: ревьюер прекрасно проверяет и полностью человеческий PR.

Разберём 7 ошибок, из‑за которых ревью перестаёт защищать продукт именно тогда, когда команда начинает всерьёз генерировать код агентами.

Для каждой — симптом, причина, что она ломает и как я обычно её чиню. Часть правил появилась не от хорошей жизни, а после разборов инцидентов.

Что показывают цифры за 2026 год

Мне как‑то попалась совместная работа GitClear и GitKraken “The Maintainability Gap”:

  • Там считают не опросы, а реальные изменения строк: 623 миллиона изменений, проанализированных за период 2023–2026 годов, причём данные за 2026-й неполные.

  • Дублированные блоки (пять и больше подряд повторяющихся значащих строк): 40,3 на миллион изменённых строк в 2023 году против 73,0 в 2026-м, рост на 81%.

  • Доля изменений, которые GitClear классифицирует как перемещённые, то есть moved/refactored: 21% в 2022-м, 13% в 2023-м и 3,8% в 2026-м на момент исследования.

  • Связность — число обращений нового кода к существующему на тысячу изменённых строк — снизилась с 343 до 223.

Здесь легко сделать слишком сильный вывод, поэтому оговорюсь: это метрики структуры изменений, а не приговор качеству кода, и речь о корреляции. Авторы не утверждают, что ИИ‑код сам по себе плохой: их данные показывают ухудшение нескольких структурных метрик на фоне роста доли ИИ‑разработки. Одно из возможных объяснений — локальная оптимизация агента под текущую задачу без учёта существующего кода.

Вторую цифру часто цитируют без источника. Отчёт CodeRabbit: выборка из 470 открытых pull request, 320 с признаками ИИ‑соавторства и 150 без них. В первых нашлось в среднем 10,83 замечания против 6,45 во вторых. Оговорок две:

  1. авторство определялось по косвенным признакам;

  2. а находки считал анализатор самого CodeRabbit — вендора инструмента для code review.

Переведу на язык дежурства: изменений больше, они чаще дублирующие и требуют больше внимания, а ревьюеров столько же.

По опросу LeadDev за 2026 год так и выходит. 68% инженеров говорят, что ИИ изменил их подход к ревью, и внутри этой группы 86% ищут проблемы моделью до того, как код посмотрит человек. При этом 29% отмечают, что ревью стало дольше, 24% — что быстрее, 47% не заметили разницы.

Ошибка 1. AI Code Review смотрит только на diff

  • Симптом. Бот молчит, человек ставит апрув, регрессия вылезает в соседнем сервисе, которого не было в списке изменённых файлов.

  • Почему возникает. Дешёвая конфигурация отдаёт модели только унифицированный diff. Это самый дешёвый по токенам вариант и одновременно самый слепой по смыслу: видны изменённые строки, но не вызывающий код, не контракты и не тесты вокруг. Хуже другое — человек подстраивается под инструмент и тоже начинает читать только подсвеченные строки.

  • Что ломает. Сквозные изменения: правка middleware аутентификации на сорок строк выглядит чистой, а рядом ломается DTO, из которого пропал обязательный атрибут.

Пример из платёжного сервиса (Java). ledgerClient — синхронный HTTP‑клиент на Feign во внешний сервис проводок. В diff код смотрится безупречно: исключение обработано, лог есть, метод возвращает Optional.

@Transactional
public Optional<PaymentReceipt> confirm(UUID paymentId) {
    Payment payment = repository.findById(paymentId).orElseThrow();
    payment.markConfirmed();                          // уедет в БД по коммиту транзакции
    try {
        ledgerClient.post(payment.toLedgerEntry());   // синхронный HTTP, Feign
    } catch (FeignException e) {
        log.warn("Ledger unavailable, skip posting: {}", e.getMessage());
        return Optional.empty();                      // транзакция при этом коммитится
    }
    return Optional.of(receiptFactory.from(payment));
}

Локальная транзакция БД не распространяется на HTTP‑вызов: коммит и успешное выполнение ledgerClient.post() не являются одной атомарной операцией. Исключение подавлено, метод завершается штатно, транзакция коммитится. Платёж помечен подтверждённым, проводки нет.

Отдельная проблема — семантика возврата. Что означает Optional.empty() из метода confirm()? Платёж не подтверждён? Квитанция не создана? Вызывающая сторона получает «не знаю, получилось ли», хотя состояние в базе изменено. Дефект тут не только в проглоченном исключении, а в разъехавшихся бизнес‑состояниях. Обнаружиться это может сильно позже: по сверке или по алерту на отсутствующую проводку — если такой алерт заведён.

Нормальный способ починки — не хитрый catch, а перенос внешнего вызова за границу транзакции через outbox (Java):

@Transactional
public PaymentReceipt confirm(UUID paymentId) {
    Payment payment = repository.findById(paymentId).orElseThrow();
    payment.markConfirmed();
    // событие уходит в ТУ ЖЕ транзакцию, что и смена статуса
    outbox.save(LedgerEntryRequested.from(payment, payment.idempotencyKey()));
    return receiptFactory.from(payment);
}

Предполагается, что outbox.save() пишет в ту же базу и участвует в той же локальной транзакции, что и изменение Payment. Отдельный publisher работает только с уже закоммиченными записями outbox и публикует соответствующие сообщения. Дальше нужны ключ идемпотентности на стороне леджера и ретраи на стороне публикации, а для асинхронного контура — ещё и DLQ или parking lot для сообщений, которые не удалось доставить. Именно такой разговор я жду от ревьюера в платёжном сервисе — и его не будет, если в контекст ушли только изменённые строки.

Как чинить. Минимум — отдавать модели целиком, изменённые файлы. Дальше — поиск по репозиторию: определения вызываемых символов, вызывающий код, контракты, связанные тесты. Тут важно не обмануться: даже с окном на миллион токенов задача не «залить весь репозиторий», а отобрать релевантное.

Ошибка 2. AI‑ревьюер блокирует merge с первого дня

  • Симптом. Через две недели после внедрения в рабочем чате появляется вопрос «а можно этого бота отключить, он мешает».

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

  • Что ломает. Доверие, а с ним и весь смысл затеи. Инструмент, который шумит, начинают игнорировать. А инструмент, который игнорируют, приучает игнорировать комментарии вообще, включая человеческие.

Как чинить. Первую версию делаем неблокирующей: обязательной к запуску — да, блокирующей слияние — нет.

С чего начинать — вопрос, на котором я сам сначала ошибся. Логика «давайте со стиля, там не страшно» выглядит безопасной, но противоречит ошибке 4: стиль ловится форматтером и линтером, отдавать его модели незачем. Начинать стоит с узких категорий, где дефект формулируется достаточно однозначно, а замечание можно независимо проверить: подозрительная обработка исключений, нарушения ваших же инженерных правил, небезопасные конструкции, изменения публичных контрактов при наличии явной спецификации.

Расширять зону тоже стоит не по ощущениям. У LLM, как правило, нет надёжно калиброванной вероятности правильности, которую можно трактовать как классический порог, поэтому решение «публиковать эту категорию» я принимаю по статистике: какая доля замечаний в ней подтверждалась людьми на прошлых ревью.

Технически это выглядит так (YAML, GitLab CI):

ai-review:
  stage: review
  script:
    - python -m aireview --pr "$CI_MERGE_REQUEST_IID" --context full-files
  allow_failure: true          # упрощённо: технический сбой ревью не роняет pipeline
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Оговорюсь про allow_failure: он лишь про то, что падение job не валит pipeline. Решение «не блокировать слияние по замечаниям» живёт в логике самого ревьюера: он не выставляет статус, который branch protection считает обязательным для merge.

Право блокировать при этом заработать можно. В Cloudflare серьёзные находки и уязвимости могут становиться блокирующими для merge — но это появилось после десятков тысяч merge request и большой работы над точностью. Это финал пути, а не его начало.

Ошибка 3. Модель возвращает свободный текст вместо структурированного ответа

  • Симптом. Бот пишет складное эссе на полстраницы под pull request, и с этим эссе решительно нечего делать.

  • Почему возникает. Первый прототип почти всегда собирают так: «посмотри diff и напиши замечания». Выглядит убедительно, дальше не масштабируется.

  • Что ломает. Всё, что идёт после генерации: замечание не привязать к строкам, не разложить по критичности, не посчитать долю ложных срабатываний, не дедуплицировать при повторном запуске.

Как чинить. Требовать структурированный ответ с первого дня. Упрощённый контракт ответа — это псевдосхема, реальную придётся описать строгой JSON Schema — выглядит так (JSON):

{
  "summary": "Краткая оценка изменения в 1-3 предложениях",
  "comments": [
    {
      "text": "Что не так и как поправить",
      "file_path": "src/payment/ConfirmService.java",
      "line_start": 42,
      "line_end": 47,
      "severity": "major"
    }
  ]
}

Допустимые значения severity: critical, major, minor, info. По ним фильтруем, по file_path раскладываем inline, по истории считаем, сколько замечаний команда реально приняла.

Небольшая история: MVP собирается за дни, доверие — за месяцы

Помню, как однажды на встрече мне сказали, что своё ревью — это квартал работы и отдельная команда. Поэтому мне была интересна публикация ребят из Content AI, где всё описано довольно честно.

MVP они собрали за три дня. На каждый pull request в CI поднимается контейнер, Python‑обвязка забирает diff и метаданные, готовит контекст, дёргает агента в неинтерактивном режиме и раскладывает ответ обратно как inline‑комментарии. Все ревьюерские знания при этом живут в промпте.

Дальше цифры из их собственного отчёта, то есть self‑reported. За первый месяц: прогон около пяти минут, около 20% комментариев нерелевантны из‑за нехватки контекста, расходы выросли примерно с пяти до пятнадцати тысяч рублей после подключения всей команды. И самый честный вывод: авторы считают, что ревью ускорилось — но допускают, что просто потому, что люди стали смотреть менее вдумчиво.

Отдельно отмечу их решение не давать агенту широкий доступ к репозиторию: отдельный технический пользователь, токен с минимальными правами.

Договорю мысль, которой в кейсах обычно не хватает. Как только ревьюер умеет не только читать diff, но и вызывать инструменты, его надо рассматривать как агента с недоверенным входом: код, комментарии, описание PR и тестовые фикстуры вполне могут содержать prompt injection в духе «игнорируй предыдущие инструкции». Минимальные права, песочница и ограничение инструментов по allowlist — часть модели угроз, а не только вопрос прав токена.

Доступ к репозиторию по возможности делаем read‑only, но сам по себе он проблему не закрывает: инъекция опасна ровно настолько, насколько широк набор инструментов, доступных агенту дальше.

У больших команд то же самое, только на другом масштабе. В Cloudflare ревьюер запускается на merge request автоматически, и они опубликовали цифры: 131 246 прогонов на 48 095 merge request в 5 169 репозиториях за первый месяц, в среднем 2,7 прогона на MR. Работает не «одна модель с большим промптом», а оркестрация: до семи специализированных ревьюеров плюс координатор, который схлопывает дубли и публикует один структурированный комментарий. Самое интересное там результат фильтрации: около 1,2 находки на прогон.

Система намеренно публикует лишь часть найденного, жертвуя полнотой ради качества опубликованных замечаний. При этом обходить её вердикт через break glass инженерам понадобилось 288 раз — 0,6% merge request.

Ошибка 4. LLM ставят на детерминированные проверки

  • Симптом. Бот сегодня ругается на кодировку файла, завтра на неё же молчит. Счёт за токены растёт, польза — нет.

  • Почему возникает. После первого успеха хочется поручить модели всё подряд. Но LLM не стоит считать детерминированным механизмом проверки: одинаковый вход не гарантирует идентичный результат во всех реализациях и настройках.

  • Что ломает. Предсказуемость проверок и бюджет. Плюс размывается ответственность: непонятно, почему одно и то же правило срабатывает нестабильно.

Как чинить. Разделить слои. Что формулируется как правило — должно быть правилом: линтер, форматтер, Semgrep. Модели оставляем то, что требует разбора предполагаемого намерения и нетривиальных зависимостей.

Намеренно упрощённая иллюстрация идеи, не готовое production‑правило (YAML, Semgrep):

rules:
  - id: swallowed-exception-in-transaction
    patterns:
      - pattern-inside: |
          @Transactional
          $RET $METHOD(...) { ... }
      - pattern: |
          catch ($EXC $E) { log.$LEVEL(...); return ...; }
    message: "Исключение проглочено внутри транзакции: состояние закоммитится частично"
    languages: [java]
    severity: ERROR

Шаблон узкий: он не поймает ни catch с возвратом заранее подготовленного результата, ни вариант со счётчиком метрик вместо лога, ни молчаливый return. Боевая версия потребует более точных семантических паттернов и тестов на реальные варианты кода — зато сработает одинаково каждый раз, чего от модели ждать не приходится.

Как контуры складываются вместе, показано на рисунке 2.

Рис. 2. Слои контроля качества pull request

Рис. 2. Слои контроля качества pull request

Главное из схемы: контуры логически независимы и могут выполняться параллельно — человек вправе открыть diff одновременно с ботом. И они не заменяют друг друга: детерминированные проверки дают повторяемость, модель — разбор предполагаемого намерения, человек — ответ на вопрос «а что мы вообще строим». Попытка закрыть один контур другим — одна из самых частых ошибок при внедрении.

Ошибка 5. Большие сгенерированные PR проходят ревью формально

  • Симптом. Pull request на 1500 строк, ревьюер листает его четыре минуты и ставит апрув. Комментариев ноль.

  • Почему возникает. Агент генерирует быстрее, чем человек читает. Раньше размер PR ограничивался усталостью автора, теперь этот ограничитель исчез.

  • Что ломает. Ревью превращается в ритуал. Болезнь не новая: и без ИИ разработчик часто смотрел на большой кусок чужой системы, думал «вроде нормально» и одобрял. ИИ просто увеличил дозу.

Как чинить. Ограничивать размер того, что приходит на ревью. У нас два правила: базовое — не больше 400 строк дельты, иначе изменение возвращается автору на разбиение; для заранее известных механических изменений (массовый rename, обновление зависимостей) действует список исключений. И второе: в описании PR автор своими словами объясняет решение и перечисляет то, что решил не делать.

Первое правило удобно сделать детерминированным (Bash, шаг в CI):

CHANGED=$(git diff --numstat "origin/$TARGET_BRANCH...HEAD" 
          -- . ':(exclude)**/*.lock' ':(exclude)**/generated/**' 
          | awk '{added+=$1; removed+=$2} END {print added+removed}')
if [ "$CHANGED" -gt 400 ]; then
  echo "Дельта $CHANGED строк при лимите 400. Разбейте изменение на несколько PR."
  exit 1
fi

Пример упрощённый: в нём исключены только lock‑файлы и каталог сгенерированного кода, а боевая версия должна отдельно обрабатывать бинарные и другие нетекстовые изменения, для которых --numstat возвращает прочерки, и явно исключать протобуфы, Terraform и сгенерированные клиенты. И про саму цифру оговорюсь дважды. Во‑первых, 400 — наш ориентир, а не константа: машинный код в дельту считать бессмысленно. Во‑вторых, лимит строк — предохранитель, а не оценка сложности: PR на 600 строк тестов безопаснее восьмидесяти строк, меняющих семантику распределённой транзакции. Поэтому рядом с размером живёт список зон риска — аутентификация, платежи, миграции схемы, публичные контракты, конкурентность. Попадание в них означает второго ревьюера независимо от объёма.

По сути мы гоняемся не за размером, а за тем, чтобы изменение вообще можно было отревьюить.

Маленький PR не ценен сам по себе. Ценен PR, который можно качественно проверить.

Проверяю тремя вопросами: что изменилось и зачем; какие инварианты обязаны сохраниться; какие сценарии автор проверил. Не может ответить — код на ревью не идёт. Знаю, что выглядит бюрократией, но за год ничего мягче не сработало.

Ошибка 6. Модель плодит дубли вместо переиспользования

  • Симптом. В кодовой базе появляется третий маппер, вторая схема обработки ошибок и новый сервис, повторяющий существующий слой доступа к данным:

src/main/java/com/acme/billing/
├── mapper/PaymentMapper.java             # был исходно
├── payment/support/PaymentDtoMapper.java # добавил агент в марте
├── api/v2/PaymentConverter.java          # добавил агент в июне
└── payment/PaymentQueryService.java      # дублирует BillingRepository
  • Почему возникает. Без поиска по репозиторию и инструментов навигации модель просто не получает сигнала о том, что аналогичное решение уже есть. Ревьюер, который смотрит только на diff, тоже этого не увидит: в границах изменения код выглядит нормально.

  • Что ломает. Сопровождение. Продублированный блок создаёт налог на распространение: правя одну копию, вы обязаны найти все остальные, в файлах и доменах, которых можете не знать. Механизм согласуется с ростом дублирования на 81%, наблюдаемым в исследовании GitClear, хотя причинную связь отчёт не доказывает.

Как чинить. Дать модели инструменты навигации: поиск по символу и типу, обход caller/callee, индекс репозитория. Полный контекст здесь не нужен: нужен способ быстро ответить на вопрос «есть ли в проекте что‑то похожее». Тот же вопрос вынести отдельным пунктом в человеческий чек‑лист. И держать в репозитории два‑три эталонных примера: сервис, миграция, обработчик.

Ошибка 7. Эффект AI Code Review не измеряют

  • Симптом. На вопрос «стало ли лучше» команда отвечает «субъективно да».

  • Почему возникает. Метрики закладывают в последнюю очередь, а обычно не закладывают вовсе. Считать начинают то, что легко: количество комментариев бота в неделю.

  • Что ломает. Возможность управлять. Без базовой линии вы не отличите ускорение ревью от его деградации, а выглядят они одинаково: цикл сократился, все довольны.

Как чинить. Снять замеры до внедрения. Вот таблица, которую мы ведём у себя, цифры в колонке «было» — реальная база одной из команд за месяц до запуска:

Метрика

Было

Целевое поведение

Медианное время ревью PR

19 ч

Снижается

Время до первого комментария

6,5 ч

Снижается

Доля замечаний, после которых действительно потребовалась правка

Растёт, порог задаём после базового замера

Доля ложных срабатываний

Снижается, условие для расширения категории

Дефекты, обнаруженные после merge

11 за месяц

Не растёт

Повторные изменения того же кода в течение двух недель

7 PR за месяц

Не растёт, это сигнал, а не доказательство дефекта

Ложному срабатыванию нужно определение, иначе метрика превращается в спор. У нас это замечание, которое после проверки человеком признано некорректным. Замечание, с которым разработчик не согласился, но проблема реальна, ложным не считается — для него есть категория «не требует изменений».

И сразу оговорюсь: одной доли ложных срабатываний мало. Ревьюер, который выдаёт один идеально верный комментарий на сотню PR, имеет великолепный показатель и нулевую пользу.

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

Маршрут внедрения показан на рисунке 3. Он разложен по шагам, но переход между ними завязан не на календарь.

Рис. 3. Пример поэтапного внедрения AI Code Review

Рис. 3. Пример поэтапного внедрения AI Code Review

Главная мысль схемы: расширение зоны доверия — не календарь, а условие. Порог по доле ложных срабатываний и по доле замечаний, приводящих к правке, задаём до пилота, а не по факту результатов.

Пока категория его не проходит, следующую не открываем. Обратная стрелка на шаг с контекстом стоит там не случайно: во многих случаях причина плохих замечаний не только модель, но и недостаток контекста.

Где этот подход не сработает

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

В закрытом контуре, где код нельзя отдавать наружу, приходится жить на self‑hosted моделях и своём инференсе. Качество и стоимость эксплуатации там могут заметно отличаться от коммерческих моделей, особенно на задачах с длинными рассуждениями, — это стоит замерить на своих PR до того, как строить процесс. На legacy без тестов ревьюер не заменяет отсутствующую страховку: подозрительное место подсветит, а подтвердить регрессию будет нечем.

И главное: если ревью и так было формальностью, ИИ ничего не починит, он усилит то, что есть.

Сводная таблица

Ошибка

Признак в процессе

Что проверить

Ревью смотрит только на diff

Регрессии вне изменённых файлов

Какой контекст реально уходит в модель

Блокирующий ревьюер с первого дня

Просьбы отключить бота

Статус шага в CI и выбор стартовой категории

Ответ в свободной форме

Нельзя посчитать долю ложных срабатываний

Есть ли контракт ответа и severity

LLM на детерминированных проверках

Нестабильные замечания, растущий счёт

Что из проверок выносится в правила

Ревью объёма вместо решения

Апрув за четыре минуты на 1500 строк

Лимит дельты, зоны риска, описание решения

Дубли вместо переиспользования

Третий маппер и два способа обработки ошибок

Есть ли у модели поиск по репозиторию

Эффект не измеряют

Ответ «субъективно лучше»

Дефекты после merge и доля корректных замечаний

Какой навык на самом деле проверяет этот список

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

Есть и более фундаментальное ограничение. Модель не может проверить требование, которого нет в её контексте: если в контекст передан только diff, она вынуждена проверять код в основном относительно самого этого контекста. if (amount > limit) выглядит корректно ровно до момента, пока кто‑то не откроет требование, где написано >=. Пока в контекст не попали критерии приёмки, ADR, контракт API и доменные инварианты, у части дефектов для модели просто нет наблюдаемого эталона. В платёжном сервисе это особенно заметно: вопрос «правильно ли написан метод» там менее важен, чем «сохраняются ли идемпотентность операции, защита от двойного списания и границы авторизации между ролями и арендаторами».

Отсюда вывод за год. AI Code Review не решает проблему ревью, он меняет её форму. Когда код генерируется дешевле, чем его можно прочитать, узким местом становится не написание, а верификация. И зрелое ревью — это не «подключить LLM к diff», а связка: контекст, детерминированные проверки, структурированный результат, человек и измерение качества. Как и предполагал, самой дорогой частью проекта у нас оказалась не модель, а обвязка вокруг неё: контекст, правила, работа над качеством замечаний и измерение эффекта.

Чек‑лист перед тем, как включать AI‑ревьюера:

  • базовая линия по времени ревью и дефектам, обнаруженным после merge, снята до внедрения;

  • шаг в CI обязателен к запуску и не блокирует слияние;

  • стартовая категория узкая, с объективно проверяемым результатом;

  • модель отдаёт структурированный ответ с привязкой к строкам и severity;

  • в контекст уходят изменённые файлы, связанные тесты и результаты символьного поиска;

  • детерминированные проверки живут в правилах, а не в промпте;

  • у изменения есть лимит размера, список зон риска и описание решения от автора;

  • ревьюер рассматривается как агент с недоверенным входом: доступ read‑only, инструменты ограничены allowlist, права минимально необходимые;

  • определено, что считается ложным срабатыванием, и это измеряется.

Если из всего списка вы возьмёте один пункт, возьмите первый. Без базовой линии вы не узнаете, помог инструмент или просто сделал ревью быстрее и слепее.

Код‑ревью в эпоху ИИ: 7 ошибок, ведущих к инцидентам - 4

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

На бесплатных открытых уроках преподаватели‑практики OTUS покажут, как устроены локальные LLM и современные ИИ‑технологии, а также как выбирать подход под конкретные инженерные задачи.

  • 3 сентября в 20:00. «Локальные LLM модели для разработки». Записаться

  • 17 сентября в 20:00. «Обзор ИИ‑технологий для разработчиков. От идей до рабочих решений». Записаться

А полный список открытых уроков августа собрали в дайджесте.

Автор: sproshchaev

Источник