правило выбора метки уехало в свой документ, в скилле остался диспетчер
SKILL.md конвейера дорос до 1168 строк, и двести с лишним из них отвечали на вопрос, который на обычной задаче не задаётся: как выбирается метка. Называет её review-scope один раз, до обеих стадий, а всем остальным нужна не процедура выбора, а состав по уже названной метке — три строки таблицы. В references/review-levels.md переехали правило двух осей, «спорное решается вниз», «максимум по поверхности», разбор того, чем small дешевле medium, и обе проверки долей. В скилле остались таблица состава, схема процесса и раздача тем: метка названа — состав читается. Форма выбрана одна на все метки, а не по документу на метку, как у типов задач в av-dev-pm:tasks. Аналогия не переносится дважды. Типы задач разъединены — общее лежит в task-format.md, в файле типа только своё; метки вложены: medium это small плюс два прохода, large — medium плюс доказательство, и три файла повторяли бы костяк трижды. Такое расхождение copies.py не ловит: он сверяет дословные копии по маркерам, а вышли бы почти-копии с намеренными мелкими отличиями, неотличимые от задуманного. Причина сильнее: ценность текста в сравнении. Вопрос читателя не «что делает small», а «чем small отличается от medium» — на него отвечают и выбор метки, и «спорное вниз», и корректор; сравнение, разложенное по трём файлам, не читается. Механика рычагов осталась в скилле. Непуск, вход и потолок общие для всех проходов и всех меток, их дом — «Модель по проходу»; в переехавшем тексте от них только то, что они делают с small, и ссылка на дом. Точные потолки не продублированы, чтобы не заводить второй источник чисел. Ссылку на дом правила получили review-scope, для которого он основная опора, и task-pipeline, где раньше стояло безадресное «правило живёт в скилле конвейера». Заодно вычищено последнее живое упоминание quick и standard: имена удалены каноном 6, но уцелели в объяснении, зачем нужна проверка доли. Решение — 46. SKILL.md: 1168 → 1026 строк. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2992,3 +2992,42 @@ JJJ): у профиля обязан быть один правильный от
|
|||||||
164. **Оценка по одному источнику — оценка по остатку.** Источники о задаче
|
164. **Оценка по одному источнику — оценка по остатку.** Источники о задаче
|
||||||
отвечают на разные вопросы; пропущенный не ухудшает точность понемногу, а
|
отвечают на разные вопросы; пропущенный не ухудшает точность понемногу, а
|
||||||
оставляет ось без данных.
|
оставляет ось без данных.
|
||||||
|
|
||||||
|
## 46. Правило выбора метки съехало из скилла в отдельный документ (2026-08-07)
|
||||||
|
|
||||||
|
**АЕАЗА. У правила выбора метки теперь свой дом — `references/review-levels.md`,
|
||||||
|
а в скилле остался диспетчер.** `SKILL.md` конвейера дорос до 1168 строк, и
|
||||||
|
двести с лишним из них отвечали на вопрос, который на обычной задаче не задаётся
|
||||||
|
вовсе: **как** выбирается метка. Метку называет `review-scope` один раз, до обеих
|
||||||
|
стадий; всем остальным нужна не она, а состав по уже названной метке — три строки
|
||||||
|
таблицы. Переехали правило двух осей, «спорное решается вниз», «максимум по
|
||||||
|
поверхности», разбор того, чем `small` дешевле `medium`, и обе проверки долей.
|
||||||
|
Остались таблица состава, схема процесса и раздача тем.
|
||||||
|
|
||||||
|
**Форма выбрана одна на все метки, а не по документу на метку.** Предлагался
|
||||||
|
разрез по образцу типов задач в `av-dev-pm:tasks`, где у `fix`, `feature` и
|
||||||
|
`chore` по своему файлу. Аналогия не переносится, и по двум причинам. Типы задач
|
||||||
|
**разъединены** — общее вынесено в `task-format.md`, а в файле типа лежит только
|
||||||
|
своё; метки же **вложены**: `medium` это `small` плюс два прохода, `large` —
|
||||||
|
`medium` плюс доказательство. Три файла повторяли бы костяк трижды, а `copies.py`
|
||||||
|
такое не ловит: он сверяет дословные копии по маркерам, тогда как здесь вышли бы
|
||||||
|
почти-копии с намеренными мелкими отличиями — расхождение, неотличимое от
|
||||||
|
задуманного. Вторая причина сильнее первой: ценность этого текста **в
|
||||||
|
сравнении**. Читателю нужно не «что делает `small`», а «чем `small` отличается от
|
||||||
|
`medium`» — на этот вопрос отвечают и выбор метки, и «спорное вниз», и корректор.
|
||||||
|
Сравнение, разложенное по трём файлам, не читается.
|
||||||
|
|
||||||
|
**Механика рычагов осталась в скилле, а не уехала с меткой.** Непуск, вход и
|
||||||
|
потолок общие для всех проходов и всех меток, их дом — раздел «Модель по
|
||||||
|
проходу». В переехавшем тексте от них только то, что они делают с `small`, и
|
||||||
|
ссылка на дом; точные потолки не продублированы.
|
||||||
|
|
||||||
|
### Что из этого следует
|
||||||
|
|
||||||
|
165. **Дом правила — там, где правило выбирают, а не там, где его применяют.**
|
||||||
|
Применяют состав на каждой задаче, выбирают метку один раз; текст,
|
||||||
|
обслуживающий выбор, в потоке применения лежит мёртвым грузом.
|
||||||
|
166. **Вложенные вещи не режутся по файлу на вещь.** Разъединённое (типы задач)
|
||||||
|
режется, вложенное (метки) — нет: разрез вложенного даёт дублирование
|
||||||
|
общей части, а дублирование намеренно неточное машина не сверит.
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,11 @@ color: green
|
|||||||
**Ты меряешь изменение по двум независимым осям и называешь обе.** Метка — не
|
**Ты меряешь изменение по двум независимым осям и называешь обе.** Метка — не
|
||||||
ответ на один вопрос, а максимум по двум измерениям.
|
ответ на один вопрос, а максимум по двум измерениям.
|
||||||
|
|
||||||
|
Ниже рабочая выжимка. Дом правила — скилл `av-dev-pipeline:review-pipeline`,
|
||||||
|
`references/review-levels.md`: там разобрано, почему оси именно эти, чем `small`
|
||||||
|
дешевле `medium` и какие доли служат проверкой правила. Открывай его, когда
|
||||||
|
метка **спорная или оспорена**; на обычной задаче хватает того, что здесь.
|
||||||
|
|
||||||
**Ось «размер» — про объём: сколько мест трогается.**
|
**Ось «размер» — про объём: сколько мест трогается.**
|
||||||
|
|
||||||
- **малое** — помещается в один узел;
|
- **малое** — помещается в один узел;
|
||||||
|
|||||||
@@ -373,61 +373,17 @@ flowchart TD
|
|||||||
отвечал на тот же вопрос сам — то есть о размере изменения судили дважды и в
|
отвечал на тот же вопрос сам — то есть о размере изменения судили дважды и в
|
||||||
одном из двух мест без разведённости с автором.
|
одном из двух мест без разведённости с автором.
|
||||||
|
|
||||||
**`small` дешевле `medium` тремя разными способами сразу, и каждый назван.**
|
|
||||||
|
|
||||||
1. **Составом.** `basics` на `small` не запускается — кроме случая, когда у
|
|
||||||
проекта есть свои темы; тогда он идёт **только с ними**, ровно как в `large`.
|
|
||||||
Три темы ядра, которые он держал бы, переходят к `code` сверкой по
|
|
||||||
инвариантам.
|
|
||||||
2. **Входом.** На `small` `specs` читает только дельта-спеку, а `code` — только
|
|
||||||
**индекс** конвенций (перечень родов и что механизировано), не весь их дом. На
|
|
||||||
`medium` оба читают дома целиком.
|
|
||||||
3. **Потолком.** На `small` потолки жёсткие и напечатаны: `specs` — 3 находки,
|
|
||||||
`code` — 3 технических плюс 2 конвенционных плюс 1 по трём темам ядра.
|
|
||||||
|
|
||||||
**Что `small` за это не проверяет, названо поимённо и обязано идти строкой в
|
|
||||||
границы покрытия:** темы `security`, `operations` и `architecture` смотрятся
|
|
||||||
только против **записанных инвариантов** `CLAUDE.md`. Свойство, которого в
|
|
||||||
инвариантах нет, с этой меткой не спросит никто — ни сценарием, ни чтением
|
|
||||||
дома темы. Это и есть цена метки, и она заметно больше прежней: раньше `small`
|
|
||||||
отличался от `medium` одним проходом на один вопрос, то есть не экономил
|
|
||||||
ничего и назывался отдельной меткой зря.
|
|
||||||
|
|
||||||
**Три глубины, и они не про старательность, а про способ доказательства.**
|
**Три глубины, и они не про старательность, а про способ доказательства.**
|
||||||
**Сверка** — открыть дом темы, открыть дифф, сравнить. **Разбор** — построить
|
**Сверка** — открыть дом темы, открыть дифф, сравнить. **Разбор** — построить
|
||||||
сценарий рассуждением, ничего не запуская. **Доказательство** — прогнать,
|
сценарий рассуждением, ничего не запуская. **Доказательство** — прогнать,
|
||||||
померить, построить путь. Только третья требует машины, и только она стоит часов.
|
померить, построить путь. Только третья требует машины, и только она стоит часов.
|
||||||
|
|
||||||
**`large` назван по тому, что он добавляет: вход шире диффа.** Он единственный, где
|
**Здесь диспетчер и кончается: метка названа — состав читается.** Само правило
|
||||||
живут тяжёлые проходы, и единственный, где что-то **запускается**. `basics` в нём
|
выбора — две оси, «спорное решается вниз», максимум по поверхности, — а с ним
|
||||||
берёт только проектные темы; своих тем у проекта нет — он не запускается вовсе, и
|
разбор того, чем именно `small` дешевле `medium` и почему доли служат проверкой
|
||||||
план говорит об этом строкой. **На `small` действует то же правило и по той же
|
правила, живут в [references/review-levels.md](references/review-levels.md). Тот
|
||||||
причине** — приёмник запускается только тогда, когда ему есть что принимать.
|
файл открывают, когда метку **выбирают, оспаривают или калибруют**; его
|
||||||
Совпадение неслучайное: `basics` держит темы ядра ровно при одной метке из трёх,
|
единственный постоянный читатель — `review-scope`.
|
||||||
а приёмником проектных тем работает на всех.
|
|
||||||
|
|
||||||
**Доли — не пожелание, а проверка правила, и проверок теперь две.**
|
|
||||||
|
|
||||||
**Сверху: `large` — 5–10%.** Если туда уходит каждая третья задача, метку
|
|
||||||
выбирают по ощущению важности. Обратный перекос виден по журналу проскочивших
|
|
||||||
дефектов: класс, который ловят только меряющие проходы, начинает всплывать после
|
|
||||||
мерджа.
|
|
||||||
|
|
||||||
**Снизу: `small` не должен обгонять `medium`.** Ориентир — до трети задач, но
|
|
||||||
сравнение важнее числа: **перевес `small` над `medium` значит, что рабочее
|
|
||||||
умолчание сместилось, а решения об этом никто не принимал.** Проверка нужна
|
|
||||||
именно теперь: пока `quick` и `standard` совпадали составом, дрейф между ними не
|
|
||||||
стоил ничего, и её не было. Сейчас он стоит трёх тем ядра, которые на `small`
|
|
||||||
смотрятся только против инвариантов, — то есть ровно того, чем `small` и дёшев.
|
|
||||||
|
|
||||||
Считается это по журналу дефектов и по отчётам, а не по ощущению: метка
|
|
||||||
напечатана в каждом отчёте, и посчитать её за спринт — работа на минуту.
|
|
||||||
|
|
||||||
**У дрейфа вниз есть свой стимул, и его стоит назвать.** `small` дешевле по
|
|
||||||
времени и по деньгам, а выбирает метку хоть и не автор, но проход, читающий
|
|
||||||
описание, написанное автором. Занижённое описание даёт занижённую метку без
|
|
||||||
чьего-либо злого умысла — потому корректор и вынесен в `code`, который смотрит
|
|
||||||
уже на код, а не на описание.
|
|
||||||
|
|
||||||
**Состав сверяется до коммита — по плану разметки задачи, а не по этой таблице.** План
|
**Состав сверяется до коммита — по плану разметки задачи, а не по этой таблице.** План
|
||||||
и есть реестр: тема, дом, глубина, кто закрывает. Это единственная защита от
|
и есть реестр: тема, дом, глубина, кто закрывает. Это единственная защита от
|
||||||
@@ -437,106 +393,6 @@ flowchart TD
|
|||||||
запускался» с причиной, а не отсутствует. Цена молчащего пропуска измерена: семь
|
запускался» с причиной, а не отсутствует. Цена молчащего пропуска измерена: семь
|
||||||
находок и отдельная задача на их дозакрытие.
|
находок и отдельная задача на их дозакрытие.
|
||||||
|
|
||||||
### Правило выбора — две оси, а не один вопрос
|
|
||||||
|
|
||||||
Дом правила здесь, а применяет его `review-scope` при разметке задачи — не автор
|
|
||||||
изменения. **Оси две, они измеряют разное, и метка есть максимум по ним.**
|
|
||||||
|
|
||||||
| | **знакомое** — форму решения можно назвать до начала | **незнакомое** — форму предстоит нащупать по ходу |
|
|
||||||
|---|---|---|
|
|
||||||
| **малое** — один узел | `small` | `large` |
|
|
||||||
| **среднее** — несколько узлов одного слоя | `medium` | `large` |
|
|
||||||
| **крупное** — несколько слоёв, перенос ответственности, большой рефакторинг | `large` | `large` |
|
|
||||||
|
|
||||||
**Метка — не синоним размера.** Совпадают они только в левом верхнем углу: малое
|
|
||||||
**незнакомое** изменение получает `large`, трогая один узел. Поэтому в плане
|
|
||||||
стоят три строки, а не одна: размер, сложность и метка — каждая со своим
|
|
||||||
обоснованием. Проход, выведший объём диффа из метки, ошибётся ровно на этом
|
|
||||||
случае — а он и есть самый опасный: незнакомая форма в одном узле течёт там, где
|
|
||||||
её никто не ждёт.
|
|
||||||
|
|
||||||
**Размер** — про объём: сколько мест трогается. **Сложность** — про
|
|
||||||
неизвестность: знаем ли мы форму решения заранее. Признак незнакомого простой и
|
|
||||||
проверяемый: **перед работой нельзя назвать, какие узлы будут тронуты**.
|
|
||||||
|
|
||||||
Раньше обе оси были склеены в один вопрос «крупное **или** незнакомое?». Ответ
|
|
||||||
получался тот же, но две вещи под одним именем не измеришь по отдельности, и
|
|
||||||
потому разметка не могла сказать «изменение среднее, но совершенно знакомое» —
|
|
||||||
а именно эта пара и есть рабочее умолчание. Теперь обе оси называются в плане
|
|
||||||
поимённо, и обе — с обоснованием.
|
|
||||||
|
|
||||||
**Оси называются и на стадии дизайна, и на стадии кода — но считаются один
|
|
||||||
раз.** Это и есть причина, по которой разметка переехала к `propose`: состав
|
|
||||||
ревью дизайна выводится из той же пары, что и состав ревью кода, а считать её
|
|
||||||
дважды значит один раз посчитать без разведённости с автором.
|
|
||||||
|
|
||||||
**Обратимость — не третья ось, а отрицательный тест.** Она не уточняет размер и
|
|
||||||
не уточняет сложность: она запрещает нижнюю метка независимо от обеих.
|
|
||||||
|
|
||||||
**Отрицательный тест `small`, и он важнее положительного:** изменение, которое
|
|
||||||
после мерджа **не откатывается обратной правкой**, — не `small`, каким бы
|
|
||||||
маленьким ни был дифф. Сюда попадают миграция схемы и данных, формат на диске,
|
|
||||||
публичный контракт, имя, которое разойдётся по кодовой базе. Три строки миграции
|
|
||||||
— это `medium`, а не `small`: размер диффа и цена ошибки здесь расходятся.
|
|
||||||
|
|
||||||
Что здесь считается крупным, что — незнакомым и что — мелким, проект уточняет в
|
|
||||||
`docs/review.md`, подразделе «Триггеры метки»: **тремя списками** — по одному на
|
|
||||||
каждую ось вверх и один вниз, поимённо, узлами или capability. Это **уточнение**,
|
|
||||||
а не отмена: не записано — работает таблица выше.
|
|
||||||
|
|
||||||
### Спорный случай решается вниз, и у этого есть цена
|
|
||||||
|
|
||||||
Правило асимметрично, потому что асимметрична цена ошибки.
|
|
||||||
|
|
||||||
- **Спорно между `medium` и `large` → бери `medium`.** Ошибка в эту сторону
|
|
||||||
стоит находки, которая всплывёт на следующей задаче или в журнале дефектов.
|
|
||||||
Ошибка в обратную стоит трёх тяжёлых проходов, двое из которых держат машину и
|
|
||||||
идут цепочкой, — и платится она **на каждой** задаче, выбранной неверно.
|
|
||||||
- **Спорно между `small` и `medium` → бери `medium`.** Раньше эта строка
|
|
||||||
обосновывалась тем, что состав одинаков и ошибка почти бесплатна. Теперь состав
|
|
||||||
разный, и обоснование стало прямо противоположным: на `small` три темы ядра
|
|
||||||
смотрятся **только против записанных инвариантов**, а спорный случай — ровно тот,
|
|
||||||
где неизвестно, покрыт ли он инвариантом. Сомнение здесь стоит дороже, чем
|
|
||||||
раньше, и потому решается вниз тем более твёрдо.
|
|
||||||
|
|
||||||
**Выбор сделан в пользу пропускной способности, и это записано, а не подразумевается.**
|
|
||||||
Конвейер настроен на поток задач, а не на максимум находок с каждой: поправить в
|
|
||||||
следующей задаче дешевле, чем держать одну два часа. Отсюда три обязанности,
|
|
||||||
без которых сделка превращается в незаметную потерю качества:
|
|
||||||
|
|
||||||
- **границы покрытия называют темы и их глубину**, а не только запущенные
|
|
||||||
проходы — иначе `small` выглядит так же, как `large` без находок;
|
|
||||||
- **журнал дефектов в `docs/review.md` перестаёт быть хорошей практикой и
|
|
||||||
становится единственной обратной связью**: проскочивший дефект — единственный
|
|
||||||
сигнал, что метка выбрана слишком низко;
|
|
||||||
- **возврат в код — повод пересмотреть метку.** Задача, которая приходит в тот
|
|
||||||
же узел третий раз, уже не мелкая, чем бы ни выглядел её дифф.
|
|
||||||
|
|
||||||
### Метка — максимум по поверхности
|
|
||||||
|
|
||||||
**Обе оси меряются по всему диффу разом, и максимум по каждой отвечает за весь
|
|
||||||
дифф.** Метка изменения — не средневзвешенное: одна строка в перечне границ
|
|
||||||
задачи поднимает метку всему остальному, включая ту часть, которая сама по себе
|
|
||||||
была бы `small`.
|
|
||||||
|
|
||||||
Обратное тоже верно и тоже не бесплатно: у каждой задачи есть **несокращаемый
|
|
||||||
костяк — гейт, спеки, код, триаж**. Разрезать задачу, обе половины которой
|
|
||||||
остаются в одной метке, значит заплатить костяк дважды за ту же проверку.
|
|
||||||
Резать стоит там, где разрез **снимает доказательство с большей части диффа**.
|
|
||||||
Шов и правило нарезки живут у того, кто ведёт задачи, — скилл `av-dev-pm:tasks`,
|
|
||||||
его `references/split.md`. Пути туда конвейер не выносит: за пределы своего
|
|
||||||
плагина он ходит вызовом скилла, а не файлом.
|
|
||||||
|
|
||||||
Разметка в костяк не входит — она платится один раз на задачу, а не один раз на
|
|
||||||
прогон, и потому **разрез задачи её не удваивает**. Это единственное, что стало
|
|
||||||
дешевле от переезда разметки к `propose`, и это же снимает прежний довод против
|
|
||||||
нарезки.
|
|
||||||
|
|
||||||
**Размер, сложность, метка и глубина объявляются в отчёте, и все четыре с
|
|
||||||
обоснованием.** Метка выбирает `review-scope`; он вправе и поднять, и понизить
|
|
||||||
её — но не молча: строка «метка X, потому что размер Y и сложность Z»
|
|
||||||
обязательна на каждом прогоне, а не только когда метка отличается от ожидаемой.
|
|
||||||
|
|
||||||
## Порядок прогона — граф, а не очередь
|
## Порядок прогона — граф, а не очередь
|
||||||
|
|
||||||
Метка отвечает «какие темы и на какой глубине», порядок — «что кого ждёт».
|
Метка отвечает «какие темы и на какой глубине», порядок — «что кого ждёт».
|
||||||
@@ -1161,6 +1017,8 @@ flowchart TD
|
|||||||
|
|
||||||
- [references/project-facts.md](references/project-facts.md) — что нужно проходу
|
- [references/project-facts.md](references/project-facts.md) — что нужно проходу
|
||||||
и где это лежит в документах проекта; таблица поразрядной деградации.
|
и где это лежит в документах проекта; таблица поразрядной деградации.
|
||||||
|
- [references/review-levels.md](references/review-levels.md) — дом правила выбора
|
||||||
|
метки: две оси, спорное вниз, чем `small` дешевле, доли как проверка правила.
|
||||||
- Skill `av-dev-pm:canon` — приведение проекта к канону документов.
|
- Skill `av-dev-pm:canon` — приведение проекта к канону документов.
|
||||||
- [references/finding-contract.md](references/finding-contract.md) — контракт находок.
|
- [references/finding-contract.md](references/finding-contract.md) — контракт находок.
|
||||||
- [references/promote.md](references/promote.md) — промоут находка → конвенция → правило → удаление.
|
- [references/promote.md](references/promote.md) — промоут находка → конвенция → правило → удаление.
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
# Метки задачи — выбор, цена, доли
|
||||||
|
|
||||||
|
**Дом правила выбора метки.** Состав проходов по каждой метке, схема процесса и
|
||||||
|
раздача тем живут в [SKILL.md](../SKILL.md) — там диспетчер, и на готовой задаче
|
||||||
|
его достаточно. Здесь то, что читают, когда метку **выбирают, оспаривают или
|
||||||
|
калибруют**.
|
||||||
|
|
||||||
|
Применяет правило `review-scope` при разметке задачи — не автор изменения. Его
|
||||||
|
рабочая выжимка лежит в уставе агента; расходиться она с этим файлом не вправе, а
|
||||||
|
при расхождении прав этот.
|
||||||
|
|
||||||
|
## Правило выбора — две оси, а не один вопрос
|
||||||
|
|
||||||
|
**Оси две, они измеряют разное, и метка есть максимум по ним.**
|
||||||
|
|
||||||
|
| | **знакомое** — форму решения можно назвать до начала | **незнакомое** — форму предстоит нащупать по ходу |
|
||||||
|
|---|---|---|
|
||||||
|
| **малое** — один узел | `small` | `large` |
|
||||||
|
| **среднее** — несколько узлов одного слоя | `medium` | `large` |
|
||||||
|
| **крупное** — несколько слоёв, перенос ответственности, большой рефакторинг | `large` | `large` |
|
||||||
|
|
||||||
|
**Метка — не синоним размера.** Совпадают они только в левом верхнем углу: малое
|
||||||
|
**незнакомое** изменение получает `large`, трогая один узел. Поэтому в плане
|
||||||
|
стоят три строки, а не одна: размер, сложность и метка — каждая со своим
|
||||||
|
обоснованием. Проход, выведший объём диффа из метки, ошибётся ровно на этом
|
||||||
|
случае — а он и есть самый опасный: незнакомая форма в одном узле течёт там, где
|
||||||
|
её никто не ждёт.
|
||||||
|
|
||||||
|
**Размер** — про объём: сколько мест трогается. **Сложность** — про
|
||||||
|
неизвестность: знаем ли мы форму решения заранее. Признак незнакомого простой и
|
||||||
|
проверяемый: **перед работой нельзя назвать, какие узлы будут тронуты**.
|
||||||
|
|
||||||
|
Раньше обе оси были склеены в один вопрос «крупное **или** незнакомое?». Ответ
|
||||||
|
получался тот же, но две вещи под одним именем не измеришь по отдельности, и
|
||||||
|
потому разметка не могла сказать «изменение среднее, но совершенно знакомое» —
|
||||||
|
а именно эта пара и есть рабочее умолчание. Теперь обе оси называются в плане
|
||||||
|
поимённо, и обе — с обоснованием.
|
||||||
|
|
||||||
|
**Оси называются и на стадии дизайна, и на стадии кода — но считаются один
|
||||||
|
раз.** Это и есть причина, по которой разметка переехала к `propose`: состав
|
||||||
|
ревью дизайна выводится из той же пары, что и состав ревью кода, а считать её
|
||||||
|
дважды значит один раз посчитать без разведённости с автором.
|
||||||
|
|
||||||
|
**Обратимость — не третья ось, а отрицательный тест.** Она не уточняет размер и
|
||||||
|
не уточняет сложность: она запрещает нижнюю метку независимо от обеих.
|
||||||
|
|
||||||
|
**Отрицательный тест `small`, и он важнее положительного:** изменение, которое
|
||||||
|
после мерджа **не откатывается обратной правкой**, — не `small`, каким бы
|
||||||
|
маленьким ни был дифф. Сюда попадают миграция схемы и данных, формат на диске,
|
||||||
|
публичный контракт, имя, которое разойдётся по кодовой базе. Три строки миграции
|
||||||
|
— это `medium`, а не `small`: размер диффа и цена ошибки здесь расходятся.
|
||||||
|
|
||||||
|
Что здесь считается крупным, что — незнакомым и что — мелким, проект уточняет в
|
||||||
|
`docs/review.md`, подразделе «Триггеры метки»: **тремя списками** — по одному на
|
||||||
|
каждую ось вверх и один вниз, поимённо, узлами или capability. Это **уточнение**,
|
||||||
|
а не отмена: не записано — работает таблица выше.
|
||||||
|
|
||||||
|
## Спорный случай решается вниз, и у этого есть цена
|
||||||
|
|
||||||
|
Правило асимметрично, потому что асимметрична цена ошибки.
|
||||||
|
|
||||||
|
- **Спорно между `medium` и `large` → бери `medium`.** Ошибка в эту сторону
|
||||||
|
стоит находки, которая всплывёт на следующей задаче или в журнале дефектов.
|
||||||
|
Ошибка в обратную стоит трёх тяжёлых проходов, двое из которых держат машину и
|
||||||
|
идут цепочкой, — и платится она **на каждой** задаче, выбранной неверно.
|
||||||
|
- **Спорно между `small` и `medium` → бери `medium`.** Раньше эта строка
|
||||||
|
обосновывалась тем, что состав одинаков и ошибка почти бесплатна. Теперь состав
|
||||||
|
разный, и обоснование стало прямо противоположным: на `small` три темы ядра
|
||||||
|
смотрятся **только против записанных инвариантов**, а спорный случай — ровно тот,
|
||||||
|
где неизвестно, покрыт ли он инвариантом. Сомнение здесь стоит дороже, чем
|
||||||
|
раньше, и потому решается вниз тем более твёрдо.
|
||||||
|
|
||||||
|
**Выбор сделан в пользу пропускной способности, и это записано, а не подразумевается.**
|
||||||
|
Конвейер настроен на поток задач, а не на максимум находок с каждой: поправить в
|
||||||
|
следующей задаче дешевле, чем держать одну два часа. Отсюда три обязанности,
|
||||||
|
без которых сделка превращается в незаметную потерю качества:
|
||||||
|
|
||||||
|
- **границы покрытия называют темы и их глубину**, а не только запущенные
|
||||||
|
проходы — иначе `small` выглядит так же, как `large` без находок;
|
||||||
|
- **журнал дефектов в `docs/review.md` перестаёт быть хорошей практикой и
|
||||||
|
становится единственной обратной связью**: проскочивший дефект — единственный
|
||||||
|
сигнал, что метка выбрана слишком низко;
|
||||||
|
- **возврат в код — повод пересмотреть метку.** Задача, которая приходит в тот
|
||||||
|
же узел третий раз, уже не мелкая, чем бы ни выглядел её дифф.
|
||||||
|
|
||||||
|
## Метка — максимум по поверхности
|
||||||
|
|
||||||
|
**Обе оси меряются по всему диффу разом, и максимум по каждой отвечает за весь
|
||||||
|
дифф.** Метка изменения — не средневзвешенное: одна строка в перечне границ
|
||||||
|
задачи поднимает метку всему остальному, включая ту часть, которая сама по себе
|
||||||
|
была бы `small`.
|
||||||
|
|
||||||
|
Обратное тоже верно и тоже не бесплатно: у каждой задачи есть **несокращаемый
|
||||||
|
костяк — гейт, спеки, код, триаж**. Разрезать задачу, обе половины которой
|
||||||
|
остаются в одной метке, значит заплатить костяк дважды за ту же проверку.
|
||||||
|
Резать стоит там, где разрез **снимает доказательство с большей части диффа**.
|
||||||
|
Шов и правило нарезки живут у того, кто ведёт задачи, — скилл `av-dev-pm:tasks`,
|
||||||
|
его `references/split.md`. Пути туда конвейер не выносит: за пределы своего
|
||||||
|
плагина он ходит вызовом скилла, а не файлом.
|
||||||
|
|
||||||
|
Разметка в костяк не входит — она платится один раз на задачу, а не один раз на
|
||||||
|
прогон, и потому **разрез задачи её не удваивает**. Это единственное, что стало
|
||||||
|
дешевле от переезда разметки к `propose`, и это же снимает прежний довод против
|
||||||
|
нарезки.
|
||||||
|
|
||||||
|
**Размер, сложность, метка и глубина объявляются в отчёте, и все четыре с
|
||||||
|
обоснованием.** Метка выбирает `review-scope`; он вправе и поднять, и понизить
|
||||||
|
её — но не молча: строка «метка X, потому что размер Y и сложность Z»
|
||||||
|
обязательна на каждом прогоне, а не только когда метка отличается от ожидаемой.
|
||||||
|
|
||||||
|
## Чем `small` дешевле `medium` и что это стоит
|
||||||
|
|
||||||
|
Экономят три рычага — непуск, вход, потолок, — и они общие для всех проходов и
|
||||||
|
всех меток; их дом и точные числа в [SKILL.md](../SKILL.md), раздел «Модель по
|
||||||
|
проходу». Здесь только то, что рычаги делают **с этой меткой**:
|
||||||
|
|
||||||
|
1. **Составом.** `basics` на `small` не запускается — кроме случая, когда у
|
||||||
|
проекта есть свои темы; тогда он идёт **только с ними**, ровно как в `large`.
|
||||||
|
Три темы ядра, которые он держал бы, переходят к `code` сверкой по
|
||||||
|
инвариантам.
|
||||||
|
2. **Входом.** На `small` `specs` читает только дельта-спеку, а `code` — только
|
||||||
|
**индекс** конвенций (перечень родов и что механизировано), не весь их дом. На
|
||||||
|
`medium` оба читают дома целиком.
|
||||||
|
3. **Потолком.** На `small` потолки самые жёсткие из трёх меток, и каждый
|
||||||
|
напечатан в границах покрытия своего прохода.
|
||||||
|
|
||||||
|
**Что `small` за это не проверяет, названо поимённо и обязано идти строкой в
|
||||||
|
границы покрытия:** темы `security`, `operations` и `architecture` смотрятся
|
||||||
|
только против **записанных инвариантов** `CLAUDE.md`. Свойство, которого в
|
||||||
|
инвариантах нет, с этой меткой не спросит никто — ни сценарием, ни чтением
|
||||||
|
дома темы. Это и есть цена метки, и она заметно больше прежней: раньше `small`
|
||||||
|
отличался от `medium` одним проходом на один вопрос, то есть не экономил
|
||||||
|
ничего и назывался отдельной меткой зря.
|
||||||
|
|
||||||
|
**`large` назван по тому, что он добавляет: вход шире диффа.** Он единственный, где
|
||||||
|
живут тяжёлые проходы, и единственный, где что-то **запускается**. `basics` в нём
|
||||||
|
берёт только проектные темы; своих тем у проекта нет — он не запускается вовсе, и
|
||||||
|
план говорит об этом строкой. **На `small` действует то же правило и по той же
|
||||||
|
причине** — приёмник запускается только тогда, когда ему есть что принимать.
|
||||||
|
Совпадение неслучайное: `basics` держит темы ядра ровно при одной метке из трёх,
|
||||||
|
а приёмником проектных тем работает на всех.
|
||||||
|
|
||||||
|
## Доли — не пожелание, а проверка правила, и проверок две
|
||||||
|
|
||||||
|
**Сверху: `large` — 5–10%.** Если туда уходит каждая третья задача, метку
|
||||||
|
выбирают по ощущению важности. Обратный перекос виден по журналу проскочивших
|
||||||
|
дефектов: класс, который ловят только меряющие проходы, начинает всплывать после
|
||||||
|
мерджа.
|
||||||
|
|
||||||
|
**Снизу: `small` не должен обгонять `medium`.** Ориентир — до трети задач, но
|
||||||
|
сравнение важнее числа: **перевес `small` над `medium` значит, что рабочее
|
||||||
|
умолчание сместилось, а решения об этом никто не принимал.** Проверка нужна
|
||||||
|
именно теперь: пока две нижние метки совпадали составом, дрейф между ними не
|
||||||
|
стоил ничего, и проверки не было. Сейчас он стоит трёх тем ядра, которые на
|
||||||
|
`small` смотрятся только против инвариантов, — то есть ровно того, чем `small` и
|
||||||
|
дёшев.
|
||||||
|
|
||||||
|
Считается это по журналу дефектов и по отчётам, а не по ощущению: метка
|
||||||
|
напечатана в каждом отчёте, и посчитать её за спринт — работа на минуту.
|
||||||
|
|
||||||
|
**У дрейфа вниз есть свой стимул, и его стоит назвать.** `small` дешевле по
|
||||||
|
времени и по деньгам, а выбирает метку хоть и не автор, но проход, читающий
|
||||||
|
описание, написанное автором. Занижённое описание даёт занижённую метку без
|
||||||
|
чьего-либо злого умысла — потому корректор и вынесен в `code`, который смотрит
|
||||||
|
уже на код, а не на описание.
|
||||||
@@ -317,8 +317,9 @@ change `<id>`, **план разметки с шага 4** и указание,
|
|||||||
`review-scope` ещё на шаге 4 — по размеру и сложности, с обоснованием по каждой
|
`review-scope` ещё на шаге 4 — по размеру и сложности, с обоснованием по каждой
|
||||||
оси. Причина в разведённости: ты только что написал этот код, и решать, насколько
|
оси. Причина в разведённости: ты только что написал этот код, и решать, насколько
|
||||||
глубоко его проверять, тебе нельзя — под давлением «я почти закончил» решение
|
глубоко его проверять, тебе нельзя — под давлением «я почти закончил» решение
|
||||||
известно заранее. Правило выбора живёт в скилле конвейера, проектные триггеры — в
|
известно заранее. Правило выбора живёт в скилле конвейера —
|
||||||
`docs/review.*`, подраздел «Триггеры метки».
|
`av-dev-pipeline:review-pipeline`, `references/review-levels.md`; проектные
|
||||||
|
триггеры — в `docs/review.*`, подраздел «Триггеры метки».
|
||||||
|
|
||||||
**Метка не пересматривается по факту диффа.** Дифф может выйти крупнее, чем
|
**Метка не пересматривается по факту диффа.** Дифф может выйти крупнее, чем
|
||||||
ожидалось при разметке, — это не повод её поднимать: пересмотр означал бы второй
|
ожидалось при разметке, — это не повод её поднимать: пересмотр означал бы второй
|
||||||
|
|||||||
Reference in New Issue
Block a user