классификация задачи: три категории документов и метка вместо ступени

Канон 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>
This commit is contained in:
av
2026-08-07 10:57:15 +03:00
co-authored by Claude Opus 5
parent 61cd9fcd37
commit d5bee11a6b
31 changed files with 1809 additions and 689 deletions
+46 -21
View File
@@ -51,7 +51,7 @@ description: Проводит несколько задач разом — пл
- **Батч не владеет спринтом и целями.** Он сообщает исход по каждой задаче в тех
же трёх словах, что и `task-pipeline`: сделана / не доведена / оказалась крупнее
задачи.
- **Задачи закрывает пайплайн внутри каждого сабагента**, шагом 11 — после
- **Задачи закрывает пайплайн внутри каждого сабагента**, шагом 12 — после
коммита работы и **отдельным коммитом учёта**, вызовом Skill `av-dev-pm:tasks`.
Батч сам записей учёта не трогает: он не знает, чем кончилась приёмка, и
дублировать закрытие ему незачем. Но грязное дерево после сабагента — **его**
@@ -104,21 +104,20 @@ description: Проводит несколько задач разом — пл
параллельном она гонится в волне **одна** (обоснование — ниже, в шаге 4).
Помечается здесь, на планировании, а не во время прогона, и **независимо от
режима**: состав волны определяется сейчас, режим может смениться просьбой уже
после плана, а ступень ревью выберет разметчик уже внутри прогона — ключевать
волну на ещё не сделанный выбор нельзя. Триггеры — по фактам о задаче, каждый
после плана, а метка ревью назовёт разметчик уже внутри пайплайна задачи,
после `propose`, — ключевать волну на ещё не сделанный выбор нельзя. Триггеры — по фактам о задаче, каждый
сам по себе достаточен:
- трогает схему хранилища, миграцию, формат на диске или объём хранимого;
- трогает конкурентность: транзакции, блокировки, фоновые циклы, общее
состояние;
- трогает размер тела, буфер, память, сжатие, ретеншен, темп потока;
- её тема названа в `docs/research/` или в журнале `docs/review.md` как место,
где уже мерили или уже ломалось.
- её тема названа в журнале `docs/review.md` как место, где уже ломалось.
Ни один триггер не сработал — задача не замеряющая, даже если её ревью
окажется `wide`. Ступень про глубину проверки, замеряющая — про соревнование за
окажется `large`. Метка про глубину проверки, замеряющая — про соревнование за
железо; это разные вопросы, и совпадают они не всегда. Обратное тоже бывает и
тоже законно: помеченная задача, чьё ревью пошло профилем `quick` или
`standard`, машину не займёт вовсе — меряющие проходы живут только в `wide`.
тоже законно: помеченная задача, чьё ревью пошло меткой `small` или
`medium`, машину не займёт вовсе — меряющие проходы живут только в `large`.
Пометка от этого не снимается: она ставится **до** разметки, и перестраховка
здесь стоит одной волны, а ошибка — испорченных чисел;
- **нумерованные артефакты — номера раздаёт оркестратор заранее.** Если проект
@@ -238,8 +237,10 @@ flowchart TD
- прогони Skill **`av-dev-pipeline:task-pipeline`** ровно на этой задаче,
полный цикл SDD с обоими чекпоинтами ревью;
- если задаче назначен **номер артефакта** — используй строго его;
- **ступень ревью выбирает разметчик конвейера, а не ты и не сабагент.**
Профиль в вызов не передаётся вовсе. Батч не повод её понижать: «нас много и
- **метка ревью выбирает разметчик конвейера, а не ты и не сабагент.** Он
идёт внутри пайплайна задачи, шагом 4, сразу после `propose`, и его план
обслуживает оба чекпоинта. Метка в вызов не передаётся вовсе. Батч не
повод её понижать: «нас много и
мы спешим» — ровно тот стимул, из-за которого проходы пропускают, и он снят
тем, что регулятор не в руках у автора;
- **режим прогона проходов ревью — от режима батча**, и его называет charter,
@@ -249,15 +250,15 @@ flowchart TD
Внутренние рёбра графа — цепочку проходов, держащих машину — конвейер
соблюдает сам, в любом режиме;
- **если вложенные сабагенты недоступны** (движок не даёт запускать агентов из
агента) — не пропускай ревью и не понижай ступень: проведи его **инлайн** по
агента) — не пропускай ревью и не понижай метка: проведи его **инлайн** по
тем же charter'ам `av-dev-pipeline`, сохранив обязательное — разметку первой
(план с темами и ступенью), гейт до опиниативных проходов, состав по плану,
(план с темами и меткой), гейт до опиниативных проходов, состав по плану,
триаж последним. И **скажи в отчёте прямым текстом, что ревью шло инлайн**:
инлайновый проход видит контекст автора и потому разведён с ним слабее — а
инлайновая разметка вдобавок означает, что ступень выбрал автор, и это
инлайновая разметка вдобавок означает, что метка выбрал автор, и это
отдельная строка;
- **вернуть отчёт**, в котором обязательно: исход задачи одним из трёх слов;
**план прогона: ступень с обоснованием, темы и их глубины**, и режим; что сделано; какие вопросы
**план прогона: метка с обоснованием, темы и их глубины**, и режим; что сделано; какие вопросы
записаны и куда; изменённые файлы; добавлялся ли нумерованный артефакт и с
каким номером; затронутые capability; состояние гейта; **перечень
тем с исходом по каждой**; **путь к
@@ -284,9 +285,9 @@ flowchart TD
Сверка идёт в три шага, и порядок важен:
1. **Возьми план прогона** из отчёта задачи — таблицу «тема → дом → глубина → кто
закрывает» со ступенью и обоснованием; он затем и заказан в обязательных полях
закрывает» с меткой и обоснованием; он затем и заказан в обязательных полях
шага 4. Плана в отчёте нет — сверять не с чем; это само по себе основание не
вливать, пока сабагент не покажет план разметчика.
вливать, пока сабагент не покажет план разметки задачи.
2. **Сверяй с независимым артефактом, а не с прозой отчёта.** Перечень проходов
бери из **сохранённого отчёта триажа** (`openspec/changes/<id>/review/` или
`openspec/changes/archive/<id>/review/` — задача доведена, change заархивирован) —
@@ -294,13 +295,18 @@ flowchart TD
проход и пропустить: она подтверждает сама себя. Отчёта триажа на месте нет —
считай, что состав неизвестен, и дозапускай ревью целиком.
3. **Сверь план с исходом**: против каждой темы плана обязан стоять отчёт либо
названная причина его отсутствия. Раскладка «тема → кто закрывает на этой
ступени» — в скилле `av-dev-pipeline:review-pipeline`.
названная причина его отсутствия. Раскладка «тема → кто закрывает с этой меткой» — в скилле `av-dev-pipeline:review-pipeline`.
Расхождение — не повод отменять задачу: дозапусти недостающие проходы **на
ветке**, в её worktree, через `av-dev-pipeline:review-pipeline`, и только потом
интегрируй.
**Передай в дозапуск тот же план.** Триаж требует его обязательным входом — без
плана он не может сверить, все ли размеченные темы вернули отчёт, а эта сверка и
есть то, ради чего дозапуск затевается. Плана не осталось (сабагент не сохранил
его в отчёте) — пусть повторит разметку задачи: это самый дешёвый проход
конвейера, и он дешевле, чем прогон, который нечем сверить.
**Находки дозапуска — такие же находки, и зелёный гейт их не отменяет.** Правило
интеграции «вливаем только зелёные» смотрит на гейт, а дозапущенный `critical`
гейт не красит: он был бы пропущен молча, если это не сказать прямо. Поэтому:
@@ -337,7 +343,7 @@ rebase делается **внутри worktree задачи**, а ff-слиян
(`git -C <path> rebase --abort`), оставь ветку и worktree как есть, вынеси это
в доклад как нераспознанное пересечение;
- **дерево сабагента обязано быть чистым.** `git -C <path> status --porcelain`
до `rebase`: непусто — значит сабагент не довёл шаг 11 до коммита учёта (или
до `rebase`: непусто — значит сабагент не довёл шаг 12 до коммита учёта (или
оставил мусор). Не форсируй и не коммить за него: назови задачу в докладе
недоведённой и оставь ветку с worktree. Молчаливый `rebase` на грязном дереве
всё равно откажет, но с сообщением про unstaged changes — а причина другая;
@@ -395,7 +401,26 @@ rebase в файле X», а не «нераспознанное пересеч
- **заверши триажем.** Он единственный, кто агрегирует, и без него у находок нет
ни оракула, ни пометки `инлайн`/`развилка` — а следующий абзац на неё
опирается. Прогон из двух проходов без триажа — это сырые находки, выданные за
разобранные.
разобранные;
- **план триажу собери сам, здесь, — разметчика на этой сверке нет.** Триаж
требует план обязательным входом: он сверяет размеченное с пришедшим, и без
плана эта сверка не выполняется вовсе. Разметка задачи сюда не годится — она
описывала одну задачу, а сверка идёт по интегрированной ветке. План здесь
короткий и составляется по факту запуска:
```
метка: не применяется — сверка стыка, а не ревью изменения
тема дом глубина закрывает
requirements openspec/specs/<capability-1>/ разбор specs (стык)
requirements openspec/specs/<capability-2>/ разбор specs (стык)
architecture docs/architecture.md разбор architecture
+ источник docs/passport.md
```
Темы, которых в этом списке нет (`autotests`, `conventions`, `security`,
`operations`, свои темы проекта), назови строкой «не проверяется на сверке
стыка: закрыто прогонами отдельных задач». Это не формальность — без такой
строки отчёт сверки читается как полное ревью ветки.
Граф этой сверки — веер в один сток, и он такой же, как у обычного прогона:
@@ -421,7 +446,7 @@ flowchart TD
`git worktree prune`. Worktree и ветки **провалившихся** не трогай — они нужны
для ручного дожатия.
- **Записей учёта батч не трогает** — их правит пайплайн внутри сабагента на
шаге 11. Батч сообщает исход по каждой задаче; если какой-то сабагент дошёл до
шаге 12. Батч сообщает исход по каждой задаче; если какой-то сабагент дошёл до
коммита, но закрытия не сделал (плагина нет, вызов не разрешился), скажи это
строкой — иначе задача останется открытой молча.
- Доложи кратко: