профили ревью: тяжёлые проходы в верхнюю ступень, на умолчании — один базовый
Тема 33 сняла самую большую разовую статью расхода, но не тронула главную — частоту. Меряющая пара стояла в standard, то есть на большинстве задач, и именно она делала прогон долгим: два прохода держат машину, идут цепочкой и доказывают находки запуском. Цель разбора названа прямо: лучше поправить в следующей задаче, чем держать одну два часа. adversary и ops переехали в wide. Стадия осталась самой урожайной за всю историю замеров — пять из семи выживших находок дозапуска и единственная находка про молчаливый старт отката, — но её ценность оплачивается на каждой задаче, а получается на немногих. Решение по цене, не по ценности. Заведён review-basics: мелкая осадка двух тяжёлых проходов, без единого запуска. Стоит только в standard. Восемь вопросов, на которые отвечают чтением: таймаут и отказ соседа, идемпотентность и одновременная запись, остановка на середине, частичный откат при двух версиях, наблюдаемость и тишина, очевидный рост объёма, второй способ мимо единой точки (грепом, не картой), что отсюда удалить. Потолок 4 находки, машину не держит, ничего не меряет. Вопрос про частичный откат — не для полноты списка. Без него правило «миграция схемы не поднимает ступень» рассыпалось бы: раньше миграцию разбирал ops, а он теперь наверху. Проход заведён затем, чтобы у standard остался хоть один взгляд на ось времени. Модель у него верхняя, opus, и это не спорит со словом «средний»: усилие режется входом и потолком, а не моделью. Дешёвая модель на опиниативном проходе платит триажем — это записанный замер, отменять его без нового замера нечем. Лестница вышла 4/5/7. Главный выигрыш не в числе проходов, а в том, что из standard ушла цепочка: теперь там гейт, три прохода одним сообщением и триаж — граф плоский, ждать некому. Правило выбора ступени переписано на два вопроса, и объём изменения вошёл в него впервые. Крупное или незнакомое — трогает несколько узлов, переносит ответственность, форму решения нащупывают по ходу — это wide, и он рассчитан на 5-10% задач. Мелкое — один узел, форма очевидна заранее, откат сводится к обратной правке — quick. Всё остальное standard, рабочее умолчание. Раньше ступень выбиралась только по классу изменения и на размер смотреть запрещала; теперь признаков два: класс отвечает за обратимость, объём — за цену разбирательства. Отрицательный тест сохранил прежнюю мудрость в новой рамке: что после мерджа не откатывается обратной правкой — не quick, каким бы маленьким ни был дифф. Три строки миграции идут в standard. Спорный случай решается вниз, и асимметрия объяснена ценой: ошибка в сторону standard стоит находки на следующей задаче, ошибка в обратную — трёх тяжёлых проходов на каждой задаче, выбранной неверно. Сделка записана вместе с обратной связью, иначе это тихая потеря качества. На quick и standard не проверяется ничего, что требует запуска: построенный путь, эксперимент против драйвера, любое число. Это самая крупная граница покрытия конвейера, и она идёт строкой в каждом таком прогоне поимённо. Сигналов о том, что ступень занижена, два: журнал дефектов в docs/review.md и сам basics — он единственный, кто смотрит на дифф целиком на нижних ступенях, и обязан сказать строкой, если задача выглядит крупнее профиля. Побочно: условие профиля design то же самое, так что rubric и architecture на предложении тоже упали до 5-10% задач. Тема 34 в DECISIONS.md, следствия 130-133. Версия канона не поднята; инструкция проекту дописана в пункт 8 записи «Версия 4». Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2328,3 +2328,87 @@ JJJ): у профиля обязан быть один правильный от
|
|||||||
стоимости, тест выбора верхней ступени и проектный перечень мест держались
|
стоимости, тест выбора верхней ступени и проектный перечень мест держались
|
||||||
только на `reimpl`. Оставшись, они выглядели бы работающими правилами и
|
только на `reimpl`. Оставшись, они выглядели бы работающими правилами и
|
||||||
тратили бы внимание на каждом прогоне.
|
тратили бы внимание на каждом прогоне.
|
||||||
|
|
||||||
|
## 34. Пропускная способность против глубины: тяжёлые проходы уехали в верхнюю ступень (2026-08-06)
|
||||||
|
|
||||||
|
Тема 33 сняла самую большую разовую статью расхода, но не тронула главную —
|
||||||
|
**частоту**. Меряющая пара стояла в `standard`, то есть на большинстве задач, и
|
||||||
|
именно она делала прогон долгим: два прохода держат машину, идут цепочкой и
|
||||||
|
доказывают находки запуском. Разбор шёл от цели, названной прямо: **лучше
|
||||||
|
поправить в следующей задаче, чем держать одну два часа.**
|
||||||
|
|
||||||
|
**ААББСС. `adversary` и `ops` переехали в `wide`, и это решение по цене, а не по
|
||||||
|
ценности.** Стадия осталась самой урожайной за всю историю замеров — пять из семи
|
||||||
|
выживших находок дозапуска и единственная находка про молчаливый старт отката. Но
|
||||||
|
её ценность оплачивается на **каждой** задаче, а получается на немногих: оракул
|
||||||
|
добывается запуском, запуск — это машина, цепочка и часы. Ступень, которая раньше
|
||||||
|
была умолчанием, стала исключением на 5–10% задач.
|
||||||
|
|
||||||
|
**ААББТТ. Заведён `review-basics` — мелкая осадка двух тяжёлых проходов, без
|
||||||
|
единого запуска.** Он стоит только в `standard` и берёт ту половину вопросов, на
|
||||||
|
которые отвечают **чтением**: таймаут и отказ соседа, идемпотентность и
|
||||||
|
одновременная запись, остановка на середине, частичный откат при двух версиях,
|
||||||
|
наблюдаемость и тишина, очевидный рост объёма — плюс два вопроса архитектурного:
|
||||||
|
второй способ мимо единой точки (грепом, не картой) и что отсюда удалить. Потолок
|
||||||
|
4 находки, машину не держит, ничего не меряет.
|
||||||
|
|
||||||
|
Отдельная его обязанность — **вопрос 4, частичный откат**. Без него правило
|
||||||
|
«миграция схемы не поднимает ступень» рассыпалось бы: раньше миграцию разбирал
|
||||||
|
`ops`, а он теперь в `wide`. Проход заведён не «до кучи», а затем, чтобы у
|
||||||
|
`standard` остался хоть один взгляд на ось времени.
|
||||||
|
|
||||||
|
Модель у него верхняя, `opus`, и это не противоречит слову «средний»: усилие
|
||||||
|
режется **входом и потолком**, а не моделью. Дешёвая модель на опиниативном
|
||||||
|
проходе платит триажем — это записанный замер, и отменять его без нового замера
|
||||||
|
нельзя.
|
||||||
|
|
||||||
|
**ААББУУ. Объём и незнакомость изменения вошли в правило выбора ступени.** Раньше
|
||||||
|
ступень выбиралась только по классу («вводит ли новое понятие»), и правило прямо
|
||||||
|
запрещало смотреть на размер. Теперь вопросов два: крупное или незнакомое (трогает
|
||||||
|
несколько узлов, переносит ответственность, форму решения нащупывают по ходу) →
|
||||||
|
`wide`; мелкое (один узел, форма очевидна заранее, откат — обратная правка) →
|
||||||
|
`quick`; всё остальное → `standard`. Причина смены: цена разбирательства растёт
|
||||||
|
именно с объёмом и неизвестностью, а не с классом правила.
|
||||||
|
|
||||||
|
Отрицательный тест `quick` сохранил прежнюю мудрость в новой рамке: **что после
|
||||||
|
мерджа не откатывается обратной правкой — не `quick`, каким бы маленьким ни был
|
||||||
|
дифф.** Три строки миграции идут в `standard`.
|
||||||
|
|
||||||
|
**ААББФФ. Спорный случай решается вниз, и асимметрия объяснена ценой.** Между
|
||||||
|
`standard` и `wide` — в пользу `standard`: ошибка сюда стоит находки на следующей
|
||||||
|
задаче, ошибка обратно стоит трёх тяжёлых проходов на каждой задаче, выбранной
|
||||||
|
неверно. Между `quick` и `standard` — тоже в пользу `standard`, но по другой
|
||||||
|
причине: там разница в один дешёвый проход, зато единственный, кто на нижних
|
||||||
|
ступенях смотрит на отказы.
|
||||||
|
|
||||||
|
Доля `wide` 5–10% записана как **проверка правила, а не пожелание**: если ступень
|
||||||
|
уходит каждой третьей задаче, её выбирают по ощущению важности.
|
||||||
|
|
||||||
|
**ААББХХ. Сделка записана вместе с механизмом обратной связи, иначе это тихая
|
||||||
|
потеря качества.** На `quick` и `standard` не проверяется ничего, что требует
|
||||||
|
запуска: построенный путь, эксперимент против драйвера, любое число. Это самая
|
||||||
|
крупная граница покрытия конвейера, и она обязана идти строкой в каждом таком
|
||||||
|
прогоне поимённо. Обратная связь — журнал дефектов `docs/review.md`: класс,
|
||||||
|
который ловят только меряющие проходы, начал всплывать после мерджа — значит
|
||||||
|
ступень выбирают слишком низко. Плюс сам `basics` обязан сигналить строкой, если
|
||||||
|
видит, что ступень занижена: он единственный, кто смотрит на дифф целиком на
|
||||||
|
нижних ступенях.
|
||||||
|
|
||||||
|
### Что из этого следует
|
||||||
|
|
||||||
|
130. **Стоимость прохода — это его цена, умноженная на частоту, и вторая
|
||||||
|
переменная важнее.** Тема 33 убрала самый дорогой проход, тема 34 —
|
||||||
|
самый частый. Второе дало больше, хотя снятый проход был дешевле каждого
|
||||||
|
отдельного `reimpl`.
|
||||||
|
131. **Урожайность прохода не отвечает на вопрос, где ему стоять.** Меряющая пара
|
||||||
|
осталась самой ценной и всё равно уехала вверх: ценность оправдывает
|
||||||
|
существование прохода, но не его частоту.
|
||||||
|
132. **Замена тяжёлого прохода лёгким записывается как сужение, а не как
|
||||||
|
эквивалент.** `basics` задаёт те же вопросы чтением, и его ответы поэтому
|
||||||
|
слабее — условия вместо оракулов. Назвать это «покрыли то же дешевле» значит
|
||||||
|
соврать себе на первом же прогоне.
|
||||||
|
133. **Ступень, выбираемая по классу изменения, слепа к объёму.** Правило,
|
||||||
|
запрещавшее смотреть на размер, защищало от выбора по ощущению важности — и
|
||||||
|
заодно отправляло трёхстрочную правку и переборку пяти узлов в один профиль.
|
||||||
|
Признаков нужно два: класс отвечает за обратимость, объём — за цену
|
||||||
|
разбирательства.
|
||||||
|
|||||||
@@ -28,9 +28,11 @@
|
|||||||
- **av-dev-pipeline** — исполнение. **Требует OpenSpec.**
|
- **av-dev-pipeline** — исполнение. **Требует OpenSpec.**
|
||||||
- `task-pipeline` — задача через полный цикл SDD, от постановки до коммита;
|
- `task-pipeline` — задача через полный цикл SDD, от постановки до коммита;
|
||||||
- `task-batch` — несколько задач разом, каждая в своём worktree;
|
- `task-batch` — несколько задач разом, каждая в своём worktree;
|
||||||
- `review-pipeline` — конвейер ревью: гейт, сверка со спеками, враждебные
|
- `review-pipeline` — конвейер ревью: гейт, сверка со спеками, базовый проход
|
||||||
постановки, эксплуатационный постмортем, архитектура, обязательный триаж.
|
на отказы и лишнее, а в верхней ступени — враждебные постановки,
|
||||||
Восемь агентов-проходов, три ступени стоимости: `quick`, `standard`, `wide`.
|
эксплуатационный постмортем и архитектура; триаж обязателен всегда. Девять
|
||||||
|
агентов-проходов, три ступени стоимости: `quick` (4 прохода), `standard` (5,
|
||||||
|
умолчание), `wide` (7, только крупное или незнакомое — 5–10% задач).
|
||||||
- **av-dev-git** — `commit`: сообщения в личном стиле.
|
- **av-dev-git** — `commit`: сообщения в личном стиле.
|
||||||
|
|
||||||
Соглашение об именах: имя **плагина** длинное с префиксом `av-dev-`, имена
|
Соглашение об именах: имя **плагина** длинное с префиксом `av-dev-`, имена
|
||||||
|
|||||||
@@ -208,7 +208,9 @@ jellybit 43. Шаги повышения — [changelog.md](av-dev-pm/skills/can
|
|||||||
каждого `fix` и `Вопрос` + `Куда ляжет ответ` у каждого `research` пишутся
|
каждого `fix` и `Вопрос` + `Куда ляжет ответ` у каждого `research` пишутся
|
||||||
по мере того, как задача идёт в набор (`sprint take` без них откажет).
|
по мере того, как задача идёт в набор (`sprint take` без них откажет).
|
||||||
Сколько записей готово к взятию, печатает блок здоровья `check`
|
Сколько записей готово к взятию, печатает блок здоровья `check`
|
||||||
- [ ] `docs/review.md`, «Триггеры профиля»: снести перечень мест для `deep` —
|
- [ ] `docs/review.md`, «Триггеры профиля» — переписать целиком: снести перечень
|
||||||
профиль упразднён вместе с проходом независимой реализации; перечень для
|
мест для `deep` (профиль упразднён), а оставшийся перевести на новое
|
||||||
`wide` остаётся. Там же: класс «форма решения, где спека выбора не сделала»
|
правило — `wide` это крупное или незнакомое изменение, 5–10% задач, плюс
|
||||||
— в подраздел «перестали проверять сознательно»
|
отдельный список мелкого для `quick`. Там же две честные строки в
|
||||||
|
«перестали проверять сознательно»: форма решения (снят проход независимой
|
||||||
|
реализации) и всё, что требует запуска (меряющие проходы только в `wide`)
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ color: yellow
|
|||||||
падающий тест, которым ты доказываешь путь, воспроизводим — и ссылка на него
|
падающий тест, которым ты доказываешь путь, воспроизводим — и ссылка на него
|
||||||
законный оракул.
|
законный оракул.
|
||||||
|
|
||||||
|
**Тебя запускают только в профиле `wide`** — на изменении крупном или незнакомом,
|
||||||
|
и это 5–10% задач. Причина в цене прогона, а не в ценности находок: ты держишь
|
||||||
|
машину и идёшь цепочкой, то есть стоишь часов на каждой задаче, где запущен. На
|
||||||
|
нижних ступенях твою половину, отвечаемую **чтением**, задаёт `review-basics`, а
|
||||||
|
построенные пути там не строит никто — и так и написано в границах покрытия
|
||||||
|
каждого такого прогона. Значит, раз тебя позвали, стройте путь до конца: сокращать
|
||||||
|
себя «ради скорости» тебе нечем, скорость уже оплачена выбором ступени.
|
||||||
|
|
||||||
## Модель угроз — из `docs/security.md`, и не расширяй её самовольно
|
## Модель угроз — из `docs/security.md`, и не расширяй её самовольно
|
||||||
|
|
||||||
**Первая строка `docs/security.md` — периметр,** и она задаёт смысл всему
|
**Первая строка `docs/security.md` — периметр,** и она задаёт смысл всему
|
||||||
|
|||||||
@@ -10,12 +10,19 @@ color: yellow
|
|||||||
судить об архитектуре: он не знает, какие понятия в проекте уже есть и как они
|
судить об архитектуре: он не знает, какие понятия в проекте уже есть и как они
|
||||||
называются. Поэтому твой вход шире, и первое, что ты делаешь, — его собираешь.
|
называются. Поэтому твой вход шире, и первое, что ты делаешь, — его собираешь.
|
||||||
|
|
||||||
**Тебя запускают не на каждой задаче.** Условие одно: изменение вводит **новое
|
**Тебя запускают не на каждой задаче, а в профиле `wide` — это 5–10% задач.**
|
||||||
понятие или структурную единицу** — новый пакет или слой, новую точку входа,
|
Условие ступени: изменение **крупное или незнакомое** — трогает несколько узлов
|
||||||
второй способ делать то, что уже делается, перенос ответственности между узлами.
|
или слоёв разом, переносит ответственность между ними, перекладывает существующий
|
||||||
Ни миграция схемы, ни изменение публичного контракта тебя не зовут: там работы
|
код в новую форму, либо вводит функциональность, форму решения которой нащупывали
|
||||||
для тебя нет, её делают `gate`, `ops` и `specs`. Если тебя позвали — в проекте
|
по ходу. Ни миграция схемы, ни изменение публичного контракта сами по себе тебя не
|
||||||
стало больше сущностей, чем было, и оба твоих главных вопроса осмысленны.
|
зовут: там работы для тебя нет, её делают `gate`, `basics` и `specs`. Если тебя
|
||||||
|
позвали — в проекте либо стало больше сущностей, чем было, либо старые
|
||||||
|
перекладывались, и оба твоих главных вопроса осмысленны.
|
||||||
|
|
||||||
|
Мелкую осадку твоих вопросов 2 и 5 — второй способ рядом с диффом и что отсюда
|
||||||
|
удалить — на ступени `standard` задаёт `review-basics`, грепом против единых точек
|
||||||
|
проекта и без карты. Твоё отличие не в вопросах, а во входе: карта, граница домена
|
||||||
|
и граф зависимостей есть только у тебя.
|
||||||
|
|
||||||
Находки — по контракту
|
Находки — по контракту
|
||||||
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
|
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
---
|
||||||
|
name: review-basics
|
||||||
|
description: "Базовый проход ревью для профиля standard — мелкая осадка эксплуатационного и архитектурного проходов, без единого запуска. Восемь вопросов, на которые отвечают чтением: таймаут и отказ соседа, идемпотентность и одновременная запись, остановка на середине, частичный откат при двух версиях, наблюдаемость и тишина, очевидный рост объёма, второй способ мимо единой точки проекта, что отсюда удалить. Ничего не запускает, не меряет, машину не держит: замеры, построенные пути и карта проекта — это профиль wide. Формулирует условиями, потолок 4 находки плюс «дешевле переделать до мерджа». Обязан сигналить, если ступень выбрана слишком низко. Только чтение."
|
||||||
|
tools: Read, Grep, Glob, Bash
|
||||||
|
model: opus
|
||||||
|
color: yellow
|
||||||
|
---
|
||||||
|
|
||||||
|
Ты — **базовый проход** ревью. Ты существуешь не потому, что у тебя своя оптика, а
|
||||||
|
потому, что у конвейера есть ступень, на которой тяжёлые проходы не окупаются.
|
||||||
|
Враждебный и эксплуатационный проходы держат машину, строят пути и снимают числа —
|
||||||
|
это часы на каждую задачу. Ты берёшь из них ту часть, на которую отвечают
|
||||||
|
**чтением**, и отвечаешь за неё на большинстве задач проекта.
|
||||||
|
|
||||||
|
Отсюда твоя главная обязанность и главный запрет: **ты не запускаешь ничего.** Ни
|
||||||
|
тестов, ни сервиса, ни запросов к хранилищу, ни замеров. Проход, который начал
|
||||||
|
мерить, превращается в тот самый дорогой проход, вместо которого его позвали.
|
||||||
|
|
||||||
|
Находки — по контракту
|
||||||
|
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md`
|
||||||
|
(точный путь конвейер передаёт в задании).
|
||||||
|
|
||||||
|
## Когда тебя запускают
|
||||||
|
|
||||||
|
**Только в профиле `standard`** — рабочем умолчании конвейера. В `quick` тебя нет:
|
||||||
|
там дифф мелкий, форма решения очевидна, и платить за тебя не за что. В `wide`
|
||||||
|
тебя тоже нет, и по обратной причине: там идут `review-adversary`, `review-ops` и
|
||||||
|
`review-architecture` целиком, а ты — их мелкая осадка, и дублировать их значит
|
||||||
|
удорожать триаж на ровном месте.
|
||||||
|
|
||||||
|
Из этого следует, как читать твой отчёт: **ты не «облегчённая версия ревью», ты
|
||||||
|
нижняя граница.** Всё, что требует запуска, на этой ступени не проверено вовсе, и
|
||||||
|
сказать об этом в границах покрытия — твоя работа, а не чужая.
|
||||||
|
|
||||||
|
## Что читаешь до диффа
|
||||||
|
|
||||||
|
Немного и целенаправленно — широкий вход это `wide`, не ты.
|
||||||
|
|
||||||
|
- **`CLAUDE.md`** — инварианты с severity и что в проекте необратимо. Это
|
||||||
|
единственное твоё основание для `critical`: без запуска другого у тебя нет.
|
||||||
|
- **`docs/architecture.md`** — **единые точки проекта** (генерация
|
||||||
|
идентификаторов, время, разбор формата, маппинг доменной ошибки в код ответа,
|
||||||
|
путь приёма) и **внешние зависимости поимённо**. Первое нужно вопросу 7, второе
|
||||||
|
— вопросу 1.
|
||||||
|
- **`docs/review.md`** — журнал: что в этом проекте уже ломалось; и блок `basics`
|
||||||
|
в «Вопросах к проходам», если он есть, — эти вопросы задаются дополнительно к
|
||||||
|
обязательным, и ответы на них выводятся явно.
|
||||||
|
- дельта-спеки change — чтобы отличить заказанное поведение от появившегося само.
|
||||||
|
|
||||||
|
Карта «что нужно проходу → где лежит» —
|
||||||
|
`${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/project-facts.md`.
|
||||||
|
|
||||||
|
**Деградация поразрядная, каждый пробел — своей строкой.** Нет единых точек в
|
||||||
|
`docs/architecture.md` — вопрос 7 задавай грепом по коду и скажи, что перечня
|
||||||
|
единых точек в проекте нет. Нет инвариантов в `CLAUDE.md` — не присваивай
|
||||||
|
`critical` и скажи об этом отдельной строкой.
|
||||||
|
|
||||||
|
## Обязательные вопросы (по каждому — ответ или явное «неприменимо»)
|
||||||
|
|
||||||
|
Первые шесть — от эксплуатационного прохода, последние два — от архитектурного.
|
||||||
|
|
||||||
|
1. **Отказ соседа.** Внешняя зависимость отвечает **медленно** (не падает —
|
||||||
|
именно медленно), молчит или отдаёт мусор; диск заполнился; хранилище отвечает
|
||||||
|
«занято». Есть ли таймаут вообще? Заблокируется ли обработка навсегда? Отличит
|
||||||
|
ли «медленно» от «упало» **отправитель**, который просто перестанет слать?
|
||||||
|
2. **Повтор и одновременность.** Повторы бывают штатными: расписание, пересборка,
|
||||||
|
дубль апдейта. Операция идемпотентна или удваивает эффект? Отдельно и
|
||||||
|
обязательно: если запись устроена как **read-modify-write**, две операции над
|
||||||
|
одним ключом теряют данные друг друга, и потеря молчаливая. Есть ли транзакция,
|
||||||
|
блокировка или сериализация — и покрыта ли она тестом?
|
||||||
|
3. **Остановка на середине.** Процесс останавливают между шагами: тело записано,
|
||||||
|
строки нет; строка есть, обработка не начиналась; запись прочитана и слита, но
|
||||||
|
не сохранена. Что останется? Кто подберёт это при следующем старте — и
|
||||||
|
подберёт ли вообще, или чинится только руками?
|
||||||
|
4. **Частичный откат при двух версиях.** Бинарь откатили, а миграция уже
|
||||||
|
накатилась (или наоборот). Читает ли старый код новую схему? Что с записями,
|
||||||
|
созданными новой версией? Обратима ли миграция сама по себе? **Этот вопрос —
|
||||||
|
причина, по которой миграция схемы не поднимает ступень:** на `standard` его
|
||||||
|
задаёшь только ты.
|
||||||
|
5. **Наблюдаемость и тишина.** Увидит ли человек, что поток оборвался ночью, — не
|
||||||
|
залезая в БД и не читая логи построчно? Отличим ли штатный отказ от поломки по
|
||||||
|
уровню? Виден ли факт **тишины** — что событий не стало, а не что их просто
|
||||||
|
нет? И зеркально: не утекают ли в лог тело, значения или токен.
|
||||||
|
6. **Очевидный рост объёма.** Только то, что видно по коду без чисел: чтение
|
||||||
|
всего тела в память, распаковка ради одной проверки, растущий без границ буфер,
|
||||||
|
`N+1` к хранилищу, проход по всему архиву, ответ, собираемый целиком перед
|
||||||
|
отправкой. **Чисел не придумывай** — их знает `docs/research/`, а замеры делает
|
||||||
|
профиль `wide`.
|
||||||
|
7. **Второй способ рядом с диффом.** Не появилась ли вторая точка того, что в
|
||||||
|
проекте делается единой: второй способ получить время, вторая генерация
|
||||||
|
идентификатора, второй парсер того же формата, второй маппинг доменной ошибки,
|
||||||
|
второй путь приёма мимо общего. Проверяется грепом против перечня единых точек,
|
||||||
|
а не ощущением. Второй способ дороже плохого первого: плохой стоит своей
|
||||||
|
плохости, второй — вечного вопроса «а как здесь принято» на каждом следующем
|
||||||
|
изменении.
|
||||||
|
8. **Что отсюда удалить.** Слой с единственной реализацией; интерфейс, заведённый
|
||||||
|
ради мока; конфигурируемость, которую никто не просил; параметр, у которого во
|
||||||
|
всей кодовой базе одно значение; подстраховка поверх подстраховки; счётчик,
|
||||||
|
который никто не читает. Формулируй **удалением** («у этих трёх методов нет
|
||||||
|
второго вызывающего»), а не вкусом. Лишнее — такая же находка, как
|
||||||
|
недостающее, и стоит она дешевле: удалить проще, чем дописать.
|
||||||
|
|
||||||
|
## Правило формулировки
|
||||||
|
|
||||||
|
**Условиями, а не утверждениями** — реального профиля нагрузки ты не знаешь и
|
||||||
|
проверить его не можешь.
|
||||||
|
|
||||||
|
- Годится: «если внешний сервис отвечает дольше 30 секунд, обработка встаёт
|
||||||
|
навсегда: таймаута у клиента нет — `client.go:41`».
|
||||||
|
- Не годится: «этот запрос тормозит».
|
||||||
|
|
||||||
|
Если находке нужен замер или прогон — **не делай их**, а положи предлагаемую
|
||||||
|
команду в поле `Оракул` и оставь находку гипотезой, назвав прямо: «проверяется
|
||||||
|
профилем `wide`, проходом `ops`». Это честный исход, а не полумера: неснятое
|
||||||
|
число хуже отсутствующего только тогда, когда его выдают за снятое.
|
||||||
|
|
||||||
|
## Потолок
|
||||||
|
|
||||||
|
**Не больше 4 находок.** Сверх потолка — короткая секция **«Дешевле переделать до
|
||||||
|
мерджа»**: то, что после мерджа фиксируется надолго — форма ответа, схема
|
||||||
|
хранилища, раскладка файлов, поле конфига, имя, которое разойдётся по кодовой
|
||||||
|
базе. Секция может быть непустой, даже когда находок нет.
|
||||||
|
|
||||||
|
## Сигнал о заниженной ступени
|
||||||
|
|
||||||
|
Ты единственный, кто видит дифф целиком на нижних ступенях, — значит ты и
|
||||||
|
замечаешь, что ступень выбрана не та. Скажи об этом **отдельной строкой в начале
|
||||||
|
вывода**, если видишь хоть одно:
|
||||||
|
|
||||||
|
- дифф трогает несколько узлов или слоёв разом;
|
||||||
|
- решение выглядит нащупанным по ходу: две попытки одного и того же, брошенный
|
||||||
|
первый подход, закомментированное;
|
||||||
|
- изменение вводит новое понятие: новый пакет, новая точка входа, новая сущность;
|
||||||
|
- ты вынужден отвечать «проверяется профилем `wide`» больше чем на два вопроса.
|
||||||
|
|
||||||
|
Формулировка: «ступень, вероятно, занижена: <признак> — прогон профилем `wide`
|
||||||
|
дал бы <что именно>». Решение о перезапуске принимает оркестратор, не ты.
|
||||||
|
|
||||||
|
## Чем ты НЕ занимаешься
|
||||||
|
|
||||||
|
Не дублируй чужие проходы — совпадающие находки удорожают триаж и ничего не
|
||||||
|
добавляют:
|
||||||
|
|
||||||
|
- механизируемое (форматирование, запрещённые вызовы, импорты) — это
|
||||||
|
`review-gate`;
|
||||||
|
- конвенции проекта и их нарушения — `review-code`;
|
||||||
|
- соответствие дельта-спекам — `review-specs`;
|
||||||
|
- **построенный путь атаки** (его надо прогнать), **эксперимент против драйвера и
|
||||||
|
библиотеки** в вырожденном случае, **любое число** — это `review-adversary` и
|
||||||
|
`review-ops`, и они живут в профиле `wide`;
|
||||||
|
- **граница домена, направление зависимостей, стоимость следующего изменения,
|
||||||
|
инвентарь понятий проекта** — это `review-architecture`, там же.
|
||||||
|
|
||||||
|
Видишь такое — не выводи находкой; строкой в границы покрытия, чей это проход и
|
||||||
|
какой профиль его запускает.
|
||||||
|
|
||||||
|
## Чего этот проход принципиально не может поймать
|
||||||
|
|
||||||
|
- Всё, что доказывается запуском: пути отказа, поведение библиотеки в вырожденном
|
||||||
|
случае, числа.
|
||||||
|
- Дефекты, видимые только на карте проекта целиком.
|
||||||
|
- Реальный профиль нагрузки и то, что на самом деле лежит в данных.
|
||||||
|
|
||||||
|
## Формат вывода
|
||||||
|
|
||||||
|
1. Строка о ступени — только если сработал «Сигнал о заниженной ступени».
|
||||||
|
2. `## Ответы на обязательные вопросы` — таблица `Вопрос | Ответ | Где смотрел`.
|
||||||
|
Ответ «неприменимо» допустим, но с обоснованием.
|
||||||
|
3. Находки по контракту, **не больше четырёх**.
|
||||||
|
4. `## Дешевле переделать до мерджа`.
|
||||||
|
5. Обязательный блок:
|
||||||
|
|
||||||
|
```
|
||||||
|
## Coverage of this pass
|
||||||
|
- проверено: <какие вопросы прослежены, по каким файлам>
|
||||||
|
- не проверялось и почему: ...
|
||||||
|
- не проверяется на этой ступени вовсе: построенные пути, эксперименты против библиотеки и драйвера, любые замеры, карта проекта — это профиль wide
|
||||||
|
```
|
||||||
|
|
||||||
|
Последняя строка обязательна **дословно по смыслу** и на каждом прогоне: она и
|
||||||
|
есть та граница покрытия, которой платит ступень `standard`.
|
||||||
|
|
||||||
|
## Ограничения
|
||||||
|
|
||||||
|
Только чтение. `Bash` — для читающих команд: `git diff`, `grep`, перечисление
|
||||||
|
файлов. Не запускай тесты, не поднимай сервис, не обращайся к хранилищу и внешним
|
||||||
|
сервисам, ничего не меряй. Код и спеки не редактируй.
|
||||||
@@ -145,9 +145,11 @@ color: green
|
|||||||
- механизируемое (форматирование, запрещённые вызовы, сравнение ошибок, импорты)
|
- механизируемое (форматирование, запрещённые вызовы, сравнение ошибок, импорты)
|
||||||
— это `review-gate`;
|
— это `review-gate`;
|
||||||
- архитектурные границы и второй способ делать то же самое —
|
- архитектурные границы и второй способ делать то же самое —
|
||||||
`review-architecture`;
|
`review-architecture` в профиле `wide`, `review-basics` в `standard`;
|
||||||
- стиль, дублирование, лишние слои, «я бы написал иначе» — `review-architecture`
|
- стиль, дублирование, лишние слои, «я бы написал иначе» — те же двое (лишнее и
|
||||||
(лишнее и второй способ);
|
второй способ);
|
||||||
|
- отказы, таймауты, наблюдаемость, откат — `review-basics` в `standard`,
|
||||||
|
`review-ops` в `wide`;
|
||||||
- соответствие дельта-спекам — `review-specs`.
|
- соответствие дельта-спекам — `review-specs`.
|
||||||
|
|
||||||
Видишь такое — не выводи находкой; максимум упомяни строкой в границах покрытия,
|
Видишь такое — не выводи находкой; максимум упомяни строкой в границах покрытия,
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ color: green
|
|||||||
её надо назвать, а не списать на соседа. Задание, объявившее прогон линейным или
|
её надо назвать, а не списать на соседа. Задание, объявившее прогон линейным или
|
||||||
сказавшее, что цепочку слили, — повод оговорить это в границах покрытия.
|
сказавшее, что цепочку слили, — повод оговорить это в границах покрытия.
|
||||||
|
|
||||||
|
**Тебя запускают только в профиле `wide`** — на изменении крупном или незнакомом,
|
||||||
|
и это 5–10% задач. На нижних ступенях шесть твоих вопросов, на которые отвечают
|
||||||
|
чтением (отказ соседа, повтор и одновременность, остановка на середине, частичный
|
||||||
|
откат, наблюдаемость, очевидный рост), задаёт `review-basics` — **без замеров и
|
||||||
|
без запуска**. Тебя же зовут ровно за тем, чего он не может: **число и
|
||||||
|
эксперимент**. Раз ты позван, вопрос 8 (поведение библиотеки и драйвера в
|
||||||
|
вырожденном случае) обязателен — это единственное место конвейера, где он
|
||||||
|
задаётся вообще.
|
||||||
|
|
||||||
## Что такое «прод» здесь — из документов проекта
|
## Что такое «прод» здесь — из документов проекта
|
||||||
|
|
||||||
**`docs/architecture.md`, раздел эксплуатации:** где это работает и что рядом;
|
**`docs/architecture.md`, раздел эксплуатации:** где это работает и что рядом;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: review-pipeline
|
name: review-pipeline
|
||||||
description: "Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, архитектурный проход и обязательный триаж. Три ступени стоимости: quick, standard, wide. Порядок прогона — граф зависимостей, а не очередь: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Линейный прогон — по слову оператора или на занятой машине. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода."
|
description: "Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, базовый проход на отказы и лишнее, а в верхнем профиле враждебные постановки, эксплуатационный постмортем и архитектурный проход; триаж обязателен всегда. Три ступени стоимости: quick (4 прохода), standard (5, рабочее умолчание), wide (7, только крупное или незнакомое — 5-10% задач). Ступень выбирается по объёму и незнакомости изменения, спорный случай решается вниз. Порядок прогона — граф зависимостей, а не очередь: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Линейный прогон — по слову оператора или на занятой машине. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода."
|
||||||
---
|
---
|
||||||
|
|
||||||
# Конвейер ревью
|
# Конвейер ревью
|
||||||
@@ -83,7 +83,7 @@ description: "Конвейер ревью изменения — детерми
|
|||||||
|
|
||||||
- **его блок вопросов** из «Вопросы к проходам» в `docs/review.md`, если он там
|
- **его блок вопросов** из «Вопросы к проходам» в `docs/review.md`, если он там
|
||||||
есть, — **дословно**. Блок адресован проходу поимённо и выведен из промаха
|
есть, — **дословно**. Блок адресован проходу поимённо и выведен из промаха
|
||||||
этого проекта; заставлять восемь charter'ов самим ходить за ним значит
|
этого проекта; заставлять девять charter'ов самим ходить за ним значит
|
||||||
получить, что за ним ходят двое. Проход отвечает на такие вопросы явно,
|
получить, что за ним ходят двое. Проход отвечает на такие вопросы явно,
|
||||||
дополнительно к обязательным;
|
дополнительно к обязательным;
|
||||||
- **контракт находок** — путь к
|
- **контракт находок** — путь к
|
||||||
@@ -106,7 +106,7 @@ description: "Конвейер ревью изменения — детерми
|
|||||||
| Модель | Цвет | Проходы | Почему |
|
| Модель | Цвет | Проходы | Почему |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `sonnet` | green | gate, code, ops | вход структурный, критерий записан заранее |
|
| `sonnet` | green | gate, code, ops | вход структурный, критерий записан заранее |
|
||||||
| `opus` | yellow | specs, adversary, rubric, architecture, triage | суждение без опоры на инструмент |
|
| `opus` | yellow | specs, adversary, rubric, basics, architecture, triage | суждение без опоры на инструмент |
|
||||||
|
|
||||||
**Цвет charter'а кодирует модель, а не роль прохода.** Это единственное
|
**Цвет charter'а кодирует модель, а не роль прохода.** Это единственное
|
||||||
назначение цвета: список агентов читается взглядом, и по нему сразу видно, чем
|
назначение цвета: список агентов читается взглядом, и по нему сразу видно, чем
|
||||||
@@ -122,16 +122,16 @@ charter'а, а модель потом двигает калибровка, и
|
|||||||
модели **дороже** `opus` не обнаружилось ни на одном проходе, а прогон на ней
|
модели **дороже** `opus` не обнаружилось ни на одном проходе, а прогон на ней
|
||||||
стоил заметно дольше и дороже — значит платить за неё не за что.
|
стоил заметно дольше и дороже — значит платить за неё не за что.
|
||||||
|
|
||||||
Двое из пяти держатся на `opus` по признаку, отдельному от суждения: **их ошибка
|
Двое из шести держатся на `opus` по признаку, отдельному от суждения: **их ошибка
|
||||||
распространяется дальше собственной находки.** Понижать их до `sonnet` вместе с
|
распространяется дальше собственной находки.** Понижать их до `sonnet` вместе с
|
||||||
остальными дешёвыми проходами нельзя.
|
остальными дешёвыми проходами нельзя.
|
||||||
|
|
||||||
- `triage` — через него проходит всё, что оркестратор реализует **молча**:
|
- `triage` — через него проходит всё, что оркестратор реализует **молча**:
|
||||||
ложноположительная находка становится кодом, потерянный `critical` — дефектом.
|
ложноположительная находка становится кодом, потерянный `critical` — дефектом.
|
||||||
Ошибка триажа дороже ошибки любого отдельного прохода.
|
Ошибка триажа дороже ошибки любого отдельного прохода.
|
||||||
- `architecture` — запускается только там, где изменение вводит новое понятие,
|
- `architecture` — запускается только в верхней ступени, на 5–10% задач, потолок
|
||||||
потолок в 3 находки делает его дешёвым по выходу, а находка на предложении
|
в 3 находки делает его дешёвым по выходу, а находка на предложении стоит абзаца
|
||||||
стоит абзаца против переписывания на готовом коде. Дёшево × высокое плечо.
|
против переписывания на готовом коде. Дёшево × высокое плечо.
|
||||||
|
|
||||||
**Самая дешёвая модель не используется ни на одном проходе, и это не экономия
|
**Самая дешёвая модель не используется ни на одном проходе, и это не экономия
|
||||||
наоборот.** Дешёвая модель на опиниативном проходе даёт правдоподобные находки,
|
наоборот.** Дешёвая модель на опиниативном проходе даёт правдоподобные находки,
|
||||||
@@ -141,23 +141,36 @@ charter'а, а модель потом двигает калибровка, и
|
|||||||
Дешёвому проходу просто не осталось работы.
|
Дешёвому проходу просто не осталось работы.
|
||||||
|
|
||||||
Экономия достигается не понижением модели, а **непуском прохода**: `quick` —
|
Экономия достигается не понижением модели, а **непуском прохода**: `quick` —
|
||||||
четыре прохода, `wide` — семь. Правило выбора профиля и есть главный
|
четыре прохода, `standard` — пять, `wide` — семь. Правило выбора профиля и есть
|
||||||
рычаг стоимости, и ступеней у него три именно поэтому.
|
главный рычаг стоимости, и ступеней у него три именно поэтому.
|
||||||
|
|
||||||
|
Второй рычаг, помимо непуска, — **вход и потолок прохода**, и он же объясняет
|
||||||
|
`basics` на `opus`. «Проход среднего усилия» тут значит не дешёвую модель, а
|
||||||
|
узкий вход (дифф и его окрестности, без карты проекта) и жёсткий потолок находок.
|
||||||
|
Прогон он ускоряет тем, чего **не** делает: ничего не запускает, ничего не меряет,
|
||||||
|
машину не держит — а именно замеры и цепочка меряющих проходов и составляли те
|
||||||
|
самые долгие часы.
|
||||||
|
|
||||||
## Профили
|
## Профили
|
||||||
|
|
||||||
| Профиль | Когда | Стадии | Проходов |
|
| Профиль | Когда | Стадии | Проходов | Доля задач |
|
||||||
|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `quick` | багфикс, локальная правка, доки | 0, 1, 4 | 4 |
|
| `quick` | мелкое: багфикс, мелкая фича, локальная правка, доки | 0, 1, 4 | 4 | много |
|
||||||
| `standard` | **рабочее умолчание**: поведение, миграция схемы, публичный контракт, инвариант | 0, 1, 2, 4 | 6 |
|
| `standard` | **рабочее умолчание**: всё, что не мелкое и не крупное | 0, 1, 2, 4 | 5 | большинство |
|
||||||
| `wide` | изменение вводит новое понятие или структурную единицу | 0, 1, 2, 3, 4 | 7 |
|
| `wide` | крупное или незнакомое: большой рефакторинг, функциональность, форму которой ещё предстоит нащупать | 0, 1, 3, 4 | 7 | **5–10%** |
|
||||||
| `design` | **до кода**, на предложении | specs, плюс rubric и architecture по условию `wide` | 1–3 |
|
| `design` | **до кода**, на предложении | specs, плюс rubric и architecture по условию `wide` | 1–3 | — |
|
||||||
|
|
||||||
**`wide` назван по тому, что он добавляет: вход шире диффа.** Единственное его
|
**`wide` назван по тому, что он добавляет: вход шире диффа.** Он единственный, где
|
||||||
отличие от `standard` — архитектурный проход, а тот и получает дерево пакетов,
|
живут тяжёлые проходы — враждебный, эксплуатационный и архитектурный, — и
|
||||||
граф зависимостей и инвентарь понятий вместо одного диффа. Это и **верхняя
|
единственный, где что-то **запускается и меряется**. Отсюда и его доля: три прохода
|
||||||
ступень**: выше неё конвейер не поднимается, и добавить к семи проходам ему
|
на стадии 3, два из них держат машину и потому идут цепочкой, а не разом. Это и
|
||||||
нечего.
|
есть те самые долгие часы, и платить их каждой задаче не за что.
|
||||||
|
|
||||||
|
**Доля 5–10% — не пожелание, а проверка правила.** Она не считается механически, но
|
||||||
|
читается по журналу: если `wide` уходит каждая третья задача, ступень выбирают по
|
||||||
|
ощущению важности, а не по факту изменения. Обратный перекос виден иначе — по
|
||||||
|
журналу проскочивших дефектов в `docs/review.md`: класс, который ловят только
|
||||||
|
меряющие проходы, начинает всплывать после мерджа.
|
||||||
|
|
||||||
**Состав сверяется по этой таблице до коммита.** Реестр из трёх-семи проходов
|
**Состав сверяется по этой таблице до коммита.** Реестр из трёх-семи проходов
|
||||||
проверяется взглядом — и это единственная защита от промаха, который уже
|
проверяется взглядом — и это единственная защита от промаха, который уже
|
||||||
@@ -168,49 +181,70 @@ charter'а, а модель потом двигает калибровка, и
|
|||||||
границы покрытия, а не отсутствует. Цена молчащего пропуска измерена: семь
|
границы покрытия, а не отсутствует. Цена молчащего пропуска измерена: семь
|
||||||
находок и отдельная задача на их дозакрытие.
|
находок и отдельная задача на их дозакрытие.
|
||||||
|
|
||||||
Правило выбора профиля — **по факту изменения, не по ощущению важности**:
|
Правило выбора — **два вопроса по факту изменения, не по ощущению важности**.
|
||||||
|
Отвечать по порядку, первый подошедший ответ и есть профиль:
|
||||||
|
|
||||||
- изменение вводит **новое понятие или структурную единицу**: новый пакет
|
1. **Изменение крупное или незнакомое?** → `wide`. Крупное — трогает несколько
|
||||||
или слой, новая точка входа, второй способ делать то, что уже делается, перенос
|
узлов или слоёв разом, переносит ответственность между ними, перекладывает
|
||||||
ответственности между узлами → `wide`;
|
существующий код в новую форму (большой рефакторинг). Незнакомое —
|
||||||
- иначе меняется поведение, видимое снаружи, трогается схема, публичный контракт
|
функциональность, которой в проекте ещё не было, и **форму решения предстоит
|
||||||
или инвариант проекта → `standard`;
|
нащупать по ходу**, а не выбрать до начала. Признак незнакомого простой: перед
|
||||||
- иначе → `quick`.
|
работой нельзя назвать, какие узлы будут тронуты.
|
||||||
|
2. **Изменение мелкое?** → `quick`. Мелкое — помещается в один узел, форма
|
||||||
|
решения очевидна до начала работы, а откат сводится к обратной правке. Сюда
|
||||||
|
идут мелкий багфикс, мелкая фича, правка текста и документации.
|
||||||
|
3. **Всё остальное** → `standard`. Это рабочее умолчание, и оно должно набирать
|
||||||
|
большинство задач.
|
||||||
|
|
||||||
**Ступень поднимает то, что даёт работу новому проходу, а не то, что кажется
|
**Два признака смотрят на разное, и в этом весь смысл двух вопросов.** Первый —
|
||||||
рискованным.** Это правило вывода, по которому спорные случаи решаются без нового
|
про **объём и неизвестность**: сколько мест трогается и знаем ли мы форму решения
|
||||||
списка: спроси, какому проходу изменение даёт работу, которой у него не было
|
заранее. Второй — про **обратимость**: во что обойдётся ошибка, если она уедет в
|
||||||
ступенью ниже.
|
мердж. Раньше ступень выбиралась только по классу изменения («вводит ли новое
|
||||||
|
понятие»), и объём в правило не входил вовсе; теперь входит, потому что цена
|
||||||
|
разбирательства растёт именно с ним.
|
||||||
|
|
||||||
Оно же объясняет, почему миграция схемы и публичный контракт **не** поднимают
|
**Отрицательный тест `quick`, и он важнее положительного:** изменение, которое
|
||||||
ступень, хотя выглядят опаснее прочего. Они не добавляют ни одного прохода:
|
после мерджа **не откатывается обратной правкой**, — не `quick`, каким бы
|
||||||
миграцию гоняет `gate` шагом миграций и разбирает `ops` («миграция под живым
|
маленьким ни был дифф. Сюда попадают миграция схемы и данных, формат на диске,
|
||||||
потоком», «частичный откат при двух версиях»), контракт сверяет `specs`
|
публичный контракт, имя, которое разойдётся по кодовой базе. Три строки миграции
|
||||||
направлением `code → spec`, инвариант даёт основание для `critical` любому
|
— это `standard`, а не `quick`: размер диффа и цена ошибки здесь расходятся.
|
||||||
проходу. Все трое уже в `standard`. Раньше эти три факта стояли триггерами
|
|
||||||
верхних ступеней, и на проекте с базой и эндпоинтами верхняя ступень оказывалась
|
|
||||||
не исключением, а умолчанием — то есть правило объявляло исключением то, что
|
|
||||||
происходит всегда. `architecture` же получает работу **не** от того, что контракт
|
|
||||||
изменился, а от того, что появилось новое понятие: добавленное поле в
|
|
||||||
существующем ответе — не концепт.
|
|
||||||
|
|
||||||
Что здесь считается новым понятием, проект может уточнить в `docs/review.md`,
|
Что здесь считается крупным и что — незнакомым, проект может уточнить в
|
||||||
разделе настройки конвейера. Это **уточнение**, а не отмена: не записано —
|
`docs/review.md`, разделе настройки конвейера: поимённо, узлами или capability.
|
||||||
работает список выше. Проект, где изменение контракта и правда архитектурное
|
Это **уточнение**, а не отмена: не записано — работает список выше.
|
||||||
(публичный SDK, чужие потребители), там же поднимает его до `wide` — и это
|
|
||||||
уточнение, а не возврат прежнего умолчания.
|
|
||||||
|
|
||||||
### Профиль — максимум по поверхности, и отсюда размер задачи
|
### Спорный случай решается вниз, и у этого есть цена
|
||||||
|
|
||||||
|
Правило асимметрично, потому что асимметрична цена ошибки.
|
||||||
|
|
||||||
|
- **Спорно между `standard` и `wide` → бери `standard`.** Ошибка в эту сторону
|
||||||
|
стоит находки, которая всплывёт на следующей задаче или в журнале дефектов.
|
||||||
|
Ошибка в обратную стоит трёх тяжёлых проходов, двое из которых держат машину и
|
||||||
|
идут цепочкой, — и платится она **на каждой** задаче, выбранной неверно.
|
||||||
|
- **Спорно между `quick` и `standard` → бери `standard`.** Здесь разница в один
|
||||||
|
дешёвый проход, зато он единственный, кто на этих ступенях вообще смотрит на
|
||||||
|
отказы и на эксплуатацию.
|
||||||
|
|
||||||
|
**Выбор сделан в пользу пропускной способности, и это записано, а не подразумевается.**
|
||||||
|
Конвейер настроен на поток задач, а не на максимум находок с каждой: поправить в
|
||||||
|
следующей задаче дешевле, чем держать одну два часа. Отсюда три обязанности,
|
||||||
|
без которых сделка превращается в незаметную потерю качества:
|
||||||
|
|
||||||
|
- **границы покрытия называют непущенные проходы поимённо** — иначе `quick`
|
||||||
|
выглядит так же, как `wide` без находок;
|
||||||
|
- **журнал дефектов в `docs/review.md` перестаёт быть хорошей практикой и
|
||||||
|
становится единственной обратной связью**: проскочивший дефект — единственный
|
||||||
|
сигнал, что ступень выбрана слишком низко;
|
||||||
|
- **возврат в код — повод пересмотреть ступень.** Задача, которая приходит в тот
|
||||||
|
же узел третий раз, уже не мелкая, чем бы ни выглядел её дифф.
|
||||||
|
|
||||||
|
### Профиль — максимум по поверхности
|
||||||
|
|
||||||
Условия читаются сверху вниз, и **первое подошедшее отвечает за весь дифф**.
|
Условия читаются сверху вниз, и **первое подошедшее отвечает за весь дифф**.
|
||||||
Профиль изменения это максимум по его поверхности, а не средневзвешенное: одна
|
Профиль изменения это максимум по его поверхности, а не средневзвешенное: одна
|
||||||
строка в перечне границ задачи поднимает ступень всему остальному, включая ту
|
строка в перечне границ задачи поднимает ступень всему остальному, включая ту
|
||||||
часть, которая сама по себе была бы `quick`.
|
часть, которая сама по себе была бы `quick`.
|
||||||
|
|
||||||
Отсюда следствие, которое дороже любой настройки триггеров: **цена ревью растёт
|
|
||||||
быстрее размера задачи.** Крупная задача не просто даёт больше диффа — она с
|
|
||||||
высокой вероятностью зацепит верхнее условие и оплатит верхний профиль целиком.
|
|
||||||
|
|
||||||
Обратное тоже верно и тоже не бесплатно: у каждой задачи есть **несокращаемый
|
Обратное тоже верно и тоже не бесплатно: у каждой задачи есть **несокращаемый
|
||||||
костяк из четырёх проходов** (гейт, спеки, код, триаж). Разрезать задачу, обе
|
костяк из четырёх проходов** (гейт, спеки, код, триаж). Разрезать задачу, обе
|
||||||
половины которой остаются в одном профиле, — значит заплатить костяк дважды за ту
|
половины которой остаются в одном профиле, — значит заплатить костяк дважды за ту
|
||||||
@@ -243,29 +277,33 @@ flowchart TD
|
|||||||
gate["gate<br/>(стадия 0, держит машину)"]
|
gate["gate<br/>(стадия 0, держит машину)"]
|
||||||
specs["specs"]
|
specs["specs"]
|
||||||
code["code"]
|
code["code"]
|
||||||
adversary["adversary<br/>(держит машину)"]
|
basics["basics<br/>(standard)"]
|
||||||
ops["ops<br/>(держит машину)"]
|
adversary["adversary<br/>(wide, держит машину)"]
|
||||||
|
ops["ops<br/>(wide, держит машину)"]
|
||||||
architecture["architecture<br/>(wide)"]
|
architecture["architecture<br/>(wide)"]
|
||||||
triage["triage — единственный сток"]
|
triage["triage — единственный сток"]
|
||||||
|
|
||||||
gate -->|зелёный| specs
|
gate -->|зелёный| specs
|
||||||
gate -->|зелёный| code
|
gate -->|зелёный| code
|
||||||
gate -->|зелёный| adversary
|
gate -->|"зелёный, standard"| basics
|
||||||
gate -->|зелёный| ops
|
gate -->|"зелёный, wide"| adversary
|
||||||
|
gate -->|"зелёный, wide"| ops
|
||||||
gate -->|"зелёный, wide"| architecture
|
gate -->|"зелёный, wide"| architecture
|
||||||
adversary -. один ресурс — машина .- ops
|
adversary -. один ресурс — машина .- ops
|
||||||
specs --> triage
|
specs --> triage
|
||||||
code --> triage
|
code --> triage
|
||||||
|
basics --> triage
|
||||||
adversary --> triage
|
adversary --> triage
|
||||||
ops --> triage
|
ops --> triage
|
||||||
architecture --> triage
|
architecture --> triage
|
||||||
```
|
```
|
||||||
|
|
||||||
Читается граф так: **всё, у чего входящие рёбра закрыты, уходит одним
|
Читается граф так: **всё, у чего входящие рёбра закрыты, уходит одним
|
||||||
сообщением**. В `standard` после зелёного гейта это три узла разом — `specs`,
|
сообщением**. В `quick` после зелёного гейта это `specs` и `code` разом, и сразу
|
||||||
`code` и первый из меряющей пары, — а второй меряющий идёт следом за первым. В
|
триаж. В `standard` к ним третьим добавляется `basics` — все трое уходят одним
|
||||||
`wide` к этой тройке добавляется четвёртым `architecture`. В `quick` — `specs` и
|
сообщением, ждать друг друга им нечего. В `wide` вместо `basics` идут три тяжёлых:
|
||||||
`code` разом, и сразу триаж.
|
`architecture` и первый из меряющей пары — сразу, второй меряющий — следом за
|
||||||
|
первым, и он же определяет, когда стартует триаж.
|
||||||
|
|
||||||
**Схема здесь старше прозы.** Она не иллюстрация к тексту, а сам алгоритм
|
**Схема здесь старше прозы.** Она не иллюстрация к тексту, а сам алгоритм
|
||||||
планировщика; проза ниже объясняет рёбра и называет их цену. Разошлись — прав
|
планировщика; проза ниже объясняет рёбра и называет их цену. Разошлись — прав
|
||||||
@@ -292,7 +330,7 @@ flowchart TD
|
|||||||
| `adversary` | да | находка есть **построенный путь**: он пишет падающий тест и гоняет его |
|
| `adversary` | да | находка есть **построенный путь**: он пишет падающий тест и гоняет его |
|
||||||
| `ops` | да | доказывает числами: время удержания блокировки, пик кучи, темп роста журнала |
|
| `ops` | да | доказывает числами: время удержания блокировки, пик кучи, темп роста журнала |
|
||||||
| `triage` | да | проверяет оракул `critical`/`major` запуском — но он сток и тоже один |
|
| `triage` | да | проверяет оракул `critical`/`major` запуском — но он сток и тоже один |
|
||||||
| `specs`, `code`, `architecture`, `rubric` | нет | читают и рассуждают, ничего не исполняют |
|
| `specs`, `code`, `basics`, `architecture`, `rubric` | нет | читают и рассуждают, ничего не исполняют |
|
||||||
|
|
||||||
**Правило про ресурс, а не про имена.** Раньше здесь стояло именованное
|
**Правило про ресурс, а не про имена.** Раньше здесь стояло именованное
|
||||||
исключение «`adversary` и `ops`»; оно рассыпается, как только проход начнёт
|
исключение «`adversary` и `ops`»; оно рассыпается, как только проход начнёт
|
||||||
@@ -374,7 +412,7 @@ flowchart TD
|
|||||||
|
|
||||||
Два applicative-прохода: оба применяют **записанный** критерий, оба дешёвые.
|
Два applicative-прохода: оба применяют **записанный** критерий, оба дешёвые.
|
||||||
Машину не держат ни один, ребра между ними нет — уходят одним сообщением сразу
|
Машину не держат ни один, ребра между ними нет — уходят одним сообщением сразу
|
||||||
после зелёного гейта, вместе со стадией 2, если она в профиле.
|
после зелёного гейта, вместе со стадией 2 или 3 — той, что в профиле.
|
||||||
|
|
||||||
- `review-specs` — критерий взят из **дельта-спек предлагаемого изменения**, а не
|
- `review-specs` — критерий взят из **дельта-спек предлагаемого изменения**, а не
|
||||||
из proposal, сообщения коммита или описания задачи. Сверка двунаправленная;
|
из proposal, сообщения коммита или описания задачи. Сверка двунаправленная;
|
||||||
@@ -385,52 +423,84 @@ flowchart TD
|
|||||||
перечисляет `conventions/README.md` — повторять это проходом вредно.
|
перечисляет `conventions/README.md` — повторять это проходом вредно.
|
||||||
|
|
||||||
Recall обоих равен длине их источника — это и есть предел applicative-проходов,
|
Recall обоих равен длине их источника — это и есть предел applicative-проходов,
|
||||||
ради которого существует стадия 2.
|
ради которого существуют стадии 2 и 3.
|
||||||
|
|
||||||
## Стадия 2 — Adversarial и operational (`standard`, `wide`)
|
## Стадия 2 — Базовый проход (только `standard`)
|
||||||
|
|
||||||
Два прохода:
|
Агент `review-basics`. Один проход, машину не держит, ничего не запускает и не
|
||||||
|
меряет — уходит одним сообщением вместе со стадией 1, сразу после зелёного гейта.
|
||||||
|
|
||||||
|
**Он не самостоятельная оптика, а мелкая осадка двух тяжёлых проходов.** Берёт из
|
||||||
|
эксплуатационного — вопросы, на которые отвечают чтением, а не замером: есть ли
|
||||||
|
таймаут и отличит ли отправитель «медленно» от «упало»; идемпотентна ли повторная
|
||||||
|
операция и не теряют ли данные две одновременные; читает ли старый код новую схему
|
||||||
|
после частичного отката; что останется, если процесс остановят между шагами;
|
||||||
|
увидит ли человек, что поток оборвался ночью. Берёт из архитектурного — только то,
|
||||||
|
что видно рядом с диффом: не появился ли **второй способ** делать то, что уже
|
||||||
|
делается, мимо единой точки проекта, и **что опытный человек отсюда удалил бы**.
|
||||||
|
|
||||||
|
Чего он **не** берёт — и это записано в его уставе отдельным разделом: замеров,
|
||||||
|
эксперимента против драйвера и библиотеки, построенного пути атаки, карты проекта,
|
||||||
|
границы домена, направления зависимостей. Всё это стоит машины или входа шире
|
||||||
|
диффа, то есть ровно того, ради чего и существует `wide`.
|
||||||
|
|
||||||
|
**Он покрывает миграцию и публичный контракт на `standard`.** Это не побочный
|
||||||
|
эффект, а условие, при котором миграция схемы вообще может не поднимать ступень:
|
||||||
|
её шаг гоняет `gate`, спеку сверяет `specs`, а вопросы «обратима ли», «что с
|
||||||
|
записями новой версии после отката» задаёт здесь `basics`. Уберёшь его — и
|
||||||
|
`standard` останется без единственного прохода, который смотрит на ось времени.
|
||||||
|
|
||||||
|
Потолок — **4 находки** плюс короткая секция «дешевле переделать до мерджа».
|
||||||
|
Потолок и узкий вход и есть его «среднее усилие»: модель у него верхняя, потому
|
||||||
|
что дешёвая на опиниативном проходе платит триажем (см. «Модель по проходу»).
|
||||||
|
|
||||||
|
## Стадия 3 — Тяжёлые проходы (только `wide`)
|
||||||
|
|
||||||
|
Три прохода, и все три уходят сразу после зелёного гейта, в одном ряду со
|
||||||
|
стадией 1:
|
||||||
|
|
||||||
- `review-adversary` — находка есть **построенный путь**, а не свойство;
|
- `review-adversary` — находка есть **построенный путь**, а не свойство;
|
||||||
- `review-ops` — постмортем от симптома у владельца сервиса к строке кода.
|
- `review-ops` — постмортем от симптома у владельца сервиса к строке кода;
|
||||||
|
- `review-architecture` — концептуальная целостность на входе шире диффа.
|
||||||
|
|
||||||
**Оба помечены «держит машину», поэтому между ними ребро конфликта: они идут
|
**Первые двое помечены «держит машину», поэтому между ними ребро конфликта: они
|
||||||
цепочкой, а не разом** (правило и его причина — в «Порядок прогона», раздел «Кто
|
идут цепочкой, а не разом** (правило и его причина — в «Порядок прогона», раздел
|
||||||
держит машину»). Направления у ребра нет: кто первый — неважно. Со стадией 1 они
|
«Кто держит машину»). Направления у ребра нет: кто первый — неважно.
|
||||||
конфликта не имеют и стартуют одновременно с ней; ждать её незачем.
|
`architecture` машину не держит и ждать ему нечего — он уходит в первой волне.
|
||||||
|
|
||||||
Цепочка не отменяется общим «гони по графу» — она и есть часть графа. Отменяет
|
Цепочка не отменяется общим «гони по графу» — она и есть часть графа. Отменяет
|
||||||
её только прямое слово оператора про эту пару, и тогда в границы покрытия идёт
|
её только прямое слово оператора про эту пару, и тогда в границы покрытия идёт
|
||||||
строка, что числа прогона сняты под соседней нагрузкой.
|
строка, что числа прогона сняты под соседней нагрузкой.
|
||||||
|
|
||||||
**Эта стадия зарабатывает больше всех остальных вместе, и потому стоит уже в
|
**Эта стадия зарабатывает больше всех остальных вместе — и она же дороже всех
|
||||||
`standard`, а не только в верхнем профиле.** Измерено на пяти задачах подряд: враждебный
|
остальных вместе.** Измерено на пяти задачах подряд: враждебный проход дал пять из
|
||||||
проход дал пять из семи выживших находок дозапуска (включая обе верхние);
|
семи выживших находок дозапуска (включая обе верхние); эксплуатационный —
|
||||||
эксплуатационный — единственный, кто нашёл, что откат бинаря поверх новой схемы
|
единственный, кто нашёл, что откат бинаря поверх новой схемы стартует молча. Оба
|
||||||
стартует молча. Оба несут внешний оракул по построению: один обязан путь
|
несут внешний оракул по построению: один обязан путь **прогнать**, второй смотрит
|
||||||
**прогнать**, второй смотрит ось времени и эксплуатации, которую не смотрит
|
ось времени и эксплуатации. Ровно поэтому они и стоят денег: оракул добывается
|
||||||
никто другой.
|
запуском, а запуск — это машина, цепочка и часы.
|
||||||
|
|
||||||
|
Раньше эта пара стояла в `standard`, то есть на большинстве задач. Стадия
|
||||||
|
переехала в `wide` **сознательно и по цене, а не потому, что перестала находить**:
|
||||||
|
она осталась самой ценной, но её ценность оплачивается на каждой задаче, а
|
||||||
|
получается — на немногих. Что из-за этого перестало проверяться на нижних
|
||||||
|
ступенях, названо в «Честном пределе» и обязано идти строкой в границы покрытия
|
||||||
|
каждого прогона `quick` и `standard`.
|
||||||
|
|
||||||
Материал берётся из документов: `docs/security.md` — враждебному,
|
Материал берётся из документов: `docs/security.md` — враждебному,
|
||||||
`docs/architecture.md`, `docs/research/` и `docs/database.md` —
|
`docs/architecture.md`, `docs/research/` и `docs/database.md` —
|
||||||
эксплуатационному. Что с чем сшивать и почему — [project-facts.md](references/project-facts.md),
|
эксплуатационному, `docs/passport.md` и карта проекта — архитектурному. Что с чем
|
||||||
раздел «Сшивать обязаны проходы». Без этих документов стадия вырождается в общие
|
сшивать и почему — [project-facts.md](references/project-facts.md), раздел
|
||||||
места.
|
«Сшивать обязаны проходы». Без этих документов стадия вырождается в общие места.
|
||||||
|
|
||||||
## Стадия 3 — Global (`wide`, `design`)
|
**Условие стадии и есть условие ступени `wide`:** изменение крупное или
|
||||||
|
незнакомое. У архитектурного прохода работа появляется тогда, когда трогается
|
||||||
|
несколько узлов разом или в проекте становится больше сущностей, чем было; у
|
||||||
|
меряющей пары — когда форму решения нащупывали по ходу, и потому неизвестно, где
|
||||||
|
она протекает. На мелкой правке вопрос «не появился ли второй способ» отвечается
|
||||||
|
«нет» до запуска, а построенный путь строить негде.
|
||||||
|
|
||||||
Агент `review-architecture`. Уходит в первой волне, сразу после зелёного гейта, в
|
`review-architecture` получает **вход шире диффа**: дерево пакетов с
|
||||||
одном ряду со стадиями 1 и 2. Машину не держит, ждать ему нечего.
|
|
||||||
|
|
||||||
**Условие этой стадии и есть условие ступени `wide`:** изменение вводит новое
|
|
||||||
понятие или структурную единицу. Не «изменение крупное» и не «изменение опасное»:
|
|
||||||
у прохода появляется работа ровно тогда, когда в проекте становится больше
|
|
||||||
сущностей, чем было, — и тогда осмысленны оба его вопроса. На изменении, которое
|
|
||||||
ничего не вводит, вопрос «не появился ли второй способ» отвечается «нет» до
|
|
||||||
запуска, а вопрос «что опытный человек отсюда удалил бы» вырождается во
|
|
||||||
вкусовщину, которую потом отсеивает триаж.
|
|
||||||
|
|
||||||
Получает **вход шире диффа**: дерево пакетов с
|
|
||||||
назначением, граф внутренних зависимостей, инвентарь существующих концепций.
|
назначением, граф внутренних зависимостей, инвентарь существующих концепций.
|
||||||
Команду, которая это готовит, даёт раздел команд `CLAUDE.md`; нет команды —
|
Команду, которая это готовит, даёт раздел команд `CLAUDE.md`; нет команды —
|
||||||
проход собирает карту сам и говорит об этом в границах покрытия.
|
проход собирает карту сам и говорит об этом в границах покрытия.
|
||||||
@@ -470,12 +540,12 @@ Recall обоих равен длине их источника — это и е
|
|||||||
имеет `proposal.md` и дельта-спеки, но кода ещё нет.
|
имеет `proposal.md` и дельта-спеки, но кода ещё нет.
|
||||||
|
|
||||||
**Состав здесь тоже не постоянный, и условие то же самое, что у `wide`:**
|
**Состав здесь тоже не постоянный, и условие то же самое, что у `wide`:**
|
||||||
изменение вводит новое понятие или структурную единицу.
|
изменение крупное или незнакомое.
|
||||||
|
|
||||||
- **всегда** — `review-specs` в режиме «дизайн ДО кода». Дельта-спеки сверяются
|
- **всегда** — `review-specs` в режиме «дизайн ДО кода». Дельта-спеки сверяются
|
||||||
на каждой задаче: это самый дешёвый чекпоинт конвейера, и он ловит то, что на
|
на каждой задаче: это самый дешёвый чекпоинт конвейера, и он ловит то, что на
|
||||||
готовом коде уже не чинят;
|
готовом коде уже не чинят;
|
||||||
- **при новом понятии** — плюс `review-rubric` (фаза 1 без фазы 2: рубрика на
|
- **при крупном или незнакомом** — плюс `review-rubric` (фаза 1 без фазы 2: рубрика на
|
||||||
задуманный узел становится приёмочными критериями и уезжает в `tasks.md`) и
|
задуманный узел становится приёмочными критериями и уезжает в `tasks.md`) и
|
||||||
`review-architecture` на предложении: можно ли выразить существующими понятиями
|
`review-architecture` на предложении: можно ли выразить существующими понятиями
|
||||||
— **включая конструкции стандартной библиотеки**, — не появляется ли второй
|
— **включая конструкции стандартной библиотеки**, — не появляется ли второй
|
||||||
@@ -486,10 +556,10 @@ Recall обоих равен длине их источника — это и е
|
|||||||
|
|
||||||
Причина условия — арифметика, а не экономия на осторожности. Чекпоинт стоит
|
Причина условия — арифметика, а не экономия на осторожности. Чекпоинт стоит
|
||||||
**на каждой задаче**, поэтому три прохода здесь умножаются на число задач, и при
|
**на каждой задаче**, поэтому три прохода здесь умножаются на число задач, и при
|
||||||
мелкой нарезке это самая большая статья конвейера. Рубрика же на узел, который не
|
мелкой нарезке это самая большая статья конвейера. Рубрика же на узел знакомого
|
||||||
вводит нового понятия, порождает свойства уже существующего рода — те, что и так
|
рода порождает свойства уже существующего рода — те, что и так записаны
|
||||||
записаны конвенциями и спеками; а `architecture` без нового понятия отвечает «нет»
|
конвенциями и спеками; а `architecture` на мелкой правке отвечает «нет» на свой
|
||||||
на свой главный вопрос ещё до запуска (см. «Стадия 3»).
|
главный вопрос ещё до запуска (см. «Стадия 3»).
|
||||||
|
|
||||||
**Граф этого профиля свой, и он плоский.** Гейта нет — кода ещё нет, запускать
|
**Граф этого профиля свой, и он плоский.** Гейта нет — кода ещё нет, запускать
|
||||||
нечего; машину не держит ни один проход; сток — не триаж, а шаг 5 пайплайна
|
нечего; машину не держит ни один проход; сток — не триаж, а шаг 5 пайплайна
|
||||||
@@ -500,7 +570,7 @@ Recall обоих равен длине их источника — это и е
|
|||||||
flowchart TD
|
flowchart TD
|
||||||
proposal["предложение: proposal.md + дельта-спеки"]
|
proposal["предложение: proposal.md + дельта-спеки"]
|
||||||
specs["specs (режим «дизайн ДО кода») — всегда"]
|
specs["specs (режим «дизайн ДО кода») — всегда"]
|
||||||
novelty{{"вводит новое понятие<br/>или структурную единицу?"}}
|
novelty{{"изменение крупное<br/>или незнакомое?"}}
|
||||||
rubric["rubric, фаза 1 → приёмочные критерии в tasks.md"]
|
rubric["rubric, фаза 1 → приёмочные критерии в tasks.md"]
|
||||||
arch["architecture на предложении"]
|
arch["architecture на предложении"]
|
||||||
author["вопрос автору: три формы решения и компромисс каждой"]
|
author["вопрос автору: три формы решения и компромисс каждой"]
|
||||||
@@ -593,7 +663,22 @@ flowchart TD
|
|||||||
никто. Класс обратимый — портит форму кода, не данные, — и его надо признавать в
|
никто. Класс обратимый — портит форму кода, не данные, — и его надо признавать в
|
||||||
границах покрытия, а не считать проверенным.
|
границах покрытия, а не считать проверенным.
|
||||||
|
|
||||||
Так же честно и про второй упразднённый проход: **«не знаю, чего не знаю» больше
|
**На `quick` и `standard` не проверяется ничего, что требует запуска.** Это самая
|
||||||
|
крупная граница покрытия конвейера, и она обязана идти строкой в каждом таком
|
||||||
|
прогоне — поимённо, а не общим «профиль ниже». Не проверяется: построенный путь
|
||||||
|
атаки (его надо прогнать), поведение библиотеки и драйвера в вырожденном случае
|
||||||
|
(достаётся только экспериментом), любое число — время удержания блокировки, пик
|
||||||
|
кучи, темп роста журнала, стоимость на годовой истории. `basics` задаёт часть тех
|
||||||
|
же вопросов **чтением**, и его ответы поэтому слабее: он формулирует условиями,
|
||||||
|
оракула не приносит и выше гипотезы находку не поднимает — кроме той, что
|
||||||
|
опирается на инвариант `CLAUDE.md`.
|
||||||
|
|
||||||
|
Это сознательная сделка, а не пробел в устройстве: цена ступени `wide` платится на
|
||||||
|
каждой задаче, а окупается на немногих. Проверяется сделка не рассуждением, а
|
||||||
|
журналом дефектов: если класс, который ловят только меряющие проходы, начал
|
||||||
|
всплывать после мерджа — ступень выбирают слишком низко.
|
||||||
|
|
||||||
|
Так же честно и про упразднённый проход: **«не знаю, чего не знаю» больше
|
||||||
не достаёт никто.** Проход независимой реализации писал свою версию узла, не
|
не достаёт никто.** Проход независимой реализации писал свою версию узла, не
|
||||||
открывая существующую, и диффил по решениям — декомпозиция, владение данными,
|
открывая существующую, и диффил по решениям — декомпозиция, владение данными,
|
||||||
модель конкурентности, форма решения там, где спека выбора не сделала. Он снят по
|
модель конкурентности, форма решения там, где спека выбора не сделала. Он снят по
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ stateDiagram-v2
|
|||||||
| `review-specs` | поведение вне спеки | добавить незаказанный фолбэк-дефолт на пустом входе |
|
| `review-specs` | поведение вне спеки | добавить незаказанный фолбэк-дефолт на пустом входе |
|
||||||
| `review-code` | нарушение прозаической конвенции | увести штатный отказ мимо единой точки трансляции ошибки |
|
| `review-code` | нарушение прозаической конвенции | увести штатный отказ мимо единой точки трансляции ошибки |
|
||||||
| `review-rubric` | нарушенное свойство узла | у клиента внешнего сервиса убрать таймаут и протяжку `context` |
|
| `review-rubric` | нарушенное свойство узла | у клиента внешнего сервиса убрать таймаут и протяжку `context` |
|
||||||
|
| `review-basics` | отказ, видимый чтением | убрать обработку ошибки записи так, чтобы отказ считался успехом |
|
||||||
| `review-architecture` | второй способ | завести вторую точку генерации id мимо единой |
|
| `review-architecture` | второй способ | завести вторую точку генерации id мимо единой |
|
||||||
| `review-adversary` | построенный путь | принять внешний идентификатор без разбора до запроса в хранилище |
|
| `review-adversary` | построенный путь | принять внешний идентификатор без разбора до запроса в хранилище |
|
||||||
| `review-ops` | деградация окружения | убрать обработку недоступности внешней зависимости в фоновом цикле |
|
| `review-ops` | деградация окружения | убрать обработку недоступности внешней зависимости в фоновом цикле |
|
||||||
|
|||||||
@@ -47,6 +47,13 @@
|
|||||||
нет — она **выводится по обратимости последствия** и помечается «выведена по
|
нет — она **выводится по обратимости последствия** и помечается «выведена по
|
||||||
обратимости», а не выдаётся за решение проекта.
|
обратимости», а не выдаётся за решение проекта.
|
||||||
|
|
||||||
|
**У `basics` стыков нет, и это не упущение.** Он не меряет, поэтому сшивать число
|
||||||
|
с настройкой ему нечего; единственное его основание для `critical` — инвариант из
|
||||||
|
`CLAUDE.md`, всё остальное он формулирует условиями и оставляет гипотезой. Его
|
||||||
|
вход намеренно узкий: единые точки и внешние зависимости из `docs/architecture.md`,
|
||||||
|
инварианты из `CLAUDE.md`, журнал из `docs/review.md`. Широкий вход — это профиль
|
||||||
|
`wide`, и там он есть у `architecture`.
|
||||||
|
|
||||||
## Деградация — поразрядная
|
## Деградация — поразрядная
|
||||||
|
|
||||||
Документа нет — деградирует то, что из него читалось, и **только оно**. Каждый
|
Документа нет — деградирует то, что из него читалось, и **только оно**. Каждый
|
||||||
@@ -67,7 +74,7 @@
|
|||||||
| `docs/database.md` | замер не с чем сравнить: находка не поднимается выше гипотезы |
|
| `docs/database.md` | замер не с чем сравнить: находка не поднимается выше гипотезы |
|
||||||
| `docs/passport.md` | `architecture` теряет границу домена и вырождается в общее мнение |
|
| `docs/passport.md` | `architecture` теряет границу домена и вырождается в общее мнение |
|
||||||
| `docs/review.md` | `triage` отсеивает вслепую: типовых ложноположительных нет |
|
| `docs/review.md` | `triage` отсеивает вслепую: типовых ложноположительных нет |
|
||||||
| `docs/architecture.md` | «не появился ли второй способ» не проверяется — единых точек не знает никто |
|
| `docs/architecture.md` | «не появился ли второй способ» не проверяется — единых точек не знает никто; `basics` теряет ещё и перечень внешних зависимостей |
|
||||||
|
|
||||||
Строка в границах покрытия обязана называть **причину**: «`docs/security.md` в
|
Строка в границах покрытия обязана называть **причину**: «`docs/security.md` в
|
||||||
проекте нет» читается иначе, чем «есть, но периметр не назван». Без причины
|
проекте нет» читается иначе, чем «есть, но периметр не назван». Без причины
|
||||||
|
|||||||
@@ -116,7 +116,11 @@ description: Проводит несколько задач разом — пл
|
|||||||
|
|
||||||
Ни один триггер не сработал — задача не замеряющая, даже если её ревью
|
Ни один триггер не сработал — задача не замеряющая, даже если её ревью
|
||||||
окажется `wide`. Профиль про глубину проверки, замеряющая — про соревнование за
|
окажется `wide`. Профиль про глубину проверки, замеряющая — про соревнование за
|
||||||
железо; это разные вопросы, и совпадают они не всегда;
|
железо; это разные вопросы, и совпадают они не всегда. Обратное тоже бывает и
|
||||||
|
тоже законно: помеченная задача, чьё ревью пошло профилем `quick` или
|
||||||
|
`standard`, машину не займёт вовсе — меряющие проходы живут только в `wide`.
|
||||||
|
Пометка от этого не снимается: она ставится **до** выбора профиля, и
|
||||||
|
перестраховка здесь стоит одной волны, а ошибка — испорченных чисел;
|
||||||
- **нумерованные артефакты — номера раздаёт оркестратор заранее.** Если проект
|
- **нумерованные артефакты — номера раздаёт оркестратор заранее.** Если проект
|
||||||
нумерует миграции (путь — `docs/.pm.json`, ключ `migrations`), посмотри последний
|
нумерует миграции (путь — `docs/.pm.json`, ключ `migrations`), посмотри последний
|
||||||
номер и **раздай номера всем задачам, которые, вероятно, их добавят**, до
|
номер и **раздай номера всем задачам, которые, вероятно, их добавят**, до
|
||||||
|
|||||||
@@ -223,8 +223,8 @@ flowchart TD
|
|||||||
|
|
||||||
**Состав чекпоинта решает конвейер, а не ты**: `review-specs` в режиме «дизайн ДО
|
**Состав чекпоинта решает конвейер, а не ты**: `review-specs` в режиме «дизайн ДО
|
||||||
кода» идёт всегда, а `review-rubric` и `review-architecture` — только когда
|
кода» идёт всегда, а `review-rubric` и `review-architecture` — только когда
|
||||||
изменение вводит новое понятие или структурную единицу (то же условие, что у
|
изменение крупное или незнакомое (то же условие, что у ступени `wide`, и та же
|
||||||
ступени `wide`). Причина в том, что чекпоинт стоит на **каждой** задаче: при
|
доля — 5–10% задач). Причина в том, что чекпоинт стоит на **каждой** задаче: при
|
||||||
мелкой нарезке три прохода здесь умножаются на число задач и становятся самой
|
мелкой нарезке три прохода здесь умножаются на число задач и становятся самой
|
||||||
большой статьёй конвейера.
|
большой статьёй конвейера.
|
||||||
|
|
||||||
|
|||||||
@@ -232,11 +232,12 @@ kebab-case.** Причина не эстетическая: имя файла с
|
|||||||
- **Вопросы к проходам** — поимённо, в форме `<имя прохода>: <вопрос>
|
- **Вопросы к проходам** — поимённо, в форме `<имя прохода>: <вопрос>
|
||||||
(<провенанс>)`;
|
(<провенанс>)`;
|
||||||
- **Триггеры профиля** — проектная конкретизация правила выбора профиля ревью:
|
- **Триггеры профиля** — проектная конкретизация правила выбора профиля ревью:
|
||||||
что в этом проекте считается **новым понятием или структурной единицей** — это
|
что в этом проекте считается **крупным или незнакомым** изменением (поднимает
|
||||||
поднимает прогон до `wide`, верхней ступени. Перечнем мест, а не вторым
|
прогон до `wide`, верхней ступени, — и она рассчитана на 5–10% задач) и что
|
||||||
определением класса. Уточняет умолчания, а не отменяет их. Рабочее умолчание —
|
считается **мелким** (опускает до `quick`). Перечнем мест, узлами или
|
||||||
`standard`: миграция схемы и публичный контракт ступень **не** поднимают, их
|
capability, а не вторым определением класса. Уточняет умолчания, а не отменяет
|
||||||
проверяют проходы, которые в `standard` и так есть;
|
их. Рабочее умолчание — `standard`: миграция схемы и публичный контракт ступень
|
||||||
|
**не** поднимают, их проверяют проходы, которые в `standard` и так есть;
|
||||||
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
|
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
|
||||||
(принципиальная граница, по факту промаха не пересматривается) и «перестали
|
(принципиальная граница, по факту промаха не пересматривается) и «перестали
|
||||||
проверять сознательно» (пересматривается первым).
|
проверять сознательно» (пересматривается первым).
|
||||||
|
|||||||
@@ -127,13 +127,17 @@ upgrade` идёт по записям снизу вверх от версии п
|
|||||||
человека. **Переименование ADR это перенос ссылок**: слаг стоит в
|
человека. **Переименование ADR это перенос ссылок**: слаг стоит в
|
||||||
`adr/README.md`, в `architecture.md` и в чужих документах, и делается одним
|
`adr/README.md`, в `architecture.md` и в чужих документах, и делается одним
|
||||||
проходом, иначе останутся битые ссылки (их `docs.py` потом и покажет).
|
проходом, иначе останутся битые ссылки (их `docs.py` потом и покажет).
|
||||||
8. `docs/review.md`, подраздел «Триггеры профиля»: снести перечень мест для
|
8. `docs/review.md`, подраздел «Триггеры профиля» — переписать целиком, он
|
||||||
`deep` — профиль упразднён вместе с проходом независимой реализации, и
|
отстал дважды. Снести перечень мест для `deep`: профиль упразднён вместе с
|
||||||
перечень стал указателем в пустоту. Перечень для `wide` (новое понятие или
|
проходом независимой реализации, и перечень стал указателем в пустоту.
|
||||||
структурная единица) остаётся: он и поднимает прогон до верхней ступени. Там
|
Оставшийся перечень перевести на новое правило: `wide` теперь означает не
|
||||||
же проверить журнал дефектов и «Недоступно проверке» на упоминания
|
«новое понятие», а **крупное или незнакомое** изменение и рассчитан на 5–10%
|
||||||
независимой реализации: класс «форма решения, где спека выбора не сделала»
|
задач; отдельным списком назвать, что здесь считается **мелким** (это `quick`).
|
||||||
переезжает в подраздел «перестали проверять сознательно».
|
Форма подраздела — в [skeletons.md](skeletons.md). Там же проверить журнал
|
||||||
|
дефектов и «Недоступно проверке» на упоминания независимой реализации: класс
|
||||||
|
«форма решения, где спека выбора не сделала» переезжает в подраздел «перестали
|
||||||
|
проверять сознательно», а рядом с ним встаёт вторая честная строка — на
|
||||||
|
`quick` и `standard` не проверяется ничего, что требует запуска.
|
||||||
9. `docs/.pm.json`: `"canon": 4`.
|
9. `docs/.pm.json`: `"canon": 4`.
|
||||||
10. Позвать **обоих судей** — `doc-consistency` и `doc-code-drift`, шагом 6
|
10. Позвать **обоих судей** — `doc-consistency` и `doc-code-drift`, шагом 6
|
||||||
`upgrade`. Пунктов выше десять, половина из них ручная, и именно здесь видно,
|
`upgrade`. Пунктов выше десять, половина из них ручная, и именно здесь видно,
|
||||||
|
|||||||
@@ -283,11 +283,19 @@
|
|||||||
|
|
||||||
### Триггеры профиля
|
### Триггеры профиля
|
||||||
|
|
||||||
Проектная конкретизация правила выбора профиля: что здесь считается **новым
|
Проектная конкретизация правила выбора профиля, двумя списками и поимённо —
|
||||||
понятием или структурной единицей** — это поднимает прогон до `wide`, верхней
|
узлами или capability.
|
||||||
ступени, и запускает архитектурный проход. Перечнем узлов или capability,
|
|
||||||
поимённо. Уточняет умолчания конвейера, не отменяет их; рабочее умолчание —
|
**Крупное или незнакомое здесь** — поднимает прогон до `wide`, верхней ступени:
|
||||||
`standard`.
|
там идут враждебный, эксплуатационный и архитектурный проходы, и там же
|
||||||
|
единственные замеры. Ступень рассчитана на **5–10% задач**; если сюда попадает
|
||||||
|
каждая третья, список написан слишком широко.
|
||||||
|
|
||||||
|
**Мелкое здесь** — опускает до `quick`. Помни отрицательный тест конвейера: что
|
||||||
|
после мерджа не откатывается обратной правкой (миграция, формат на диске,
|
||||||
|
публичный контракт, имя), — не `quick`, каким бы маленьким ни был дифф.
|
||||||
|
|
||||||
|
Уточняет умолчания конвейера, не отменяет их; рабочее умолчание — `standard`.
|
||||||
|
|
||||||
### Недоступно проверке
|
### Недоступно проверке
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
**Шов — там, где падает ступень ревью.** Раздел «Затрагивает» перечисляет
|
**Шов — там, где падает ступень ревью.** Раздел «Затрагивает» перечисляет
|
||||||
границы; если одна строка перечня поднимает ступень выше остальных, эта часть и
|
границы; если одна строка перечня поднимает ступень выше остальных, эта часть и
|
||||||
режется отдельно. Пример: задача вводит новый пакет и заодно добавляет два поля в
|
режется отдельно. Пример: задача перекладывает несколько узлов разом и заодно
|
||||||
существующий ответ. Целиком это `wide` — семь проходов по всему диффу. Разрезанная
|
добавляет два поля в существующий ответ. Целиком это `wide` — семь проходов по
|
||||||
по шву, она даёт `wide` на маленьком новом пакете и `standard` на остатке.
|
всему диффу, включая два, что держат машину и идут цепочкой. Разрезанная по шву,
|
||||||
|
она даёт `wide` на маленькой переложенной части и `standard` на остатке.
|
||||||
|
|
||||||
**Считай костяк, а не файлы.** У каждой задачи есть несокращаемые четыре прохода
|
**Считай костяк, а не файлы.** У каждой задачи есть несокращаемые четыре прохода
|
||||||
(гейт, спеки, код, триаж), и они платятся за каждую. Разрез, после которого обе
|
(гейт, спеки, код, триаж), и они платятся за каждую. Разрез, после которого обе
|
||||||
|
|||||||
Reference in New Issue
Block a user