ревью: цикл задачи проверяет механику, метки сняты

Состав прогона постоянный: гейт, спеки, код, триаж; приёмник тем идёт,
когда у проекта есть свои темы. Метка, разметка и проход review-scope
упразднены, review-levels.md удалён, ось «метка» снята из axes.md.

Ступень 4 ушла из цикла: review-proof упразднён через день после
заведения, review-architecture переехал в code-deep-review вслед за
adversary и ops. Темы security, operations и architecture закрывает
review-code сверкой с записанными инвариантами, потолком 1 находка.

Умолчание разметки действий перевёрнуто на инлайн; развилка осталась
за необратимым, изменением дельта-спек и нарушенным инвариантом.
Задачи из урожая заводятся по слову человека, а не шагом сценария.

Чекпоинт назван единственным местом, где решается форма решения.
Потеряны ось времени в цикле и суждение о форме после кода — обе
потери названы в «Честном пределе» строкой границ покрытия.

Журнал — тема 77.
This commit is contained in:
av
2026-08-23 17:26:07 +03:00
parent daf9f8b824
commit 3c89d7111d
30 changed files with 1055 additions and 1781 deletions
+97 -116
View File
@@ -11,13 +11,12 @@
пересказывается.
**OpenSpec — жёсткая предпосылка именно этого сценария** (SKILL.md,
«Предпосылки»): на нём стоят шаги 2, 4 и 7 и проход `review-specs`.
«Предпосылки»): на нём стоят шаги 2, 4 и 6 и проход `review-specs`.
Тонкая обёртка над каноническими скиллами `opsx:propose` / `opsx:apply` /
`opsx:archive` — их шаги не переизобретаются, а **зовёт их агент**, не ты
(SKILL.md, «Кто пишет: письмо уходит агентам»). Ревью — скилл
`av-dev:code-review`; он же держит правило выбора метки, а называет её агент
`review-scope` — один раз на задачу, **после того как код написан**.
`av-dev:code-review`; состав его прогона постоянный, выбирать и размечать нечего.
## Ход работы
@@ -28,17 +27,15 @@ flowchart TD
s2["2. opsx:propose — change, дельта-спеки,<br/>tasks.md — агентом"]
s3(["3. ЧЕКПОИНТ: объяснение<br/>в чём проблема, как решаем,<br/>чем рискуем"])
s4["4. opsx:apply — код, гейт,<br/>поведенческая верификация — агентом"]
s5["5. разметка — review-scope по диффу:<br/>размер, сложность, метка, план тем"]
s6["6. ревью кода по метке<br/>+ отработка замечаний агентом"]
s7["7. opsx:archive + синк документации —<br/>одним агентом"]
s8["8. коммит работы — av-dev-git:commit"]
s9["9. закрыть задачу — av-dev:task-track,<br/>вторым коммитом учёта"]
s5["5. ревью кода — постоянный состав<br/>+ отработка замечаний агентом"]
s6["6. opsx:archive + синк документации —<br/>одним агентом"]
s7["7. коммит работы — av-dev-git:commit"]
s8["8. закрыть задачу — av-dev:task-track,<br/>вторым коммитом учёта"]
in --> s1
s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9
s5 -.->|"план задачи: темы и глубины"| s6
s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8
s3 -.->|"скорректировать:<br/>правка спек и дизайна"| s3
s6 -.->|"находка отменяет дизайн:<br/>меняются дельта-спеки"| s3
s5 -.->|"находка отменяет дизайн:<br/>меняются дельта-спеки"| s3
```
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при
@@ -63,8 +60,8 @@ flowchart TD
Задача сделана, когда верно всё:
1. гейт проекта зелёный;
2. ревью проведено, **план прогона сверен с исходом по каждой теме**, темы без
отчёта и без дома названы в границах покрытия;
2. ревью проведено, **перечень тем сверен с исходом по каждой**, темы без отчёта
и без дома названы в границах покрытия;
3. решение прошло чекпоинт и не разошлось с одобренным — либо разошлось, и
чекпоинт был пройден заново;
4. change заархивирован, дельты влиты в актуальные спеки;
@@ -141,6 +138,13 @@ flowchart TD
нечем: человек читает предложение как оно есть. Взамен стоп пришёл **раньше**
коррекция здесь стоит правки спеки, а не переписывания готового кода.
**Это единственное место процесса, где решается форма решения, и решает её
человек.** Ревью после кода судит корректность и механику против записанного
критерия; «то ли это решение» там не спрашивает ни один проход, а глубокое ревью
области придёт позже и не всегда. Значит, чекпоинт — не формальность и не
доклад о ходе работ: одобренное здесь уезжает в код без второго суждения о
замысле.
**Объяснение не сочиняется заново — оно собирается из артефактов**, `proposal.md`
и `design.md`. Третий пересказ был бы третьим домом одного и того же и разошёлся
бы с обоими. Что показываешь:
@@ -180,8 +184,7 @@ flowchart TD
(SKILL.md, «Кто пишет»): сказанное человеком уходит ему дословно, вместе с
идентификатором change и требованием перепрогнать
`openspec validate --strict <id>`. Затем чекпоинт **заново** — правленое
объяснение читает тот же человек. Разметки на этот момент ещё нет, и повторять
здесь нечего: она идёт после кода;
объяснение читает тот же человек;
- **не одобрено** — исход «не доведена» с причиной. Change остаётся
незаархивированным, задача не закрывается, ничего не коммитится наполовину.
@@ -192,7 +195,7 @@ flowchart TD
поведенческая верификация. Возврат — адреса тронутого, исход гейта и строка
верификации; диффа в нём нет. **Исход гейта возвращается сводкой, путём к логам
шагов и отпечатком дерева** (SKILL.md, «Возврат — не длиннее экрана»): его
передача на шаг 6 избавляет ревью от второго прогона того же гейта.
передача на шаг 5 избавляет ревью от второго прогона того же гейта.
Код — по конвенциям проекта
(каталог `docs/conventions/`). Меняешь схему — обнови её описание в документации
@@ -208,87 +211,47 @@ flowchart TD
**Сервис не оставляем лежать.** Если запуск упал — агент чинит или откатывает до
конца шага; возврат с лежащим сервисом — незакрытый шаг, а не исход.
### 5. Разметка задачи — агент `review-scope`
### 5. Ревью кода — состав постоянный
**Один запуск на всю задачу, и он идёт после кода.** Запусти агента
`review-scope`, дав ему корень проекта, идентификатор change, базу диффа и запись
задачи. Код уже написан, и **дифф — его источник размера**: он видит, сколько
мест тронуто на самом деле, а не сколько обещала постановка.
Вызови Skill **`av-dev:code-review`**, дав ссылку на change `<id>`, базу диффа,
режим запуска и **исход гейта с шага 4** — сводку, путь к логам шагов и отпечаток
дерева.
Он возвращает **план задачи**:
- **размер** (малое / среднее / крупное) и **сложность** (знакомое /
незнакомое), каждое с обоснованием по факту;
- **метку** как максимум по двум осям: `small`, `medium` или `large`;
- **таблицу тем** «тема → дом → глубина → кто закрывает» — для шага 6;
- разнесение документов проекта по трём категориям и строку про директивы.
**Метку выбираешь не ты, и это правило держится разведённостью.** Код только что
написан по твоему заданию, и решать, насколько глубоко его проверять, тебе нельзя:
под давлением «я почти закончил» решение известно заранее. Разметчик работу не
писал, а обе оси выводит из фактов — из диффа и из постановки, — и обязан назвать
признак по каждой.
**План держи в контексте до конца задачи.** На диск он не пишется: файл-план стал
бы четвёртым артефактом рядом с `proposal.md`, `tasks.md` и `design.md`, пережил
бы задачу и разошёлся бы с ней молча. Прервался прогон — повтори шаг 5, это самый
дешёвый его проход.
**Разметка повторяется ровно в одном случае** — если правки изменили сами
**дельта-спеки**: план выведен из задачи, и план по отменённым требованиям назовёт
не те темы. Во всех прочих случаях, включая отработку находок инлайна на шаге 6,
метка остаётся прежней: дифф от правок по находкам растёт, а задача — нет.
### 6. Ревью кода — по метке разметки
Вызови Skill **`av-dev:code-review`**, дав ссылку на change `<id>`,
базу диффа, **план разметки с шага 5**, режим запуска и **исход гейта с шага 4**
сводку, путь к логам шагов и отпечаток дерева.
**Метку ты не выбираешь, и это правило, а не упрощение.** Её назвал
`review-scope` шагом раньше — по размеру и сложности, с обоснованием по каждой
оси; причина в разведённости, и она разобрана там же. Правило выбора живёт в
скилле конвейера — `av-dev:code-review`, `references/review-levels.md`; проектные
триггеры — в `docs/review.*`, подраздел «Триггеры метки».
**Метка, названная по диффу, внутри прогона больше не пересматривается.**
Разметчик видел дифф целиком и посчитал по нему обе оси; второй запуск на том же
дереве вернул бы то же самое.
**Считаешь метку заниженной — скажи это в докладе строкой, а не переспорь.**
Разметчик вправе и поднять, и понизить; твоё несогласие это факт для человека, а
не команда конвейеру. Место, где такое несогласие превращается в изменение
правил, — журнал дефектов `docs/review.md`, и только постфактум.
**Плана нет — ревью кода не запускается.** Триаж требует план обязательным
входом: без него он не может сверить, все ли размеченные темы вернули отчёт, а
эта сверка — единственная защита от молчащего пропуска. Потерял план (прервалась
сессия, ушёл контекст) — повтори шаг 5, а не гони прогон без него.
**Выбирать и размечать нечего.** Состав прогона один и тот же на всякой задаче:
гейт, сверка со спекой, разбор кода, триаж; приёмник тем идёт, когда у проекта
есть свои темы. Прежде между кодом и ревью стоял отдельный проход разметки — он
считал размер по диффу, сложность по постановке и выдавал метку, из которой
выводился состав. Метка снята вместе с ним: цикл задачи проверяет корректность и
механику, а этой работе нечего добавить и нечего убавить от размера изменения.
**Режим по умолчанию — `по графу`, и обосновывать его не надо.** Конвейер сам
знает свои рёбра: гейт открывает проходы с мнением, проходы с пометкой «держит
машину» идут цепочкой (иначе замеры портят друг друга и находка выглядит
доказанной), триаж — сток. Просить **`линейно`** нужно только по причине, и она
называется строкой: так сказал оператор; машина занята чем-то ещё; идёт разбор
самого конвейера.
знает свои рёбра: гейт открывает проходы с мнением, триаж — сток. Просить
**`линейно`** нужно только по причине, и она называется строкой: так сказал
оператор; машина занята чем-то ещё; идёт разбор самого конвейера.
Скилл сам гоняет гейт, нужные проходы и обязательный триаж. Возвращает отчёт с
потолком 7 пунктов, разметкой `Действие: инлайн | развилка` и секцией границ
покрытия.
потолком 7 пунктов, разметкой `Действие: инлайн | развилка`, секцией `Урожай`,
секцией отложенного в глубокое ревью и границами покрытия.
**Сверь план прогона с исходом, прежде чем коммитить.** Отчёт начинается планом
разметчика — таблицей «тема → дом → глубина → кто закрывает», — и против каждой
темы обязан стоять исход. Тема без отчёта и тема без дома — разные вещи, и обе
должны быть названы. Реестр короткий — темы ядра плюс свои проекта, — и сверка стоит
одного взгляда.
**Сверь перечень тем с исходом, прежде чем коммитить.** Отчёт начинается таблицей
«тема → кто закрывает → против чего», и против каждой темы обязан стоять исход.
Тема без отчёта и тема без дома — разные вещи, и обе должны быть названы.
Реестр постоянный и короткий, сверка стоит одного взгляда.
#### Отработка, и здесь появляется одно новое правило
#### Отработка — чинится молча, спрашивается редко
Помеченное `инлайн` чинит **агент** (SKILL.md, «Кто пишет»): находки уходят ему
**дословно, вместе с оракулом**, одним заданием на весь урожай инлайна, и гейт
после правок гоняет он же. Логировать их по-прежнему не надо. `развилка`
вопросом в запись (он уже сформулирован триажем, его остаётся перенести), и
агенту она не отдаётся.
после правок гоняет он же. Логировать их не надо. **Это умолчание, и оно
широкое** — прогон, вернувший человеку список замечаний вместо готового
результата, свою работу не сделал.
`развилка` — вопросом в запись (он уже сформулирован триажем, его остаётся
перенести), и агенту она не отдаётся. Оснований у неё три, и все узкие: правка
меняет **дельта-спеки**, находка сидит в **необратимом** месте (миграция, формат
на диске, публичный контракт), находка трогает **инвариант** `CLAUDE.md`.
Развилок больше двух на задачу — это факт для доклада: либо задача не та, либо
разметка действий съехала.
**Находка, отменяющая одобренный дизайн, отменяет и одобрение.** Признак
проверяемый: **меняются ли дельта-спеки**.
@@ -296,8 +259,8 @@ flowchart TD
- не меняются — находка внутри дизайна, дожимай сам, это обычная отработка;
- меняются — решение стало другим, а одобрено было прежнее. **Вернись на чекпоинт
шага 3** с тем, что изменилось и почему; дальше задача идёт своим ходом заново —
код, разметка, ревью. Такая находка агенту не отдаётся ни при каких условиях:
она отменяет одобрение, а это разговор с человеком.
код, ревью. Такая находка агенту не отдаётся ни при каких условиях: она отменяет
одобрение, а это разговор с человеком.
**Это правило старше правила о развилке.** Находка класса `развилка`, чьё
основание — «надо менять спеку», подпадает под оба; побеждает возврат на
@@ -308,31 +271,44 @@ flowchart TD
ревью, не значит ничего, а человек при этом уверен, что одобрил именно то, что
уехало в коммит.
**Урожай — списком, не задачами.** Отложенные находки (реальный `major` не для
этого мерджа, развилка, решённая «потом», пачка `nit`) собери в секцию доклада
`Урожай`: формулировка, оракул, откуда взялась. Задачи из него **заводит не этот
скилл** — их заводит `av-dev:task-track` своим сценарием «задачи из ревью и
аудита»: своя нарезка, свой формат, свои правила дублей. Твоя обязанность — не
потерять и передать.
#### Урожай — список в докладе, задачи только по слову человека
Отложенные находки (реальный `major` не для этого мерджа, развилка, решённая
«потом», пачка `nit`) собери в секцию доклада `Урожай`: формулировка, оракул,
откуда взялась.
**Задачи из урожая заводятся только тогда, когда человек сказал «заводим».**
Покажи список одной репликой и спроси. Сказал — зови `av-dev:task-track`, у него
на этот вход отдельный сценарий «задачи из ревью и аудита»: своя нарезка, свой
формат, свои правила дублей, и передавать находку туда надо дословно. Не сказал —
урожай остаётся строками доклада, и это исход, а не потеря.
**Молча беклог не наполняется.** Очередь работ ведёт человек, и задача, заведённая
за него по ходу чужого прогона, отнимает у него ровно то решение, ради которого
очередь и существует. Прежде вызов `av-dev:task-track` был обязательным шагом —
теперь он шаг по ответу.
**Границы покрытия из отчёта не выбрасывай** — они уезжают в финальный доклад
сжатой строкой. Отчёт, из которого исчезло «что проверить было невозможно»,
превращается в ложное ощущение проверенности.
**Строку «отложено в `av-dev:code-deep-review`» перенеси дословно.** Проход
`review-proof` называет в ней тему, место и запуск, которым это проверяется, —
всё, что доказывается только прогоном и замером, цикл задачи не доказывает ни на
одной метке. Эти строки копятся и однажды становятся поводом позвать глубокое
ревью области; пересказанные своими словами, они теряют оракул и перестают быть
поводом.
**Строки «отложено в `av-dev:code-deep-review`» перенеси дословно.** Их пишут
проходы, упёршиеся в предел цикла: нужен замер, нужен прогнанный путь, нужен вход
шире диффа. В цикле задачи это не доказывается ничем, а строки копятся и однажды
становятся поводом позвать глубокое ревью области; пересказанные своими словами,
они теряют оракул и перестают быть поводом.
**Отчёт триажа сохрани вместе с change (`openspec/changes/<id>/review/`; шаг 7
**Сигнал «это изменение просит глубокого ревью»** приходит от `review-code` и
подтверждается `review-basics`. Он не команда и не стоп — строка доклада: когда
звать глубокий прогон, решает человек.
**Отчёт триажа сохрани вместе с change (`openspec/changes/<id>/review/`; шаг 6
унесёт его в архив вместе с change) — это обязательно, а не «если удобно».** По
нему потом видно, что было найдено и что из этого осталось в урожае. И это
единственный **независимый** артефакт о составе прогона: своей прозе здесь верить
нельзя — она написана тем же, кто мог проход и пропустить.
нельзя — её написал тот, кто мог проход и пропустить.
### 7. Архивация и синк документации — одним агентом
### 6. Архивация и синк документации — одним агентом
**Оба шага уходят одному агенту, и это один запуск** (SKILL.md, «Кто пишет»).
Работа здесь письменная от начала до конца: `opsx:archive` вливает дельты в
@@ -373,7 +349,7 @@ flowchart TD
задачу нельзя: документ, заведённый мимо канона, окажется вторым домом ровно
тому, что канон потом заведёт своим.
### 8. Коммит
### 7. Коммит
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
создавай и не переключай, ничего не пушь.
@@ -383,14 +359,14 @@ flowchart TD
напиши сообщение сам и скажи строкой доклада, что форму коммита не сверял никто.
Одна задача — один осмысленный коммит.
### 9. Закрыть задачу — **после коммита, не раньше**
### 8. Закрыть задачу — **после коммита, не раньше**
**Вызови Skill `av-dev:task-track`** и попроси закрыть задачу как реализованную —
он владеет форматом и двигает строку индекса сам. Путь к его скрипту не выясняй и
индексы руками не правь: мост между плагинами — вызов скилла, а не путь.
**Порядок обязателен.** Закрытие удаляет файл задачи; сделанное до коммита оно
оставило бы задачу закрытой без единого следа работы, если шаг 8 упадёт.
оставило бы задачу закрытой без единого следа работы, если шаг 7 упадёт.
**Закрытие тоже коммитится — вторым коммитом, тут же.** Удаление файла задачи и
правка индексов (их имена знает `av-dev:task-track`, не ты) — это правки в рабочем
@@ -418,8 +394,12 @@ change. Заводить запись задним числом, чтобы её
- ссылка на архивный change и хеш коммита;
- по каждому критерию приёмки, если они были: **оракул и наблюдаемый исход**
это доклад приёмщику, а не отметка «принято»;
- **`Урожай`** — отложенные находки списком (формулировка, оракул, откуда взялась);
- **одна строка границ покрытия**: какая метка и режим гонялись, какие проходы не
- **`Урожай`** — отложенные находки списком (формулировка, оракул, откуда
взялась) и **что человек по нему решил**: заведены задачи или список остался в
докладе;
- **сколько находок ушло инлайном и сколько развилкой** — числом. По нему видно,
во что прогон обошёлся человеку;
- **одна строка границ покрытия**: какой режим гонялся, какие проходы не
запускались и что проверить было невозможно;
- **отложенное в `av-dev:code-deep-review`** — дословно из отчёта, либо «нечего». Доклад без неё сообщает
«проверено», не сообщая, что именно.
@@ -430,14 +410,15 @@ change. Заводить запись задним числом, чтобы её
перезапускать, а не «посмотреть заодно».
- Стиль правок — заточка под проект и конвенции, по размеру задачи, без
улучшений заодно.
- **Занизить метку ревью, пропустить тему или проскочить чекпоинт — самый дешёвый
способ «ускориться», и он же самый дорогой по последствиям.** Защита устроена
так, что регулятора у тебя нет: метку выбирает **не ты, а разметчик, и выводит
её из диффа**, план сверяется по темам, непокрытое называется строкой, а
расхождение с одобренным — отдельным пунктом доклада.
- **Заведение задач из урожая ревью — не твоя работа.** Отложенные находки
отдаются **списком**; превращает их в задачи `av-dev:task-track`, у него на
этот вход отдельный сценарий «задачи из ревью и аудита». Каталога задач в
- **Пропустить тему или проскочить чекпоинт — самый дешёвый способ «ускориться»,
и он же самый дорогой по последствиям.** Защита устроена так, что регулятора у
тебя нет: состав прогона постоянный и сокращению не подлежит, перечень тем
сверяется по исходу, непокрытое называется строкой, а расхождение с одобренным
— отдельным пунктом доклада.
- **Заведение задач из урожая ревью — не твоя работа и не работа этого прогона по
умолчанию.** Отложенные находки отдаются **списком**, и в задачи их превращает
`av-dev:task-track` — по слову человека, у него на этот вход отдельный сценарий
«задачи из ревью и аудита». Каталога задач в
проекте нет — урожай остаётся списком в докладе, и это говорится строкой.
- **Способ решения ты не выбираешь.** Он приходит известным: из постановки, из
разведки, от человека. Выбор между двумя подходами с разной ценой делается в