Правила репозитория для AI-кода, которые сокращают повторные правки на ревью
Правила репозитория для AI-кода помогают командам превращать повторяющиеся замечания на ревью в тесты, линтеры и шаблоны, которые ловят ошибки ещё до того, как pull request начнут копиться.

Почему одни и те же комментарии всё время возвращаются
Самые раздражающие комментарии на ревью — не самые сложные. Это те, которые ваша команда уже написала десять раз за этот месяц.
Открывается pull request, и снова появляются одни и те же замечания: переименуй эту функцию, добавь проверку на null, вынеси этот хелпер из файла страницы, напиши недостающий тест. Каждый такой фикс сам по себе небольшой. Но вместе они съедают часы и тормозят каждый merge.
Сценарий знакомый. Обработчику дают размытое имя вроде processData вместо названия, связанного с фичей. Nullable-поле используют без проверки, потому что happy path однажды сработал. В ветку добавляют тесты на успех, но пропускают пустой ввод или неудачный запрос. Файл оказывается не там, где нужно, потому что в репозитории никогда не делали структуру папок очевидной.
С AI-инструментами это становится только хуже, если в репозитории слишком много места для догадок. Модель видит то, что уже есть, идёт по самому простому шаблону и заполняет пробелы тем, что кажется правдоподобным. Если кодовая база допускает смешанные названия, неровное покрытие тестами или случайную структуру файлов, инструмент будет с уверенностью повторять этот хаос.
Вот почему разовые исправления не приживаются. Ревьюер может подчистить один pull request, но следующая сгенерированная ветка часто приносит ту же проблему снова. Команда продолжает платить за один и тот же урок, потому что сам репозиторий не учит этому заранее.
Правила решают проблему в нужной точке процесса. Линтер может отклонить слабые названия или небезопасный доступ. Тест может поймать пропущенный null-case ещё до ревью. Шаблон может подсказать, куда класть файлы и какой тестовый файл обязательно добавить. Эти проверки скучные. Именно поэтому они полезны. Скучные правила освобождают внимание людей для тех комментариев, где действительно нужна оценка.
Сеньор-инженеры не должны тратить время на то, чтобы в пятнадцатый раз писать «пожалуйста, добавьте проверку на nil». Если ошибка повторяется, относитесь к ней как к проблеме репозитория, а не людей.
Что первым должно стать правилом
Если одно и то же замечание на ревью появляется каждую неделю, перестаньте считать его единичной ошибкой. Это хороший кандидат на правило. Первые правила должны ловить повторяющиеся, скучные проблемы, а не хитрые крайние случаи.
Выбирайте комментарии, у которых есть один очевидно правильный ответ. Правило лучше всего работает, когда инструмент может сказать pass или fail без споров. «Добавь тест, если меняется бизнес-логика» — понятно. «Сделай код чище» — нет.
Перед автоматизацией помогает короткий фильтр:
- Этот комментарий часто повторяется?
- Может ли инструмент проверить его с чётким pass или fail?
- Тратит ли он время ревью, когда человек проверяет это вручную?
- Может ли он привести к багам, проблемам безопасности или сломанной сборке, если его пропустить?
Лучшие первые цели обычно находятся в середине обсуждений на ревью. Пропущенные тесты, необработанные ошибки, небезопасные значения по умолчанию, забытые миграции или файлы не в той папке — хорошие примеры. Ревьюерам не стоит снова и снова тратить по десять минут на такие вещи в каждом pull request.
Споры о вкусе лучше пропускать. Если два сеньор-инженера могут одинаково убедительно защитить разные варианты, не превращайте это пока в жёсткое правило. То же касается редких крайних случаев. Ошибка, которая случается два раза в год, не заслуживает того же внимания, что и ошибка, которая появляется каждую пятницу днём.
Риск для продакшена важнее, чем раздражение. Если повторяющаяся проблема может сломать auth, повредить данные, раскрыть секреты или обойти логирование, поднимайте её наверх списка. Если она лишь делает diff менее аккуратным, оставьте на потом.
Хорошо работает простой способ приоритизации. Дайте каждому повторяющемуся комментарию две оценки от 1 до 5: время ревью и риск для продакшена. Сложите их. Начинайте с самых больших итогов.
Небольшие команды обычно приходят к практичному первому набору: обязательные тесты для изменённой логики, проверки линтера для небезопасных паттернов и шаблоны pull request, которые каждый раз запрашивают недостающий контекст. Такие правила убирают трение на раннем этапе и дают ревьюерам больше времени на архитектуру, компромиссы и поведение продукта.
Начните с самых простых защитных барьеров
Хорошие правила репозитория должны сначала блокировать дешёвые ошибки. Начните с проверок, для которых уже есть понятные инструменты и понятный результат. Formatter, линтер и одна стандартная команда для тестов поймают много шума на ревью ещё до того, как человек откроет diff.
Поместите эти проверки в одно и то же место для каждого репозитория. Если в одном проекте используется make test, в другом npm test, а в третьем ожидаются три отдельные команды, люди будут забывать. AI-инструменты тоже будут забывать. Выберите одну точку входа для тестов, одно место для определения порядка импортов и один файл, где объясняются правила именования.
На этом этапе простые решения лучше сложной автоматизации. Запускайте formatter на каждом коммите или в CI. Запускайте линтер в CI с короткой конфигурацией. Опишите именование файлов, порядок импортов и команды для тестов в корне репозитория. Добавьте шаблоны веток и pull request для повторяющихся запросов.
Шаблоны помогают сильнее, чем многие ожидают. Если ревьюеры всё время просят один и тот же контекст, заставьте авторов предоставить его заранее. Шаблон pull request может спросить про влияние на пользователей, шаги проверки, изменения конфигурации и план отката. Правило для имени ветки может убрать расплывчатые варианты вроде fix-stuff и сразу сделать цель ветки понятной.
Делайте каждое правило узким. Команды сопротивляются новым правилам, если те пытаются решить пять проблем сразу. Обычно принимают то, что убирает один раздражающий повторяющийся комментарий. «Всем новым handlers нужен тест» — легко понять. «Весь код должен следовать умному архитектурному чек-листу» обычно умирает через неделю.
Это особенно важно, когда часть кода пишет AI. Самые частые ошибки крутятся вокруг одних и тех же базовых вещей: пропущенные тесты, грязные импорты, странное размещение файлов и pull request без полезного контекста. Для этого не нужна сложная внутренняя платформа. Нужны несколько скучных правил, которые работают каждый раз.
Превращайте комментарии на ревью в тесты
Самый быстрый способ сократить повторяющуюся работу на ревью прост: перестаньте спорить с одной и той же ошибкой в каждом pull request и заставьте репозиторий ловить её первым.
Хорошие правила часто начинаются с одного предложения, которое ревьюер постоянно пишет вручную.
Запишите это предложение простыми словами. Не используйте внутренний жаргон команды. Хорошее правило звучит так: «Если API-запрос падает, верни правильный статус и стабильный код ошибки». Это поймёт любой в команде, включая человека, который будет обновлять тест через шесть месяцев.
Затем сведите ошибку к самому маленькому примеру, который можно сделать. Не начинайте с полноценной фичи. Сделайте крошечный случай, который показывает плохое поведение в нескольких строках кода или в одном запросе и одном ответе. Небольшие примеры проще хранить, проще запускать и гораздо проще им доверять.
Процесс простой: выберите один комментарий на ревью, который появляется каждую неделю, создайте маленький пример, который его воспроизводит, добавьте тест, который падает на плохой версии, добавьте исправление и запускайте этот тест в CI, чтобы ветка останавливалась ещё до ревью.
Допустим, ваша команда постоянно говорит AI-инструментам не проглатывать ошибки базы данных. Сделайте маленький handler, который ловит ошибку и всё равно возвращает ok. Напишите тест, который ожидает настоящий ответ с ошибкой. Когда AI-код повторит старую ошибку, ветка упадёт в CI ещё до того, как ревьюеру снова придётся на неё указывать.
CI важен, потому что локальные привычки расходятся. Один разработчик запускает весь набор тестов, другой пропускает его, а спешно написанный код проскакивает дальше. Если ветка не может слиться, пока тест падает, правило становится настоящим.
У каждого правила должен быть владелец. Назначьте одного человека или одну команду, которая будет обновлять тест, когда кодовая база меняется. Без владельца старые тесты начинают шуметь, люди перестают им доверять, и кто-то начинает обходить их «ну, только сейчас». Так правила и умирают.
Если комментарий появляется достаточно часто, чтобы раздражать ревьюера, он, скорее всего, уже готов стать тестом. Когда репозиторий ловит это сам, ревью может сосредоточиться на дизайне и продуктовых решениях, а не на одном и том же исправлении снова и снова.
Используйте правила линтера для стиля и безопасности
Если один и тот же pull request постоянно возвращается с неиспользуемым хелпером, забытым await или слишком широким any, значит, ревью происходит слишком поздно. Линтер ловит такие проблемы за секунды.
AI-сгенерированный код часто выглядит нормально на первый взгляд. А потом начинают вылезать мелочи: мёртвые импорты, async-вызовы, которые никто не awaited, типы, которые стали слишком широкими, потому что модель не смогла вывести их аккуратно. Такие ошибки не редкость. Это именно тот повторяющийся труд, который машина должна блокировать ещё до того, как человек откроет diff.
Небольшой набор правил обычно закрывает большую часть боли. Отклоняйте неиспользуемые импорты и переменные. Помечайте promises, которые созданы, но так и не awaited или обработаны. Запрещайте any, когда должен быть настоящий тип. Держите порядок импортов единообразным. Запрещайте кросс-папочные импорты, которые ломают архитектуру. Вводите простые правила именования для файлов, компонентов, hooks и тестов.
Границы между папками важнее, чем думают многие команды. Если frontend-код начинает тянуть в себя server-only модули, а код фичи глубоко лезет во внутренности другой фичи, репозиторий быстро становится грязным. AI-инструменты делают это часто, потому что оптимизируются под тот путь импорта, который кажется рабочим, а не под границу, которую команда хотела сохранить.
Делайте правила линтера читаемыми. Если конфигурация такая большая, что никто не понимает, что именно она проверяет, команда будет её игнорировать, пока она что-нибудь не сломает. Начните с короткого набора правил, которые убирают повторяющиеся комментарии, а потом добавляйте новые только когда необходимость очевидна.
Используйте шаблоны, когда код должен быть одной и той же формы
Когда новый код каждый раз следует одному и тому же паттерну, шаблон экономит больше времени на ревью, чем ещё одно письменное правило. Люди пропускают документацию, особенно когда работают быстро. Стартовый файл даёт им структуру ещё до того, как они начнут допускать обычные ошибки.
Это хорошо работает для новых API endpoints, фоновых задач, UI-компонентов, миграционных скриптов и admin tools. Если каждому из них нужны одни и те же тесты, логирование, обработка ошибок и заметка в документации, заложите эту форму в репозиторий сразу. Тогда автор будет дорабатывать готовый каркас, а не собирать всё из памяти.
Хороший шаблон — это не просто набор пустых файлов. Он включает вещи, которые ревьюеры чаще всего просят добавить: заготовку теста, короткий раздел для документации и базовые проверки безопасности. На практике шаблон нового endpoint может уже содержать проверку входных данных, пример файла с тестом, место для описания кодов ошибок и заметку про метрики или алерты.
Плейсхолдеры важны. Они должны заставлять сделать реальный выбор, а не позволять оставлять размытые значения по умолчанию. Хорошие подсказки просят выбрать режим auth, описать поведение при сбое, перечислить побочные эффекты и добавить план отката.
Так рано ловится ленивое копирование и вставка. Это также делает AI-код менее скользким, потому что модели приходится заполнять конкретные решения, а не выдавать общий пустой каркас.
Шаблоны нужно обновлять. Если кодовая база изменилась, а шаблон всё ещё использует старые паттерны, он распространяет плохой код быстрее, чем отсутствие шаблона вообще. Пересматривайте шаблоны по расписанию или каждый раз, когда команда меняет тестирование, логирование, именование или структуру папок.
Простое правило помогает: если ревьюеры три раза подряд оставляют одно и то же структурное замечание, делайте шаблон.
Простой пример из одной feature-ветки
У небольшой продуктовой команды постоянно повторялись одни и те же комментарии на AI-написанном TypeScript-коде: отсутствуют проверки на null и нет тестов. Ветка выглядела достаточно просто. Она добавляла действие «отправить приглашение ещё раз» для администраторов.
Первый pull request прошёл быстрый ручной просмотр, но код предполагал, что у каждой учётной записи есть contact record. У одного клиента его не было.
const email = account.contact.email;
await inviteService.resend(email);
return { ok: true };
Замечания на ревью были короткими и однообразными:
- Проверь, что
account.contactне null - Добавь тест для случая без contact record
- Не исправляй это через
!, только чтобы заглушить ошибку типов
Этот pull request прошёл через три раунда ревью. Автор добавил проверку на null, потом тест, потом поправил ответ об ошибке. Ничто в репозитории не мешало той же ошибке появиться снова в следующей ветке.
Тогда команда сделала три небольших изменения вместо того, чтобы полагаться на память.
- Они добавили одно правило линтера:
@typescript-eslint/no-non-null-assertion - Они добавили один падающий тест для
contact = null - Они создали стартовый шаблон для новых action handlers с проверкой и подходящей заготовкой теста
Шаблон был намеренно простым. Он начинался с проверок входных данных ещё до любого обращения к сервису:
if (!account.contact?.email) {
throw new AppError("Missing contact email");
}
На следующей ветке команда делала действие «поставить подписку на паузу». AI использовал стартовый шаблон, сначала написал проверку и скопировал форму теста из предыдущего исправления. Pull request не был идеальным, но привычные замечания исчезли.
Ревью тоже стало намного короче. Первая ветка заняла почти весь день, потому что ревьюеру пришлось дважды просить об одном и том же исправлении. Следующая слилась после одного раунда и одного замечания про название.
В этом и смысл. Вам не нужен огромный файл политики. Вам нужно небольшое правило для ошибки, которая всё время возвращается. Если одна ветка показывает, что не хватает проверок на null и тестов, превратите этот урок во что-то, что репозиторий сможет enforced на следующей ветке.
Ошибки, из-за которых правила дают обратный эффект
Правила экономят время только тогда, когда они убирают повторяющиеся ошибки и не замедляют обычную работу. Команды обычно попадают в неприятности, когда превращают вкусовщину в политику, навешивают слишком много собственных проверок или заставляют всех идти одним и тем же путём.
Первая ловушка проста: не каждое замечание на ревью должно блокировать merge. Если одному ревьюеру нравятся более короткие названия функций, а другому — больше комментариев, это место для примеров или командных заметок, а не для CI. Жёсткие правила оставляйте для проблем, которые потом стоят реального времени: пропущенные тесты, небезопасные запросы, сломанные типы или неотработанная обработка ошибок.
Ещё одна частая ошибка — делать хитрые проверки, которые никто не может починить. Собственный скрипт может казаться умным в первый день, а через месяц стать балластом. Если команда не может объяснить, что делает проверка, быстро её обновлять и тестировать при изменении кодовой базы, не выпускайте её. Обычное правило линтера, которому люди доверяют, лучше самодельного gate, который ломается через каждую вторую пятницу.
Сообщения об ошибках тоже должны быть понятными. «Structure check failed» — это слабо. «API handler в файле X не хватает auth middleware» — уже говорит автору, что не так. «Добавьте shared request schema до merge» ещё лучше, потому что сразу подсказывает исправление.
Команды также забывают убирать старые ручные шаги ревью после появления автоматизации. Если тест уже доказывает, что сгенерированный SQL использует безопасный helper, ревьюерам больше не нужно проверять это вручную в каждом pull request. Если оставить оба шага, люди начнут игнорировать один из них.
Оставляйте место для исключений. Скрипты миграций, экстренные патчи, сгенерированные файлы и vendor code часто требуют другого пути. Сделайте этот путь явным: разрешите обход, попросите короткую причину и назначьте одного человека, который это подтвердит. Так правило остаётся полезным и не превращается в стену.
Если правило вызывает больше обсуждений, чем исходная ошибка, с ним нужно что-то делать.
Быстрая проверка перед merge
Правило заслуживает места только если оно ловит ошибку, с которой команда сталкивается часто. Если оно обнаруживает один странный крайний случай из прошлого полугодия, оно будет восприниматься как наказание, а не помощь.
Перед тем как сделать новую проверку обязательной в CI, прочитайте её глазами новичка. Когда она падает, сообщение должно прямо указывать на проблему простыми словами и предлагать исправление. «Auth check missing in API handler» — полезно. «Validation failed» — нет.
Скорость важнее, чем готовы признавать многие команды. Если ещё один тест добавляет три-четыре минуты к каждому pull request, люди быстро начнут раздражаться. Держите путь по умолчанию лёгким. Запускайте маленькие, часто нужные проверки на каждой ветке, а более тяжёлые задания оставляйте для ночных прогонов или более позднего этапа.
Полезно сделать быструю проверку перед merge. Посмотрите, на какой часто встречающийся комментарий на ревью ориентировано правило. Прочитайте сообщение об ошибке вслух и проверьте, звучит ли оно понятно. Измерьте, сколько времени это добавляет в CI. Протестируйте его на реальных открытых ветках, а не на игрушечных примерах. Запишите один случай, когда человек может это пропустить.
Последний шаг сильно снижает трение. Некоторым правилам действительно нужен человеческий override, но такое исключение должно быть редким и легко объяснимым. Короткой заметки в репозитории достаточно, если в ней сказано, кто может пропустить правило, когда именно и как записать причину в pull request.
Команды, которые работают с AI-generated code, обычно понимают это после нескольких болезненных запусков: правило, которое мешает обычной работе, — всё равно плохое правило. Сначала проверьте его на реальных feature-ветках. Если оно ловит нужную проблему, остаётся быстрым и формулируется понятно, тогда можно включать его в путь merge.
Что делать дальше
Откройте pull requests за последний месяц и найдите три комментария, которые возвращаются снова и снова. Выберите те, что каждую неделю съедают время, а не те, что звучат драматично. Пропущенные тесты на крайние случаи, слабые проверки на null, повторяющаяся структура файлов и забытое логирование — обычно хорошие места для старта.
Потом превратите каждый из них в отдельный защитный барьер. Один сделайте тестом, второй — правилом линтера, третий — шаблоном. Такое разделение хорошо работает, потому что у каждой проблемы есть естественное место. Повторяющийся баг в поведении должен жить в тесте. Повторяющаяся правка стиля или безопасности должна быть в linting. Повторяющаяся форма кода должна быть в шаблоне или сниппете.
Первый проход держите маленьким. Примените правило к одной активной части репозитория, а потом посмотрите, как пойдут следующие несколько pull request. Если разработчики постоянно борются с правилом, оно, скорее всего, слишком широкое. Если же никто не замечает его, потому что автоматизация ловит проблему рано, вы выбрали правильную цель.
Ведите несколько простых метрик две или три недели: количество раундов ревью на один pull request, время от открытия до merge и число повторно открытых pull request после merge. Эти числа покажут, убрало ли правило переделки или просто перенесло их в другое место. Если раундов ревью стало меньше с трёх до одного на том же типе изменения — это настоящий успех. Если merge не стал заметно быстрее, а повторно открытых pull request стало больше, ужесточите тесты, прежде чем добавлять ещё правила линтера.
Если вашей команде нужна внешняя помощь, Oleg Sotnikov at oleg.is работает как Fractional CTO и advisor для стартапов и небольших компаний. Он помогает наводить практичный порядок в стандартах репозитория, тестировании, инфраструктуре и AI-augmented development workflows без того, чтобы процесс превращался в тяжёлую обязанность.
Часто задаваемые вопросы
Как понять, что замечание с ревью уже пора превратить в правило репозитория?
Превращайте комментарий в правило, когда одно и то же замечание появляется снова и снова, а инструмент может проверить его по чёткому принципу pass/fail. Хорошие первые кандидаты — пропущенные тесты, проверки на null, небезопасная обработка ошибок и файлы не в той папке.
Что автоматизировать в первую очередь?
Начните с скучных вещей, на которые каждую неделю уходит время ревью. Пропущенные тесты для изменённой логики, слабая безопасность типов, забытые await и недостаток контекста в pull request обычно дают быстрый эффект.
Что выбрать: тест, линтер или шаблон?
Используйте тест для поведения, линтер — для стиля или безопасности, а шаблон — для повторяющейся структуры. Если проблема меняет то, что делает код, пишите тест. Если она влияет на внешний вид кода или его безопасность, используйте линтинг. Если авторы каждый раз заново собирают один и тот же файл по памяти, добавьте шаблон.
Почему AI-код снова и снова делает одни и те же ошибки?
AI-инструменты копируют те паттерны, которые видят, и заполняют пробелы тем, что выглядит достаточно похоже. Если в репозитории допускаются смешанные названия, неровные тесты или хаотичная структура папок, модель будет продолжать воспроизводить то же самое.
Насколько строгим должно быть новое правило репозитория?
Сделайте первую версию узкой и простой для объяснения. Правило вроде new handlers need a test хорошо работает, потому что его быстро понимают, а CI может проверить его без споров.
Нужно ли для этого писать свою автоматизацию?
Обычно на старте не нужны собственные скрипты. Formatter, линтер, одна стандартная команда для тестов и пара шаблонов закрывают много повторяющейся работы на ревью и требуют меньше поддержки.
Как не сделать CI слишком медленным?
Запускайте быстрые проверки на каждой ветке, а более тяжёлые выносите на поздний этап или ночной запуск. Если новое правило добавляет слишком много времени к каждому pull request, сузьте его или сначала выберите более дешёвую проверку.
Кто должен отвечать за правила репозитория?
Назначьте у каждого правила владельца, который будет обновлять его вместе с изменениями в кодовой базе. Без владельца тесты начинают шуметь, шаблоны устаревают, и люди начинают их обходить.
Когда можно делать исключение из правила?
Дайте исключения для экстренных исправлений, миграций, сгенерированных файлов или vendor-кода. Сделайте обходной путь простым: короткое объяснение и один назначенный человек, который подтвердит исключение, чтобы команда не превращала каждую ситуацию в спор.
Как понять, что новые правила действительно работают?
Смотрите на количество раундов ревью на один pull request, время от открытия до merge и число повторно открытых pull request после merge. Если раундов ревью стало меньше, а одни и те же комментарии исчезли, правило помогает. Если merge занимает больше времени, а баги всё равно проскакивают, подстройте правило.