стоимость ревью: снят проход независимой реализации и самая дорогая модель
Прогоны стали долгими, а счёт в токенах заметным. Разбор шёл не по находкам, а по статьям расхода. Две названы прямо: убрать 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:
@@ -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`. Оставшись, они выглядели бы работающими правилами и
|
||||
тратили бы внимание на каждом прогоне.
|
||||
|
||||
@@ -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-`, имена
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
Ты — архитектурный проход ревью. Агент, видящий только дифф, физически не может
|
||||
|
||||
@@ -147,7 +147,7 @@ color: green
|
||||
- архитектурные границы и второй способ делать то же самое —
|
||||
`review-architecture`;
|
||||
- стиль, дублирование, лишние слои, «я бы написал иначе» — `review-architecture`
|
||||
(лишнее и второй способ) и `review-reimpl` (когда прогон идёт профилем `deep`);
|
||||
(лишнее и второй способ);
|
||||
- соответствие дельта-спекам — `review-specs`.
|
||||
|
||||
Видишь такое — не выводи находкой; максимум упомяни строкой в границах покрытия,
|
||||
|
||||
@@ -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,8 +2,8 @@
|
||||
name: review-triage
|
||||
description: "Обязательный финальный проход конвейера ревью — единственный, кто агрегирует. Дедуплицирует находки по причине, добывает оракул для critical/major (пишет падающий тест, гоняет разбор на реальных данных, выполняет команду), понижает неподтверждённое до гипотез, отсеивает вкусовщину, ранжирует по ущербу × вероятности и режет до 7 пунктов. Помечает каждую находку «инлайн» или «развилка» для оркестратора. Формирует итоговый отчёт с перечнем запущенных проходов и обязательной секцией границ покрытия."
|
||||
tools: Read, Grep, Glob, Bash, Write
|
||||
model: fable
|
||||
color: red
|
||||
model: opus
|
||||
color: yellow
|
||||
---
|
||||
|
||||
Ты — триаж конвейера ревью. Единственный проход, который видит выводы всех
|
||||
|
||||
@@ -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` | 1–3 |
|
||||
|
||||
**`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'а, а модель потом двигает калибровка, и
|
||||
|
||||
Профиль отвечает «какие проходы», порядок — «что кого ждёт». Стадии остаются
|
||||
единицей **состава** (профиль набирается стадиями, см. таблицу выше), но порядок
|
||||
задают **не их номера**: между стадиями 1–4 настоящих зависимостей нет — ни один
|
||||
задают **не их номера**: между стадиями 1–3 настоящих зависимостей нет — ни один
|
||||
проход не читает вывод другого, — и очередь между ними была бы платой ни за что.
|
||||
|
||||
Рёбер три вида, и они разной природы. Путать их нельзя: первое про
|
||||
Рёбер два вида, и они разной природы. Путать их нельзя: первое про
|
||||
**осмысленность** (на красном гейте опиниативный проход не о чем), второе про
|
||||
**железо**, третье про **деньги**.
|
||||
**железо**.
|
||||
|
||||
| Ребро | Смысл | Между кем |
|
||||
|---|---|---|
|
||||
| **зависимость** | 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` отсеивает вслепую: типовых ложноположительных нет |
|
||||
|
||||
@@ -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,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
|
||||
---
|
||||
|
||||
Ты — **сверка документов канона с кодом**. Один вопрос: **этот факт ещё верен?**
|
||||
|
||||
@@ -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` и так есть;
|
||||
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
|
||||
(принципиальная граница, по факту промаха не пересматривается) и «перестали
|
||||
проверять сознательно» (пересматривается первым).
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -284,19 +284,11 @@
|
||||
### Триггеры профиля
|
||||
|
||||
Проектная конкретизация правила выбора профиля: что здесь считается **новым
|
||||
понятием или структурной единицей** (поднимает прогон до `wide` и запускает
|
||||
архитектурный проход) и **где живут правила идентичности, слияния и разбора**
|
||||
(до `deep`, запускает независимую реализацию) — перечнем узлов или capability,
|
||||
понятием или структурной единицей** — это поднимает прогон до `wide`, верхней
|
||||
ступени, и запускает архитектурный проход. Перечнем узлов или capability,
|
||||
поимённо. Уточняет умолчания конвейера, не отменяет их; рабочее умолчание —
|
||||
`standard`.
|
||||
|
||||
Перечень для `deep` **производен от теста конвейера**, а не заменяет его:
|
||||
правило попадает в класс, когда вариантов несколько, спека между ними не
|
||||
выбирает, а неверный выбор не падает, а молча меняет смысл данных. Перечисляй
|
||||
места, где этот класс здесь живёт, а не переписывай определение. Таких мест нет
|
||||
вовсе — так и напиши: `deep` тогда не запускается никогда, и это законное
|
||||
состояние.
|
||||
|
||||
### Недоступно проверке
|
||||
|
||||
**Не проверит ни один проход** — принципиальная граница; по факту промаха не
|
||||
|
||||
@@ -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"}
|
||||
|
||||
Reference in New Issue
Block a user