resolve: ревью дизайна снято, разметка переехала за код

Сценарий решения идёт от предложения сразу к чекпоинту и коду: стадия ревью
дизайна упразднена целиком, review-scope запускается после apply и меряет
размер по диффу, сложность — сверкой обещанных границ с тронутыми. Чекпоинт
остался единственным плановым стопом и стоит теперь до кода. review-rubric
конвейером не зовётся, слот рубрики в скелете config.yaml снят. Журнал —
тема 74.
This commit is contained in:
av
2026-08-23 15:08:17 +03:00
parent 17be316634
commit 72d9aa8034
19 changed files with 356 additions and 417 deletions
+88 -187
View File
@@ -1,6 +1,6 @@
---
name: code-review
description: "Конвейер ревью изменения, устроенный по темам: документ проекта либо заводит тему ревью, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Ядро тем — requirements, autotests, conventions, architecture, security, operations; список тем открытый, свои темы проект заводит документом. Разметка задачи идёт один раз, после propose: агент review-scope выводит размер и сложность, из их максимума — метка, и раздаёт темы проходам обеих стадий. Метка правит и ревью дизайна (small — только specs; medium — плюс rubric; large — плюс architecture), и ревью кода (small — гейт, спеки, код, триаж; medium — плюс приёмник тем; large — плюс доказательство: враждебные постановки, эксплуатационный постмортем, архитектурный проход на широком входе). Триаж обязателен всегда. Порядок прогона — граф зависимостей: гейт открывает проходы с мнением, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Проектная специфика приходит из документов канона проекта. Вызывается из скилла av-dev:code-resolve — двумя стадиями: ревью дизайна до кода и ревью кода после apply. Третий вызов идёт от сценария обслуживания: без change и без метки, фиксированным планом (autotests, operations, плюс conventions, если тронут код), разметчик при этом не запускается."
description: "Конвейер ревью изменения, устроенный по темам: документ проекта либо заводит тему ревью, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Ядро тем — requirements, autotests, conventions, architecture, security, operations; список тем открытый, свои темы проект заводит документом. Разметка задачи идёт один раз, после apply: агент review-scope выводит размер по диффу и сложность по форме решения, из их максимума — метка, и раздаёт темы проходам. Метка правит состав ревью кода: small — гейт, спеки, код, триаж; medium — плюс приёмник тем; large — плюс доказательство: враждебные постановки, эксплуатационный постмортем, архитектурный проход на широком входе. Триаж обязателен всегда. Порядок прогона — граф зависимостей: гейт открывает проходы с мнением, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Проектная специфика приходит из документов канона проекта. Вызывается из скилла av-dev:code-resolve после apply. Второй вызов идёт от сценария обслуживания: без change и без метки, фиксированным планом (autotests, operations, плюс conventions, если тронут код), разметчик при этом не запускается."
---
# Конвейер ревью
@@ -245,6 +245,11 @@ description: "Конвейер ревью изменения, устроенны
| `sonnet` | green | scope, autotests, ops | вывод перечислим и сверяется механически |
| `opus` | yellow | specs, code, basics, adversary, rubric, architecture, triage | дорога ошибка — ложная либо пропущенная |
**`rubric` в составе прогона не стоит и в таблице держится за компанию.** Стадия,
где он жил, снята: рубрику на задуманный узел он порождает, не видя кода, а
конвейер работает по готовому диффу. Устав остаётся для прямого вызова человеком,
и модель у него та же — потому строка и не убрана.
**Цвет charter'а кодирует модель, а не роль прохода.** Это единственное
назначение цвета: список агентов читается взглядом, и по нему сразу видно, чем
платит прогон. Роль прохода из имени и так понятна, а цвет, розданный по ролям,
@@ -272,20 +277,20 @@ charter'а, а модель потом двигает калибровка, и
проде, и он тоже не оставляет следа ни в отчёте, ни в границах покрытия. По той
же причине, что `specs`, и это дороже всего в конвейере: проход идёт на каждой
задаче.
- `architecture` — запускается только со старшей меткой, на 5–10% задач, потолок
в 3 находки делает его дешёвым по выходу, а находка на предложении стоит абзаца
против переписывания на готовом коде. Дёшево × высокое плечо.
- `architecture` — запускается только со старшей меткой, на 5–10% задач, и
потолок в 3 находки делает его дешёвым по выходу. Его находка дороже прочих по
последствиям: второй способ делать то, что уже делается, переписыванием не
чинится, а живёт в кодовой базе годами. Дёшево × высокое плечо.
**`scope` внизу, и это не противоречие, хотя его ошибка расходится дальше всех —
теперь ещё дальше, чем прежде.** С переездом разметки к `propose` он правит
состав **обеих** стадий и не пересматривается после кода: ошибка метки стоит
всей задачи, а не одного прогона. Модель он всё же держит нижнюю, и вот почему.
Его работа распадается надвое: разнесение документов по категориям и раздача тем
**перечислимы** — план сверяется с `ls docs/` за секунду, пропущенный документ
виден без рассуждения. Выбор метки — суждение, но с переходом на две оси оно
стало **дважды перечислимым**: размер считается по перечню границ задачи и
дельта-спекам, сложность отвечается одним проверяемым признаком («можно ли до
работы назвать тронутые узлы»). Плюс три независимых корректора: отрицательный
**`scope` внизу, и это не противоречие, хотя его ошибка расходится дальше
всех.** Он правит состав всего прогона и внутри прогона не пересматривается:
ошибка метки стоит всей проверки задачи, а не одного прохода. Модель он всё же
держит нижнюю, и вот почему. Его работа распадается надвое: разнесение документов
по категориям и раздача тем **перечислимы** — план сверяется с `ls docs/` за
секунду, пропущенный документ виден без рассуждения. Выбор метки — суждение, но с
переходом на две оси оно стало **дважды перечислимым**: размер считается по
диффу, сложность отвечается одним проверяемым признаком («можно ли было до работы
назвать тронутые узлы»). Плюс три независимых корректора: отрицательный
тест `small`, правило «спорный случай вниз» и **сигнал о заниженной метке от
`code`** — тот идёт при любой метке и видит дифф целиком. Дешёвая модель
безопасна ровно потому, что её вывод устроен как список,
@@ -325,21 +330,20 @@ charter'а, а модель потом двигает калибровка, и
## Метки
**«Стадия» и «ступень» — разные членения, и путать их нельзя.** Стадий ревью
две — дизайна и кода, — и они видны снаружи: их зовёт `av-dev:code-resolve` в
разных точках цикла. Ступеней внутри прогона кода пять, они нумерованы и наружу
не выходят. Перечень осей процесса целиком — [shared/axes.md](../../shared/axes.md).
**Ступени нумерованы и наружу не выходят.** Прогон ревью один, и зовёт его
`av-dev:code-resolve` после того, как код написан; членение внутри прогона —
ступени, и знать их снаружи не нужно. Перечень осей процесса целиком —
[shared/axes.md](../../shared/axes.md).
**Классификация задачи выдаёт ровно одно значение — метку**: `small`, `medium`
или `large`. Это **единственный вход, по которому конвейер выбирает
исполнителей**: и на дизайне, и на коде состав читается из неё, а не из класса
задачи, не из её типа и не из ощущения важности. Метку ставит `review-scope` при
разметке задачи; все проходы получают её в задании и обязаны напечатать в своих
границах покрытия.
исполнителей**: состав читается из неё, а не из класса задачи, не из её типа и не
из ощущения важности. Метку ставит `review-scope` при разметке задачи; все
проходы получают её в задании и обязаны напечатать в своих границах покрытия.
**Метка одна на всю задачу и правит обе стадии ревью** и дизайна, и кода. У
изменения нет двух разных «глубин проверки»: величина, из которой выводится
состав, — одна и та же пара «размер × сложность», посчитанная один раз.
**Метка одна на всю задачу.** У изменения нет двух разных «глубин проверки»:
величина, из которой выводится состав, — пара «размер × сложность», посчитанная
один раз по готовому диффу.
**Метка не меняет список тем — она меняет их дом и глубину.** Все темы ядра
названы при любой метке; разница в том, против чего их смотрят (дом темы
@@ -367,18 +371,12 @@ charter'а, а модель потом двигает калибровка, и
```mermaid
flowchart TD
propose["opsx:propose — change, дельта-спеки, tasks.md"]
scope["review-scope — разметка задачи<br/>размер × сложность → МЕТКА"]
checkpoint(["чекпоинт: объяснение человеку"])
apply["opsx:apply — код, гейт зелёный"]
scope["review-scope — разметка по диффу<br/>размер × сложность → МЕТКА"]
label{{"метка"}}
subgraph design["Ревью дизайна — до кода"]
dS["specs — всегда"]
dR["+ rubric"]
dA["+ architecture<br/>+ вопрос автору о трёх формах"]
end
apply["opsx:apply — код, гейт зелёный"]
subgraph code["Ревью кода — после apply"]
subgraph code["Ревью кода"]
cGate["autotests — гейт, источник графа"]
cS["specs — requirements"]
cC["code — conventions + техника"]
@@ -389,19 +387,9 @@ flowchart TD
cT["triage — единственный сток"]
end
propose --> scope --> label
propose --> checkpoint --> apply --> scope --> label
label -->|small| dS
label -->|medium| dR
label -->|large| dA
dR -.-> dS
dA -.-> dR
dS --> apply
dR --> apply
dA --> apply
apply --> cGate
label -->|любая метка| cGate
cGate -->|зелёный| cS
cGate -->|зелёный| cC
label -->|small| cInv
@@ -418,27 +406,18 @@ flowchart TD
cHeavy --> cT
```
Пунктир между проходами дизайна значит «включает предыдущее»: `medium` это
`specs` **плюс** `rubric`, `large` — они же плюс `architecture`.
Отсюда состав прогона:
Отсюда состав обеих стадий:
| Метка | Когда | Ревью дизайна | Ревью кода: ступени | Проходов всего | Доля задач |
|---|---|---|---|---|---|
| `small` | малое **и** знакомое: багфикс, локальная правка, доки | `specs` | 1, 2, 5 (+3 при своих темах) | **56** | **до трети, и меньше, чем `medium`** |
| `medium` | **рабочее умолчание**: среднее и знакомое | `specs`, `rubric` | 1, 2, 3, 5 | **7** | **большинство** |
| `large` | крупное **или** незнакомое: большой рефакторинг, функциональность, форму которой ещё предстоит нащупать | `specs`, `rubric`, `architecture` | 1, 2, 4, 5 (+3 при своих темах) | **1011** | **510%** |
Ревью дизайна разбирается отдельно ниже — оно идёт до кода, у него свой плоский
граф и свой сток. Здесь оно стоит в таблице потому, что **метка у обеих стадий
общая**, и увидеть цену задачи можно только сложив их.
| Метка | Когда | Ступени | Проходов | Доля задач |
|---|---|---|---|---|
| `small` | малое **и** знакомое: багфикс, локальная правка, доки | 1, 2, 5 (+3 при своих темах) | **45** | **до трети, и меньше, чем `medium`** |
| `medium` | **рабочее умолчание**: среднее и знакомое | 1, 2, 3, 5 | **5** | **большинство** |
| `large` | крупное **или** незнакомое: большой рефакторинг, функциональность, форму которой ещё предстоит нащупать | 1, 2, 4, 5 (+3 при своих темах) | **78** | **510%** |
**Разметка в этих числах не считается — её платят один раз на задачу, а не один
раз на прогон.** Она ушла из состава ревью кода целиком: `review-scope` идёт
после `propose`, до ревью дизайна, и его план обслуживает **обе** стадии. Раньше
разметка стояла первой в каждом ревью кода, а перед ревью дизайна вызывающий
отвечал на тот же вопрос сам — то есть о размере изменения судили дважды и в
одном из двух мест без разведённости с автором.
раз на прогон.** Она ушла из состава прогона целиком: `review-scope` идёт после
`apply`, до первой ступени. Раньше разметка стояла первой в каждом ревью кода и
повторялась при каждом перезапуске прогона.
**Три глубины, и они не про старательность, а про способ доказательства.**
**Сверка** — открыть дом темы, открыть дифф, сравнить. **Разбор** — построить
@@ -463,8 +442,8 @@ flowchart TD
## Порядок прогона — граф, а не очередь
Метка отвечает «какие темы и на какой глубине», порядок — «что кого ждёт».
Стадии остаются единицей **состава**, но порядок задают **не их номера**: между
стадиями 2–4 настоящих зависимостей нет — ни один проход не читает вывод другого,
Ступени остаются единицей **состава**, но порядок задают **не их номера**: между
ступенями 2–4 настоящих зависимостей нет — ни один проход не читает вывод другого,
— и очередь между ними была бы платой ни за что.
Рёбер два вида, и они разной природы. Путать их нельзя: первое про
@@ -476,10 +455,10 @@ flowchart TD
| **зависимость** | B не стартует, пока A не закончил, потому что без A задание B не определено | гейт → все проходы с мнением; все проходы → триаж |
| **конфликт за ресурс** | A и B не держат машину одновременно; кто из них первый — неважно, направления у ребра нет | проходы, помеченные «держит машину» |
**План разметки — вход графа, а не его узел.** Он готов до того, как ревью кода
началось: разметка идёт один раз на задачу, после `propose`. Раньше она была
**План разметки — вход графа, а не его узел.** Он готов до того, как прогон
начался: разметка идёт один раз на задачу, сразу после `apply`. Раньше она была
первым узлом каждого прогона, и ребро «разметка → все» стояло здесь; теперь этого
ребра нет, потому что нет и узла.
ребра нет, потому что нет и узла — перезапуск прогона разметку не повторяет.
```mermaid
flowchart TD
@@ -604,46 +583,48 @@ flowchart TD
Режим объявляется в отчёте наравне с меткой: **`по графу`** — одним словом,
**`линейно`** — с причиной (какой именно из трёх).
## Разметка задачи — один раз, до обеих стадий ревью
## Разметка задачи — один раз, после кода
Агент `review-scope`. Идёт **после `propose`, до ревью дизайна**, и один: до его
плана неизвестно ни что проверять, ни на какой метке, ни сколько ревьюверов
звать на предложение.
Агент `review-scope`. Идёт **после `apply`, до первой ступени**, и один: до его
плана неизвестно ни что проверять, ни на какой метке, ни сколько проходов звать.
**Это не стадия прогона, и в счёт проходов метки она не входит.** Раньше
разметка была стадией 0 ревью кода и платилась на каждом прогоне, а перед ревью
дизайна тот же вопрос — «крупное или незнакомое?» — задавал сам вызывающий, то
есть оркестратор, который только что написал предложение. Одна и та же величина
считалась дважды, и один из двух раз — без разведённости с автором. Теперь она
считается один раз и обслуживает обе стадии.
**Это не ступень прогона, и в счёт проходов метки она не входит.** Она платится
один раз на задачу: перезапуск прогона по находке «переделать форму» её не
повторяет, потому что план описывает задачу, а не дифф.
**Что он читает.** `docs/` на уровне имён и заголовков, `CLAUDE.md` и
`AGENTS.md`, `openspec/specs/`, `docs/review.*` — раздел настройки. Плюс **корпус
оценки**: пять письменных источников о задаче, из которых выводятся обе оси.
оценки**, и у двух осей он разный.
| Источник | Размер | Сложность |
|---|---|---|
| **дифф** | **сколько мест тронуто на самом деле** | — |
| запись задачи, «Затрагивает» | перечень границ, названный до работы | узлы названы поимённо — знакомое |
| `proposal.md` | что делаем и зачем | вводит ли новое понятие |
| `design.md` | какие узлы в решении | **разбирались ли альтернативы** |
| `tasks.md` | число шагов и их разнородность | шаг «разобраться», «выяснить» |
| дельта-спеки | сколько capability и требований | `ADDED` целой capability против `MODIFIED` |
**Диффа он не читает: кода ещё нет** — и это причина, по которой корпус должен
быть широким. Одни дельта-спеки описывают заказанное поведение, но молчат об
объёме работы: шесть шагов в двух узлах видны в `tasks.md`, а факт, что форму
решения выбирали из нескольких, — только в `design.md`. Оценка по одному
источнику это оценка по остатку.
**Размер он меряет по диффу, и это главный источник.** Написанное о задаче до
работы описывает заказанное, а не сделанное: перечень границ мог оказаться
неполным, а `tasks.md` — обещать шесть шагов там, где хватило двух. Дифф этого не
обещает, он это показывает. Прочие источники размер **уточняют**: они называют
то, чего в диффе не видно, — например, что тронутые места лежат в разных слоях.
**Сложность дифф не отвечает вовсе.** Признак незнакомого — нельзя было назвать
тронутые узлы до работы, — проверяется сверкой перечня границ задачи с тем, что
реально тронуто: разошлись поимённо, значит формы решения не знали. Оттого запись
задачи и `design.md` остаются в корпусе и после кода.
**Расхождение источников по объёму разрешается в пользу большего** — не «спорное
вниз»: там ничья при равных данных, здесь один источник просто видел больше.
Само расхождение при этом идёт доводом за `незнакомое`: если о задаче написано
так, что источники не сходятся в объёме, формы решения не знают.
так, что источники не сходятся в объёме, формы решения не знали.
Возвращает **план задачи**: размер и сложность с обоснованием, метка как
максимум по ним, состав ревью дизайна, список тем с домами и глубинами для ревью
кода, разнесение документов по трём категориям и строку про найденные директивы.
План уезжает в отчёты обеих стадий целиком и служит границами покрытия.
максимум по ним, список тем с домами и глубинами, разнесение документов по трём
категориям и строку про найденные директивы. План уезжает в отчёт прогона целиком
и служит границами покрытия.
**Он не судит по существу** — ни одной находки об изменении. Его ошибка это
пропущенная тема или не та метка, и обе видны: разнесение документов сверяется
@@ -660,13 +641,11 @@ flowchart TD
повторяется; это самый дешёвый проход конвейера, и платить за его вечность
дороже, чем перезапустить.
**Метка, названная до кода, после кода не пересматривается.** Дифф может выйти
крупнее ожидания — метка от этого не двинется. Решение сознательное: пересмотр
означал бы либо второй запуск разметчика (ровно то, что здесь убрано), либо
машинный порог, который на всякой нетипичной задаче срабатывает не туда.
Расхождение факта с разметкой ловится **журналом дефектов** в `docs/review.md`,
постфактум, и это единственный сигнал — ровно как и для всякой другой ошибки
выбора метки.
**Внутри прогона метка не пересматривается.** Разметчик видел дифф целиком, и
второй запуск на том же дереве вернул бы то же самое; правки по находкам инлайна
дифф растят, а задачу — нет. Ошибка выбора ловится **журналом дефектов** в
`docs/review.md`, постфактум, и это единственный сигнал — ровно как и для всякой
другой ошибки метки.
## Прогон без change — сценарий обслуживания
@@ -683,7 +662,7 @@ change**: у работы, не меняющей поведения, дельт
**Прогон ревью идёт в одном из двух режимов, и режим — не глубина.**
- **С меткой** — обычный прогон по change: разметку сделал `review-scope`, состав
обеих стадий выведен из метки.
прогона выведен из метки.
- **Без метки** — прогон сценария обслуживания: change нет, размечать нечего,
план фиксирован и назван сценарием. Разметчик не запускается вовсе.
@@ -804,7 +783,7 @@ change**: у работы, не меняющей поведения, дельт
Два прохода, оба против **записанного** критерия. Машину не держат ни один, ребра
между ними нет — уходят одним сообщением сразу после зелёного гейта, вместе со
стадией 3 или 4 — той, которую назначила метка.
ступенью 3 или 4 — той, которую назначила метка.
- `review-specs` закрывает тему `requirements`. Критерий взят из **дельта-спек
предлагаемого изменения**, а не из proposal, сообщения коммита или описания
@@ -854,7 +833,7 @@ Recall темы `conventions` равен длине конвенций прое
## Ступень 3 — Темы (`medium` целиком; `small` и `large` — только свои темы проекта)
Агент `review-basics`. Один проход, машину не держит, ничего не запускает и не
меряет — уходит одним сообщением вместе со стадией 2, сразу после зелёного гейта.
меряет — уходит одним сообщением вместе со ступенью 2, сразу после зелёного гейта.
**Он не самостоятельная оптика, а держатель тем, у которых с этой меткой нет
своего проходчика.** На `medium` это `security`, `operations` и `architecture`:
@@ -891,7 +870,7 @@ Recall темы `conventions` равен длине конвенций прое
## Ступень 4 — Доказательство (только `large`)
Три прохода, и все три уходят сразу после зелёного гейта, в одном ряду со
стадией 2. Каждый берёт свою тему и доводит её до **доказательства**:
ступенью 2. Каждый берёт свою тему и доводит её до **доказательства**:
- `review-adversary`, тема `security` — находка есть **построенный путь**, а не
свойство: он пишет падающий тест и гоняет его;
@@ -909,7 +888,7 @@ Recall темы `conventions` равен длине конвенций прое
её только прямое слово оператора про эту пару, и тогда в границы покрытия идёт
строка, что числа прогона сняты под соседней нагрузкой.
**Эта стадия зарабатывает больше всех остальных вместе — и она же дороже всех
**Эта ступень зарабатывает больше всех остальных вместе — и она же дороже всех
остальных вместе.** Измерено на пяти задачах подряд: враждебный проход дал пять из
семи выживших находок дозапуска (включая обе верхние); эксплуатационный —
единственный, кто нашёл, что откат бинаря поверх новой схемы стартует молча. Оба
@@ -927,9 +906,9 @@ Recall темы `conventions` равен длине конвенций прое
(эксплуатация и хранилище) — эксплуатационному, `architecture` (устройство,
граница домена) — архитектурному. Что с чем сшивать и почему —
[project-facts.md](references/project-facts.md), раздел «Сшивать обязаны
проходы». Без домов стадия вырождается в общие места.
проходы». Без домов ступень вырождается в общие места.
**Числа и решения проекта эта стадия больше не читает.** `research.*` и `adr.*`
**Числа и решения проекта эта ступень больше не читает.** `research.*` и `adr.*`
процессные документы, и прогон их не открывает. Для эксплуатационного прохода это
значит, что **число он обязан снять сам** — замером, а не цитатой из чужой
записки; для архитектурного — что граница домена берётся из `passport.*`, а не из
@@ -987,85 +966,6 @@ change»: сверять исход с планом триаж обязан и
понижение неподтверждённого до гипотезы → отсев вкусовщины → ранжирование по
ущербу × вероятности → потолок 7 пунктов в основном списке.
## Ревью дизайна — до кода
Запускается на первой стадии ревью (шаг 4 скилла
`av-dev:code-resolve`), когда change уже имеет `proposal.md` и
дельта-спеки, но кода ещё нет. Разметка задачи к этому моменту уже прошла — она
шагом раньше, и метка известна.
**Состав растёт метками — теми же, что у ревью кода, и по той же паре осей.**
Их называет разметка задачи, а не вызывающий: величина считается один раз и
служит обеим стадиям.
| Метка | Проходы на предложении | Проходов |
|---|---|---|
| `small` — малое и знакомое | `specs` | **1** |
| `medium` — среднее и знакомое | `specs`, `rubric` | **2** |
| `large` — крупное или незнакомое | `specs`, `rubric`, `architecture` + вопрос автору | **3** |
- **всегда** — `review-specs` в режиме «дизайн ДО кода». Дельта-спеки сверяются
на каждой задаче: это самый дешёвый проход конвейера, и он ловит то, что на
готовом коде уже не чинят;
- **со `medium`** — `review-rubric`: рубрика на задуманный узел, по ней же
разбирается дельта-спека, а сами пункты уезжают приёмочными критериями в
`tasks.md`;
- **только в `large`** — `review-architecture` на предложении: можно ли выразить
существующими понятиями — **включая конструкции стандартной библиотеки**, — не
появляется ли второй способ. Вопрос «не изобретаем ли то, что уже есть в
библиотеке» живёт здесь; тогда же задаётся вопрос автору дизайна: **«предложи
три формы решения и назови компромисс каждой»** — если ответ показывает, что
рассматривалась одна, это находка.
**Рубрика съехала на метку вниз, а архитектура осталась наверху — и это не
симметричная правка.** Раньше оба прохода включались одним условием, и `medium`
получал на предложении ровно один проход, то есть не отличался от `small` вовсе.
Разводятся они потому, что зарабатывают на разном: рубрика порождает **свойства
узла** и окупается уже на среднем изменении — её выход уезжает приёмочными
критериями в `tasks.md` и работает потом на всей задаче; архитектура отвечает на
вопрос «не появился ли второй способ», а он на среднем знакомом изменении
отвечается «нет» ещё до запуска. Держать её ниже `large` значит платить за
предсказуемый ответ на каждой задаче.
Причина меток — арифметика, а не экономия на осторожности. Стадия стоит
**на каждой задаче**, поэтому каждый проход здесь умножается на число задач, и при
мелкой нарезке это самая большая статья конвейера.
**Граф этой стадии свой, и он плоский.** Гейта нет — кода ещё нет, запускать
нечего; метка уже названа разметкой задачи; машину не держит ни один проход;
сток — не триаж, а шаг скилла `av-dev:code-resolve`, где замечания
отрабатываются правкой спек. Триаж здесь не нужен: находок единицы, и каждая
либо правит спеку, либо
становится развилкой.
```mermaid
flowchart TD
plan[/"план разметки задачи:<br/>размер, сложность, метка"/]
proposal["предложение: proposal.md + дельта-спеки"]
specs["specs (режим «дизайн ДО кода») — всегда"]
rubric["rubric → приёмочные критерии в tasks.md"]
arch["architecture на предложении"]
author["вопрос автору: три формы решения и компромисс каждой"]
fix["шаг resolve: правка спек, развилки — вопросом в запись"]
plan --> proposal
proposal --> specs
proposal -->|"метка ≥ medium"| rubric
proposal -->|"метка = large"| arch
proposal -->|"метка = large"| author
specs --> fix
rubric --> fix
arch --> fix
author --> fix
```
Смысл стадии: архитектурная находка на готовом коде стоит переписывания и
поэтому игнорируется; та же находка на предложении стоит абзаца обсуждения.
`rubric` живёт **только** на этой стадии. Судить код по критерию, под который он
писался, — корреляция по построению; те же 8–12 свойств уже лежат приёмочными
критериями в `tasks.md`.
## Контракт находок
Единый для всех проходов — [references/finding-contract.md](references/finding-contract.md).
@@ -1185,10 +1085,11 @@ flowchart TD
он тратил больше всех остальных проходов вместе, — а не по замеру, который
[calibration.md](references/calibration.md) требует перед удалением. Значит и
записывается это как сознательное сужение, а не как «класс оказался пустым»:
остаток независимого взгляда даёт ревью дизайна (код пишется под его находки) и
`architecture` (второй способ, лишние слои), но **альтернативной реализации, с
которой можно сдиффить решения, у конвейера теперь нет**. Класс идёт строкой в
границы покрытия каждого прогона — там же, где проект перечисляет своё в
остаток независимого взгляда даёт `architecture` (второй способ, лишние слои), но
**альтернативной реализации, с которой можно сдиффить решения, у конвейера теперь
нет**. Сузилось это дважды: вместе с проходом независимой реализации ушла и
стадия ревью дизайна, ловившая форму решения до того, как код написан. Класс
идёт строкой в границы покрытия каждого прогона — там же, где проект перечисляет своё в
подразделе «перестали проверять сознательно».
Это и есть причина, по которой конвейер готовит ревью, а не заменяет его.
@@ -42,10 +42,12 @@
а именно эта пара и есть рабочее умолчание. Теперь обе оси называются в плане
поимённо, и обе — с обоснованием.
**Оси называются и на стадии дизайна, и на стадии кода — но считаются один
раз.** Это и есть причина, по которой разметка переехала к `propose`: состав
ревью дизайна выводится из той же пары, что и состав ревью кода, а считать её
дважды значит один раз посчитать без разведённости с автором.
**Обе оси считаются один раз — по готовому диффу.** Раньше разметка шла до кода,
и размер приходилось выводить из написанного о задаче: перечня границ, `tasks.md`,
дельта-спек. Теперь размер меряется по тому, что тронуто на самом деле, а
написанное о задаче остаётся источником **сложности**: признак незнакомого —
нельзя было назвать тронутые узлы заранее — проверяется сверкой обещанного с
сделанным.
**Обратимость — не третья ось, а отрицательный тест.** Она не уточняет размер и
не уточняет сложность: она запрещает нижнюю метку независимо от обеих.
@@ -105,9 +107,8 @@
пределы своего скилла он ходит вызовом, а не файлом.
Разметка в костяк не входит — она платится один раз на задачу, а не один раз на
прогон, и потому **разрез задачи её не удваивает**. Это единственное, что стало
дешевле от переезда разметки к `propose`, и это же снимает прежний довод против
нарезки.
прогон, и потому **перезапуск прогона её не удваивает**. Разрез задачи, впрочем,
удваивает: у каждой половины свой дифф, и мерить его приходится порознь.
**Размер, сложность, метка и глубина объявляются в отчёте, и все четыре с
обоснованием.** Метка выбирает `review-scope`; он вправе и поднять, и понизить