ревью: цикл задачи проверяет механику, метки сняты
Состав прогона постоянный: гейт, спеки, код, триаж; приёмник тем идёт, когда у проекта есть свои темы. Метка, разметка и проход review-scope упразднены, review-levels.md удалён, ось «метка» снята из axes.md. Ступень 4 ушла из цикла: review-proof упразднён через день после заведения, review-architecture переехал в code-deep-review вслед за adversary и ops. Темы security, operations и architecture закрывает review-code сверкой с записанными инвариантами, потолком 1 находка. Умолчание разметки действий перевёрнуто на инлайн; развилка осталась за необратимым, изменением дельта-спек и нарушенным инвариантом. Задачи из урожая заводятся по слову человека, а не шагом сценария. Чекпоинт назван единственным местом, где решается форма решения. Потеряны ось времени в цикле и суждение о форме после кода — обе потери названы в «Честном пределе» строкой границ покрытия. Журнал — тема 77.
This commit is contained in:
+310
-458
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
state "проход в составе метки" as live
|
||||
state "проход в составе прогона" as live
|
||||
state "retune №1 — правка charter'а" as r1
|
||||
state "retune №2 — последняя попытка" as r2
|
||||
state "проход удалён" as dead
|
||||
@@ -79,7 +79,6 @@ stateDiagram-v2
|
||||
|
||||
| Проход | Класс дефекта для инъекции | Заготовка пробы |
|
||||
|---|---|---|
|
||||
| `review-scope` | пропущенная тема | положить в `docs/` новый документ и проверить, попал ли он в план темой |
|
||||
| `review-autotests` | отсутствующая верификация | убрать тест на изменённую ветку, оставить код рабочим |
|
||||
| `review-specs` | поведение вне спеки | добавить незаказанный фолбэк-дефолт на пустом входе |
|
||||
| `review-code` | нарушение прозаической конвенции | увести штатный отказ мимо единой точки трансляции ошибки |
|
||||
@@ -88,7 +87,9 @@ stateDiagram-v2
|
||||
| `review-basics` | отказ, видимый чтением | убрать обработку ошибки записи так, чтобы отказ считался успехом |
|
||||
| `review-basics` | своя тема проекта | нарушить правило из документа, у которого нет именного прохода |
|
||||
| `review-architecture` | второй способ | завести вторую точку генерации id мимо единой |
|
||||
| `review-proof` | набросок пути и ось времени | принять внешний идентификатор без разбора до запроса в хранилище; убрать обработку недоступности внешней зависимости в фоновом цикле |
|
||||
| `review-code` | инвариант проекта | нарушить записанный в `CLAUDE.md` запрет по темам `security`, `operations` или `architecture` |
|
||||
| `review-adversary` | построенный путь | принять внешний идентификатор без разбора до запроса в хранилище |
|
||||
| `review-ops` | ось времени | убрать обработку недоступности внешней зависимости в фоновом цикле |
|
||||
| `review-triage` | шум | подать 20 находок, из них 15 вкусовщина и 3 дубля — проверить потолок и дедуп |
|
||||
|
||||
Метрик сверх этого не заводим. Precision, корреляция между проходами, стоимость
|
||||
@@ -100,7 +101,7 @@ stateDiagram-v2
|
||||
|
||||
## Когда калибровать
|
||||
|
||||
- при заведении нового прохода — **до** включения в состав метки по умолчанию;
|
||||
- при заведении нового прохода — **до** включения в состав прогона;
|
||||
- при правке charter'а существующего — иначе непонятно, правка помогла или нет;
|
||||
- при появлении записи в журнале проскочивших дефектов — калибруем тот проход,
|
||||
который должен был поймать;
|
||||
|
||||
@@ -75,19 +75,23 @@ Severity — ось процесса; перечень осей — [shared/axes
|
||||
1. `Блокирует мердж` (≤3, каждая с оракулом);
|
||||
2. `Стоит исправить сейчас` (≤4);
|
||||
3. `Гипотезы без доказательства` — что понижено и почему;
|
||||
4. `Promote candidates` — кандидаты в конвенцию или правило линтера;
|
||||
5. `Границы покрытия` — сводная, обязательная.
|
||||
4. `Урожай` — реальные находки не для этого мерджа: формулировка, оракул,
|
||||
происхождение. Задачи из них заводит человек своим словом, не отчёт;
|
||||
5. `Отложено в av-dev:code-deep-review` — что доказывается только запуском,
|
||||
замером или входом шире диффа: тема, место, чем проверяется;
|
||||
6. `Promote candidates` — кандидаты в конвенцию или правило линтера;
|
||||
7. `Границы покрытия` — сводная, обязательная.
|
||||
|
||||
Перед секциями — сводка для человека: размер, сложность, метка и режим
|
||||
прогона, состояние гейта, **план разметки задачи с исходом по каждой теме**,
|
||||
сколько находок пришло на вход и сколько осталось.
|
||||
Перед секциями — сводка для человека: режим прогона, состояние гейта, **перечень
|
||||
тем с исходом по каждой**, сколько находок пришло на вход и сколько осталось,
|
||||
сколько из них помечено `инлайн` и сколько `развилка`.
|
||||
|
||||
**Реестр сводки — темы, а не проходы, и это не оформление.** Перечень запущенных
|
||||
проходов отвечает «все, кто должен был, отработали» и молчит о том, что именно
|
||||
осталось непроверенным: уехавший в старшую метку проход уносит тему с собой
|
||||
беззвучно. План же называет тему, её дом, глубину и исполнителя — и тема,
|
||||
осталось непроверенным: уехавший в другой скилл проход уносит тему с собой
|
||||
беззвучно. Перечень тем называет тему, её дом, глубину и исполнителя — и тема,
|
||||
оставшаяся без отчёта, видна сразу. Перечень проходов из сводки не исчезает, но
|
||||
идёт **внутри** плана, колонкой «кто закрывает».
|
||||
идёт **внутри** него, колонкой «кто закрывает».
|
||||
|
||||
Каждая находка в секциях 1–2 несёт дополнительное поле:
|
||||
|
||||
@@ -95,10 +99,12 @@ Severity — ось процесса; перечень осей — [shared/axes
|
||||
- Действие: инлайн | развилка
|
||||
```
|
||||
|
||||
`инлайн` — оркестратор чинит сам, не спрашивая и не логируя. `развилка` — цена
|
||||
исправления сопоставима с переработкой, либо выбор меняет scope, либо решение
|
||||
трогает инвариант: уезжает вопросом с вариантами и ценой каждого туда, где
|
||||
проект держит вопросы, а работа продолжается на остатке.
|
||||
`инлайн` — оркестратор чинит сам, не спрашивая и не логируя, **и это
|
||||
умолчание**. `развилка` — узкий выход с тремя основаниями: правка меняет
|
||||
дельта-спеки, находка сидит в необратимом месте (миграция, формат на диске,
|
||||
публичный контракт), находка трогает инвариант. Она уезжает вопросом с вариантами
|
||||
и ценой каждого туда, где проект держит вопросы, а работа продолжается на
|
||||
остатке.
|
||||
|
||||
Потребитель отчёта — оркестратор, который **реализует прочитанное**. Поэтому
|
||||
потолок в 7 пунктов — не забота о внимании читателя, а защита кодовой базы от
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
## Карта тем
|
||||
|
||||
**Дом бывает файлом или каталогом** — `docs/security.md` и `docs/security/`
|
||||
называют одну и ту же тему. Форму дома называет план разметки задачи; проход её не
|
||||
называют одну и ту же тему. Форму дома называет задание прохода; проход её не
|
||||
угадывает.
|
||||
|
||||
| Тема | Дом | Что оттуда берётся |
|
||||
@@ -34,10 +34,11 @@
|
||||
второй — `operations` и `requirements`; обе строки убраны, и цена этого названа в
|
||||
`SKILL.md`, раздел «Честный предел».
|
||||
|
||||
**Дом темы зависит ещё и от метки.** На `small` темы `security`, `operations` и
|
||||
`architecture` смотрятся не против домов из этой таблицы, а против **инвариантов
|
||||
`CLAUDE.md`**, и закрывает их `code`. Таблица описывает полный дом темы; сколько
|
||||
из него открыто на этом прогоне, говорит план разметки задачи.
|
||||
**Дом темы зависит от того, кто её закрывает.** В цикле задачи темы `security`,
|
||||
`operations` и `architecture` смотрятся не против домов из этой таблицы, а против
|
||||
**инвариантов `CLAUDE.md`**, и закрывает их `code`. Полные дома открывает скилл
|
||||
`av-dev:code-deep-review` своими проходами. Таблица описывает полный дом темы;
|
||||
что из него открыто на этом прогоне, говорит состав прогона.
|
||||
|
||||
Сквозное, не привязанное к теме:
|
||||
|
||||
@@ -45,12 +46,12 @@
|
||||
| --- | --- |
|
||||
| инварианты **с severity рядом с формулировкой** | `CLAUDE.md` (и `AGENTS.md`, если он рядом), раздел инвариантов |
|
||||
| что запускать запрещено, с путями; `testdata`; куда писать временное; имя основной ветки | `CLAUDE.md` |
|
||||
| типовые узлы, типовые ложноположительные, **вопросы по темам**, триггеры метки, недоступно проверке | `docs/review.*`, раздел настройки |
|
||||
| типовые узлы, типовые ложноположительные, **вопросы по темам**, недоступно проверке | `docs/review.*`, раздел настройки |
|
||||
| прецеденты: воспроизведённые дефекты с оракулом | `docs/review.*`, журнал |
|
||||
|
||||
**Вопросы проекта привязаны к теме, а не к имени прохода.** Раньше блок в
|
||||
`docs/review.md` адресовался поимённо (`ops: <вопрос>`), и когда проход уехал в
|
||||
старшую метку, вопрос перестал задаваться молча. Тема переезд прохода
|
||||
другой скилл, вопрос перестал задаваться молча. Тема переезд прохода
|
||||
переживает.
|
||||
|
||||
## Сшивать обязаны проходы
|
||||
@@ -65,7 +66,8 @@
|
||||
«запись лежит сжатой и распаковывается целиком»; «блокировка удерживалась
|
||||
5.019 с» — гарантированный отказ соседа только рядом с известным таймаутом
|
||||
занятости. **Число проход снимает сам, на этом прогоне**, настройки берёт из
|
||||
`docs/database.md`, и сшивает их `proof`. Раньше числа брались из
|
||||
`docs/database.md`, и сшивает их `ops` в глубоком ревью — в цикле задачи не
|
||||
снимает чисел никто. Раньше числа брались из
|
||||
`docs/research/`; теперь этот документ процессный, и замер неизвестной свежести
|
||||
больше не выдаёт себя за оракул.
|
||||
- **инвариант + обратимость.** severity берётся из `CLAUDE.md`; если её там
|
||||
@@ -75,15 +77,16 @@
|
||||
**У `basics` стыков нет, и это не упущение.** Он не меряет, поэтому сшивать число
|
||||
с настройкой ему нечего; единственное его основание для `critical` — инвариант из
|
||||
`CLAUDE.md`, всё остальное он формулирует условиями и оставляет гипотезой. Его
|
||||
вход намеренно узкий: дома тем из плана плюс инварианты и журнал. Широкий вход —
|
||||
это метка `large`, и там он есть у `architecture`. Греп по базе ему разрешён
|
||||
вход намеренно узкий: дома тем из задания плюс инварианты и журнал. Широкий вход
|
||||
есть только у `architecture`, а он работает в глубоком ревью. Греп по базе ему разрешён
|
||||
точечный — «есть ли второй вызывающий», — но обход всей базы и инвентарь
|
||||
концепций не его работа.
|
||||
|
||||
**У `scope` стыков нет по другой причине: он не читает содержимого.** Его дело —
|
||||
найти дома и раздать темы, а не пересказать написанное. Пересказ сделал бы его
|
||||
посредником между документом и проходом, а посредник расходится с источником и при
|
||||
этом выглядит актуальным.
|
||||
**Дома передаются адресом, а не пересказом, и это правило пережило проход,
|
||||
который его исполнял.** Прежде темы раздавал `review-scope`: он находил дома и
|
||||
называл их путём с разделом, ничего не пересказывая. Прохода нет, состав
|
||||
постоянный, но правило то же — проход, получивший проинтерпретированный периметр,
|
||||
не заметит, что интерпретация неверна.
|
||||
|
||||
## Деградация — поразрядная
|
||||
|
||||
@@ -94,7 +97,7 @@
|
||||
|
||||
**Кто какой документ читает — из документа не выводится, а назначается планом.**
|
||||
Документ питает тему (это записано на стороне канона, таблица «Роли документов и
|
||||
темы ревью»), а тему на этом прогоне закрывает тот, кого назвала разметка задачи; вся
|
||||
темы ревью»), а тему на этом прогоне закрывает тот, кто назван в составе прогона; вся
|
||||
раскладка «тема → проход → глубина» — в `SKILL.md` этого скилла и больше нигде.
|
||||
**Списка читателей не ведёт никто, и это не пробел.** Он жил бы на стороне
|
||||
канона, а документ живёт дольше, чем раскладка проходов: список разошёлся бы с
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
и `docs/adr/`.
|
||||
|
||||
Отдельно сюда попадают **решения о составе прогонов**: перестали звать проход,
|
||||
понизили метку правилом, сузили класс проверяемого. Не потому, что это промах,
|
||||
переселили его в другой скилл, сузили класс проверяемого. Не потому, что это промах,
|
||||
а потому, что здесь лежит цена: если что-то теперь проскочит, первый вопрос —
|
||||
«не тот ли это класс, который мы перестали проверять».
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
что необратимо и какой шаг гейта красит безусловно → `CLAUDE.md`; периметр и
|
||||
недоверенный вход → `docs/security.*`. **Вопрос по теме**, если промах лечится
|
||||
не фактом, а заданным вопросом, → раздел «Вопросы по темам» того же
|
||||
`docs/review.*`; адресуй теме, а не имени прохода — проход уедет между
|
||||
метками, тема останется. Самый частый адрес и самый дешёвый. Прежде чем
|
||||
`docs/review.*`; адресуй теме, а не имени прохода — проход уедет в другой
|
||||
скилл, тема останется. Самый частый адрес и самый дешёвый. Прежде чем
|
||||
править charter, проверь, не хватит ли факта или вопроса: charter общий для
|
||||
всех проектов, документ — про этот.
|
||||
- **в конвенции или в правило линтера** — если свойство выражается
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
# Метки задачи — выбор, цена, доли
|
||||
|
||||
**Дом правила выбора метки.** Состав проходов по каждой метке, схема процесса и
|
||||
раздача тем живут в [SKILL.md](../SKILL.md) — там диспетчер, и на готовой задаче
|
||||
его достаточно. Здесь то, что читают, когда метку **выбирают, оспаривают или
|
||||
калибруют**.
|
||||
|
||||
Применяет правило `review-scope` при разметке задачи — не автор изменения. Сама
|
||||
матрица уехала в его устав **помеченной копией**, и дословность её держит
|
||||
`copies.py`, а не обещание: прежде здесь стояло «расходиться не вправе», и
|
||||
подкреплено это было ничем. Проза вокруг матрицы — отрицательный тест `small`,
|
||||
доли, цена — принадлежит месту и живёт только здесь.
|
||||
|
||||
## Правило выбора — две оси, а не один вопрос
|
||||
|
||||
**Оси две, они измеряют разное, и метка есть максимум по ним.**
|
||||
|
||||
<!-- дом: матрица-метки -->
|
||||
|
||||
| | **знакомое** — форму решения можно назвать до начала | **незнакомое** — форму предстоит нащупать по ходу |
|
||||
|---|---|---|
|
||||
| **малое** — один узел | `small` | `large` |
|
||||
| **среднее** — несколько узлов одного слоя | `medium` | `large` |
|
||||
| **крупное** — несколько слоёв, перенос ответственности, большой рефакторинг | `large` | `large` |
|
||||
|
||||
<!-- /дом: матрица-метки -->
|
||||
|
||||
**Метка — не синоним размера.** Совпадают они только в левом верхнем углу: малое
|
||||
**незнакомое** изменение получает `large`, трогая один узел. Поэтому в плане
|
||||
стоят три строки, а не одна: размер, сложность и метка — каждая со своим
|
||||
обоснованием. Проход, выведший объём диффа из метки, ошибётся ровно на этом
|
||||
случае — а он и есть самый опасный: незнакомая форма в одном узле течёт там, где
|
||||
её никто не ждёт.
|
||||
|
||||
**Размер** — про объём: сколько мест трогается. **Сложность** — про
|
||||
неизвестность: знаем ли мы форму решения заранее. Признак незнакомого простой и
|
||||
проверяемый: **перед работой нельзя назвать, какие узлы будут тронуты**.
|
||||
|
||||
Раньше обе оси были склеены в один вопрос «крупное **или** незнакомое?». Ответ
|
||||
получался тот же, но две вещи под одним именем не измеришь по отдельности, и
|
||||
потому разметка не могла сказать «изменение среднее, но совершенно знакомое» —
|
||||
а именно эта пара и есть рабочее умолчание. Теперь обе оси называются в плане
|
||||
поимённо, и обе — с обоснованием.
|
||||
|
||||
**Обе оси считаются один раз — по готовому диффу.** Раньше разметка шла до кода,
|
||||
и размер приходилось выводить из написанного о задаче: перечня границ, `tasks.md`,
|
||||
дельта-спек. Теперь размер меряется по тому, что тронуто на самом деле, а
|
||||
написанное о задаче остаётся источником **сложности**: признак незнакомого —
|
||||
нельзя было назвать тронутые узлы заранее — проверяется сверкой обещанного с
|
||||
сделанным.
|
||||
|
||||
**Обратимость — не третья ось, а отрицательный тест.** Она не уточняет размер и
|
||||
не уточняет сложность: она запрещает нижнюю метку независимо от обеих.
|
||||
|
||||
**Отрицательный тест `small`, и он важнее положительного:** изменение, которое
|
||||
после мерджа **не откатывается обратной правкой**, — не `small`, каким бы
|
||||
маленьким ни был дифф. Сюда попадают миграция схемы и данных, формат на диске,
|
||||
публичный контракт, имя, которое разойдётся по кодовой базе. Три строки миграции
|
||||
— это `medium`, а не `small`: размер диффа и цена ошибки здесь расходятся.
|
||||
|
||||
Что здесь считается крупным, что — незнакомым и что — мелким, проект уточняет в
|
||||
`docs/review.md`, подразделе «Триггеры метки»: **тремя списками** — по одному на
|
||||
каждую ось вверх и один вниз, поимённо, узлами или capability. Это **уточнение**,
|
||||
а не отмена: не записано — работает таблица выше.
|
||||
|
||||
## Спорный случай решается вниз, и у этого есть цена
|
||||
|
||||
Правило асимметрично, потому что асимметрична цена ошибки.
|
||||
|
||||
- **Спорно между `medium` и `large` → бери `medium`.** Ошибка в эту сторону
|
||||
стоит находки, которая всплывёт на следующей задаче или в журнале дефектов.
|
||||
Ошибка в обратную стоит двух лишних проходов на каждой задаче, выбранной
|
||||
неверно. Цена этого шага заметно упала: тяжёлая пара, что держала машину и шла
|
||||
цепочкой, переехала в `av-dev:code-deep-review`, и `large` теперь добавляет два
|
||||
прохода чтением, а не часы запусков.
|
||||
- **Спорно между `small` и `medium` → бери `medium`.** Раньше эта строка
|
||||
обосновывалась тем, что состав одинаков и ошибка почти бесплатна. Теперь состав
|
||||
разный, и обоснование стало прямо противоположным: на `small` три темы ядра
|
||||
смотрятся **только против записанных инвариантов**, а спорный случай — ровно тот,
|
||||
где неизвестно, покрыт ли он инвариантом. Сомнение здесь стоит дороже, чем
|
||||
раньше, и потому решается вниз тем более твёрдо.
|
||||
|
||||
**Выбор сделан в пользу пропускной способности, и это записано, а не подразумевается.**
|
||||
Конвейер настроен на поток задач, а не на максимум находок с каждой: поправить в
|
||||
следующей задаче дешевле, чем держать одну два часа. Отсюда три обязанности,
|
||||
без которых сделка превращается в незаметную потерю качества:
|
||||
|
||||
- **границы покрытия называют темы и их глубину**, а не только запущенные
|
||||
проходы — иначе `small` выглядит так же, как `large` без находок;
|
||||
- **журнал дефектов в `docs/review.md` перестаёт быть хорошей практикой и
|
||||
становится единственной обратной связью**: проскочивший дефект — единственный
|
||||
сигнал, что метка выбрана слишком низко;
|
||||
- **возврат в код — повод пересмотреть метку.** Задача, которая приходит в тот
|
||||
же узел третий раз, уже не мелкая, чем бы ни выглядел её дифф.
|
||||
|
||||
## Метка — максимум по поверхности
|
||||
|
||||
**Обе оси меряются по всему диффу разом, и максимум по каждой отвечает за весь
|
||||
дифф.** Метка изменения — не средневзвешенное: одна строка в перечне границ
|
||||
задачи поднимает метку всему остальному, включая ту часть, которая сама по себе
|
||||
была бы `small`.
|
||||
|
||||
Обратное тоже верно и тоже не бесплатно: у каждой задачи есть **несокращаемый
|
||||
костяк — гейт, спеки, код, триаж**. Разрезать задачу, обе половины которой
|
||||
остаются в одной метке, значит заплатить костяк дважды за ту же проверку.
|
||||
Резать стоит там, где разрез **снимает старшую метку с большей части диффа**.
|
||||
Шов и правило нарезки живут у того, кто ведёт задачи, — скилл
|
||||
`av-dev:task-track`, его раздел о нарезке. Пути туда конвейер не выносит: за
|
||||
пределы своего скилла он ходит вызовом, а не файлом.
|
||||
|
||||
Разметка в костяк не входит — она платится один раз на задачу, а не один раз на
|
||||
прогон, и потому **перезапуск прогона её не удваивает**. Разрез задачи, впрочем,
|
||||
удваивает: у каждой половины свой дифф, и мерить его приходится порознь.
|
||||
|
||||
**Размер, сложность, метка и глубина объявляются в отчёте, и все четыре с
|
||||
обоснованием.** Метка выбирает `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`, который смотрит
|
||||
уже на код, а не на описание.
|
||||
Reference in New Issue
Block a user