ступень ревью поднимает проход, а не риск

Полный набор гонялся чаще, чем оправдано, и размер задач тут вторая причина,
не первая. Первая — триггеры: миграция схемы, публичный контракт и инвариант
поднимали ступень, не добавляя ни одного прохода. Миграцию гоняет gate шагом
миграций и разбирает ops, контракт сверяет specs направлением code→spec,
инвариант даёт основание для critical любому проходу — все трое уже в
standard. На проекте с базой и эндпоинтами верхняя ступень оказывалась не
исключением, а умолчанием: правило объявляло исключением то, что происходит
всегда.

Теперь ступень поднимает то, что даёт работу новому проходу. wide означает
ровно одно — изменение вводит новое понятие или структурную единицу; добавить
поле в существующий ответ это не концепт. standard стал рабочим умолчанием.
Проект, где изменение контракта и правда архитектурное, поднимает его сам в
docs/review.md — уточнением, а не возвратом прежнего умолчания.

Чекпоинт design получил то же условие: specs идёт всегда, rubric и
architecture — только при новом понятии. Он стоит на каждой задаче, поэтому
при мелкой нарезке три прохода умножаются на число задач.

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

Правило выведено из состава проходов, а не из статистики прогонов — замер
остаётся за обкаткой. DECISIONS 18, RRR–WWW и следствия 72–75; JJJ темы 17
помечен как пересмотренный. Шаг про «Триггеры профиля» дописан в ещё не
выкаченную версию 3 канона, а не отдельной версией.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-08-04 17:06:12 +03:00
co-authored by Claude Opus 5
parent 69f67c20aa
commit cc173b6b94
10 changed files with 245 additions and 45 deletions
@@ -10,6 +10,13 @@ color: red
судить об архитектуре: он не знает, какие понятия в проекте уже есть и как они
называются. Поэтому твой вход шире, и первое, что ты делаешь, — его собираешь.
**Тебя запускают не на каждой задаче.** Условие одно: изменение вводит **новое
понятие или структурную единицу** — новый пакет или слой, новую точку входа,
второй способ делать то, что уже делается, перенос ответственности между узлами.
Ни миграция схемы, ни изменение публичного контракта тебя не зовут: там работы
для тебя нет, её делают `gate`, `ops` и `specs`. Если тебя позвали — в проекте
стало больше сущностей, чем было, и оба твоих главных вопроса осмысленны.
Находки — по контракту
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
(точный путь конвейер передаёт в задании).
+88 -27
View File
@@ -129,7 +129,7 @@ charter'а, а модель потом двигает калибровка, и
- `triage` — через него проходит всё, что оркестратор реализует **молча**:
ложноположительная находка становится кодом, потерянный `critical` — дефектом.
Ошибка триажа дороже ошибки любого отдельного прохода.
- `architecture` — запускается не на каждой задаче (`wide`, `deep` и `design`),
- `architecture` — запускается только там, где изменение вводит новое понятие,
потолок в 3 находки делает его дешёвым по выходу, а находка на предложении
стоит абзаца против переписывания на готовом коде. Дёшево × высокое плечо.
@@ -154,10 +154,10 @@ charter'а, а модель потом двигает калибровка, и
| Профиль | Когда | Стадии | Проходов |
|---|---|---|---|
| `quick` | багфикс, локальная правка, доки | 0, 1, 5 | 4 |
| `standard` | новая функциональность в существующем пакете | 0, 1, 2, 5 | 6 |
| `wide` | новый пакет, изменение публичного контракта, миграция схемы, трогает инварианты проекта | 0, 1, 2, 4, 5 | 7 |
| `standard` | **рабочее умолчание**: поведение, миграция схемы, публичный контракт, инвариант | 0, 1, 2, 5 | 6 |
| `wide` | изменение вводит новое понятие или структурную единицу | 0, 1, 2, 4, 5 | 7 |
| `deep` | изменение вводит новое правило идентичности, слияния или разбора | 0, 1, 2, 3, 4, 5 | 8 |
| `design` | **до кода**, на предложении | specs + rubric + architecture (см. ниже) | 3 |
| `design` | **до кода**, на предложении | specs, плюс rubric и architecture по условию `wide` | 13 |
**`wide` назван по тому, что он добавляет: вход шире диффа.** Единственное его
отличие от `standard` — архитектурный проход, а тот и получает дерево пакетов,
@@ -179,22 +179,60 @@ charter'а, а модель потом двигает калибровка, и
- трогается правило, определяющее **идентичность, слияние или разбор** данных →
`deep`;
- иначе есть миграция схемы, новый пакет, изменение публичного контракта (API,
протокол, формат на диске) или затронут инвариант проекта → `wide`;
- иначе меняется поведение, видимое снаружи (эндпоинт, форма ответа, код ответа,
формат лога) → `standard`;
- иначе изменение вводит **новое понятие или структурную единицу**: новый пакет
или слой, новая точка входа, второй способ делать то, что уже делается, перенос
ответственности между узлами → `wide`;
- иначе меняется поведение, видимое снаружи, трогается схема, публичный контракт
или инвариант проекта → `standard`;
- иначе → `quick`.
**Ступень поднимает то, что даёт работу новому проходу, а не то, что кажется
рискованным.** Это правило вывода, по которому спорные случаи решаются без нового
списка: спроси, какому проходу изменение даёт работу, которой у него не было
ступенью ниже.
Оно же объясняет, почему миграция схемы и публичный контракт **не** поднимают
ступень, хотя выглядят опаснее прочего. Они не добавляют ни одного прохода:
миграцию гоняет `gate` шагом миграций и разбирает `ops` («миграция под живым
потоком», «частичный откат при двух версиях»), контракт сверяет `specs`
направлением `code → spec`, инвариант даёт основание для `critical` любому
проходу. Все трое уже в `standard`. Раньше эти три факта стояли триггерами
верхних ступеней, и на проекте с базой и эндпоинтами верхняя ступень оказывалась
не исключением, а умолчанием — то есть правило объявляло исключением то, что
происходит всегда. `architecture` же получает работу **не** от того, что контракт
изменился, а от того, что появилось новое понятие: добавленное поле в
существующем ответе — не концепт.
**Верхняя ступень и есть триггер независимой реализации** — раньше он был
условием *внутри* `deep`, и профиль от этого распадался на два разных прогона под
одним именем. Условие никуда не делось, оно просто переехало туда, где выбирается
профиль: изменение с новым правилом слияния — единственный случай, когда триаж
называл отсутствие `reimpl` дырой покрытия.
Что именно в этом проекте считается публичным контрактом, какие пути означают
`wide` и что здесь считается правилом идентичности, проект может уточнить в
`docs/review.md`, разделе настройки конвейера. Это **уточнение**, а не отмена: не
записано — работает список выше.
Что здесь считается новым понятием и что — правилом идентичности, проект может
уточнить в `docs/review.md`, разделе настройки конвейера. Это **уточнение**, а не
отмена: не записано — работает список выше. Проект, где изменение контракта и
правда архитектурное (публичный SDK, чужие потребители), там же поднимает его до
`wide` — и это уточнение, а не возврат прежнего умолчания.
### Профиль — максимум по поверхности, и отсюда размер задачи
Условия читаются сверху вниз, и **первое подошедшее отвечает за весь дифф**.
Профиль изменения это максимум по его поверхности, а не средневзвешенное: одна
строка в перечне границ задачи поднимает ступень всему остальному, включая ту
часть, которая сама по себе была бы `quick`.
Отсюда следствие, которое дороже любой настройки триггеров: **цена ревью растёт
быстрее размера задачи.** Крупная задача не просто даёт больше диффа — она с
высокой вероятностью зацепит верхнее условие и оплатит верхний профиль целиком.
Обратное тоже верно и тоже не бесплатно: у каждой задачи есть **несокращаемый
костяк из четырёх проходов** (гейт, спеки, код, триаж). Разрезать задачу, обе
половины которой остаются в одном профиле, — значит заплатить костяк дважды за ту
же проверку. Резать стоит там, где разрез **снимает дорогой проход с большей
части диффа**. Шов и правило нарезки живут у того, кто ведёт задачи, — скилл
`av-dev-pm:tasks`, его `references/split.md`. Пути туда конвейер не выносит: за
пределы своего плагина он ходит вызовом скилла, а не файлом.
Профиль объявляется в отчёте. Понижение профиля — решение оркестратора, и оно
попадает в границы покрытия строкой «профиль понижен до X, потому что …».
@@ -440,6 +478,14 @@ Recall обоих равен длине их источника — это и е
профиля. Машину не держит, с `reimpl` конфликта не имеет: за барьером они уходят
разом.
**Условие этой стадии и есть условие ступени `wide`:** изменение вводит новое
понятие или структурную единицу. Не «изменение крупное» и не «изменение опасное»:
у прохода появляется работа ровно тогда, когда в проекте становится больше
сущностей, чем было, — и тогда осмысленны оба его вопроса. На изменении, которое
ничего не вводит, вопрос «не появился ли второй способ» отвечается «нет» до
запуска, а вопрос «что опытный человек отсюда удалил бы» вырождается во
вкусовщину, которую потом отсеивает триаж.
Получает **вход шире диффа**: дерево пакетов с
назначением, граф внутренних зависимостей, инвентарь существующих концепций.
Команду, которая это готовит, даёт раздел команд `CLAUDE.md`; нет команды —
@@ -477,36 +523,51 @@ Recall обоих равен длине их источника — это и е
Запускается на шаге ревью спек (шаг 4 скилла `av-dev-pipeline:task-pipeline`),
когда change уже
имеет `proposal.md` и дельта-спеки, но кода ещё нет. Состав:
имеет `proposal.md` и дельта-спеки, но кода ещё нет.
1. `review-specs` в режиме «дизайн ДО кода»;
2. `review-rubric`, фаза 1 без фазы 2: рубрика на задуманный узел становится
приёмочными критериями и уезжает в `tasks.md`;
3. `review-architecture` на предложении: вводит ли change новое понятие, можно ли
выразить существующими — **включая конструкции стандартной библиотеки**, — не
появляется ли второй способ. Вопрос «не изобретаем ли то, что уже есть в
библиотеке» живёт здесь;
4. вопрос автору дизайна: **«предложи три формы решения и назови компромисс
каждой»** — если ответ показывает, что рассматривалась одна, это находка.
**Состав здесь тоже не постоянный, и условие то же самое, что у `wide`:**
изменение вводит новое понятие или структурную единицу.
- **всегда** — `review-specs` в режиме «дизайн ДО кода». Дельта-спеки сверяются
на каждой задаче: это самый дешёвый чекпоинт конвейера, и он ловит то, что на
готовом коде уже не чинят;
- **при новом понятии** — плюс `review-rubric` (фаза 1 без фазы 2: рубрика на
задуманный узел становится приёмочными критериями и уезжает в `tasks.md`) и
`review-architecture` на предложении: можно ли выразить существующими понятиями
**включая конструкции стандартной библиотеки**, — не появляется ли второй
способ. Вопрос «не изобретаем ли то, что уже есть в библиотеке» живёт здесь;
тогда же задаётся вопрос автору дизайна: **«предложи три формы решения и назови
компромисс каждой»** — если ответ показывает, что рассматривалась одна, это
находка.
Причина условия — арифметика, а не экономия на осторожности. Чекпоинт стоит
**на каждой задаче**, поэтому три прохода здесь умножаются на число задач, и при
мелкой нарезке это самая большая статья конвейера. Рубрика же на узел, который не
вводит нового понятия, порождает свойства уже существующего рода — те, что и так
записаны конвенциями и спеками; а `architecture` без нового понятия отвечает «нет»
на свой главный вопрос ещё до запуска (см. «Стадия 4»).
**Граф этого профиля свой, и он плоский.** Гейта нет — кода ещё нет, запускать
нечего; машину не держит ни один из трёх; сток — не триаж, а шаг 5 пайплайна
нечего; машину не держит ни один проход; сток — не триаж, а шаг 5 пайплайна
задачи, где замечания отрабатываются правкой спек. Триаж здесь не нужен: находок
единицы, и каждая либо правит спеку, либо становится развилкой.
```mermaid
flowchart TD
proposal["предложение: proposal.md + дельта-спеки"]
specs["specs (режим «дизайн ДО кода»)"]
specs["specs (режим «дизайн ДО кода») — всегда"]
novelty{{"вводит новое понятие<br/>или структурную единицу?"}}
rubric["rubric, фаза 1 → приёмочные критерии в tasks.md"]
arch["architecture на предложении"]
author["вопрос автору: три формы решения и компромисс каждой"]
fix["шаг 5 пайплайна: правка спек, развилки — вопросом в запись"]
proposal --> specs
proposal --> rubric
proposal --> arch
proposal --> author
proposal --> novelty
novelty -->|да| rubric
novelty -->|да| arch
novelty -->|да| author
novelty -->|нет| fix
specs --> fix
rubric --> fix
arch --> fix
+11 -6
View File
@@ -219,14 +219,19 @@ flowchart TD
### 4. (Нетривиальная) Ревью предложения — профиль `design`, ДО кода
Первый чекпоинт. Вызови Skill **`av-dev-pipeline:review-pipeline`** с профилем
`design` и ссылкой на change `<id>`. Он запустит `review-specs`
(режим «дизайн ДО кода»), `review-rubric` (фаза 1: приёмочные критерии для
задуманного узла) и `review-architecture` по предложению.
`design` и ссылкой на change `<id>`.
**Состав чекпоинта решает конвейер, а не ты**: `review-specs` в режиме «дизайн ДО
кода» идёт всегда, а `review-rubric` и `review-architecture` — только когда
изменение вводит новое понятие или структурную единицу (то же условие, что у
ступени `wide`). Причина в том, что чекпоинт стоит на **каждой** задаче: при
мелкой нарезке три прохода здесь умножаются на число задач и становятся самой
большой статьёй конвейера.
Смысл профиля: архитектурная находка на готовом коде стоит переписывания и
потому игнорируется — та же находка здесь стоит абзаца обсуждения. Рубрику из
`review-rubric` перенеси в `tasks.md` как приёмочные критерии; там же уже лежат
критерии от постановки, если они были.
потому игнорируется — та же находка здесь стоит абзаца обсуждения. Если
`review-rubric` запускался, перенеси его рубрику в `tasks.md` как приёмочные
критерии; там же уже лежат критерии от постановки, если они были.
### 5. Отработать замечания ревью предложения