Синк документации делил правки по документам, а делить их надо по роду. Отражение сделанного (вливание дельт, миграция, компонент в обзоре) пишется молча: без правки документ станет ложным. Новая запись и новая норма — ADR, конвенция, записка разведки, инвариант, периметр, дефект в журнале — только предлагаются, а пишет их третий такт шага 6 после слова человека. Реплика при этом одна на весь хвост: вопрос про урожай ревью переехал с шага 5 на шаг 6 и слился с предложениями синка — решение одно, «что из найденного переживёт задачу». Плановых стопов в сценарии решения стало ровно два, и оба про решения человека. Сверка документов получила счётчик: doc-healthcheck оставляет след ключом [healthcheck] last в .av-dev.toml, синк считает по нему задачи с прошлого прогона и говорит строкой. Прежде признак «десяток задач» держался в памяти, то есть не срабатывал. Журнал — тема 78.
11 KiB
Промоут: находка → конвенция → правило → удаление
Механизм храповика. Без него конвейер выдаёт одни и те же находки бесконечно, а конвенции не растут — то есть внимание тратится повторно на уже решённое.
Роли уровней:
- generative-проходы — механизм открытия неявного (дорого, шумно, но только они достают то, чего нет в списках);
- конвенции — дешёвая регрессионная сетка на уже открытое;
- правила линтера — то же с детерминированным оракулом и нулевой ценой внимания.
flowchart TD
f["находка ревью"]
cond{"принята и не специфична<br/>для одного места?"}
no["промоуту не подлежит:<br/>место одно — комментарий в коде;<br/>вкусовщина — вон на триаже;<br/>нужен рантайм — в журнал ревью"]
conv["конвенция:<br/>проверяемое свойство + какой проход нашёл"]
rule["правило линтера, запретитель,<br/>тест-сканер или анализатор"]
clean["шаг 3: формулировка удалена из конвенций,<br/>строка — в перечень механизированного"]
f --> cond
cond -->|нет| no
cond -->|да| conv
conv --> rule
rule --> clean
rule -->|"ложных чаще, чем ловит (~треть)"| conv
Ребро назад — обратное движение (внизу): правило, дающее ложные срабатывания
чаще, чем ловит, снимается в прозу. Ребро rule → clean обязательное: без
него первые два шага не окупаются, а именно его и пропускают.
Схема — сводка: условия каждого шага в его разделе, и при расхождении прав текст.
Шаг 1. Находка → конвенция
Условия: находка принята при ревью (не отвергнута, не понижена в гипотезу) и не специфична для одного места.
- Формулируется как проверяемое свойство, а не как совет: «уровень доменного отказа выбирает единственный логирующий чекпоинт», а не «внимательнее с уровнями логов».
- Записывается источник — какой проход нашёл. Это единственные данные для
калибровки: проход, чьи находки регулярно доезжают до конвенции, оправдан;
проход, чьи находки не доезжают никогда, — кандидат на
drop(см. calibration.md). - Место записи — конвенции проекта, файл или нужный файл каталога (путь — в
каталог
docs/conventions/). Если тема относится к поведению системы, а не к тому, как мы пишем код, — это не конвенция, а требование: заводится дельта-спека обычным путём.
Конвенция заводится по слову человека, и это не формальность. Одна её строка
становится входом каждого следующего прогона ревью и критерием для всех будущих
задач — из всего, что пишет хвост задачи, конвенция связывает дальше всего.
В цикле задачи она поэтому предлагается, а не заводится: строка предложения
называет проверяемое свойство и проход, который его нашёл, и по этой паре человек
решает (av-dev:code-resolve, references/solve.md, шаг 6, такт второй).
Промоут идёт тем же путём, что change → spec: правка попадает в тот же
коммит, что и исправление кода, с пометкой в сообщении — история промоутов
остаётся видна в git log по файлу конвенций.
Шаг 2. Конвенция → правило
Как только свойство выражается детерминированно, оно переезжает в инструмент. Порядок предпочтения — от дешёвого к дорогому:
- готовое правило существующего линтера — включить в конфиг;
- запрет идентификатора или импорта правилом-«запретителем» с собственным паттерном;
- правило с настройкой формы — когда важно не имя, а конструкция;
- тест-сканер исходников — когда правило про структуру проекта или про схему: направление зависимостей, форма миграций, матчинг ошибки по тексту, бизнес-логика в транспорте;
- собственный анализатор — последний рубеж, заводим только если 1–4 не выражают правило.
Правило обязано быть зелёным на текущем коде в момент включения: иначе хук блокирует любой коммит, и правило снимут первым же раздражённым движением. Приводить код в соответствие — часть шага 2, отдельным коммитом.
Отсюда и место шага 2: он не помещается в хвост чужой задачи. Конфиг,
сканер и приведение кода к зелёному — это работа размером с задачу, и сделанная
попутно она удваивает прогон, который человек заводил ради другого. Согласованный
промоут даёт строку конвенции сейчас и задачу chore на механизацию;
задачу заводит av-dev:task-track тем же словом, что и саму конвенцию.
Шаг 3. Удаление из конвенций и из промптов
Шаг, который пропускают чаще всего, и единственный, ради которого затевались первые два.
Как только правило работает:
- из файла конвенций убирается формулировка правила; остаётся, если нужно, одна
строка «проверяется линтером
<имя>» — но только там, где без неё раздел теряет связность; - правило переезжает в перечень механизированного в доме конвенций
(
docs/conventions/README.mdу каталога, отдельный разделdocs/conventions.mdу файла) — со ссылкой на место механизации: конфиг линтера, собственный анализатор, тест-сканер исходников. Не названное место означает, что проход будет добросовестно проверять уже проверенное; - из контекста инструмента спек убирается дубль, если он там был.
Charter'ы проходов при этом не правятся: они общие и живут в плагине, а предмет проверки приходит из документов проекта. Именно поэтому шаг 3 дешевле, чем был: вычеркнуть строку в одном файле проекта, а не в девяти промптах.
Практический критерий: в прозаических конвенциях остаётся только то, что принципиально не выражается правилом. Файл конвенций на несколько сотен строк размазывает внимание модели по тривиальному — она добросовестно проверит именование полей лога и не дойдёт до формы решения. Каждая строка конвенций, которую можно было бы проверить машиной, оплачивается дефектом, который не поймали где-то ещё.
Обратное движение
Правило, которое даёт ложные срабатывания чаще, чем ловит (порядка трети от общего числа), снимается и возвращается в прозу — или удаляется совсем, если свойство перестало быть важным. Снятие фиксируется там же, где включалось, с одной строкой «почему».
Что промоуту не подлежит
- Находка, специфичная для одного места (её лечит комментарий в коде).
- Вкусовщина: не меняет поведения, не влияет на стоимость следующего изменения, не нарушает записанного. Такое выбрасывается на триаже и не хранится.
- Свойство, требующее знания рантайма (профиль нагрузки, история инцидентов) — его нельзя проверить ни промптом, ни линтером; место такому — в журнале ревью как «признано неавтоматизируемым» (см. review-journal.md).