- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель; - буквенные метки решений заменены сквозными Р1–Р234, следствия получили префикс С при прежних номерах: схема букв выродилась до пятибуквенных и сломалась — `АЕАКЛ` была занята и темой 53, и темой 65; - 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер означал тему, а слово стояло «решение», формулировка исправлена.
108 lines
10 KiB
Markdown
108 lines
10 KiB
Markdown
# 18. Ступень поднимает проход, а не риск (2026-08-04)
|
||
|
||
## Что было
|
||
|
||
Наблюдение с живых проектов: полный набор проходов гоняется чаще, чем оправдано —
|
||
архитектура и независимая реализация нужны заметно реже, чем запускаются. Развилка
|
||
названа сразу: крупные задачи с частым полным ревью либо мелкие и средние задачи
|
||
со средним ревью. Выбран второй путь.
|
||
|
||
Разбор показал, что размер задач — только половина причины, и не главная.
|
||
|
||
## Решено
|
||
|
||
**Р70. Профиль — максимум по поверхности, а не средневзвешенное.** Условия
|
||
читаются сверху вниз, первое подошедшее отвечает за весь дифф. Значит цена ревью
|
||
растёт быстрее размера задачи: на крупной задаче верхний профиль оплачивается в
|
||
том числе за ту её часть, которая сама по себе была бы `quick`. Это и есть
|
||
механизм, ради которого выбран путь мелких задач.
|
||
|
||
**Р71. Ступень поднимает то, что даёт работу новому проходу, а не то, что
|
||
кажется рискованным.** Правило вывода, по которому спорные случаи решаются без
|
||
нового списка. Проверка нынешних триггеров этим правилом:
|
||
|
||
| Триггер | Кто закрывает | Где этот проход |
|
||
| --- | --- | --- |
|
||
| миграция схемы | `gate` (шаг миграций), `ops` (миграция под потоком, откат при двух версиях) | уже в `standard` |
|
||
| публичный контракт | `specs`, направление `code → spec` | во всех профилях |
|
||
| инвариант проекта | основание для `critical` у любого прохода | во всех |
|
||
| новый пакет, новое понятие | `architecture` | только `wide` |
|
||
| новое правило слияния | `reimpl` | только `deep` |
|
||
|
||
Три верхних триггера не добавляли ни одного прохода — они поднимали ступень «на
|
||
всякий случай». На проекте с базой и эндпоинтами это делало верхнюю ступень
|
||
умолчанием, то есть правило объявляло исключением то, что происходит всегда.
|
||
|
||
**Р72. Миграция схемы, публичный контракт и инвариант уехали в `standard`.**
|
||
`wide` теперь означает ровно одно: изменение вводит **новое понятие или
|
||
структурную единицу** — новый пакет или слой, новая точка входа, второй способ
|
||
делать то, что уже делается, перенос ответственности между узлами. Добавленное
|
||
поле в существующем ответе концептом не является. Это **отменяет часть JJJ темы
|
||
17**: ступень `wide` остаётся, её содержание меняется. Проект, где изменение
|
||
контракта и правда архитектурное (публичный SDK, чужие потребители), поднимает
|
||
его сам в `docs/review.md` — уточнением, а не возвратом прежнего умолчания.
|
||
|
||
**Р73. Чекпоинт `design` получил то же условие.** `review-specs` в режиме
|
||
«дизайн ДО кода» идёт всегда — это самый дешёвый чекпоинт конвейера.
|
||
`review-rubric` и `review-architecture` — только при новом понятии. Причина
|
||
арифметическая: чекпоинт стоит на **каждой** задаче, поэтому при мелкой нарезке
|
||
три прохода умножаются на число задач и становятся самой большой статьёй.
|
||
Причина по существу та же, что в SSS: рубрика на узел без нового понятия
|
||
порождает свойства уже существующего рода, записанные конвенциями и спеками.
|
||
|
||
**Р74. Шов нарезки — граница, за которой падает ступень.** Тест декомпозиции
|
||
отвечает, **допустим** ли разрез; шов отвечает, **где** его провести. Раздел
|
||
«Затрагивает» перечисляет границы; строка, поднимающая ступень выше остальных, и
|
||
есть кандидат на отдельную задачу.
|
||
|
||
**Р75. Костяк из четырёх проходов платится за каждую задачу.** Гейт, спеки, код,
|
||
триаж несокращаемы, поэтому разрез, после которого обе половины остаются в одной
|
||
ступени, делает ревью **дороже**: тот же объём тем же составом, но костяк
|
||
оплачен дважды. Резать — когда разрез снимает дорогой проход с большей части
|
||
диффа.
|
||
|
||
**Р76. Верхняя ступень задана тестом, а не списком.** «Идентичность, слияние,
|
||
разбор» — формулировка, пришедшая из одного проекта, и в общем виде она не
|
||
читалась: вопрос «как это применить к моему проекту» не имел ответа в тексте.
|
||
Теперь класс задан тремя условиями, независимыми от домена и языка: вариантов
|
||
несколько и оба защитимы; спека между ними не выбирает; неверный выбор не
|
||
падает, а молча меняет смысл данных. Отрицательный тест сильнее положительных —
|
||
то, что красит гейт или роняет запрос, в класс не входит. Три слова остались как
|
||
**три места**, где такие правила водятся (граница входа данных и место их
|
||
встречи), а проект перечисляет свои места в `docs/review.md` — перечень
|
||
производен от теста и не расширяет класс.
|
||
|
||
Оговорка, без которой правило вырождается: триггер — **новое или изменённое по
|
||
существу правило**, а не код рядом с ним. Проект, чей домен и состоит из таких
|
||
правил, иначе оказывался бы в `deep` всегда — та же болезнь, от которой лечилась
|
||
ступень `wide`.
|
||
|
||
## Что из этого следует
|
||
|
||
**С72. Порога в числе границ не заводится.** Тот же принцип, что в теме 16
|
||
([Р55](16-directory-instead-of-file.md)): размер не триггер. Шов проходит по
|
||
скачку ступени, а не по длине перечня.
|
||
|
||
**С73. Ступень — признак для планирования, но не запись в задаче.** Строка
|
||
«делать профилем standard» в теле — тот самый второй дом правила выбора, который
|
||
снимает гигиена полей. Профиль выбирает тот, кто видит изменение.
|
||
|
||
**С74. Дешёвое место заметить разнородную задачу — показ набора спринта.** Там
|
||
«Затрагивает» уже написан, а предложение об изменении ещё не заведено: разрез
|
||
стоит одного `edit` вместо выброшенного предложения.
|
||
|
||
**С75. Замер остаётся за обкаткой.** Правило выведено из состава проходов, а не
|
||
из статистики прогонов: считать, какая доля задач попадает в каждую ступень,
|
||
можно только на спринтах нового процесса (TODO шаг 4).
|
||
|
||
**С76. Отсутствие верхней ступени — законное состояние проекта.** Бывают
|
||
проекты, где данные приходят нормализованными, ничего ни с чем не сливается, а
|
||
внешних форматов нет: `deep` там не срабатывает никогда, и придумывать ему повод
|
||
не надо. Раньше это читалось как недонастройка.
|
||
|
||
**С77. Ступень определяет класс правила, а не вид работы.** Миграция схемы —
|
||
`standard`, но миграция, переносящая данные по правилу («сложить дубли»,
|
||
«привести к одному виду перед сравнением»), несёт правило идентичности и потому
|
||
`deep`. Одно слово в описании задачи попадает в разные ступени — это не
|
||
противоречие, смотрят не на слово.
|