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

Прогоны стали долгими, а счёт в токенах заметным. Разбор шёл не по находкам, а
по статьям расхода. Две названы прямо: убрать reimpl и убрать fable.

reimpl писал свою реализацию узла, не открывая существующую, и диффил по
решениям. Его счёт определялся объёмом вывода — он один писал код, а не читал
его, — и на прогоне это была самая большая строка. Снят по цене.

Профиль deep от этого не похудел, а исчез: reimpl был единственным, чем он
отличался от wide, и без него у двух имён оказался бы один состав. Ровно от
этой болезни лечилась ступень wide решением JJJ — у профиля обязан быть один
правильный ответ, иначе реестр состава нечем проверять. Ступеней три: quick,
standard, wide.

Вместе с профилем снято всё, что обслуживало только его. Барьер стоимости —
он держал дорогой проход, чтобы тот не писал реализацию против кода, который
через час перепишут; дорогого прохода нет, граф стал плоским во всех профилях,
рёбер осталось два вида вместо трёх. Тест «идентичность, слияние, разбор» —
полторы страницы, служившие единственной цели: выбрать deep не по ощущению;
вместе с ним ушёл проектный перечень мест в docs/review.md и его скелет в
каноне. Стадии перенумерованы: 0 гейт, 1 сверка, 2 враждебный и
эксплуатационный, 3 архитектурный, 4 триаж — дыра на месте третьей читалась бы
как пропущенная стадия.

Снятие записано как сознательное сужение, а не как «класс оказался пустым».
calibration.md требует замера на двух проектах перед удалением прохода; замера
не было, было решение о цене. Поэтому в «Честном пределе» стоит строка: «не
знаю, чего не знаю» больше не достаёт никто. Остаток независимого взгляда дают
профиль design и architecture, но альтернативной реализации, с которой можно
сдиффить решения, у конвейера нет. Класс уходит в границы покрытия каждого
прогона, у проекта — в подраздел «перестали проверять сознательно». Без этой
записи снятие через месяц читается как «проверено и признано лишним».

fable снят с троих: review-triage, review-architecture, doc-code-drift — все на
opus. Основание верхней модели «ошибка распространяется дальше самой находки»
осталось, но оно объясняет, почему двое не опускаются до sonnet, а не почему им
нужна ступень выше opus: разницы в пользу более дорогой модели не показал ни
один прогон, а время и счёт она множила. Палитра схлопнулась до двух цветов,
красного в репозитории больше нет, frontmatter.py теперь отвергнет модель вне
sonnet и opus.

Версия канона не поднята сознательно. Проектам всё равно надо снести перечень
мест для deep из docs/review.md, поэтому пункт вписан в «Что сделать проекту»
записи «Версия 4» — её ещё не гонял ни один проект, оба ждут в TODO.

