Files
dev-skills/av-dev-pipeline/skills/review-pipeline/references/finding-contract.md
T
avandClaude Opus 5 d5bee11a6b классификация задачи: три категории документов и метка вместо ступени
Канон 5 объявил «каждый документ docs/ — тема ревью». Правило верно ровно
наполовину и потому вредно целиком. Паспорт и схему хранилища ревью читает, но
темами они не являются: по ним нельзя сказать «в этом изменении сделано не так»,
они задают границу, по которой судит чужая тема. Журнал решений и журнал
наблюдений ревью изменения не нужны вовсе — ADR объясняет прошлое, а не
предъявляет требование. Разметчик, применявший правило буквально, обязан был
либо завести фантомные темы passport, adr, database, research и продублировать
ими работу architecture и operations, либо потерять четыре документа молча;
случались обе ветки, и в собственном образце плана docs/passport.md не попадал
ни строкой, а обязательная арифметика покрытия при этом не сходилась.

Категорий теперь три, разрез проверяемый. Тема — да, прямо: conventions,
security, architecture и любой свой документ проекта. Источник темы — нет, но он
задаёт границу для чужой: passport, database, CLAUDE.md, openspec/specs.
Процессный — нет, он про то, как мы работаем: tasks, review, adr, research,
.pm.json. Открыта одна категория из трёх, две другие перечислены поимённо, так
что документ вне раскладки — однозначно своя тема. adr и research прогон больше
не открывает ни одним проходом; docs/review остаётся читаемым, но как настройка
конвейера, а не критерий. Цена записана и стала обязательной строкой границ
покрытия: расхождение с записанным решением ловит теперь только сверка
документации, а число под находкой обязано быть снято на этом прогоне, с
приложенной командой.

Классификация выдаёт задаче метку — small, medium, large. Прежние quick,
standard и wide назывались ступенью и описывали ревью: как глубоко смотрим.
Классифицируется же задача, и пока величина называлась свойством прогона, её
естественно было пересчитывать на каждом прогоне — что конвейер и делал. Слово
«ступень» удалено, а не оставлено синонимом: два имени одной вещи расходятся.
Выводится метка из двух разведённых осей — размер (малое, среднее, крупное) и
сложность (знакомое, незнакомое), — и равна максимуму по ним. Метка не синоним
размера: малое незнакомое изменение получает large, трогая один узел, поэтому
план печатает три строки с обоснованием каждая и выводить одну из другой
запрещено. Оси остались русскими словами — это суждение прозой; метка
английская — это идентификатор, который проходы сравнивают.

Разметка переехала из ревью кода в шаг 4 пайплайна, сразу после propose. Она
шла первым проходом каждого ревью кода, а перед ревью дизайна ту же величину
называл сам пайплайн — то есть оркестратор, который только что довёл
предложение до propose. Одно и то же измерялось дважды, и один из двух раз без
разведённости с автором, ровно в той точке, ради которой разметчик заведён.
Теперь запуск один на задачу, диффа он не видит, план обслуживает обе стадии, и
метка после кода не пересматривается: расхождение факта с разметкой ловит журнал
дефектов постфактум, как и всякую другую ошибку выбора. На диск план не пишется —
четвёртый артефакт рядом с proposal, tasks и design пережил бы задачу и разошёлся
бы с ней молча.

Ревью дизайна тоже растёт меткой: small — specs, medium — плюс rubric, large —
плюс architecture и вопрос автору о трёх формах решения. Раньше rubric и
architecture включались одним условием, и medium получал ровно один проход, то
есть не отличался от quick ничем. Разведены они потому, что зарабатывают на
разном: рубрика порождает свойства узла и окупается уже на среднем изменении,
её выход уезжает приёмочными критериями в tasks.md; архитектура отвечает на
вопрос про второй способ, а он на среднем знакомом изменении отвечается «нет»
ещё до запуска.

small подешевел тремя способами сразу. Составом: приёмник тем не запускается,
три темы ядра переходят к code сверкой по записанным инвариантам CLAUDE.md с
потолком в одну находку, и это не «глубина ниже», а другой дом темы. Входом:
specs читает только дельта-спеку, code — только индекс конвенций. Потолком: он
появился у каждого опиниативного прохода, а не у одного basics, и у половин code
он раздельный, потому что конвенционных находок больше по построению и в общем
списке они вытеснили бы техническую половину. Сработавший потолок обязан быть
объявлен строкой — молчащий срез неотличим от «больше не нашлось». Отрицательный
тест small от этого стал жёстче, а не мягче: вопросы про обратимость миграции
задавал приёмник тем, и на этой метке их не задаст никто.

Пайплайн задачи вырос до двенадцати шагов. Тривиальность перестала решать состав
ревью — она влияет только на explore; глубину обеих стадий называет метка.

Проверено прогоном ревьюверов по готовому результату: девять расхождений найдено
и починено — контракт находок печатал старый перечень проходов вместо плана по
темам, три ссылки в task-batch указывали на шаг коммита вместо закрытия, запись
changelog не переводила вопросы, адресованные passport и database, ops и
adversary утверждали, что на нижних метках их вопросы задаёт basics, шаблон
покрытия в review-code зашивал потолки small намертво, триггеры метки рассыпались
на два списка против трёх, тема из директивы CLAUDE.md могла остаться без запуска
исполнителя. Гейт зелёный: фронтматтеры, копии, одиннадцать диаграмм, ruff,
pyrefly; docs.py прогнан на живом фикстуре и печатает категорию в отказе.

Канон повышен до версии 6 с записью, выполнимой upgrade. Решения — 40–44.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 10:57:15 +03:00

8.7 KiB
Raw Blame History

Контракт находок

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

Форма находки

### <краткая формулировка ПОСЛЕДСТВИЯ, не симптома>
- Файл: internal/<пакет>/<файл>.go:120-134
- Severity: critical | major | minor | nit
- Confidence: high | medium | low
- Оракул: <падающий тест / команда с выводом / положение руководства / нет>
- Последствие: <что произойдёт и при каких условиях>
- Предложение: <конкретное изменение>
- Найдено проходом: <имя агента; у проходов с раздельными потолками — имя и половина, например `code/техника`>

Правила

  • Заголовок через последствие. Не «нет проверки токена», а «читатель без токена выгрузит всю историю». Не «слияние перезаписывает запись», а «повторная доставка сотрёт поля у уже сохранённой записи, и восстановить их нечем». Симптом в заголовке — это заявка на то, что читатель сам достроит последствие; он не достроит, он просто починит симптом.
  • critical без оракула или построенного пути не существует. Оракул — это падающий тест, вывод выполненной команды или поимённое положение руководства. Не «вероятно, здесь гонка», а прогон детектора гонок с его выводом.
  • confidence: low — это «так обычно пишут». Такие находки допустимы, но не поднимаются выше minor. Частотность конструкции в публичном коде — не аргумент.
  • Находка без поля «Последствие» не выводится вовсе. Пустое «Последствие: ухудшает читаемость» равносильно отсутствию поля.
  • nit допустим только при нарушении записанной конвенции — со ссылкой на файл и раздел конвенций проекта (docs/conventions/) либо на правило линтера. Если правило механизируемо, но не механизировано — это не находка ревью, это Promote candidate (см. promote.md).
  • critical по основанию «нарушен инвариант проекта» требует инвариантов. Ссылка идёт на пункт раздела инвариантов CLAUDE.md дословно. Без них основание недоступно — см. project-facts.md, поразрядная деградация.
  • Расхождение — не дефект, пока не названо последствие. Особенно для архитектурного прохода: «я бы сделал иначе» без последствия не выводится.

Шкала severity

Severity Что это Пример
critical нарушение инварианта проекта, потеря или порча данных, утечка секрета, построенный путь к отказу запись потеряна при слиянии; тело пользовательской выгрузки в поле лога
major сломанное требование дельта-спеки, необрабатываемый отказ штатного сценария, флаки-тест, поведение вне спеки, меняющее исход приём отвечает 200, не записав тело: доставка считается принятой, а данных нет
minor отступление от конвенции с реальной ценой, отсутствующая наблюдаемость, дублирование, которое разойдётся ни одного чекпоинта на пути разбора: молчащая автоматизация неотличима от пустого потока
nit нарушение записанной конвенции без последствий за пределами чтения msg с интерполяцией вместо константы

Шкала привязана к обратимости, а не к громкости: класс «необратимо и молча» всегда весит больше класса «шумно и лечится повтором». Что здесь необратимо, говорит CLAUDE.md — что в этом проекте необратимо.

Блок границ покрытия

Каждый проход завершает вывод этим блоком. Он не сокращается и не заменяется фразой «всё проверено».

## Coverage of this pass
- проверено: <что реально прочитано/запущено, с путями и командами>
- не проверялось и почему: <бюджет, недоступный инструмент, вне входа>
- принципиально недоступно этому проходу: <из charter'а агента>

Финальный отчёт триажа

Секции строго в этом порядке, потолок — 7 пунктов в первых двух:

  1. Блокирует мердж (≤3, каждая с оракулом);
  2. Стоит исправить сейчас (≤4);
  3. Гипотезы без доказательства — что понижено и почему;
  4. Promote candidates — кандидаты в конвенцию или правило линтера;
  5. Границы покрытия — сводная, обязательная.

Перед секциями — сводка для человека: размер, сложность, метка и режим прогона, состояние гейта, план разметки задачи с исходом по каждой теме, сколько находок пришло на вход и сколько осталось.

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

Каждая находка в секциях 1–2 несёт дополнительное поле:

- Действие: инлайн | развилка

инлайн — оркестратор чинит сам, не спрашивая и не логируя. развилка — цена исправления сопоставима с переработкой, либо выбор меняет scope, либо решение трогает инвариант: уезжает вопросом с вариантами и ценой каждого туда, где проект держит вопросы, а работа продолжается на остатке.

Потребитель отчёта — оркестратор, который реализует прочитанное. Поэтому потолок в 7 пунктов — не забота о внимании читателя, а защита кодовой базы от правок, которых никто не заказывал.