команда · проверка

«Замечаний нет» — а бот вообще смотрел?

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

Различить эти случаи можно по самой сводке: у каждого своя строка. А вот объяснить, почему вышло пусто, сводка по умолчанию не может: настройка diagnostics выключена, и без неё бот оставляет при себе самую полезную часть ответа — каких кандидатов подняли и почему каждого сняли. Включайте её заранее: следующий прогон того же MR будет уже другим — например, проверит только новые изменения.

Для MR, который уже вышел пустым, есть обходной путь: прогоните ту же ветку через CLI с флагом --json. В этом отчёте, как и в ответе MCP, снятые кандидаты с причинами есть всегда, включён diagnostics или нет. Прогон будет новым, но через сервер ревью он идёт на том же движке и тех же моделях, что и у бота. Обычный вывод CLI снятых не печатает, а хук передаёт агенту не больше пяти находок — и без снятых.

Как включить блок диагностики

Хватит одной строки в конфиге репозитория:

.reviewgate/config.yml
# .reviewgate/config.yml
diagnostics: true

На всю инсталляцию — DIAGNOSTICS=true в окружении бота. Но если в конфиге репозитория стоит diagnostics: false, побеждает он. Отдельного вызова модели за блоком нет: он показывает числа, которые прогон уже собрал, и стоит только нескольких строк в сводке.

Со следующего прогона в сводке появится свёрнутый блок «🔬 Диагностика прогона». Вот такой он был на живом прогоне в нашем учебном репозитории:

в сводке
**Контекст модели**: дифф: 2 файлов · полные файлы: 3 (6K симв.) · окружение: ✓ · по правилам команды (6 шт.): 1 из 1 находок

**Вызовы**:

- генератор `claude-sonnet-5` — 11,7K→1,9K токенов · 22 с · находок: 1
- валидатор `claude-opus-5` — 11,1K→359 токенов · 8,3 с · дропнуто: 0 · понижено: 0

**Судья дропнул / понизил / снял fix (✂️)**:

- ✂️ `src/reports/reports.service.ts:23` `periods-in-customer-zone` — «фикс не подтверждён (keepSuggestion=false): Границы квартала считаются в UTC вопреки правилу periods-in-customer-zone; фикс меняет публичную сигнатуру, вызывающий код не показан.»

В блоке три части, и каждая отвечает на свой вопрос о пустоте. Контекст модели — что модель на самом деле получила: сколько файлов в диффе, сколько из них скрыл ignore, сколько полных файлов получил генератор (при full_file_context), не остались ли файлы за бюджетом и сколько находок совпало с правилами команды. Вызовы — кто отработал, на какой модели, сколько времени и сколько находок дал каждый. Если у генератора находок: 0, пусто стало ещё до судейства: судья в таком прогоне не вызывается. Третья часть — что судья снял, понизил или лишил фикса, с причиной для каждого кандидата, чаще всего словами самого судьи.

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

Четыре разных «ничего»

Что говорит сводкаЧто произошлоКуда смотреть
🤖 ReviewGate — после фильтра ignore файлов для ревью не осталось. (или вариант про маркер)до модели не дошёл ни один файл: все отсеялись ещё до вызовасписок ignore и маркеры reviewgate-ignore-file в файлах; сюда же попадают бинарные файлы и изменения без строк кода — переименования, смена прав, удаления. Разбивка по причинам есть только в логе бота
➖ Новых замечаний нет: кандидатов было 5, все сняты проверяющей модельюгенератор нашёл кандидатов, а судья снял всех. Такая строка бывает, только если настроен судьяблок 🔬 — у каждого снятия есть причина
✅ Замечаний не найдено.модель посмотрела и ничего не нашлаКонтекст модели в блоке и строка ⚠️ о бюджете в сводке: какую часть изменения модель на самом деле увидела
Ранее найденные и не закрытые замечания (3) остаются в тредах ниже.приходит вдобавок ко второй или третьей: нового прогон не нашёл, но прежние замечания не закрытысами треды — и гейт, если он включён: из-за них он может остаться красным

