Ревью кода
Проверяйте изменения кода на корректность, безопасность, производительность и качество с помощью команды
/review.
Быстрый старт
# Проверить локальные незакоммиченные изменения
/review
# Проверить pull request (по номеру или URL)
/review 123
/review https://github.com/org/repo/pull/123
# Проверить и оставить inline-комментарии в PR
/review 123 --comment
# Проверить локальные изменения и применить находки к рабочему дереву
/review --fix
# Продолжить прерванное ревью того же PR вместо начала заново
/review 123 --resume
# Проверить конкретный файл
/review src/utils/auth.ts
# Быстрая непроверенная проходка (без субагентов)
/review --effort low
/review 123 --effort mediumЕсли незакоммиченных изменений нет, /review сообщит об этом и остановится — агенты не запускаются.
Уровни детализации
--effort low|medium|high — trade-off между глубиной и скоростью:
| Уровень | Что выполняется | Лимит находок | Вердикт | Публикация в PR |
|---|---|---|---|---|
low | 3-6 направленных inline-проходов по диффу (масштабируется по размеру диффа) плюс gap sweep — без субагентов, без сборки/тестов, без правил проекта | 10 (непроверенных) | Нет | Никогда |
medium | Полный пайплайн high без самых затратных проходов: параллельный fan-out finder’ов по сокращённому набору измерений, плюс сборка/тесты и один проход проверки | Без лимита (проверенных) | Approve ограничен до Comment | Никогда |
high | Полный пайплайн: до 16 параллельных агентов → шардированная проверка → итеративный обратный аудит | Без лимита (проверенных) | Approve / Request changes / Comment | С --comment |
По умолчанию: high для ревью PR, medium для локальных ревью и ревью файлов. Использование --comment принудительно устанавливает high (опубликованные комментарии должны пройти проверку) — для цели не-PR --comment игнорируется с предупреждением и не меняет уровень детализации. Medium сохраняет агентов безопасности и покрытия тестами, а также сборку/тесты, но убирает состязательные персоны, специалистов по языковым ловушкам и маршрутизации обёрток/прокси (агенты 1d/1e), diff-специализированные finder’ы и обратный аудит — поэтому тонкая Critical, которую обнаружит только второй проход, может проскочить; используйте --effort high для security-чувствительных или предрелизных ревью. Только low является непроверенным. Изоляция worktree применяется к ревью PR в том же репозитории; кросс-репозиторные PR работают в облегчённом режиме (только diff, без worktree и сборки/тестов). Проход low помечен как непроверенный, не выдаёт вердикт и никогда не записывает инкрементальный кэш ревью, поэтому последующий запуск --effort high никогда не будет пропущен как «уже проверено»; medium проверен, но его Approve ограничен до Comment, потому что никто не смотрел дважды на то, что первый проход пропустил. Механика получения диффа идентична на всех уровнях — ревью PR всегда используют изолированный worktree и то же разрешение базы, поэтому ревью никогда не идёт против неправильной базы. Одно различие в области остаётся: инкрементальный кэш — только для high, поэтому повторное ревью high может покрыть только новые коммиты (lastCommitSha..HEAD), тогда как low/medium всегда ревьюят полный diff PR.
Как это работает
Команда /review запускает многоэтапный пайплайн:
Шаг 1: Определение области + уровня детализации (локальный diff / worktree PR / файл)
Захват diff в файл + разбиение на чанки
Шаг 2: Загрузка правил ревью проекта (medium/high)
Шаг 3C: low effort: 3-6 inline-проходов + gap sweep [0 вызовов субагентов]
Шаг 3A: high, <=500 src И <=3200 всего: до 16 агентов [16+ вызовов LLM]
|-- Агент 0: Issue Fidelity и присвоение корневой причины
|-- Агент 1a: Корректность — построчный скан
|-- Агент 1b: Корректность — аудит удалённого поведения
|-- Агент 1c: Корректность — кросс-файловый трассировщик
|-- Агент 1d: Корректность — скан языковых ловушек
|-- Агент 1e: Корректность — маршрутизация обёрток/прокси
|-- Агент 2: Безопасность
|-- Агент 3a: Переиспользование и дублирование
|-- Агент 3b: Уровень абстракции
|-- Агент 3c: Согласованность и ясность
|-- Агент 4: Производительность и эффективность
|-- Агент 5: Покрытие тестами
|-- Агент 6: Свободный аудит (3 персоны: 6a/6b/6c)
|-- Агент 8: Diff-специализированные finder'ы (0-2, только когда
| домен диффа их требует)
'-- Агент 7: Сборка и тесты (запускает shell-команды)
Шаг 3B: high, >500 src ИЛИ >3200 всего: территория × измерение [N+5..7+3H вызовов]
(N чанков, 5-7 агентов по всему диффу, 3 инвариантных
агента на каждый тяжёлый файл H)
|-- 1 агент на чанк (~400 строк диффа, все измерения,
| только его территория, возвращает квитанцию покрытия)
|-- 3 инвариантных агента на каждый сильно переписанный
| исходный файл (весь файл; state/timers, counters/
| returns/errors, config/early-returns)
|-- Агент 0: Issue Fidelity (весь diff)
|-- Агент 7: Сборка и тесты (весь репозиторий)
|-- Агент 1b: Удалённое поведение (весь diff —
| кросс-чанковая половина; чанки хранят локальную)
|-- Агент 1c: Кросс-файловый трассировщик (весь diff)
|-- Агент 8: Специализированные finder'ы (весь diff, 0-2)
'-- Матрица покрытия тестами (весь diff)
Шаг 4: Дедупликация --> Шардированная проверка (<=8 находок на агента)
--> Агрегация [ceil(F/8) вызовов, F=находки]
Шаг 5: Итеративный обратный аудит, fan-out по чанкам;
остановка после 2 последовательных сухих раундов (лимит 10/5/3 по топологии)
Шаг 6: Предоставление результатов + вердикт (high; при low: только находки)
Каноникализация находок -> .qwen/tmp/...-findings.json
Шаг 6B: Применение находок + запись результатов по каждой находке (только --fix)
Шаг 7: Отправка ревью PR (inline-комментарии, если запрошено; только high)
Шаг 8: Сохранение отчёта + инкрементальный кэш (кэш: только high)
Шаг 9: Очистка (удаление worktree + временных файлов)Шаги 3A/3B/4/5 — это пайплайн high-effort; при --effort low|medium единый inline-проход (Шаг 3C) заменяет их.
Агенты ревью
| Агент | Фокус |
|---|---|
| Агент 0: Issue Fidelity | Доказательства из связанного issue, присвоение корневой причины и проверка того, решает ли PR заявленную проблему |
| Агент 1a: Построчный скан | Проходит каждый hunk вместе с окружающей функцией: неправильные условия, off-by-one, пропущенный await, граничные случаи, гонки |
| Агент 1b: Аудит удалённого поведения | Проходит каждую удалённую/заменённую строку: называет инвариант, который она обеспечивала, и ищет, где новый код его восстанавливает — включая удалённые экспорты, чья замена часто живёт в другом файле и тихо меняет значение по умолчанию. В 3B работает по всему диффу (чанк-агенты хранят локальную половину) |
| Агент 1c: Кросс-файловый трассировщик | Проходит всех вызывающих каждого изменённого символа (направление потребителя) и все сайты чтения каждого добавленного поля (направление производителя), а также изменения callee в том же PR |
| Агент 1d: Скан языковых ловушек | Несёт чек-лист классических граблей для языка диффа (== приведение, ловушки falsy-значений, захват переменной цикла, мутабельные значения по умолчанию, запись в nil-мапу, SQL-конкатенация, арифметика DST) и паттерн-матчит каждый hunk против него |
| Агент 1e: Маршрутизация обёрток/прокси | Для каждого типа, который дифф добавляет или изменяет и который обёртывает другой (кэш, прокси, декоратор, адаптер): каждый метод маршрутизируется через обёрнутый экземпляр, и обёртка перенаправляет каждый метод, который используют вызывающие. Включается в ростер только когда дифф сигнализирует о wrapping-типе |
| Агент 2: Безопасность | Инъекции, XSS, SSRF, обход аутентификации, утечка конфиденциальных данных |
| Агент 3a: Переиспользование и дублирование | Уже ли есть это в кодовой базе? Ищет поведение через grep, называет существующий helper для использования вместо нового, и помечает мёртвый код, оставленный диффом |
| Агент 3b: Уровень абстракции | На правильной ли глубине исправление — или это пластырь на общей инфраструктуре, компенсация downstream для бага upstream, или абстракция для одного вызова? |
| Агент 3c: Согласованность и ясность | Согласованность между соседями (guard, который есть у одного члена параллельного семейства, но отсутствует у другого), дрейф соглашений со ссылкой на локальный пример, вводящие в заблуждение имена/комментарии, излишняя сложность |
| Агент 4: Производительность и эффективность | N+1 запросы, утечки памяти, лишние ре-рендеры, размер бандла |
| Агент 5: Покрытие тестами | Непокрытые тестами пути кода в диффе, отсутствующее покрытие ветвлений, слабые ассерты |
| Агент 6: Свободный аудит | 3 параллельные персоны (атакующий / дежурный в 3 часа ночи / мейнтейнер) — выявляет междисциплинарные проблемы |
| Агент 7: Сборка и тесты | Запускает команды сборки и тестов, сообщает о сбоях |
| Агент 8: Diff-специализированные finder’ы | 0-2 дополнительных finder’а, создаваемых для каждого ревью, когда diff концентрируется в домене с известными режимами отказов (логика переподключения, загрузчики модулей, планировщики, кодеки) |
Три агента корректности являются процедурными: каждый определяется тем, как он проходит diff (построчно / удалённые строки / кросс-файловые рёбра), а не таксономией багов — поэтому их покрытие комплементарно, а не пересекается. Два дополнительных специализированных направления (1d/1e) выносят чек-лист языковых ловушек и маршрутизацию обёрток/прокси из построчного прохода: паттерн-матчинг чек-листа и структурное ожидание маршрутизации — это разные режимы внимания, и в составе построчного прохода они размывались его ритмом. Тот же подход разделяет качество кода на три (3a/3b/3c): один агент с чек-листом из шести пунктов на сильно переписанном файле выполняет один пункт; один агент с чек-листом из восьми пунктов нашёл 1 из 5 дефектов, а та же модель, разделённая на три части, нашла все 5 — поэтому чек-лист качества разрезан там, где вопросы действительно различаются. Все агенты работают параллельно (Агент 1 запускает 3 процедурных варианта и 2 специализированных направления, Агент 3 запускает 3 среза чек-листа, а Агент 6 запускает 3 варианта персон параллельно, в сумме до 16 параллельных задач для ревью PR в том же репозитории — Агент 1e запускается только когда дифф сигнализирует о wrapping-типе — плюс 0-2 finder’ов Агента 8, когда домен диффа их требует — итого 15-18 на практике; Агент 0 пропускается для ревью локального diff и путей к файлам, где запускается 14-17; облегчённый кросс-репозиторный режим также пропускает Агентов 1c и 7, запуская 13-16).
Каждая находка должна описывать сценарий отказа — конкретный вход, состояние или тайминг, который её запускает, и неправильный результат (для находок по качеству — конкретные затраты). Находка, которая не может назвать свой сценарий, отбрасывается у источника, а проверка перетрассирует заявленный сценарий через реальный код, а не оценивает текст находки.
Когда PR содержит более 500 строк изменений исходного кода — или более 3 200 строк диффа в целом, после которых каждый из пятнадцати читающих diff целиком оказывается слишком распылён для внимательного чтения (это ограничение внимания, а не обещание меньшего числа вызовов — тяжёлые файлы и специализированные finder’ы могут сделать 3B дороже) — этот fan-out по измерениям заменяется на fan-out территория × измерение: diff разбивается на чанки по ~400 строк — границы падают на границы hunk’ов, а hunk, слишком большой для одного чанка, разделяется только по объявлению верхнего уровня, никогда внутри функции — и каждый чанк получает собственного агента, который применяет все измерения ревью только к этому чанку.
Гейт намеренно считает строки исходного кода, а не строки диффа. Тестовый код, проза и lockfile доминируют в размере диффа — по последним 40 смержённым PR этого репозитория медианный diff на 41% состоит из тестов — поэтому гейт по сырому размеру разбил бы 173 строки продакшн-кода на территории только потому, что к ним приложено 489 строк новых тестов, оставив этот продакшн-код с одним ревьюером вместо четырнадцати линз (агентов чтения диффа — шестнадцать минус Issue Fidelity и Сборка и тесты). Разбиение на чанки в любом случае покрывает каждую строку, включая тесты; гейт решает, сколько ревьюеров и что каждый из них делает. Четырнадцать линз чтения диффа, идущих по одному большому диффу, читают одни и те же ранние hunk’и четырнадцать раз; один агент на чанк означает, что у каждой строки диффа есть ровно один ответственный ревьюер. Каждый агент чанка возвращает квитанцию Covered:, и чанк без квитанции пересматривается до продолжения — поэтому «блокеров нет» никогда не будет сообщено о коде, который никто не читал.
Исходный файл, который значительно переписан (существующий файл 300+ строк, теперь на 40%+ новый, или имеет 800+ изменённых строк), также получает три инвариантных агента по всему файлу. Тестовые и сгенерированные файлы никогда не квалифицируются — чек-лист спрашивает о полях, таймерах и таксономии ошибок, чего нет в переписанном тестовом файле. Его баги обычно не внутри одного hunk’а, а между новыми строками — таймер, установленный в начале файла, и путь teardown’а на две тысячи строк ниже. Каждый агент читает весь пост-изменённый файл и проходит два-три пункта фиксированного чек-листа: изменяемые поля, очищаемые на каждом пути выхода, таймеры, отменяемые при каждом закрытии (и отмена не отбрасывает захваченные данные), вставки в map, сопоставленные удалениями, счётчики retry, инкрементируемые на каждом входе, возвращаемые значения статуса, которые действительно проверяются, коды ошибок, исчерпывающе классифицированные как постоянные/временные, поля конфигурации, учитываемые на каждом пути, и ранние return’ы, пропускающие необходимый побочный эффект.
Чек-лист намеренно разделён на три части. Один агент со всеми восемью проверками над файлом в 2 400 строк выполнит одну из них правильно; три агента с двумя-тремя проверками каждый выполнят все. Агенты чанков не заменяют это — на PR #6457 каждый из этих дефектов был внутри их назначенной территории, и ни один не был обнаружен. Им не хватало не строк, а вопроса.
Находки проверяются шардированными батчами (не более 8 находок на агента проверки, все запускаются одновременно). Проверщик может отклонить Critical только процитировав код, который ему противоречит (или когда собственные комментарии диффа документируют помеченное поведение как намеренное); всё менее определённое понижается до низкой уверенности, а не удаляется — молча отклонённая Critical невидима для всех последующих этапов, тогда как пониженная всё ещё доходит до человека. После проверки итеративный обратный аудит ищет пробелы, fan-out по одному аудитору на чанк за раунд, каждый с накопительным списком находок. Цикл останавливается после двух последовательных сухих раундов (или лимита раундов плана — сообщается как таковой, а не как сходимость). Лимит зависит от топологии диффа: 10 для небольшого диффа, где раунд — один аудитор; 5 для чанкового, где это один аудитор на чанк; и 3 для огромного диффа (≥ 3000 эффективных строк), когда у запуска есть дедлайн, потому что пять ~90-минутных раундов не помещаются в шестичасовой потолок CI, а ревью, прерванное на полпути, ничего не публикует — без дедлайна огромный diff сохраняет чанковый лимит 5. Оператор может снизить применимый лимит для каждого ревью с помощью настройки review.reverseAuditRounds; повысить его нельзя. Один сухой раунд — не доказательство сходимости, и находки обратного аудита проверяются как любые другие.
Уровни критичности
| Критичность | Значение | Публикуется как комментарий в PR? |
|---|---|---|
| Критично | Обязательно к исправлению перед мержем (баги, безопасность, потеря данных, падение сборки) | Да (только с высокой достоверностью) |
| Рекомендация | Рекомендуемое улучшение | Да (только с высокой достоверностью) |
| Желательно | Опциональная оптимизация | Нет (только в терминале) |
Результаты с низкой достоверностью отображаются в отдельной секции “Needs Human Review” в терминале и никогда не публикуются как комментарии в PR.
Изоляция worktree
При ревью PR команда /review создает временный git worktree (.qwen/tmp/review-pr-<number>) вместо переключения текущей ветки. Это означает:
- Ваше рабочее дерево, проиндексированные изменения и текущая ветка никогда не затрагиваются
- Зависимости устанавливаются в worktree (
npm ciи т.д.), чтобы сборка/тесты работали - Команды сборки и тестов запускаются изолированно, не засоряя локальный кэш сборки
- Если что-то пойдет не так, ваша среда не пострадает — просто удалите worktree
- Worktree автоматически очищается после завершения ревью
- Если ревью прервано (Ctrl+C, сбой), следующая команда
/reviewдля того же PR автоматически очистит устаревший worktree перед началом работы. Если прерванная сессия всё ещё оставляет свою аренду — жёсткое завершение, пропускающее это, или многипромптовое ревью, прерванное на более позднем промпте —/reviewотказывается и называет файл аренды для удаления. Чистые остановки освобождают её: завершённое ревью и ранние остановки (пустой diff, нет новых изменений с момента последнего ревью) все запускаютcleanup, который освобождает аренду - Worktree арендован своей сессии: повторный
/reviewдля PR, который уже находится на ревью, отказывается запускаться (называя владельца), а не разбирает worktree работающего ревью - Отчеты о ревью и кэш сохраняются в основную директорию проекта (не в worktree)
- Шаги, изменяющие код для измерений — мутанты зонда эффективности тестов и зонд верификатора для конкретной находки — каждый запускается в своём одноразовом worktree рядом с основным (
…-probe,…-scratch-<агент>), чтобы эксперимент одного агента не был виден другим, читающим общее дерево. В качестве страховочного предела, каждому агенту в каждой волне также сообщается, какие пути (если вообще есть) отличаются от проверяемого коммита на момент его запуска, и что сбой, ограниченный этими путями, не является находкой. Все эти деревья убираются вместе с worktree в конце ревью.
Ревью PR из другого репозитория
Вы можете делать ревью PR из других репозиториев, передав полный URL:
/review https://github.com/other-org/other-repo/pull/456Это выполняется в облегчённом режиме — без worktree, без сборки/тестов. Ревью основано только на тексте diff (полученном через GitHub API). Комментарии в PR все еще могут быть опубликованы, если у вас есть доступ на запись.
| Возможность | В том же репо | Из другого репо |
|---|---|---|
| Ревью LLM (Агенты 0, 1a, 1b, 1d, 1e, 2-6 + проверка + итеративный обратный аудит) | ✅ | ✅ |
| Агент 1c: Кросс-файловый трассировщик | ✅ | ❌ (нет локальной кодовой базы для grep) |
| Агент 7: Сборка и тесты | ✅ | ❌ (нет локальной кодовой базы) |
| Агент 8: Diff-специализированные finder’ы (0-2, когда домен требует) | ✅ | ✅ (нужен только diff) |
| Inline-комментарии в PR | ✅ | ✅ (если есть доступ на запись) |
| Инкрементальный кэш ревью | ✅ | ❌ |
Inline-комментарии в PR
Используйте --comment, чтобы публиковать находки прямо в PR:
/review 123 --commentИли, после запуска /review 123, введите post comments, чтобы опубликовать находки без повторного запуска ревью.
Что публикуется:
- Находки уровня Critical и Suggestion с высокой достоверностью в виде inline-комментариев к конкретным строкам, каждая с префиксом
**[Critical]**или**[Suggestion]**, чтобы блокеры отличались от рекомендаций - Когда исправление — это одно локализованное изменение, блок
```suggestion, который можно применить одним кликом - Для вердиктов Approve/Request changes: сводка ревью с вердиктом
- Для вердикта Comment, когда все inline-комментарии опубликованы: отдельная сводка не выводится (inline-комментариев достаточно)
- Сноска об авторстве модели и версии CLI в каждом комментарии (например, — qwen3-coder via Qwen Code /review (v0.21.2)); установите
review.attributionвfalseв вашем пользовательском или системномsettings.json(рабочий.qwen/settings.jsonигнорируется для настроекreview.*), чтобы публиковать без неё — комментарии и списки тела также теряют маркеры критичности**[Critical]**/**[Suggestion]**, и модель исключается из маркера машинного журнала ревью, поэтому в новых окружениях (без кэша ревью) восстановленный инкрементальный якорь не проходит проверку одной модели и повторное ревью откатывается к полному диапазону
Что остается только в терминале:
- Находки уровня Nice to have
- Находки с низкой достоверностью
Собственные PR: GitHub не позволяет отправлять ревью с APPROVE или REQUEST_CHANGES на ваши собственные pull request — оба варианта завершаются ошибкой HTTP 422. Когда /review обнаруживает, что автор PR совпадает с текущим аутентифицированным пользователем, он автоматически понижает событие API до COMMENT независимо от вердикта, чтобы отправка прошла успешно. В терминале при этом отображается честный вердикт (“Approve” / “Request changes” / “Comment”) — нейтрализуется только событие ревью на стороне GitHub. Сами находки по-прежнему появляются в виде inline-комментариев к конкретным строкам, поэтому содержательная обратная связь не меняется.
Повторное ревью PR с предыдущими комментариями Qwen Code: когда /review запускается для PR, в котором уже есть предыдущие комментарии ревью Qwen Code, он классифицирует их перед публикацией новых. Только перекрытие на одной строке (существующий комментарий на той же (path, line), что и новая находка) требует подтверждения — это тот случай, когда вы увидите визуальный дубликат на одной и той же строке кода. Комментарии из старых коммитов, комментарии с ответами (считаются решенными) и комментарии, которые просто не пересекаются ни с одной новой находкой, молча пропускаются, с записью в логе терминала, чтобы вы знали, что было отфильтровано.
Проверка статуса CI / сборки перед APPROVE: если вердикт — “Approve”, /review запрашивает check-runs и commit statuses PR перед отправкой. Если какая-либо проверка упала (или все проверки еще в ожидании), событие API автоматически понижается с APPROVE до COMMENT, а тело ревью объясняет причину. Обоснование: ревью LLM читает код статически и не может увидеть ошибки тестов во время выполнения; одобрение при красном CI было бы вводящим в заблуждение. Inline-находки при этом публикуются без изменений. Если вы все равно хотите одобрить (например, при известном нестабильном падении CI), отправьте одобрение GitHub вручную после проверки.
Применение находок (--fix)
--fix — это зеркальное отражение --comment. --comment пишет в pull request, поэтому ему нужен PR; --fix пишет в рабочее дерево, поэтому ему нужно дерево, которое переживёт ревью:
/review --fix # локальные незакоммиченные изменения
/review src/auth.ts --fix # один файлДля PR-цели он игнорируется с предупреждением — ревью PR работает в эфемерном worktree, который удаляется после завершения ревью, поэтому «исправленные» правки там будут отброшены через несколько минут. Вместо этого используйте --comment для публикации находок.
Эффективный --fix устанавливает минимум effort в medium, потому что он редактирует ваши файлы, а low не запускает проверку: применение непроверенной находки — та же ошибка, что и её публикация, только направленная в ваше рабочее дерево, а не в чей-то PR. Он не принуждает к high — находки medium проверены, а обратный аудит, который добавляет high, ищет пропущенные находки, что не относится к решению о применении.
После ревью каждая находка применяется инструментом edit и затем учитывается одним из трёх способов:
| Результат | Значение | Остаётся на вас? |
|---|---|---|
fixed | Правка в вашем дереве | Нет |
skipped | Реальная, не применена — причина сообщается вместе | Да |
no_change_needed | Находка была ошибочной, или код уже обрабатывал это | Нет |
Находка пропускается, когда её исправление изменило бы предполагаемое поведение, потребовало бы изменений далеко за пределами проверяемого диффа, или при повторном рассмотрении оказывается ложным срабатыванием.
Каждая находка получает результат, и это обеспечивается, а не запрашивается. Реестр проходит через qwen review findings --outcomes, который отказывается принимать набор, не покрывающий все — фиксер, который применяет шесть из девяти находок и сообщает о шести, не солгал ни об одной из них, он молча сократил список, и у вас не было бы способа увидеть три, которые выпали.
Возобновление прерванного ревью (--resume)
Длительное ревью, погибшее на полпути — обрыв соединения, таймаут, убитый терминал — оставляет всё сделанное на диске: worktree, захваченный diff и собственную запись запуска о каждом агенте. --resume продолжает оттуда вместо начала заново:
/review 123 --resumeЭто применяется только к целям PR (diff локального ревью берётся из живого рабочего дерева, которое не имеет стабильного прерванного состояния для продолжения), и это безопасно передавать, когда вы не уверены: ревью проверяет состояние на диске — worktree всё ещё на загруженном коммите и чист, захваченный diff неизменен байт в байт, голова PR не сдвинулась, лимит возобновления не исчерпан — и молча начинает заново, когда что-то не совпадает, сообщая, какая проверка отказала. Продолжение переиспользует сертифицированные результаты агентов из предыдущей попытки, поэтому отчёт показывает, сколько было восстановлено; это раскрывается, никогда не создавая пробела в покрытии.
Две вещи, которые нужно знать. При наличии только встроенного целевого значения по умолчанию продолжение сохраняет записанный effort прерванного запуска. Явный --effort, запомненный уровень проекта, настройка оператора review.effort или эффективный --comment задают требуемый уровень; если он отличается от прерванного запуска, возобновление отклоняется и свежий запуск начинается на этом уровне, потому что другой effort — это другая работа. И если голова PR сдвинулась, пока ревью было недоступно, возобновление отказывает (head-moved), и свежий запуск ревьюит новые коммиты — это то, что вам нужно, и это считается единственным перезапуском этого ревью.
Находки как данные
Подтверждённые находки каноникализируются в .qwen/tmp/qwen-review-<target>-findings.json до того, как что-либо их потребляет — терминальный отчёт, сохранённый Markdown-отчёт и JSON ревью PR все читают этот единственный артефакт вместо повторного формирования списка. Каждая находка несёт уникальный id (по чему соединяются результаты и resolved-якоря), severity, confidence, source, summary, shortSummary ограниченный 60 символами для рендеринга списков, failureScenario и один или несколько locations — находка с агрегацией по паттерну сохраняет одну локацию на каждое вхождение, поэтому каждая получает свой inline-комментарий.
Прежде всего, ревью проверяет, что оно запускает ваш код. Каждый шаг qwen review … запускает собранный бандл, а не рабочее дерево, поэтому команда ревью, отредактированная с момента последней сборки, не вступит в силу, и запуск будет измерять старое поведение. Сборка записывает дайджест источников ревью, которые она упаковала; parse-args выводит его заново и сравнивает, а drive проверяет ещё раз, потому что бриф верификатора направляет агентов прямо туда, минуя шаг 1. При несовпадении он сообщает в stderr, что бандл не был собран из этих источников, и что нужно пересобрать. Проверка запускается, когда CLI разрешается в собранный dist/cli.js (бинарник qwen или node dist/cli.js); лаунчеры, запускающие несобранный код, такие как npm start и npm run dev, пропускают её. Два случая, когда сравнение невозможно, обрабатываются по-разному: для чекаута, чья сборка предшествует записи, сообщается, что проверка не могла быть выполнена и почему, а установленный пакет — у которого нет источников для сравнения — остаётся без сообщения. Дайджест покрывает команды ревью, файл, который их регистрирует, аренду только для ревью, которую они импортируют извне своей директории, и встроенный навык ревью; он не следует за общими помощниками, которые они импортируют, поэтому тихий запуск означает, что код ревью соответствует бандлу, а не что всё дерево в целом.
Critical, которая уже падала на базовом дереве, откладывается, а не регистрируется. Когда команда тестов упала и base слияния может быть собран, test-delta записывает, какие падающие файлы также падают без pull request. Каноникализация читает это измерение обратно (qwen review findings --test-delta, рядом с --outcomes): Critical, чей собственный текст называет один из этих файлов, понижается до Suggestion, сохраняет свои доказательства, получает измерение, которое её понизило, и поле heldByMeasurement, и понижение объявляется. Тест, который уже был красным, — это не тест, который pull request делает красным — и если он теперь падает по новой причине, укажите какой тест, процитируйте обе стороны и зарегистрируйте её снова как Critical: находка, которая уже несёт измерение и всё равно повышена, остаётся там, где вы её оставили.
Команда валидирует при записи: дублирующийся id, находка без сценария отказа, пустой массив locations или неизвестная severity — это ошибка, а не молча искажённая запись.
Изображения-доказательства в комментариях PR
API GitHub не позволяет прикреплять изображения к комментариям ревью, поэтому /review может хостить изображения-доказательства (скриншоты TUI, сравнения визуализированного вывода) в назначенном вами репозитории и встраивать их по URL:
export QWEN_REVIEW_ASSETS_REPO=your-org/your-repo # репозиторий, в который вы можете пушить
/review 123 --commentУкажите репозиторий, в который вы можете пушить — рекомендуется выделенный репозиторий для хостинга изображений; также подойдёт форк или служебный репозиторий. Избегайте репозитория, который находится на ревью: ветки с изображениями, запушенные туда, становятся доступными объектами, которые каждый клон будет загружать. Изображения попадают в ветку pr-assets/<pr>-review с контентно-хешированными именами, и комментарии ссылаются на них по зафиксированному коммитом URL — неизменному, даже если ветка позже сдвинется, и работающему без изменений на GitHub Enterprise.
Для ревью, запускаемых по триггеру GitHub (workflow ревью PR), та же переменная подключается из переменной репозитория с тем же именем, и workflow передаёт её только в выделенный внешний хост: при неустановленной переменной или при указании репозитория на ревью (сравнивается после обрезки пробелов и нормализации регистра, поэтому дополненные или написанные с другим регистром названия того же репозитория считаются самоцелевыми), workflow передаёт пустое значение и публикация отклоняется — ничего не меняется, и ревью сохраняет свои доказательства как текст и локальные пути к артефактам. Мейнтейнер, установивший QWEN_REVIEW_ASSETS_REPO в Actions-переменных репозитория на отдельный репозиторий для хостинга изображений, включает возможность комментариев ревью встраивать PNG-снимки. Внешний получатель управляет своим собственным хранением; workflow очистки визуальных материалов только очищает исторические ветки pr-assets/*, которые прежние издатели на базе Git оставили в этом репозитории.
Публикация ограничена точно так же, как и постинг: нет назначенного репозитория — нет публикации, а неавторизованный запуск (без эффективного --comment) отклоняется так же, как submit отклоняет. Принимаются только типы изображений (SVG исключён намеренно), с ограничениями по размеру, и байты каждого файла должны соответствовать формату, который заявляет его расширение — неправильно помеченный или неопознанный контент отклоняется. Манифест записывает каждый запушенный файл. Без назначения находки хранят свои доказательства как локальные пути к файлам в терминале и сохранённом отчёте — ничего не ломается, комментарии просто остаются текстовыми.
Последующие действия
После ревью контекстные подсказки появляются в виде ghost text. Нажмите Tab, чтобы принять:
| Состояние после ревью | Подсказка | Что происходит |
|---|---|---|
Локальное ревью, --fix не передан | fix these issues | LLM интерактивно исправляет каждую находку |
| Ревью PR с находками | post comments | Публикует inline-комментарии в PR (без повторного ревью) |
| Ревью PR, ноль находок | post comments | Одобряет PR на GitHub (LGTM) |
| Локальное ревью, все чисто | commit | Коммитит ваши изменения |
Примечание: fix these issues доступно только для локальных ревью, по той же причине, что и --fix — для ревью PR worktree очищается после завершения, поэтому интерактивное исправление после ревью невозможно; используйте --comment или post comments для публикации находок. Когда --fix был передан, находки уже содержат результаты и подсказка исправления не предлагается.
Правила ревью проекта
Вы можете настроить критерии ревью для каждого проекта. /review читает правила из следующих файлов (по порядку):
.qwen/review-rules.md(нативный для Qwen Code).github/copilot-instructions.md(приоритетный) илиcopilot-instructions.md(резервный — загружается только один из них, не оба)AGENTS.md— секция## Code ReviewQWEN.md— секция## Code Review
Правила внедряются в агентов ревью LLM (0-6) как дополнительные критерии. Для ревью PR правила читаются из базовой ветки, чтобы предотвратить внедрение правил обхода злонамеренным PR.
Контекст репозитория
Репозитории могут передать ревьюерам ограниченные, специфичные для репозитория рекомендации, закоммитив строгий JSON-манифест в .qwen/review-context.json. При effort уровне medium или high /review читает манифест после захвата плана и прикрепляет подходящие рекомендации перед запуском любого агента:
{
"version": 1,
"label": "Example repository",
"rules": [
{
"paths": ["packages/*/src/**"],
"domains": ["runtime"],
"relatedPaths": ["packages/runtime/src/**"],
"recommendedTests": ["npm run test:runtime"],
"requiredConfigurations": ["debug"],
"requiredAgents": ["test-matrix"],
"unverifiedDimensions": ["Alternate runtime was not exercised"],
"verificationNotes": ["Use the repository native test runner"]
}
]
}Правило применяется, когда любой изменённый файл совпадает с одним из его glob-шаблонов paths (*, ? и сегменты **; с учётом регистра). Все совпадающие правила объединяют свои рекомендации: домены и связанные файлы для агентов ревью, рекомендуемые тесты и требуемые конфигурации для агента сборки и тестов, дополнительные роли ревьюеров (учитываются только когда выбранный effort уровень и топология их запускают), и границы доказательств, которые итоговое ревью раскрывает как непроверенные измерения. Массивы могут быть записаны в любом порядке; дубликаты записей отклоняются.
Для ревью PR манифест читается из base-коммита слияния, поэтому ревьюимый PR не может самостоятельно включить или исключить себя из рекомендаций; локальные ревью читают его из текущего worktree. Ревью с низким effort уровнем и кросс-репозиторные ревью пропускают контекст репозитория. Полный контракт и модель доверия описаны в документе дизайна.
Issue Fidelity
Для PR с исправлениями багов агент Issue Fidelity получает доказательства из issue напрямую, а не полагается на текст описания PR. Он запускает подкоманду qwen review issue-context <pr> --repo <owner/repo> --out <file>, которая определяет надежные метаданные GitHub о закрывающих issue и затем получает заголовок, body (оригинальное воспроизведение от репортера) и полную ветку комментариев каждого упомянутого issue — каждое из собственного репозитория issue (PR может закрывать issue в другом репозитории). Этот агент запускается только для целей PR; ревью локального diff и путей к файлам его пропускают.
Множество закрывающих issue — это подсказка для поиска, а не доказательство того, что автор связал правильный issue: если оно пусто, но PR ссылается на очевидное целевое issue, агент всё равно получает его после оценки релевантности (повторный запуск с --issue <n>; простое число разрешается в репозитории PR, тогда как --issue <owner>/<repo>#<n> загружает кросс-репозиторную ссылку из её собственного репозитория). Полученный текст issue рассматривается как ненадежные данные (факты извлекаются, встроенные инструкции игнорируются). Для релевантных issue оригинальное воспроизведение, наблюдаемые данные, ожидаемое поведение и комментарии мейнтейнеров рассматриваются как доказательства наивысшего приоритета для определения того, решает ли PR правильную проблему.
Если доказательства из issue показывают, что вышестоящий сервис или провайдер вернул некорректные данные вне клиентского контракта, изменения клиентского парсера или санитайзера не рассматриваются как валидное исправление корневой причины, если только мейнтейнер явно не запросил защитное обходное решение. Тест, который воспроизводит некорректный вывод вышестоящего сервиса, доказывает лишь то, что обходное решение обрабатывает такую форму данных; он не доказывает, что обходное решение архитектурно уместно.
Пример .qwen/review-rules.md:
# Правила ревью
- Все API-эндпоинты должны проверять аутентификацию
- Запросы к базе данных должны использовать параметризованные выражения
- React-компоненты не должны использовать инлайн-стили
- Сообщения об ошибках не должны раскрывать внутренние путиИнкрементальное ревью
При повторном ревью ранее проверенного PR команда /review проверяет только изменения с момента последнего ревью:
# Первое ревью — полная проверка, создается кэш
/review 123
# PR обновлен новыми коммитами — проверяются только новые изменения
/review 123Кросс-модельное ревью
Если вы смените модель (через /model) и повторно проверите тот же PR, /review обнаружит изменение модели и выполнит полную проверку вместо пропуска:
# Ревью с моделью A
/review 123
# Смена модели
/model
# Повторное ревью — полная проверка моделью B (не пропускается)
/review 123
# → "Предыдущее ревью использовало qwen3-coder. Запускается полная проверка с помощью gpt-4o для получения второго мнения."Совпадение модели также определяет инкрементальное масштабирование, а не только пропуск: «очистить до закешированного коммита» — это вердикт предыдущей модели, поэтому когда новые коммиты появились с момента закешированного ревью, несовпадение модели никогда не масштабируется до lastCommitSha..HEAD — диапазон будет полным diff, с примечанием «Предыдущий раунд был проверен моделью qwen3-coder. Запускается полная проверка с помощью gpt-4o.» — если только якорь, сертифицированный текущей моделью, не восстановлен из последнего опубликованного ревью (ниже), который вместо этого определяет диапазон. Находки предыдущего раунда всё ещё переносятся для повторной проверки; только якорь не переносится. Тот же гейт связывает якорь, восстановленный из маркера машинного журнала последнего опубликованного ревью, когда кэш отсутствует или его якорь непригоден (CI, другой клон): он определяет инкрементальный диапазон, только если текущая модель сертифицировала его — маркер, сертифицированный другой моделью или не содержащий модели (ревью, опубликованное с отключённой review.attribution или до появления этого поля), откатывается к полному diff. Раунд, который не завершился чисто, публикует свой маркер без якоря (он не может сертифицировать диапазон), но эта потеря не является стойкой, когда список работы раунда сохранился целиком: восстановление переносит якорь вперёд от самого последнего предыдущего маркера, который ваша собственная учётная запись опубликовала с якорем, поэтому один нечистый раунд больше не заставляет каждый последующий раунд перечитывать полный diff — следующий раунд ограничивает anchor..HEAD, который покрывает диапазон, который нечистый раунд не мог сертифицировать. Сращение раунда с ограничением по размеру отклоняется (отброшенные находки попали бы за пределы сращённой области и тихо устарели), поэтому последующие раунды продолжают перечитывать полный diff, пока не появится полный маркер.
Кэш хранится в .qwen/review-cache/ и отслеживает как SHA коммита, так и ID модели. Убедитесь, что эта директория добавлена в .gitignore (также подойдет более общее правило, например .qwen/*). Если закешированный коммит был удален при rebase или force-push, инструмент вернется к полной проверке; Aone управляет закешированным якорем иначе — см. его абзац ниже. Только ревью high-effort обращаются к кэшу или записывают его — быстрый проход --effort low|medium никогда не считается «уже проверенным».
Отчеты о ревью
Для ревью в рамках одного репозитория результаты сохраняются в виде Markdown-файла в директории .qwen/reviews/ вашего проекта (облегченные кросс-репозиторные ревью пропускают сохранение отчетов):
.qwen/reviews/2026-04-06-143022-pr-123.md
.qwen/reviews/2026-04-06-150510-local.mdОтчеты включают: временную метку, статистику диффа, результаты сборки/тестов, все найденные проблемы со статусом проверки и итоговый вердикт. Заголовки секций и описательный текст следуют языковым настройкам вывода; технические идентификаторы (SHA, пути к файлам, имена гейтов, id находок) остаются без изменений.
Ревью уровня medium и high также сохраняют структурированный JSON-компаньон с тем же именем (например, 2026-04-06-143022-pr-123.json), содержащий канонические находки и составленный вердикт как данные. Web Shell Qwen Code рендерит этот документ как интерактивное представление ревью с фильтруемыми находками; Markdown-отчёт остаётся читаемым человеком архивом.
Детерминированные части пайплайна — разбор аргументов (qwen review parse-args) и решение о событии/теле (qwen review compose-review) — это тестированные подкоманды, а не текст промпта, поэтому грамматика --effort, принуждение --comment, ограничения вердикта и поведение понижения закреплены модульными тестами и не могут разойтись с моделью.
GitHub Enterprise: ревью PR по URL на хосте, отличном от github.com, направляет все вызовы GitHub на этот хост — подкоманды ревью (match-remote, meta, fetch-pr, pr-context, comment-status, issue-context, fetch-diff, comment-body, plan-diff, test-plan, presubmit, compose-review, submit, publish-assets) принимают --host и устанавливают его в коде, поэтому забытый хост не может молча перенаправить ревью на github.com.
Aone Code: для клона, чей origin находится на gitlab.alibaba-inc.com, запустите /review изнутри этого клона — платформа определяется по remote, и подкоманды работают через CLI a1 (не ниже 0.1.90 — старый инсталлят отклоняется при аутентификации с сообщением об обновлении) — целевой номер является глобальным id MR. fetch-pr получает refs/merge-requests/<id>/head и строит worktree + diff, поэтому агентское ревью worktree не меняется, и test-plan тоже работает — он читает описание MR через тот же ридер. pr-context тоже поддерживается: он читает метаданные MR, ветки обсуждений и ранее опубликованные сводки qwen (машинный журнал восстанавливается из них), поэтому запуск Aone видит существующее обсуждение MR точно так же, как запуск GitHub видит PR. comment-status и presubmit тоже работают через a1 (presubmit полностью: обнаружение собственных PR, дрейф головы, CI merge-gate и дедупликация существующих комментариев), поэтому повторные раунды --comment проходят дедупликацию по существующим комментариям MR вместо их повторной публикации (ветка, помеченная платформой как устаревшая — её строка больше не отображается после amend — остаётся доступной для повторной публикации), и обнаружение собственных PR тоже работает. Запись publish-assets пропускается. --comment публикует ревью через CLI a1: один комментарий на каждую inline-находку, затем сводный комментарий. У Aone нет нативного состояния request-changes — при таком вердикте сводный комментарий несёт блокирующий заголовок, и любые inline-Critical, которые были опубликованы, блокируют мерж через гейт обсуждений, пока их обсуждения не закрыты (когда inline-Critical не публиковались, заголовок носит рекомендательный характер и ничто не блокирует мерж механически). Опубликованные комментарии не несут флаг AI-комментария — a1 не может его установить — поэтому специальный гейт мержа ai_comment репозитория их не отслеживает. Нативная команда a1 repo mr approve срабатывает для вердикта Approve, когда запуск читал контекст MR (тот же гейт, что и GitHub; запуск без доступного контекста остаётся ограниченным до Comment). Инкрементальное повторное ревью следует модели обновлений AGit-Flow: обновление AMENDS единственный CR-коммит на месте, осиротляя голову, которую проверил предыдущий раунд — поэтому закешированный якорь управляется БЕЗ учёта родословной (тест якоря за головой провалился бы при каждом обновлении), и повторное ревью ограничивает diff PR файлами, которые обновление затронуло, вместо отката к полному ревью; обновление, которое также сделало rebase на более новый master, сохраняет эту область только пока дрейф rebase остаётся в файлах CR — дрейф, затрагивающий любой другой файл, откатывается к полному ревью, и никакой байт дрейфа не попадает в опубликованную область в любом случае. См. docs/design/2026-08-15-review-aone-provider.md.
Каждый запуск завершается одной машиночитаемой строкой (Review complete: <target> — <disposition>), поэтому скрипты и CI-обёртки могут определить завершение и результат одним совпадением ^Review complete: .
Headless-запуски (qwen review run)
/review — интерактивный. Когда скрипту или CI-задаче нужно запустить ревью и действовать по его результату, используйте headless-обёртку:
qwen review run [target] [--json] [--fail-on request-changes] [--comment] [--resume] [--quiet]target — это номер PR, URL PR или путь к файлу; пропустите для ревью локального рабочего дерева. Команда запускает CLI этой сборки неинтерактивно (с закрытым stdin, чтобы обнаружение slash-команд работало), направляет прогресс дочернего процесса в stderr и выводит вердикт в stdout — или, с --json, полный объект результата. Вердикт читается из артефакта, который записывает compose-review (тот же JSON, который навык считает авторитетом вердикта), а не разбирается из прозы модели.
Код выхода — это контракт, который должен читать гейт:
| Выход | Значение |
|---|---|
0 | Ревью завершено (независимо от решения) |
1 | Вердикт не достигнут — дочерний процесс упал, истёк таймаут или не оставил составленного артефакта |
3 | Завершено с REQUEST_CHANGES и --fail-on request-changes был установлен (опциональное блокирование) |
3 (не 2) позволяет гейту различать «ревью блокирует» и «инструмент сломался» — yargs уже использует 1 для ошибок использования — без разбора вывода. --timeout-minutes (по умолчанию 120, минимум 1) завершает зависшее ревью и выходит с 1, а отмена команды (Ctrl+C / SIGTERM) завершает группу процессов ревью, а не оставляет их сиротами.
--resume продолжает прерванное ревью того же PR вместо начала заново — когда длительный локальный запуск погибает на полпути (обрыв соединения, таймаут, убитый терминал), повторная попытка иначе снова загрузит diff, снова разобьёт на чанки и снова запустит агентов, чья работа уже на диске. Флаг безопасно передавать безусловно при повторе: fetch-pr проверяет состояние на диске (worktree всё ещё на загруженном SHA и чист, байты diff неизменны, голова PR не сдвинулась, лимит возобновления не исчерпан) и молча откатывается к свежему ревью, если что-то не совпадает, поэтому флаг никогда не ломает запуск, который можно начать заново. Когда текущий вызов имеет только встроенное целевое значение по умолчанию, продолжение ��стаётся привязанным к записанному effort прерванного запуска. Явный --effort, запомненный уровень проекта, настройка оператора review.effort или эффективный --comment задают требуемый уровень; несовпадение отклоняет возобновление и запускает свежее ревью на этом уровне. Только для целей PR (diff локального ревью захватывается из живого рабочего дерева, которое не имеет стабильного прерванного состояния для продолжения). Возобновление — это локальное удобство: собственный CI workflow ревью репозитория не возобновляется — каждая повторная попытка запускается заново, потому что CI-попытка работает без песочницы и её worktree удаляется при выходе, не оставляя прерванного состояния для продолжения.
Запуск с ограничением по времени также может экспортировать мягкий дедлайн, чтобы ревью остановило свой цикл обратного аудита с неограниченным временем, пока ещё есть время на проверку, составление и публикацию: QWEN_REVIEW_DEADLINE_EPOCH — момент в Unix-секундах, когда запуск будет убит, а QWEN_REVIEW_DEADLINE_RESERVE_SECONDS (по умолчанию 3600; 0 сохраняет только оценку раунда) — хвост, который должен остаться для проверки последнего раунда, compose-review и отправки. Когда оставшийся бюджет не вмещает ещё один раунд плюс этот хвост, конструктор раундов отказывается его строить, и составленный вердикт раскрывает усечённый аудит (иначе-Approve вердикт ограничен до Comment). Отсутствующий или неправильный дедлайн оставляет ревью без ограничения — внешний таймаут всё ещё ограничивает запуск.
Внутри этого резерва вложен меньший compose floor, QWEN_REVIEW_DEADLINE_COMPOSE_FLOOR_SECONDS (по умолчанию 1200; 0 полностью отключает этот гейт, в любой момент, включая время после дедлайна). Резерв — это одно число, покрывающее «проверить последний раунд плюс составить плюс отправить», что подходит для обычной повторной трассировки по каждой находке, но не для ревью безопасности, чья проверка повторно запускает реальные нагрузки файловой системы/git без ограничений. Поэтому гейт по этому полу стоит на верификаторе, а не на конструкторе раундов: когда остаётся пол или меньше, agent-prompt --role verify отказывается строить (строка VERIFY BUDGET:, выход 4), найденные находки сохраняют метку непроверенных (что ограничивает вердикт), и запускаются compose-review и отправка. Пол строго ниже резерва, поэтому здоровый запуск сначала достигает гейта обратного аудита и никогда до него не доходит; это покрытие для того спана, который резерв не может ограничить.
Анализ влияния между файлами
Специализированный кросс-файловый трассировщик (Агент 1c) выполняет этот проход от начала до конца. Когда изменения кода затрагивают экспортируемые функции, классы или интерфейсы, он ищет всех вызывающих и проверяет совместимость:
- Изменения количества или типов параметров
- Изменения типа возвращаемого значения
- Удаленные или переименованные публичные методы
- Критические изменения API
Он также проходит направление производителя: каждое поле, опция или опциональный параметр, добавленный диффом, трассируется к его сайтам чтения — включая файлы, которые diff не затрагивает. Активный путь кода, читающий поле, которое ничего не заполняет, означает, что функция, которую оно управляет, молча ничего не делает, и это помечается как Critical в сайте чтения.
Для больших диффов (>10 изменённых символов) анализ в направлении вызывающих отдаёт приоритет функциям с изменёнными сигнатурами; направление производителя никогда не ограничивается бюджетом, потому что неизменённая сигнатура — это именно его точка.
Бюджет ревью
Эластичные по размеру диффа части пайплайна масштабируются от него, и масштабирование записывается в план диффа, чтобы каждый этап читал одно число, а не принимал решение самостоятельно:
| Поле бюджета | Что ограничивает | Как масштабируется |
|---|---|---|
inlineAngles | Сколько low-проходов запускается (Шаг 3C) | 3, плюс один на 60 строк исходного кода, максимум 6 существующих углов |
candidateFloor | Когда low должен выполнить один детерминированный повторный проход | min(changed files, 4) |
sweep | Запускается ли gap sweep для low | Выключен ниже 25 строк исходного кода |
specialistCap | Потолок Агента 8 | 0 ниже 80 строк исходного кода, иначе 2 |
verifyShard | Находок на агента проверки | Фиксировано 8 — свойство проверщика, а не диффа |
Две вещи, которые он намеренно не делает. Он никогда не убирает измерение целиком: каких агентов должно быть ревью, определяется ростером, который читает уровень детализации, поэтому маленький diff всё равно получает проход по безопасности и покрытию тестами. И он читает строки исходного кода, не строки диффа — 40 строк продакшн-изменений с 900 строками новых тестов — это маленькое изменение, и та же логика уже управляет гейтом territory-fan-out.
Почему полы именно такие: на исправлении опечатки в девять строк шесть inline-проходов — это пять проходов над ничем, а sweep — свежий читатель, ищущий то, до чего первый проход не добрался — нечего искать, когда первый проход добрался до всего. Когда проход с низким effort остаётся ниже candidateFloor, он делает один детерминированный повторный просмотр каждого покрываемого hunk’а в самом большом изменённом исходном файле (переключаясь на самый большой покрываемый файл любого типа) и каждого покрываемого удалённого блока. Файлы, затрагивающие непокрываемый кусок, исключаются из выбора цели, и проход всегда выдаёт квитанцию с именем цели, количеством новых кандидатов и любыми непокрываемыми кусками; когда ни один файл не покрывается, он всё равно проверяет покрываемые удалённые блоки и раскрывает отсутствующую цель. Пол — это сигнал остановки, а не квота: чистый diff всё равно может не найти находок после этого повторного прохода. Пол Агента 8 — содержательный: «один домен доминирует в диффе» — это суждение, и суждение, сделанное о сорока строках, каждый раз находит доминирующий домен, потому что сорок строк — это обычно одна вещь.
Эффективность использования токенов
Пайплайн high-effort ограничивает каждый этап (размер шарда, раунды аудита), но общие вызовы масштабируются с находками — ceil(F/8) шардов проверки — и, при 3B, с количеством чанков (обратный аудит работает по чанкам за раунд). Типичный профиль 3A:
| Этап | Вызовы LLM | Примечания |
|---|---|---|
| Агенты ревью (Шаг 3) | 17 (+0-2) | Работают параллельно; Агент 1e только когда дифф сигнализирует о wrapping-типе (16 без него); кросс-репо пропускает Агентов 1c и 7 (15, пока план несёт идентичность PR, 13 без неё — Агент 0 и 6d выпают вместе); локальные/файловые пропускают Агента 0 и аудит счётчиков 6d (15); ещё один (prose-exec) при диффе, затрагивающем файл инструкций, когда у ревью есть дерево |
| Шардированная проверка (Шаг 4) | ceil(F/8) | F = находки; не более 8 на агента проверки, запускаются вместе |
| Итеративный обратный аудит (Шаг 5) | 2-10 (3A); раунды × чанки (3B) | Два последовательных сухих раунда для остановки; лимит следует за топологией — 10 для небольшого диффа, 5 для чанкового, 3 для огромного, когда у запуска есть дедлайн. 3B делает fan-out по одному аудитору на чанк за раунд |
| Всего | ~20-31 (~16-29) | 3A в том же репо: ~20-31 (типично ~20-22); кросс-репо или локальные/файловые: ~16-29 (минимум — кросс-репо ростер без идентичности из 13); на один меньше, когда Агент 1e не включён в ростер, на один больше, когда положен prose-exec; 3B масштабируется с чанками (см. DESIGN.md) |
Большинство PR сходятся к нижней границе диапазона; лимиты предотвращают неконтролируемый рост затрат в патологических случаях. При --effort low ревью выполняется полностью inline — 0 вызовов субагентов — проходя diff по одному разу на угол вместо одного прохода в целом.
Что НЕ помечается
Ревью намеренно исключает:
- Уже существующие проблемы в неизмененном коде (фокус только на диффе)
- Стиль или форматирование, которые автоматически нормализуются форматтером, или именование, соответствующее соглашениям вашей кодовой базы — но НЕ существенные проблемы, которые отметил бы линтер или проверка типов (неиспользуемые переменные, недостижимый код, ошибки типов), так как они входят в область проверки
- Субъективные предложения “рассмотрите возможность сделать X” без указания на реальную проблему
- Незначительный рефакторинг, который не исправляет баг или не снижает риск
- Отсутствие документации, если только логика не является по-настоящему запутанной
- Проблемы, уже обсуждавшиеся в существующих комментариях к PR (чтобы не дублировать отзывы людей)
Философия дизайна
Тишина лучше шума. Каждый комментарий должен стоить времени читателя.
- Если нет уверенности, является ли что-то проблемой → не сообщайте об этом
- Каждая находка называет конкретный сценарий отказа (триггер → неправильный результат) или конкретные затраты — находка, которая не может этого, отбрасывается до того, как дойдёт до вас
- Одинаковый паттерн в N файлах → агрегируется в одну находку
- Комментарии к PR содержат только находки с высокой степенью уверенности (и только из ревью high-effort, проверенных)
- Косметические правки стиля/форматирования, соответствующие соглашениям кодовой базы, исключаются