Замечено при сверке документов канона с составом ступеней: три документа остались без читателя ниже wide — security.md, database.md и adr/. Проект поддерживал их, а на 90% задач не открывал никто. Причина оказалась не в переезде проходов, а в том, как описан состав прогона. Список тем нигде не был записан: он существовал побочным продуктом списка проходов. Проход уезжал в верхнюю ступень — и тема уезжала с ним беззвучно. Отчёт честно говорил «ops не запускался» и не говорил «эксплуатацию не смотрел никто», а нужно второе. Теперь тема первична, проход вторичен — это правило 0 конвейера, а прогон описывается таблицей «тема → дом → глубина → кто закрывает», и таблица есть в каждом отчёте. Тема есть документ, список открытый. Всё, что проект кладёт в docs/, становится темой ревью; запретить нельзя, разрешения не надо. Не темы ровно две: docs/tasks/ и docs/review — настройка самого конвейера, слой над темами. Отсюда главное: docs/ перестал быть документацией и стал конфигурацией конвейера. Проект настраивает проверку тем, что пишет о себе, а не отдельным файлом настроек, который разошёлся бы с документами. Ядро — requirements, autotests, conventions, architecture, security, operations; всё сверх разбирает basics, потому что именных проходов конечное число, а тем столько, сколько заведёт проект. Тема живёт файлом или каталогом, на выбор проекта: docs/security.md и docs/security/ — одно и то же. Прежде форма была задана поимённо и обосновать её было нечем; заодно в TODO висел вопрос «а если architecture.md разрастётся». Теперь ответ механический: разросся — стал каталогом с README.md, и это не смена версии. Обе формы сразу — ошибка, docs.py её ловит. Заведён review-scope, sonnet, стадия 0, до гейта: находит документы, выводит темы, назначает глубины, выбирает ступень с обоснованием. Довод оказался сильнее синхронизации документов — до сих пор профиль называл тот же оркестратор, который написал код, то есть в точке выбора глубины проверки разведённости с автором не было вовсе, а решала она под давлением «я почти закончил». Вызывающий пайплайн профиль больше не передаёт. Поднять и понизить ступень разметчик вправе одинаково, но обоснование обязательно всегда. Sonnet ему хватает потому, что вывод устроен как список: каждый файл в docs/ обязан попасть в план темой или строкой «не тема, потому что», и план сверяется с ls docs/ за секунду. Выбор ступени — суждение, но у него три независимых корректора: отрицательный тест quick, правило «спорный случай вниз» и сигнал basics о заниженной ступени. Разметчик передаёт адреса, а не пересказ. Проект однажды уже держал review-brief.md и убрал его: второй дом расходится с первым и выглядит актуальным. Пересказ в задании — тот же посредник, живущий один прогон. Исключение одно: отсутствие дома, этого проход сам дёшево не выяснит. quick и standard совпали составом и разошлись глубиной — иначе требование «нижние ступени закрывают все темы, просто не так глубоко» не выполняется. Глубин три, и они про способ доказательства, а не про старательность: сверка (открыть дом, открыть дифф, сравнить), разбор (построить сценарий рассуждением), доказательство (прогнать, померить, построить путь). Третья есть только в wide. Цена принята: это единственное место, где профиль не выводится из списка проходов, поэтому глубина объявляется в отчёте наравне со ступенью. review-code переписан, и это оказалось крупнее исходной находки: код как код не читал никто. specs сверял с требованиями, basics — с отказами окружения, architecture — с устройством, а code был проходом только по прозаическим конвенциям и прямо объявлял, что рантайм и логика не его. «Здесь ошибка в логике» не говорил вообще никто. Теперь у прохода две половины: девять классов технического дефекта (необработанная ветка отказа, пустое и нулевое, граница диапазона, перепутанный операнд, неосвобождённый ресурс, изменение под итерацией, неверно применённый интерфейс библиотеки, недостижимая ветка, «сделано соседнее») и прежняя сверка с конвенциями. Модель поднята до opus по признаку темы 35: цена пропущенной находки — дефект в проде. Канон повышен до версии 5: форма дома на выбор, открытый список тем, AGENTS.md законно лежит рядом с CLAUDE.md, «Вопросы к проходам» → «Вопросы по темам» (имя прохода переезд не переживает, тема переживает), «Недоступно проверке» — тоже по темам. docs.py переписан под темы: ловит двойной дом, принимает обе формы, перечисляет свои темы проекта вместо «файл вне канона». Побочно закрыт давний пункт TODO про каталожную форму architecture.md — решать больше нечего. Прогон от всего этого стал дороже, а не дешевле, впервые за сессию: плюс scope в голове каждого прогона, плюс code на opus, плюс basics теперь и в quick. Куплены разведённость выбора ступени, видимость непокрытых тем и технический разбор кода, которого не было вовсе. Тема 36 в DECISIONS.md, следствия 137-140. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
9.2 KiB
Журнал дефектов
Артефакт проекта, а не плагина: файл живёт в репозитории — docs/review.md,
слот канона av-dev-pm. Здесь описано, зачем он и какой формы, потому что без
него конвейер не учится: находки закрываются, а почему их не поймали — забывается,
и один и тот же класс проскакивает второй раз.
Тот же файл держит настройку конвейера под проект — типовые узлы, типовые ложноположительные, вопросы к проходам, недоступно проверке. Это не соседство по случаю: все четыре раздела — производные калибровки, а журнал им источник.
Что туда попадает
Воспроизведённый дефект — с пометкой проскочил или пойман ревью.
Записывается сразу, а не ретроспективно: со временем теряется не сам факт, а то,
почему дефект не поймали, — единственное, ради чего журнал существует.
Пометка делит журнал на две выборки с разным назначением:
- проскочил — проверочный набор для калибровки конвейера. Реальный промах сильнее синтетической пробы: синтетические смещены в сторону тех, которые уже умеешь придумывать;
- пойман ревью — прецеденты с оракулом. Самая сильная опора, какая у прохода бывает: проектная, воспроизводимая и однажды уже оказавшаяся правдой. Без журнала они остаются только в отчётах триажа в архиве change, где их никто не ищет.
Реализованные задачи и принятые решения сюда не пишутся: у них есть коммит, спека
и docs/adr/.
Отдельно сюда попадают решения о составе прогонов: перестали звать проход, понизили профиль правилом, сузили класс проверяемого. Не потому, что это промах, а потому, что здесь лежит цена: если что-то теперь проскочит, первый вопрос — «не тот ли это класс, который мы перестали проверять».
Каждое такое решение обязано получить строку в подразделе «Перестали проверять сознательно» раздела «Недоступно проверке» того же файла. Журнал хранит «почему тогда так решили», раздел настройки — то, во что смотрит каждый прогон. Решение, оставшееся только в журнале, в границы покрытия не доедет.
Форма записи
Это дом формы, и у него есть копия. Скелет docs/review.md, который кладёт
в проект av-dev-pm (skills/canon/references/skeletons.md), повторяет её
дословно — он уезжает в репозиторий и обязан там что-то говорить. Правка формы
здесь обязана тянуть правку скелета и запись в журнал версий канона; иначе
проекты продолжат писать по старой форме, а конвейер — ждать поля, которого нет.
Дословность сверяет scripts/copies.py маркетплейса по маркерам ниже — но
запись в журнал версий он не проверит, это остаётся на человеке.
## ГГГГ-ММ-ДД — <краткое последствие> [проскочил|пойман]
- **Где:** путь:строка либо «конвейер, а не код»
- **Симптом:** как обнаружилось, кем и когда
- **Причина:** что на самом деле было не так
- **Чем воспроизведён:** тест, команда, замер — с числами
- **Почему не поймали:** только для проскочивших — какой проход обязан был найти
и что ему помешало
- **Что меняем:** правило прохода, шаг гейта, конвенция, факт в документе
проекта — либо «ничего, цена поимки выше цены дефекта»
Пункт «чем воспроизведён» отличает запись от байки: без него на неё нельзя сослаться как на оракул. Регрессионный тест, написанный вместе с починкой, годится наравне с независимым экспериментом — он исполняемый и падает на старом коде. Слабее он ровно в одном: сформулирован уже зная ответ, и это отмечается словом.
Последний пункт важнее остальных. Вывод «ничего не меняем» — законный исход: не всякий дефект стоит того, чтобы усложнять ради него ревью каждой задачи.
Куда ведёт запись
Три адреса, и выбор между ними — половина ценности журнала:
- в документ проекта — если проход не мог знать факта. Адрес зависит от рода
факта, и карта их всех — project-facts.md: объём и
измеренное число →
docs/research/; настройка хранилища →docs/database.md; что необратимо и какой шаг гейта красит безусловно →CLAUDE.md; периметр и недоверенный вход →docs/security.*. Вопрос по теме, если промах лечится не фактом, а заданным вопросом, → раздел «Вопросы по темам» того жеdocs/review.*; адресуй теме, а не имени прохода — проход уедет между ступенями, тема останется. Самый частый адрес и самый дешёвый. Прежде чем править charter, проверь, не хватит ли факта или вопроса: charter общий для всех проектов, документ — про этот. - в конвенции или в правило линтера — если свойство выражается детерминированно (процедура — promote.md).
- в charter прохода — если сломан метод, а не знание. Правка charter'а меняет поведение во всех проектах, поэтому она требует калибровки (calibration.md) и обоснования, почему это не лечится фактом в документе проекта.
Что журнал даёт конвейеру
- пробы для калибровки — выборка по пометке
проскочил; - готовые оракулы — выборка по пометке
пойман ревью: находка того же класса подтверждается ссылкой на запись, а не рассуждением; - основание для правил конвейера — требование называть запущенные проходы поимённо, отказ от чисел, производных от размера корпуса, и правило очереди для меряющих проходов выведены из конкретных записей, а не из общих соображений;
- счётчик обратимости решений — сузили состав проходов и через месяц поймали дефект ровно того класса, который перестали проверять: решение пересматривается фактом, а не спором.