- удалены скилл project-brief и контракт брифа; вместо них references/ project-facts.md — карта «что нужно проходу → где лежит» и таблица поразрядной деградации по документам - девять charter'ов, review-pipeline, task-pipeline и task-batch переписаны на пути канона; OpenSpec стал объявленной предпосылкой без ветки деградации - шаг синка документации переписан в построчный доклад, закрытие задачи — вызовом скилла av-dev-pm:tasks вместо строки-слота из CLAUDE.md - по находкам ревью: docs.py звал tasks.py из чужого каталога и выдавал его отказ окружения за дрейф; сверка миграций не видела рабочее дерево; плейсхолдер краснел вместо замечания; сверка capability проходила по совпадению с именем пакета; tasks.py не читал docs/.pm.json; скилл docs пересказывал канон в пяти местах
97 lines
7.7 KiB
Markdown
97 lines
7.7 KiB
Markdown
# Промоут: находка → конвенция → правило → удаление
|
|
|
|
Механизм храповика. Без него конвейер выдаёт одни и те же находки бесконечно, а
|
|
конвенции не растут — то есть внимание тратится повторно на уже решённое.
|
|
|
|
Роли уровней:
|
|
|
|
- **generative-проходы** — механизм *открытия* неявного (дорого, шумно, но
|
|
только они достают то, чего нет в списках);
|
|
- **конвенции** — дешёвая *регрессионная сетка* на уже открытое;
|
|
- **правила линтера** — то же с детерминированным оракулом и нулевой ценой
|
|
внимания.
|
|
|
|
## Шаг 1. Находка → конвенция
|
|
|
|
Условия: находка **принята** при ревью (не отвергнута, не понижена в гипотезу) и
|
|
**не специфична для одного места**.
|
|
|
|
- Формулируется как **проверяемое свойство**, а не как совет: «уровень доменного
|
|
отказа выбирает единственный логирующий чекпоинт», а не «внимательнее с
|
|
уровнями логов».
|
|
- Записывается источник — какой проход нашёл. Это единственные данные для
|
|
калибровки: проход, чьи находки регулярно доезжают до конвенции, оправдан;
|
|
проход, чьи находки не доезжают никогда, — кандидат на `drop` (см.
|
|
[calibration.md](calibration.md)).
|
|
- Место записи — конвенции проекта, файл или нужный файл каталога (путь — в
|
|
каталог `docs/conventions/`). Если
|
|
тема относится к поведению системы, а не к тому, как мы пишем код, — это не
|
|
конвенция, а требование: заводится дельта-спека обычным путём.
|
|
|
|
Промоут идёт **тем же путём, что change → spec**: правка попадает в тот же
|
|
коммит, что и исправление кода, с пометкой в сообщении — история промоутов
|
|
остаётся видна в `git log` по файлу конвенций.
|
|
|
|
## Шаг 2. Конвенция → правило
|
|
|
|
Как только свойство выражается детерминированно, оно переезжает в инструмент.
|
|
Порядок предпочтения — от дешёвого к дорогому:
|
|
|
|
1. **готовое правило существующего линтера** — включить в конфиг;
|
|
2. **запрет идентификатора или импорта** правилом-«запретителем» с собственным
|
|
паттерном;
|
|
3. **правило с настройкой формы** — когда важно не имя, а конструкция;
|
|
4. **тест-сканер исходников** — когда правило про структуру проекта или про
|
|
схему: направление зависимостей, форма миграций, матчинг ошибки по тексту,
|
|
бизнес-логика в транспорте;
|
|
5. **собственный анализатор** — последний рубеж, заводим только если 1–4 не
|
|
выражают правило.
|
|
|
|
Правило обязано быть **зелёным на текущем коде в момент включения**: иначе
|
|
хук блокирует любой коммит, и правило снимут первым же раздражённым движением.
|
|
Приводить код в соответствие — часть шага 2, отдельным коммитом.
|
|
|
|
## Шаг 3. Удаление из конвенций и из промптов
|
|
|
|
**Шаг, который пропускают чаще всего, и единственный, ради которого затевались
|
|
первые два.**
|
|
|
|
Как только правило работает:
|
|
|
|
- из файла конвенций убирается формулировка правила; остаётся, если нужно, одна
|
|
строка «проверяется линтером `<имя>`» — но только там, где без неё раздел
|
|
теряет связность;
|
|
- правило переезжает в **перечень механизированного в
|
|
`docs/conventions/README.md`** — со ссылкой на место механизации: конфиг
|
|
линтера, собственный анализатор, тест-сканер исходников. Непойманное место
|
|
означает, что проход будет добросовестно проверять уже проверенное;
|
|
- из контекста инструмента спек убирается дубль, если он там был.
|
|
|
|
Charter'ы проходов при этом **не правятся**: они общие и живут в плагине, а
|
|
предмет проверки приходит из документов проекта. Именно поэтому шаг 3 дешевле,
|
|
чем был:
|
|
вычеркнуть строку в одном файле проекта, а не в девяти промптах.
|
|
|
|
Практический критерий: **в прозаических конвенциях остаётся только то, что
|
|
принципиально не выражается правилом.** Файл конвенций на несколько сотен строк
|
|
размазывает внимание модели по тривиальному — она добросовестно проверит
|
|
именование полей лога и не дойдёт до формы решения. Каждая строка конвенций,
|
|
которую можно было бы проверить машиной, оплачивается непойманным дефектом
|
|
где-то ещё.
|
|
|
|
## Обратное движение
|
|
|
|
Правило, которое даёт ложные срабатывания чаще, чем ловит (порядка трети от
|
|
общего числа), снимается и возвращается в прозу — или удаляется совсем, если
|
|
свойство перестало быть важным. Снятие фиксируется там же, где включалось, с
|
|
одной строкой «почему».
|
|
|
|
## Что промоуту не подлежит
|
|
|
|
- Находка, специфичная для одного места (её лечит комментарий в коде).
|
|
- Вкусовщина: не меняет поведения, не влияет на стоимость следующего изменения,
|
|
не нарушает записанного. Такое выбрасывается на триаже и не хранится.
|
|
- Свойство, требующее знания рантайма (профиль нагрузки, история инцидентов) —
|
|
его нельзя проверить ни промптом, ни линтером; место такому — в журнале ревью
|
|
как «признано неавтоматизируемым» (см. [review-journal.md](review-journal.md)).
|