Чистой здесь можно назвать только третью строку, и то с оговоркой: полноту обзора она не проверяет — об этом глава «Пусто, но не чисто». Первая значит, что ревью не было, вторая — что оно было, но судья снял всё, четвёртая — что смотреть надо в старые треды. А если сводка не обновилась вовсе, это другой случай: бот промолчал.

Как читать вердикты судьи

Судья умеет только отнимать: снять кандидата, понизить его уровень или отозвать готовый фикс. Добавлять находки и повышать уровень он не может. Поэтому пустой результат после судейства значит одно: судья снял всех кандидатов. Причины снятия условно делятся на три семейства. Кроме блока 🔬 их можно прочитать в отчёте --json: снятые лежат там в dropped — файл, заголовок и причина, без номера строки.

О самой находке: «домысел», «нет доказательств». Здесь судья делает ровно то, ради чего он нужен: генератор многословен, и судья отсеивает то, что команде читать незачем.

О том, что судья смог увидеть: «вызывающий код не показан», «содержимое не видно». Судья получает файлы с находками и определения того, что они импортируют, — и только. Кода, который вызывает изменённое место, он не видит никогда, поэтому находку, чьё доказательство лежит там, снимает как домысел; настройкой бюджета это не лечится. Импорты он разбирает в TypeScript и JavaScript, а в Python, Go, Java и многих других стеках видит одни файлы с находками — там таких снятий будет больше.

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

Бывает и так, что судья не отработал вовсе. Тогда находки публикуются без проверки, и сводка говорит об этом сама, прямо под вердиктом, без всякого блока диагностики: «⚠️ судейство упало целиком — находки опубликованы без валидации». Ничего не потеряно, но ничего и не проверено; если включены готовые фиксы, они тоже уйдут с кнопкой «Применить» без проверки.

Пусто, но не чисто

Пустая сводка или MR без новых тредов ещё не значат, что всё проверено и чисто. Вот четыре случая, когда это не так.

Прогон смотрел только часть изменения. Сводка об этом говорит: Инкрементальное ревью: проверено 2 из 4 изменённых файлов (остальные не трогались с прошлого ревью). Два других файла отревьюены раньше, и их находки остались в своих тредах. Гейт, если он включён, их учитывает: ❌ Severity gate (`major`) НЕ пройден: блокирующих замечаний 3 (из них 2 — ранее открытые, этот прогон их файлы не перепроверял).

Обзор был неполным. Часть файлов модель не видела, и сводка говорит об этом по-разному. Бюджет отмечен своей строкой: «⚠️ MR превышает бюджет ревью: покрыто 4 из 11 файлов». Маркер в файле — тоже своей: «ℹ️ Исключено маркером в файле: 2». Скрытые ignore видны только в блоке диагностики, как ignore: 3 файлов рядом с числом файлов диффа. А бинарные файлы бот отбрасывает молча: их нет ни в сводке, ни в блоке, только в логе бота.

Находки есть, но новых тредов нет. Сводка тогда показывает «Замечаний: N» и «новых строчных: 0», а почему — объясняет отдельной строкой или свёрнутым блоком. Находки ниже порога min_severity уходят в блок «🔇 Ниже порога min_severity» (по умолчанию порог — info, и ниже него ничего не бывает). Уже открытые треды бот не дублирует, а закрытые вами не поднимает снова — об этом строка «Из ранее найденного — уже на ревью, не дублирую: N; закрыто вами (resolved), не поднимаю: M».

Ревью задало вопрос, а не сделало замечание. При questions: true кандидат, которого судья снял как недоказанный, может вернуться ❓-тредом. Это вопрос к автору, а не находка, и в счётчики и гейт он не входит. В сводке для него своя строка: «❓ Вопросов к автору: N (вне severity gate — см. треды)». Вопросы работают только при настроенном судье. «Замечаний не найдено» и ждущий вас вопрос друг другу не противоречат.

Дальше