Тема 33 в DECISIONS.md, следствия 127-129.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-08-06 19:02:15 +03:00
co-authored by Claude Opus 5
parent cbfae90f3f
commit ea84a4fbb3
18 changed files with 193 additions and 393 deletions
+70
View File
@@ -2258,3 +2258,73 @@ dev-skills — **маркетплейс плагинов**: скилл комм
126. **Снятое слово называется вместе с заменой и остаётся записанным.** Убрать
из текстов недостаточно: без записи «это снято и вот чем заменено» слово
возвращается первым же, кто найдёт его удачным.
## 33. Стоимость ревью: снят самый дорогой проход и самая дорогая модель (2026-08-06)
Прогоны стали долгими, а счёт в токенах — заметным. Разбор шёл не по находкам, а
по статьям расхода: что в конвейере стоит больше всего и что из этого окупается.
Две статьи названы прямо оператором.
**ААББОО. Проход независимой реализации снят целиком, и с ним профиль `deep`.**
`reimpl` писал свою реализацию узла, не открывая существующую, и диффил по
решениям. Его счёт определялся **объёмом вывода** — он один писал код, а не читал
его, — и на прогоне это была самая большая строка расхода. Снят по решению о
стоимости.
Профиль `deep` от этого не «похудел», а исчез: `reimpl` был **единственным**, чем
он отличался от `wide` (обоим оставалось бы 0, 1, 2, 4, 5). Держать два имени для
одного состава нельзя — ровно от этой болезни лечилась ступень `wide` (решение
JJJ): у профиля обязан быть один правильный ответ, иначе реестр состава нечем
проверять. Ступеней теперь три: `quick`, `standard`, `wide`.
Вместе с профилем ушло всё, что обслуживало только его:
- **барьер стоимости** — он существовал ровно затем, чтобы дорогой проход не
писал реализацию против кода, который через час перепишут. Дорогого прохода
нет, и граф стал плоским во всех профилях: от гейта до триажа. Рёбер осталось
два вида вместо трёх — зависимость и конфликт за ресурс;
- **тест «идентичность, слияние, разбор»** (решение из темы 27) — он служил
единственной цели: выбрать `deep` не по ощущению. Выбирать больше нечего, и
полторы страницы теста сняты вместе с проектным перечнем мест в
`docs/review.md`;
- **стадии перенумерованы**: 0 гейт, 1 сверка, 2 враждебный и эксплуатационный,
3 архитектурный, 4 триаж. Дыра на месте третьей читалась бы как пропущенная
стадия.
**ААББПП. Снятие записано как сознательное сужение, а не как «класс оказался
пустым».** `calibration.md` требует замера на двух проектах перед удалением
прохода, и замера не было — было решение о цене. Значит и в «Честном пределе»
стоит честная строка: **«не знаю, чего не знаю» больше не достаёт никто.** Остаток
независимого взгляда дают профиль `design` (код пишется под его находки) и
`architecture` (второй способ, лишние слои), но альтернативной реализации, с
которой можно сдиффить решения, у конвейера нет. Класс уходит в границы покрытия
каждого прогона, а у проекта — в подраздел «перестали проверять сознательно».
Без этой записи снятие через месяц читается как «проверено и признано лишним»,
и вернуть проход было бы не на чем.
**ААББРР. Самая дорогая модель снята со всех проходов.** На ней сидели трое:
`review-triage`, `review-architecture` и `doc-code-drift` из `av-dev-pm`. Все трое
переведены на `opus`. Основание для верхней модели — «ошибка распространяется
дальше самой находки» — никуда не делось, но оно объясняет, почему эти двое **не
опускаются до `sonnet`**, а не почему им нужна ступень выше `opus`: разницы в
пользу более дорогой модели не показал ни один прогон, а время и счёт она множила.
Палитра цветов схлопнулась до двух: `sonnet` → green, `opus` → yellow. Красного в
репозитории больше нет, и `frontmatter.py` теперь отвергнет модель вне этих двух —
раскладка проверяется механически, как и раньше.
### Что из этого следует
127. **Профиль, у которого не осталось собственного прохода, — не профиль.**
Ступень стоимости определяется тем, что она **добавляет**; сняли добавку —
сняли ступень, а не оставили имя. Иначе два имени указывают на один прогон, и
состав снова нечем проверить.
128. **Удаление по цене и удаление по замеру записываются по-разному.** Первое
обязано назвать класс, который перестал проверяться, и оставить его в
границах покрытия. Второе — сослаться на замер. Смешение их даёт самый
дорогой вид тишины: пробел, выглядящий как решённый вопрос.
129. **Механика, обслуживающая один проход, снимается вместе с ним.** Барьер
стоимости, тест выбора верхней ступени и проектный перечень мест держались
только на `reimpl`. Оставшись, они выглядели бы работающими правилами и
тратили бы внимание на каждом прогоне.
+2 -3
View File
@@ -29,9 +29,8 @@
- `task-pipeline` — задача через полный цикл SDD, от постановки до коммита;
- `task-batch` — несколько задач разом, каждая в своём worktree;
- `review-pipeline` — конвейер ревью: гейт, сверка со спеками, враждебные
постановки, эксплуатационный постмортем, независимая реализация,
архитектура, обязательный триаж. Девять агентов-проходов, четыре ступени
стоимости: `quick`, `standard`, `wide`, `deep`.
постановки, эксплуатационный постмортем, архитектура, обязательный триаж.
Восемь агентов-проходов, три ступени стоимости: `quick`, `standard`, `wide`.
- **av-dev-git** — `commit`: сообщения в личном стиле.
Соглашение об именах: имя **плагина** длинное с префиксом `av-dev-`, имена
+4
View File
@@ -208,3 +208,7 @@ jellybit 43. Шаги повышения — [changelog.md](av-dev-pm/skills/can
каждого `fix` и `Вопрос` + `Куда ляжет ответ` у каждого `research` пишутся
по мере того, как задача идёт в набор (`sprint take` без них откажет).
Сколько записей готово к взятию, печатает блок здоровья `check`
- [ ] `docs/review.md`, «Триггеры профиля»: снести перечень мест для `deep`
профиль упразднён вместе с проходом независимой реализации; перечень для
`wide` остаётся. Там же: класс «форма решения, где спека выбора не сделала»
— в подраздел «перестали проверять сознательно»
@@ -2,8 +2,8 @@
name: review-architecture
description: "Архитектурный проход ревью — получает вход шире диффа (дерево пакетов, граф внутренних зависимостей, инвентарь существующих концепций). Главный вопрос — концептуальная целостность: вводит ли изменение новое понятие, можно ли выразить существующими (включая конструкции стандартной библиотеки), не появился ли второй способ делать то, что уже делается, не размывается ли граница домена. Потолок 3 находки плюс секция «дешевле переделать до мерджа». Работает и на предложении до кода (профиль design). Только чтение."
tools: Read, Grep, Glob, Bash
model: fable
color: red
model: opus
color: yellow
---
Ты — архитектурный проход ревью. Агент, видящий только дифф, физически не может
+1 -1
View File
@@ -147,7 +147,7 @@ color: green
- архитектурные границы и второй способ делать то же самое —
`review-architecture`;
- стиль, дублирование, лишние слои, «я бы написал иначе» — `review-architecture`
(лишнее и второй способ) и `review-reimpl` (когда прогон идёт профилем `deep`);
(лишнее и второй способ);
- соответствие дельта-спекам — `review-specs`.
Видишь такое — не выводи находкой; максимум упомяни строкой в границах покрытия,
-164
View File
@@ -1,164 +0,0 @@
---
name: review-reimpl
description: "Самый дорогой и самый ценный generative-проход ревью — получает спеку и контракты соседей, пишет собственную реализацию во временном каталоге, НЕ ОТКРЫВАЯ существующую, и только потом диффит по решениям (декомпозиция, где обрабатываются ошибки, что вынесено в интерфейс, владение данными, протяжка context, модель конкурентности). Единственный проход, который системно достаёт «не знаю, чего не знаю». Запускается только в профиле deep — он и есть верхняя ступень стоимости. Существующий код не меняет."
tools: Read, Grep, Glob, Bash, Write
model: opus
color: yellow
---
Ты — проход **независимой реализации**. Все остальные проходы смотрят на готовое
решение и потому наследуют его рамку: увидев код, невозможно всерьёз спросить «а
нужен ли здесь вообще этот слой». Ты единственный, кто приходит без рамки — ценой
того, что сперва делаешь работу заново.
Находки — по контракту
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
(точный путь конвейер передаёт в задании).
## Что берёшь из документов проекта
- **`docs/passport.md`** — граница домена: твоя версия должна лежать по ту же
сторону, что и существующая, иначе весь дифф по решениям окажется спором о
scope.
- **`CLAUDE.md`, инварианты** — то, что твоя реализация обязана соблюсти
(дословность хранения, «сохранили — значит приняли» и подобное).
- **`docs/research/` и `docs/database.md` вместе** — измеренные объёмы и
представление данных: решение, разумное на сотне записей, неразумно на
миллионе (почему именно вместе — project-facts, «Сшивать обязаны проходы»).
- **`docs/conventions/`** — твоя версия должна быть сравнимой по форме.
Карта «что нужно проходу → где лежит» —
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
**Деградация поразрядная.** Нет инвариантов в `CLAUDE.md` — пиши версию по спеке
и конвенциям, но `critical` по основанию «нарушен инвариант проекта» не
присваивай: именно инварианты чаще всего объясняют чужое решение. Нет объёмов в
`docs/research/` — не предполагай их. Строка в границы покрытия называет, чего
именно не было. **Риск конкретно этого прохода при таком пробеле максимален:**
твоя версия проще, потому что не знает, чего проект боится.
**Тебя запускают только в верхнем профиле, `deep`, а не всегда.** Он выбирается
ровно тогда, когда вводится или меняется по существу **правило идентичности,
слияния или разбора**; ты — единственное, чем `deep` отличается от соседней
ступени `wide`.
Класс задан тестом, а не списком, и тест не зависит ни от домена, ни от языка.
Правило сюда попадает, когда сходятся три условия: **вариантов несколько** (двое
добросовестных выберут разное, и оба решения защитимы); **спека между ними не
выбирает** — она требует сравнивать, сливать или разбирать, но не называет исход
в пограничном случае; **неверный выбор не падает**, а даёт правдоподобный
результат и молча меняет смысл данных. Отрицательный тест сильнее: то, что
красит гейт или роняет запрос, — не твой класс. Три слова означают три места на
границе, где данные входят или встречаются: чем определяется, что две вещи одна и
та же (состав ключа, нормализация перед сравнением, дедупликация); что получается
при встрече двух представлений одного (победитель конфликта, накопление против
замещения, тай-брейк при равенстве); как внешнее представление становится
внутренним (границы токенов, извлечение полей, неоднозначный вход). Проектный
перечень мест — в `docs/review.md`, если он там записан; он производен от теста,
а не расширяет его.
**Если ты видишь, что тебя позвали не на этот класс** — изменение ничего не
вводит и не меняет по существу, а правило в нём одновариантно, — скажи это первой
строкой отчёта и работай в полглубины: твоя реализация совпадёт с существующей, и
дифф будет о стиле, а не о решениях. Это строка в границы покрытия, а не отказ
работать.
Вне этого случая твой счёт — самый большой в конвейере (он
определяется объёмом вывода: ты пишешь реализацию целиком), а независимый взгляд
в значительной мере уже дал профиль `design` — код писался под его находки. Если
тебя позвали, значит случай тот самый: работай в полную глубину и не экономь на
фазе 1.
## Фаза 1 — своя реализация. Существующую открывать ЗАПРЕЩЕНО
Тебе дают: требования из дельта-спеки, сигнатуры соседей, с которыми узел
договаривается, назначение узла. Описание внешнего мира (формат входа, поведение
источника) читай в `docs/architecture.md` и в `docs/research/` — это описание
мира, а не реализации под ревью.
Конвенции проекта тоже читай: они не подсказывают форму решения, но твоя версия
должна быть сравнимой.
**Категорически нельзя:** открывать файлы реализации под ревью, читать
`git diff`, `git show`, `git log -p` по ним, грепать по именам функций из них.
Читать соседние пакеты **можно и нужно** — тебе нужны их контракты, иначе ты
напишешь несовместимое. Если непонятно, где проходит граница «сосед против
объекта ревью», спроси у оркестратора, а не подглядывай.
Напиши реализацию во временном каталоге проекта (`tmp/reimpl/<узел>/`).
Требования к ней:
- решает задачу целиком, а не набросок: обработка ошибок, отмена `context`,
граничные случаи;
- собирается, если это достижимо за разумное время; несобирающийся черновик тоже
годится, но пометь это;
- пиши так, как писал бы для этого проекта.
Не подглядывай «чтобы свериться» ни на каком этапе фазы 1. Единственное
подглядывание — после того, как твоя версия дописана.
## Фаза 2 — дифф по решениям, а не по строкам
Теперь открой существующую реализацию. Сравнивай **не текст**, а решения:
- **декомпозиция** — сколько функций и типов, где проведены границы, что
оказалось внутри одной сущности у тебя и разнесено у них (или наоборот);
- **где обрабатываются ошибки** — на каком уровне принимается решение, что
оборачивается, что транслируется, что проглочено; в частности, где проходит
граница «вход принят» против «разбор не удался»;
- **что вынесено в интерфейс** — и есть ли у интерфейса больше одной реализации,
кроме мока;
- **владение данными** — кто создаёт, кто мутирует, что копируется; сохраняется
ли содержимое дословно на всём пути от входа до хранилища, или где-то
происходит перекладывание в свою структуру с потерей незнакомых полей;
- **протяжка `context`** — докуда доходит, где теряется, что происходит при
отмене на середине записи;
- **модель конкурентности** — что параллельно, что защищено, кто кого ждёт; что
происходит с двумя операциями над одним ключом.
## Главное правило вывода
**Расхождение не является дефектом, пока не названо последствие.** «Я бы сделал
иначе» — не находка и не выводится вообще. Находка выглядит так: «разбор разнесён
по трём слоям; чтобы добавить второй источник данных, придётся тронуть все три и
два теста — сейчас это N строк, дальше только дороже».
Твоя версия **не эталон**: ты тоже воспроизводишь медиану публичного кода. Там,
где существующее решение объясняется знанием, которого у тебя не было (история
проекта, реальное поведение внешних систем, цена объёма на живом потоке), — это не
находка, а запись в границы покрытия: «разошлись здесь, вероятно, из-за
контекста, которого я не видел».
Отдельно ценно обратное: место, где **их решение лучше твоего**. Выведи это одной
секцией — оно калибрует доверие к остальным твоим находкам.
## Чего этот проход принципиально не может поймать
- Всё, что зависит от истории проекта и внешних систем: почему выбраны именно
такие настройки, какие грабли уже проходили.
- Соответствие требованиям: ты писал по спеке, но сверять реализацию со спекой —
не твоя работа.
- Дефекты рантайма: гонки, поведение под нагрузкой и на реальном объёме.
- Мелкие нарушения записанных конвенций — их ловит линтер, тебе на них дорого
отвлекаться.
## Формат вывода
1. `## Что я написал` — 5–10 строк: форма твоего решения, ключевые развилки.
2. `## Дифф по решениям` — таблица `Решение | У меня | В коде | Последствие`.
3. Находки по контракту — только те, где последствие названо.
4. `## Где их решение лучше`.
5. Обязательный блок:
```
## Coverage of this pass
- проверено: <какой узел переписан, что сравнивалось>
- не проверялось и почему: <что не успел, где не хватило контракта>
- принципиально недоступно этому проходу: история проекта, поведение внешних систем, рантайм
```
## Ограничения
Пиши **только** в `tmp/reimpl/` внутри проекта (не в системный `/tmp`).
Существующий код не редактируй ни строчкой. Не коммить. За собой `tmp/reimpl/` не
убирай — оркестратор может захотеть посмотреть. Реальные данные из `testdata`
наружу не копируй.
+2 -2
View File
@@ -2,8 +2,8 @@
name: review-triage
description: "Обязательный финальный проход конвейера ревью — единственный, кто агрегирует. Дедуплицирует находки по причине, добывает оракул для critical/major (пишет падающий тест, гоняет разбор на реальных данных, выполняет команду), понижает неподтверждённое до гипотез, отсеивает вкусовщину, ранжирует по ущербу × вероятности и режет до 7 пунктов. Помечает каждую находку «инлайн» или «развилка» для оркестратора. Формирует итоговый отчёт с перечнем запущенных проходов и обязательной секцией границ покрытия."
tools: Read, Grep, Glob, Bash, Write
model: fable
color: red
model: opus
color: yellow
---
Ты — триаж конвейера ревью. Единственный проход, который видит выводы всех
+77 -182
View File
@@ -1,6 +1,6 @@
---
name: review-pipeline
description: "Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, архитектурный проход, независимая реализация в верхнем профиле и обязательный триаж. Четыре ступени стоимости: quick, standard, wide, deep. Порядок прогона — граф зависимостей, а не очередь: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, независимая реализация стоит за барьером стоимости, триаж — единственный сток. Линейный прогон — по слову оператора или на занятой машине. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода."
description: "Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, архитектурный проход и обязательный триаж. Три ступени стоимости: quick, standard, wide. Порядок прогона — граф зависимостей, а не очередь: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Линейный прогон — по слову оператора или на занятой машине. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода."
---
# Конвейер ревью
@@ -83,7 +83,7 @@ description: "Конвейер ревью изменения — детерми
- **его блок вопросов** из «Вопросы к проходам» в `docs/review.md`, если он там
есть, — **дословно**. Блок адресован проходу поимённо и выведен из промаха
этого проекта; заставлять девять charter'ов самим ходить за ним значит
этого проекта; заставлять восемь charter'ов самим ходить за ним значит
получить, что за ним ходят двое. Проход отвечает на такие вопросы явно,
дополнительно к обязательным;
- **контракт находок** — путь к
@@ -106,8 +106,7 @@ description: "Конвейер ревью изменения — детерми
| Модель | Цвет | Проходы | Почему |
|---|---|---|---|
| `sonnet` | green | gate, code, ops | вход структурный, критерий записан заранее |
| `opus` | yellow | specs, adversary, rubric, reimpl | суждение без опоры на инструмент |
| `fable` | red | triage, architecture | ошибка распространяется дальше самой находки |
| `opus` | yellow | specs, adversary, rubric, architecture, triage | суждение без опоры на инструмент |
**Цвет charter'а кодирует модель, а не роль прохода.** Это единственное
назначение цвета: список агентов читается взглядом, и по нему сразу видно, чем
@@ -116,15 +115,16 @@ description: "Конвейер ревью изменения — детерми
здесь и **проверяется механически** — цвет ставится один раз при заведении
charter'а, а модель потом двигает калибровка, и разъезжаются они молча.
**Самая дорогая модель — только двум проходам, и это калибровка, а не
осторожность.** Замер: на первом же прогоне конвейера самые ценные находки дали
`opus`-проходы — сверка спек дала 13 находок с оракулами, а проход про
идиоматичность (впоследствии упразднённый) — три эксперимента против драйвера БД
с воспроизведёнными числами. Разницы в пользу более дорогой модели на
опиниативных проходах не обнаружилось — значит платить за неё там не за что.
**Моделей две, и верхняя из них — `opus`; выше неё конвейер не платит.** Замер:
на первом же прогоне самые ценные находки дали `opus`-проходы — сверка спек дала
13 находок с оракулами, а проход про идиоматичность (впоследствии упразднённый) —
три эксперимента против драйвера БД с воспроизведёнными числами. Разницы в пользу
модели **дороже** `opus` не обнаружилось ни на одном проходе, а прогон на ней
стоил заметно дольше и дороже — значит платить за неё не за что.
Двое, у кого она остаётся, отобраны по одному признаку: **их ошибка
распространяется дальше собственной находки.**
Двое из пяти держатся на `opus` по признаку, отдельному от суждения: **их ошибка
распространяется дальше собственной находки.** Понижать их до `sonnet` вместе с
остальными дешёвыми проходами нельзя.
- `triage` — через него проходит всё, что оркестратор реализует **молча**:
ложноположительная находка становится кодом, потерянный `critical` — дефектом.
@@ -133,11 +133,6 @@ charter'а, а модель потом двигает калибровка, и
потолок в 3 находки делает его дешёвым по выходу, а находка на предложении
стоит абзаца против переписывания на готовом коде. Дёшево × высокое плечо.
`reimpl` намеренно **не** в этом списке, хотя он самый ценный из generative: его
стоимость определяется объёмом вывода (он пишет реализацию целиком), так что
дорогая модель множит самый большой счёт. Ценность же его — в **независимости**
взгляда, а не в мощности модели.
**Самая дешёвая модель не используется ни на одном проходе, и это не экономия
наоборот.** Дешёвая модель на опиниативном проходе даёт правдоподобные находки,
которые триаж обязан опровергать оракулом, — а это самая дорогая операция
@@ -146,27 +141,25 @@ charter'а, а модель потом двигает калибровка, и
Дешёвому проходу просто не осталось работы.
Экономия достигается не понижением модели, а **непуском прохода**: `quick`
четыре прохода, `deep`восемь. Правило выбора профиля и есть главный
рычаг стоимости, и ступеней у него четыре именно поэтому.
четыре прохода, `wide` — семь. Правило выбора профиля и есть главный
рычаг стоимости, и ступеней у него три именно поэтому.
## Профили
| Профиль | Когда | Стадии | Проходов |
|---|---|---|---|
| `quick` | багфикс, локальная правка, доки | 0, 1, 5 | 4 |
| `standard` | **рабочее умолчание**: поведение, миграция схемы, публичный контракт, инвариант | 0, 1, 2, 5 | 6 |
| `wide` | изменение вводит новое понятие или структурную единицу | 0, 1, 2, 4, 5 | 7 |
| `deep` | изменение вводит новое правило идентичности, слияния или разбора | 0, 1, 2, 3, 4, 5 | 8 |
| `quick` | багфикс, локальная правка, доки | 0, 1, 4 | 4 |
| `standard` | **рабочее умолчание**: поведение, миграция схемы, публичный контракт, инвариант | 0, 1, 2, 4 | 6 |
| `wide` | изменение вводит новое понятие или структурную единицу | 0, 1, 2, 3, 4 | 7 |
| `design` | **до кода**, на предложении | specs, плюс rubric и architecture по условию `wide` | 13 |
**`wide` назван по тому, что он добавляет: вход шире диффа.** Единственное его
отличие от `standard` — архитектурный проход, а тот и получает дерево пакетов,
граф зависимостей и инвентарь понятий вместо одного диффа. Ступень заведена
потому, что прыжок `standard``deep` стоил самого дорогого прохода конвейера, и
платить эту цену приходилось за одну архитектурную находку: изменений, которые
трогают публичный контракт, но не вводят нового правила слияния, — большинство.
граф зависимостей и инвентарь понятий вместо одного диффа. Это и **верхняя
ступень**: выше неё конвейер не поднимается, и добавить к семи проходам ему
нечего.
**Состав сверяется по этой таблице до коммита.** Реестр из трёх-восьми проходов
**Состав сверяется по этой таблице до коммита.** Реестр из трёх-семи проходов
проверяется взглядом — и это единственная защита от промаха, который уже
случился: пропуск прохода **не отличим от прохода без находок** (гейт зелёный,
спеки сошлись, отчёт выглядит полным), а заметить его мог бы только триаж,
@@ -177,9 +170,7 @@ charter'а, а модель потом двигает калибровка, и
Правило выбора профиля — **по факту изменения, не по ощущению важности**:
- вводится или меняется по существу правило, определяющее **идентичность, слияние
или разбор** данных (тест — ниже) → `deep`;
- иначе изменение вводит **новое понятие или структурную единицу**: новый пакет
- изменение вводит **новое понятие или структурную единицу**: новый пакет
или слой, новая точка входа, второй способ делать то, что уже делается, перенос
ответственности между узлами → `wide`;
- иначе меняется поведение, видимое снаружи, трогается схема, публичный контракт
@@ -203,74 +194,11 @@ charter'а, а модель потом двигает калибровка, и
изменился, а от того, что появилось новое понятие: добавленное поле в
существующем ответе — не концепт.
**Верхняя ступень и есть триггер независимой реализации** — раньше он был
условием *внутри* `deep`, и профиль от этого распадался на два разных прогона под
одним именем. Условие никуда не делось, оно просто переехало туда, где выбирается
профиль: изменение с новым правилом слияния — единственный случай, когда триаж
называл отсутствие `reimpl` дырой покрытия.
Что здесь считается новым понятием и что — правилом идентичности, проект может
уточнить в `docs/review.md`, разделе настройки конвейера. Это **уточнение**, а не
отмена: не записано — работает список выше. Проект, где изменение контракта и
правда архитектурное (публичный SDK, чужие потребители), там же поднимает его до
`wide` — и это уточнение, а не возврат прежнего умолчания.
### Идентичность, слияние, разбор — тест, а не список
Три слова названы затем, чтобы верхнюю ступень нельзя было выбрать по ощущению.
Читаются они **тестом**, применимым к любому проекту на любом языке; домен, стек
и имена узлов в тест не входят.
Правило принадлежит этому классу, если сходятся **три условия**:
1. **вариантов несколько** — два добросовестных исполнителя выберут разное, и оба
решения защитимы;
2. **спека между ними не выбирает** — она требует, чтобы вещи сравнивались,
сливались или разбирались, но не называет исход в пограничном случае;
3. **неверный выбор не падает** — он даёт правдоподобный результат и меняет смысл
данных молча.
**Отрицательный тест, и он важнее трёх положительных:** если неверная реализация
красит гейт, роняет запрос или ломает тест — это **не** сюда. Такое ловят проходы
дешевле, и платить за него верхней ступенью не за что.
Отсюда же и причина, по которой класс достался самому дорогому проходу:
независимая реализация **выберет другой вариант**, и дифф между двумя вариантами
и есть находка. Там, где вариант один, она совпадёт с существующей — и верхняя
ступень оплатит подтверждение того, что и так известно.
Три слова — это **три места**, где такие правила водятся, и все три стоят на
границе, где данные входят или встречаются:
| Слово | Вопрос, на который правило отвечает | Что в нём выбирается |
|---|---|---|
| **идентичность** | когда две вещи считаются одной и той же | состав ключа и что в него намеренно не входит; нормализация перед сравнением — регистр, пробелы, кодировка, время, единицы, округление; дедупликация |
| **слияние** | что получается, когда два представления одного встретились | кто побеждает при конфликте; накопительное против замещающего; что делать с отсутствующим полем; тай-брейк при равенстве |
| **разбор** | как внешнее представление становится внутренним | границы токенов; извлечение полей; сопоставление с известным набором; поведение на неоднозначном входе |
**Триггер — новое или изменённое правило, а не код рядом с ним.** Правка
сообщения об ошибке в узле, который разбирает вход, ступень не поднимает.
Поднимают: заводится ключ или меняется его состав; в слияние добавляется источник
или меняется победитель при конфликте; у разбора появляется новый вид входа или
новая ветка неоднозначности. Без этой оговорки проект, чей домен и **состоит** из
таких правил, оказывался бы в `deep` всегда — та же болезнь, от которой лечилась
ступень `wide`.
**Ступень определяет класс правила, а не вид работы.** Миграция схемы сама по
себе `standard` — но миграция, которая **переносит данные** по правилу («сложить
дубли», «привести к одному виду перед сравнением»), несёт правило идентичности и
потому `deep`. Одно и то же слово в описании задачи попадает в разные ступени, и
это не противоречие: смотрят не на слово, а на то, есть ли выбор, которого спека
не сделала.
**Проект, у которого таких правил нет вовсе, `deep` не запускает никогда.** Это
законное состояние, а не признак недонастройки: бывают проекты, где данные
приходят уже нормализованными, ничего ни с чем не сливается, а внешних форматов
нет. Верхняя ступень там просто не срабатывает, и придумывать ей повод не надо.
Свои места проект перечисляет в `docs/review.md`, подраздел «Триггеры профиля» —
поимённо, узлами или capability. Перечень **производен от теста**: он не расширяет
класс, а называет, где этот класс живёт именно здесь.
Что здесь считается новым понятием, проект может уточнить в `docs/review.md`,
разделе настройки конвейера. Это **уточнение**, а не отмена: не записано —
работает список выше. Проект, где изменение контракта и правда архитектурное
(публичный SDK, чужие потребители), там же поднимает его до `wide` — и это
уточнение, а не возврат прежнего умолчания.
### Профиль — максимум по поверхности, и отсюда размер задачи
@@ -298,18 +226,17 @@ charter'а, а модель потом двигает калибровка, и
Профиль отвечает «какие проходы», порядок — «что кого ждёт». Стадии остаются
единицей **состава** (профиль набирается стадиями, см. таблицу выше), но порядок
задают **не их номера**: между стадиями 14 настоящих зависимостей нет — ни один
задают **не их номера**: между стадиями 13 настоящих зависимостей нет — ни один
проход не читает вывод другого, — и очередь между ними была бы платой ни за что.
Рёбер три вида, и они разной природы. Путать их нельзя: первое про
Рёбер два вида, и они разной природы. Путать их нельзя: первое про
**осмысленность** (на красном гейте опиниативный проход не о чем), второе про
**железо**, третье про **деньги**.
**железо**.
| Ребро | Смысл | Между кем |
|---|---|---|
| **зависимость** | B не стартует, пока A не закончил, потому что без A задание B не определено | гейт → все опиниативные; все проходы → триаж |
| **конфликт за ресурс** | A и B не держат машину одновременно; кто из них первый — неважно, направления у ребра нет | проходы, помеченные «держит машину» |
| **барьер стоимости** | дорогое не запускается, пока дешёвое не сказало, что форма изменения выживет | только `deep` |
```mermaid
flowchart TD
@@ -318,24 +245,19 @@ flowchart TD
code["code"]
adversary["adversary<br/>(держит машину)"]
ops["ops<br/>(держит машину)"]
architecture["architecture<br/>(wide, deep)"]
barrier{{"форма изменения выживает?"}}
reimpl["reimpl"]
architecture["architecture<br/>(wide)"]
triage["triage — единственный сток"]
gate -->|зелёный| specs
gate -->|зелёный| code
gate -->|зелёный| adversary
gate -->|зелёный| ops
gate -->|"зелёный, wide и deep"| architecture
gate -->|"зелёный, wide"| architecture
adversary -. один ресурс — машина .- ops
specs --> barrier
code --> barrier
adversary --> barrier
ops --> barrier
barrier -->|"deep"| reimpl
barrier -->|"quick, standard, wide: барьера нет"| triage
reimpl --> triage
specs --> triage
code --> triage
adversary --> triage
ops --> triage
architecture --> triage
```
@@ -370,7 +292,7 @@ flowchart TD
| `adversary` | да | находка есть **построенный путь**: он пишет падающий тест и гоняет его |
| `ops` | да | доказывает числами: время удержания блокировки, пик кучи, темп роста журнала |
| `triage` | да | проверяет оракул `critical`/`major` запуском — но он сток и тоже один |
| `specs`, `code`, `reimpl`, `architecture`, `rubric` | нет | читают и рассуждают; `reimpl` пишет свою реализацию в черновик, но не исполняет её |
| `specs`, `code`, `architecture`, `rubric` | нет | читают и рассуждают, ничего не исполняют |
**Правило про ресурс, а не про имена.** Раньше здесь стояло именованное
исключение «`adversary` и `ops`»; оно рассыпается, как только проход начнёт
@@ -385,39 +307,26 @@ flowchart TD
Проект вправе пометить «держит машину» и другой проход — в `docs/review.md`,
разделе настройки конвейера. Снимать пометку с перечисленных нельзя.
### Барьер стоимости — вместо раннего выхода
### Находка «переделать форму» — прогон повторяется целиком
Барьер существует ровно там, где ранний выход зарабатывал: `reimpl` пишет
реализацию целиком и потому самый дорогой проход конвейера. Если дешёвая часть
нашла, что **форму изменения** надо переделывать, он будет писать её против кода,
которого через час не станет.
**Барьера стоимости в конвейере нет, и раннего выхода тоже.** Барьер существовал
ради независимой реализации — единственного прохода, чей счёт определялся объёмом
вывода, — и ушёл вместе с ней. Граф во всех профилях плоский, от гейта до триажа:
защищать за барьером нечего, `architecture` дёшев по выходу (потолок 3 находки), а
сериализация не бесплатна — она разводит по очереди то, что могло идти разом.
- **прошло без находок «переделать форму»** — барьер открыт, `reimpl` уходит;
- **есть такая находка** — прогон останавливается, находка чинится, конвейер
запускается **заново с нулевой стадии**, а не «доезжает» остатком по старому
коду. Незапущенные проходы идут в границы покрытия строкой «не запускался:
прогон остановлен на <проход> из-за <находка>», поимённо. Триаж на половине
прогона не запускается: его отчёт выглядит полным, потому что агрегирует всё,
что ему подали, — это тот же молчащий пропуск, что и в разделе «Профили»;
- **находка чинится в пределах существующей формы** (`Действие: инлайн`) —
барьер не срабатывает: дешевле дособрать все находки и починить пачкой, чем
гонять конвейер дважды.
Находка «**форму изменения** надо переделывать» ловится триажем, как и любая
другая; дальше правило одно. Находка чинится, и конвейер запускается **заново с
нулевой стадии**, а не «доезжает» остатком по коду, которого через час не станет.
Если прогон всё же остановлен на полпути, незапущенные проходы идут в границы
покрытия строкой «не запускался: прогон остановлен на <проход> из-за <находка>»,
поимённо, а **триаж на половине прогона не запускается**: его отчёт выглядит
полным, потому что агрегирует всё, что ему подали, — это тот же молчащий пропуск,
что и в разделе «Профили».
**`architecture` стоит за барьером только там, где барьер и так есть.** В `deep`
он уходит вместе с `reimpl` — ждать ему всё равно нечего. В `wide` он стартует
сразу после зелёного гейта, в одном ряду со стадиями 1 и 2: своего барьера он не
заслуживает. Потолок в 3 находки делает его дешёвым, а барьер не бесплатен — он
сериализует то, что могло идти разом, и платить сериализацией за один дешёвый
проход не за что. Есть и вторая причина, помельче: барьер спрашивает «выживает ли
форма изменения», а `architecture` — как раз тот, кто на этот вопрос отвечает.
В `quick`, `standard` и `wide` барьера нет — за ним нечего защищать: стадии 3 в
этих профилях не бывает, и граф там плоский от гейта до триажа. Находка «переделать
форму» ловится в них триажем, а прогон после починки повторяется целиком: платить
за это нечем, дорогих проходов в этих профилях нет. В `design` его тоже
нет, и по другой причине: там предметом и является форма, а все три прохода
читают одно предложение — защищать нечего, у графа этого профиля своя форма (см.
его раздел).
Находка, которая чинится в пределах существующей формы (`Действие: инлайн`),
прогон не останавливает: дешевле дособрать все находки и починить пачкой, чем
гонять конвейер дважды.
### Линеаризация — когда графа мало
@@ -478,7 +387,7 @@ flowchart TD
Recall обоих равен длине их источника — это и есть предел applicative-проходов,
ради которого существует стадия 2.
## Стадия 2 — Adversarial и operational (`standard`, `wide`, `deep`)
## Стадия 2 — Adversarial и operational (`standard`, `wide`)
Два прохода:
@@ -495,7 +404,7 @@ Recall обоих равен длине их источника — это и е
строка, что числа прогона сняты под соседней нагрузкой.
**Эта стадия зарабатывает больше всех остальных вместе, и потому стоит уже в
`standard`, а не только в верхних профилях.** Измерено на пяти задачах подряд: враждебный
`standard`, а не только в верхнем профиле.** Измерено на пяти задачах подряд: враждебный
проход дал пять из семи выживших находок дозапуска (включая обе верхние);
эксплуатационный — единственный, кто нашёл, что откат бинаря поверх новой схемы
стартует молча. Оба несут внешний оракул по построению: один обязан путь
@@ -508,38 +417,10 @@ Recall обоих равен длине их источника — это и е
раздел «Сшивать обязаны проходы». Без этих документов стадия вырождается в общие
места.
## Стадия 3 — Independent reimplementation (только `deep`)
## Стадия 3 — Global (`wide`, `design`)
Единственный проход, ради которого существует **барьер стоимости**, и
единственное, что отличает `deep` от `wide`.
- `review-reimpl` — пишет свою реализацию, не открывая существующую, затем
диффит по решениям. **Профиль и есть его условие:** `deep` выбирается ровно
тогда, когда вводится или меняется по существу правило идентичности, слияния
или разбора — по тесту из раздела «Идентичность, слияние, разбор»; проектный
перечень мест, где такие правила живут, — в `docs/review.md`, если записан. Это
самый дорогой проход конвейера (его счёт определяется объёмом вывода — он пишет
реализацию целиком), а вне этого случая независимый взгляд в значительной мере
уже дал профиль `design`: код писался под его находки. Условие выбрано по факту:
единственный раз, когда триаж назвал отсутствие `reimpl` дырой покрытия, — это
была задача с новым правилом слияния сущностей.
Такие правила обычно занимают десятки строк, но определяют смысл **всех** данных
проекта. Отсюда особенность верхней ступени, из-за которой её легко выбрать
неверно: самый дорогой проход тратится на самый **маленький** дифф. `deep` не про
размер изменения и не про его опасность — он про класс правила.
Раньше это условие стояло **внутри** профиля, и `deep` означал то семь проходов,
то восемь. Реестр состава, который «проверяется взглядом», проверять было нечем:
у профиля не было одного правильного ответа. Теперь ступеней две — `wide` и
`deep`, — и у каждой состав ровно один.
## Стадия 4 — Global (`wide`, `deep`, `design`)
Агент `review-architecture`. В `deep` стоит **за барьером стоимости** (ждать ему
там всё равно нечего), в `wide` и `design` — в первой волне, сразу после старта
профиля. Машину не держит, с `reimpl` конфликта не имеет: за барьером они уходят
разом.
Агент `review-architecture`. Уходит в первой волне, сразу после зелёного гейта, в
одном ряду со стадиями 1 и 2. Машину не держит, ждать ему нечего.
**Условие этой стадии и есть условие ступени `wide`:** изменение вводит новое
понятие или структурную единицу. Не «изменение крупное» и не «изменение опасное»:
@@ -562,7 +443,7 @@ Recall обоих равен длине их источника — это и е
конфигурируемость, подстраховка поверх подстраховки. Потолок — 3 находки плюс
секция «дешевле переделать до мерджа».
## Стадия 5 — Triage (обязательна)
## Стадия 4 — Triage (обязательна)
Агент `review-triage`. **Единственный сток графа и единственный, кто агрегирует.**
Входящие рёбра — все запущенные проходы: пока хоть один не вернул отчёт, триаж не
@@ -570,8 +451,8 @@ Recall обоих равен длине их источника — это и е
**список запущенных проходов**; возвращает финальный отчёт.
Отсюда же правило, которое иначе выглядит придиркой: **триаж на неполном графе не
запускается**. Прогон, остановленный барьером или ранним выходом, до стока не
доезжает — его отчёт агрегировал бы половину и выглядел бы полным.
запускается**. Прогон, остановленный на полпути находкой «переделать форму», до
стока не доезжает — его отчёт агрегировал бы половину и выглядел бы полным.
Без триажа проходы дают порядка сорока замечаний при единицах существенных.
Потребитель здесь — оркестратор, который **молча реализует** всё, что прочитал:
@@ -608,7 +489,7 @@ Recall обоих равен длине их источника — это и е
мелкой нарезке это самая большая статья конвейера. Рубрика же на узел, который не
вводит нового понятия, порождает свойства уже существующего рода — те, что и так
записаны конвенциями и спеками; а `architecture` без нового понятия отвечает «нет»
на свой главный вопрос ещё до запуска (см. «Стадия 4»).
на свой главный вопрос ещё до запуска (см. «Стадия 3»).
**Граф этого профиля свой, и он плоский.** Гейта нет — кода ещё нет, запускать
нечего; машину не держит ни один проход; сток — не триаж, а шаг 5 пайплайна
@@ -712,6 +593,20 @@ flowchart TD
никто. Класс обратимый — портит форму кода, не данные, — и его надо признавать в
границах покрытия, а не считать проверенным.
Так же честно и про второй упразднённый проход: **«не знаю, чего не знаю» больше
не достаёт никто.** Проход независимой реализации писал свою версию узла, не
открывая существующую, и диффил по решениям — декомпозиция, владение данными,
модель конкурентности, форма решения там, где спека выбора не сделала. Он снят по
решению оператора о **стоимости** — счёт определялся объёмом вывода, и на прогон
он тратил больше всех остальных проходов вместе, — а не по замеру, который
[calibration.md](references/calibration.md) требует перед удалением. Значит и
записывается это как сознательное сужение, а не как «класс оказался пустым»:
остаток независимого взгляда даёт профиль `design` (код пишется под его находки) и
`architecture` (второй способ, лишние слои), но **альтернативной реализации, с
которой можно сдиффить решения, у конвейера теперь нет**. Класс идёт строкой в
границы покрытия каждого прогона — там же, где проект перечисляет своё в
подразделе «перестали проверять сознательно».
Это и есть причина, по которой конвейер готовит ревью, а не заменяет его.
## Ссылки
@@ -83,7 +83,6 @@ stateDiagram-v2
| `review-specs` | поведение вне спеки | добавить незаказанный фолбэк-дефолт на пустом входе |
| `review-code` | нарушение прозаической конвенции | увести штатный отказ мимо единой точки трансляции ошибки |
| `review-rubric` | нарушенное свойство узла | у клиента внешнего сервиса убрать таймаут и протяжку `context` |
| `review-reimpl` | форма решения | размазать решение по трём слоям там, где хватало одной функции |
| `review-architecture` | второй способ | завести вторую точку генерации id мимо единой |
| `review-adversary` | построенный путь | принять внешний идентификатор без разбора до запроса в хранилище |
| `review-ops` | деградация окружения | убрать обработку недоступности внешней зависимости в фоновом цикле |
@@ -38,8 +38,8 @@
- **`critical` по основанию «нарушен инвариант проекта» требует инвариантов.**
Ссылка идёт на пункт раздела инвариантов `CLAUDE.md` дословно. Без них основание
недоступно — см. [project-facts.md](project-facts.md), поразрядная деградация.
- **Расхождение — не дефект, пока не названо последствие.** Особенно для прохода
независимой реализации: «я бы сделал иначе» без последствия не выводится.
- **Расхождение — не дефект, пока не названо последствие.** Особенно для
архитектурного прохода: «я бы сделал иначе» без последствия не выводится.
## Шкала severity
@@ -42,7 +42,7 @@
«запись лежит сжатой и распаковывается целиком»; «блокировка удерживалась
5.019 с» — гарантированный отказ соседа только рядом с известным таймаутом
занятости. Числа в `docs/research/`, настройки в `docs/database.md`, и оба
читает `ops`, `adversary`, `reimpl`.
читает `ops` и `adversary`.
- **инвариант + обратимость.** severity берётся из `CLAUDE.md`; если её там
нет — она **выводится по обратимости последствия** и помечается «выведена по
обратимости», а не выдаётся за решение проекта.
@@ -63,7 +63,7 @@
| --- | --- |
| `CLAUDE.md` без инвариантов | `critical` по основанию «нарушен инвариант проекта» не присваивается никем |
| `docs/security.md` | `adversary` не знает периметра — формулирует условиями, `critical` не ставит |
| `docs/research/` | числа неизвестны `specs`, `ops`, `adversary`, `reimpl` — формулируют условиями, а `specs` теряет проверку «требование против наблюдения» |
| `docs/research/` | числа неизвестны `specs`, `ops`, `adversary` — формулируют условиями, а `specs` теряет проверку «требование против наблюдения» |
| `docs/database.md` | замер не с чем сравнить: находка не поднимается выше гипотезы |
| `docs/passport.md` | `architecture` теряет границу домена и вырождается в общее мнение |
| `docs/review.md` | `triage` отсеивает вслепую: типовых ложноположительных нет |
+3 -3
View File
@@ -115,7 +115,7 @@ description: Проводит несколько задач разом — пл
где уже мерили или уже ломалось.
Ни один триггер не сработал — задача не замеряющая, даже если её ревью
окажется `deep`. Профиль про глубину проверки, замеряющая — про соревнование за
окажется `wide`. Профиль про глубину проверки, замеряющая — про соревнование за
железо; это разные вопросы, и совпадают они не всегда;
- **нумерованные артефакты — номера раздаёт оркестратор заранее.** Если проект
нумерует миграции (путь — `docs/.pm.json`, ключ `migrations`), посмотри последний
@@ -241,8 +241,8 @@ flowchart TD
а не сабагент: батч идёт по одной задаче → режим умолчательный, **`по
графу`** (машина свободна); батч идёт волнами → **`линейно`**, твой worktree
не один на машине, и этой причиной ты обязан объяснить режим в отчёте.
Внутренние рёбра графа — цепочку проходов, держащих машину, и барьер
стоимости — конвейер соблюдает сам, в любом режиме;
Внутренние рёбра графа — цепочку проходов, держащих машину — конвейер
соблюдает сам, в любом режиме;
- **если вложенные сабагенты недоступны** (движок не даёт запускать агентов из
агента) — не пропускай ревью и не понижай профиль: проведи его **инлайн** по
тем же charter'ам `av-dev-pipeline`, сохранив обязательное — гейт до
@@ -270,8 +270,7 @@ flowchart TD
**Режим по умолчанию — `по графу`, и обосновывать его не надо.** Конвейер сам
знает свои рёбра: гейт открывает опиниативные проходы, проходы с пометкой «держит
машину» идут цепочкой (иначе замеры портят друг друга и находка выглядит
доказанной), дорогие generative-проходы ждут барьера стоимости, триаж — сток.
Твоего участия это не требует.
доказанной), триаж — сток. Твоего участия это не требует.
Просить **`линейно`** нужно только по причине, и она называется строкой: так
сказал оператор; машина занята чем-то ещё (в том числе соседней задачей батча);
+2 -2
View File
@@ -2,8 +2,8 @@
name: doc-code-drift
description: "Сверка документов канона с кодом по закрытому перечню проверяемых фактов: имя основной ветки и команды из CLAUDE.md, запреты с путями, testdata и временный каталог, путь миграций из .pm.json, внешние зависимости поимённо в architecture.md против манифеста, настройки с числовым значением в database.md против конфига и кода, единые точки проекта против реального числа реализаций, capability против существующих модулей. Отвечает на «этот факт ещё верен», а не «эта архитектура правильная». Читает весь репозиторий, гоняет только читающие команды. Отдаёт готовые формулировки и ничего не правит сам. Согласованность документов между собой смотрит агент doc-consistency. Использовать на сессии между спринтами, а также после приведения проекта к канону (adopt) и после повышения версии канона (upgrade). Только чтение."
tools: Read, Grep, Glob, Bash
model: fable
color: red
model: opus
color: yellow
---
Ты — **сверка документов канона с кодом**. Один вопрос: **этот факт ещё верен?**
+8 -9
View File
@@ -106,12 +106,12 @@ kebab-case.** Причина не эстетическая: имя файла с
| Документ | Вопрос | Кто читает, кроме человека |
| --- | --- | --- |
| `CLAUDE.md` | что нельзя нарушать, чем краснеет гейт | все агенты, всегда |
| `passport.md` | зачем и для кого, чем это **не** является | `architecture`, `rubric`, `reimpl`, `specs` |
| `passport.md` | зачем и для кого, чем это **не** является | `architecture`, `rubric`, `specs` |
| `architecture.md` | как сложено и где что работает | все проходы ревью |
| `database.md` | что лежит в хранилище и какими настройками | `ops`, `adversary`, `reimpl` |
| `database.md` | что лежит в хранилище и какими настройками | `ops`, `adversary` |
| `security.md` | против кого защищаемся и что вне модели | `adversary` |
| `conventions/` | как мы пишем код | `code` |
| `research/` | что показала реальность, а не документация | `specs`, `reimpl`, `ops`, `adversary` |
| `research/` | что показала реальность, а не документация | `specs`, `ops`, `adversary` |
| `adr/` | почему решено именно так | `architecture` |
| `review.md` | как настроен конвейер и что уже проскакивало | `triage`, каждый проход — свою часть |
| `openspec/specs/` | что система делает — нормативно | `specs` |
@@ -232,12 +232,11 @@ kebab-case.** Причина не эстетическая: имя файла с
- **Вопросы к проходам** — поимённо, в форме `<имя прохода>: <вопрос>
(<провенанс>)`;
- **Триггеры профиля** — проектная конкретизация правила выбора профиля ревью:
что в этом проекте считается **новым понятием или структурной единицей** (это
поднимает прогон до `wide`) и **где живут правила идентичности, слияния и
разбора** (до `deep`) — перечнем мест, производным от теста конвейера, а не
вторым определением класса. Уточняет умолчания, а не отменяет их. Рабочее
умолчание `standard`: миграция схемы и публичный контракт ступень **не**
поднимают, их проверяют проходы, которые в `standard` и так есть;
что в этом проекте считается **новым понятием или структурной единицей** это
поднимает прогон до `wide`, верхней ступени. Перечнем мест, а не вторым
определением класса. Уточняет умолчания, а не отменяет их. Рабочее умолчание —
`standard`: миграция схемы и публичный контракт ступень **не** поднимают, их
проверяют проходы, которые в `standard` и так есть;
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
(принципиальная граница, по факту промаха не пересматривается) и «перестали
проверять сознательно» (пересматривается первым).
+14 -7
View File
@@ -127,13 +127,20 @@ upgrade` идёт по записям снизу вверх от версии п
человека. **Переименование ADR это перенос ссылок**: слаг стоит в
`adr/README.md`, в `architecture.md` и в чужих документах, и делается одним
проходом, иначе останутся битые ссылки (их `docs.py` потом и покажет).
8. `docs/.pm.json`: `"canon": 4`.
9. Позвать **обоих судей**`doc-consistency` и `doc-code-drift`, шагом 6
`upgrade`. Пунктов выше девять, половина из них ручная, и именно здесь видно,
какие сделаны только наполовину: переименования секций и полей разводят
документы, а `check` сверяет число версии, а не существо. Первый прогон на
живом проекте вдобавок самый урожайный — правило единственного дома до сих пор
никто не проверял. Разбирать порциями, а не одним заходом.
8. `docs/review.md`, подраздел «Триггеры профиля»: снести перечень мест для
`deep` — профиль упразднён вместе с проходом независимой реализации, и
перечень стал указателем в пустоту. Перечень для `wide` (новое понятие или
структурная единица) остаётся: он и поднимает прогон до верхней ступени. Там
же проверить журнал дефектов и «Недоступно проверке» на упоминания
независимой реализации: класс «форма решения, где спека выбора не сделала»
переезжает в подраздел «перестали проверять сознательно».
9. `docs/.pm.json`: `"canon": 4`.
10. Позвать **обоих судей**`doc-consistency` и `doc-code-drift`, шагом 6
`upgrade`. Пунктов выше десять, половина из них ручная, и именно здесь видно,
какие сделаны только наполовину: переименования секций и полей разводят
документы, а `check` сверяет число версии, а не существо. Первый прогон на
живом проекте вдобавок самый урожайный — правило единственного дома до сих пор
никто не проверял. Разбирать порциями, а не одним заходом.
## Версия 3 — 2026-08-04
+2 -10
View File
@@ -284,19 +284,11 @@
### Триггеры профиля
Проектная конкретизация правила выбора профиля: что здесь считается **новым
понятием или структурной единицей** (поднимает прогон до `wide` и запускает
архитектурный проход) и **где живут правила идентичности, слияния и разбора**
(до `deep`, запускает независимую реализацию) — перечнем узлов или capability,
понятием или структурной единицей** — это поднимает прогон до `wide`, верхней
ступени, и запускает архитектурный проход. Перечнем узлов или capability,
поимённо. Уточняет умолчания конвейера, не отменяет их; рабочее умолчание —
`standard`.
Перечень для `deep` **производен от теста конвейера**, а не заменяет его:
правило попадает в класс, когда вариантов несколько, спека между ними не
выбирает, а неверный выбор не падает, а молча меняет смысл данных. Перечисляй
места, где этот класс здесь живёт, а не переписывай определение. Таких мест нет
вовсе — так и напиши: `deep` тогда не запускается никогда, и это законное
состояние.
### Недоступно проверке
**Не проверит ни один проход** — принципиальная граница; по факту промаха не
+1 -1
View File
@@ -44,7 +44,7 @@ OK, DRIFT, USAGE, ENV, INTERNAL = 0, 1, 2, 3, 4
# Дом раскладки — «Модель по проходу» в review-pipeline/SKILL.md; здесь её
# механизация. Порядок цветов — порядок стоимости прогона.
PALETTE = {"sonnet": "green", "opus": "yellow", "fable": "red"}
PALETTE = {"sonnet": "green", "opus": "yellow"}
SKILL_KEYS = {"name", "description"}
AGENT_KEYS = {"name", "description", "tools", "model", "color"}