Канон 5 объявил «каждый документ docs/ — тема ревью». Правило верно ровно наполовину и потому вредно целиком. Паспорт и схему хранилища ревью читает, но темами они не являются: по ним нельзя сказать «в этом изменении сделано не так», они задают границу, по которой судит чужая тема. Журнал решений и журнал наблюдений ревью изменения не нужны вовсе — ADR объясняет прошлое, а не предъявляет требование. Разметчик, применявший правило буквально, обязан был либо завести фантомные темы passport, adr, database, research и продублировать ими работу architecture и operations, либо потерять четыре документа молча; случались обе ветки, и в собственном образце плана docs/passport.md не попадал ни строкой, а обязательная арифметика покрытия при этом не сходилась. Категорий теперь три, разрез проверяемый. Тема — да, прямо: conventions, security, architecture и любой свой документ проекта. Источник темы — нет, но он задаёт границу для чужой: passport, database, CLAUDE.md, openspec/specs. Процессный — нет, он про то, как мы работаем: tasks, review, adr, research, .pm.json. Открыта одна категория из трёх, две другие перечислены поимённо, так что документ вне раскладки — однозначно своя тема. adr и research прогон больше не открывает ни одним проходом; docs/review остаётся читаемым, но как настройка конвейера, а не критерий. Цена записана и стала обязательной строкой границ покрытия: расхождение с записанным решением ловит теперь только сверка документации, а число под находкой обязано быть снято на этом прогоне, с приложенной командой. Классификация выдаёт задаче метку — small, medium, large. Прежние quick, standard и wide назывались ступенью и описывали ревью: как глубоко смотрим. Классифицируется же задача, и пока величина называлась свойством прогона, её естественно было пересчитывать на каждом прогоне — что конвейер и делал. Слово «ступень» удалено, а не оставлено синонимом: два имени одной вещи расходятся. Выводится метка из двух разведённых осей — размер (малое, среднее, крупное) и сложность (знакомое, незнакомое), — и равна максимуму по ним. Метка не синоним размера: малое незнакомое изменение получает large, трогая один узел, поэтому план печатает три строки с обоснованием каждая и выводить одну из другой запрещено. Оси остались русскими словами — это суждение прозой; метка английская — это идентификатор, который проходы сравнивают. Разметка переехала из ревью кода в шаг 4 пайплайна, сразу после propose. Она шла первым проходом каждого ревью кода, а перед ревью дизайна ту же величину называл сам пайплайн — то есть оркестратор, который только что довёл предложение до propose. Одно и то же измерялось дважды, и один из двух раз без разведённости с автором, ровно в той точке, ради которой разметчик заведён. Теперь запуск один на задачу, диффа он не видит, план обслуживает обе стадии, и метка после кода не пересматривается: расхождение факта с разметкой ловит журнал дефектов постфактум, как и всякую другую ошибку выбора. На диск план не пишется — четвёртый артефакт рядом с proposal, tasks и design пережил бы задачу и разошёлся бы с ней молча. Ревью дизайна тоже растёт меткой: small — specs, medium — плюс rubric, large — плюс architecture и вопрос автору о трёх формах решения. Раньше rubric и architecture включались одним условием, и medium получал ровно один проход, то есть не отличался от quick ничем. Разведены они потому, что зарабатывают на разном: рубрика порождает свойства узла и окупается уже на среднем изменении, её выход уезжает приёмочными критериями в tasks.md; архитектура отвечает на вопрос про второй способ, а он на среднем знакомом изменении отвечается «нет» ещё до запуска. small подешевел тремя способами сразу. Составом: приёмник тем не запускается, три темы ядра переходят к code сверкой по записанным инвариантам CLAUDE.md с потолком в одну находку, и это не «глубина ниже», а другой дом темы. Входом: specs читает только дельта-спеку, code — только индекс конвенций. Потолком: он появился у каждого опиниативного прохода, а не у одного basics, и у половин code он раздельный, потому что конвенционных находок больше по построению и в общем списке они вытеснили бы техническую половину. Сработавший потолок обязан быть объявлен строкой — молчащий срез неотличим от «больше не нашлось». Отрицательный тест small от этого стал жёстче, а не мягче: вопросы про обратимость миграции задавал приёмник тем, и на этой метке их не задаст никто. Пайплайн задачи вырос до двенадцати шагов. Тривиальность перестала решать состав ревью — она влияет только на explore; глубину обеих стадий называет метка. Проверено прогоном ревьюверов по готовому результату: девять расхождений найдено и починено — контракт находок печатал старый перечень проходов вместо плана по темам, три ссылки в task-batch указывали на шаг коммита вместо закрытия, запись changelog не переводила вопросы, адресованные passport и database, ops и adversary утверждали, что на нижних метках их вопросы задаёт basics, шаблон покрытия в review-code зашивал потолки small намертво, триггеры метки рассыпались на два списка против трёх, тема из директивы CLAUDE.md могла остаться без запуска исполнителя. Гейт зелёный: фронтматтеры, копии, одиннадцать диаграмм, ruff, pyrefly; docs.py прогнан на живом фикстуре и печатает категорию в отказе. Канон повышен до версии 6 с записью, выполнимой upgrade. Решения — 40–44. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
156 lines
13 KiB
Markdown
156 lines
13 KiB
Markdown
---
|
||
name: docs
|
||
description: Вести содержимое документов канона по ходу разработки — синк после сделанной задачи с построчным отчётом по каждому документу, заведение ADR промоутом из архивного design.md, запись наблюдения в research, запись дефекта и настройки конвейера в review.md, чистка architecture.md от поведения с маркерами долга. Использовать, когда задача сделана и надо обновить документацию, когда просят завести ADR или записать решение, занести находку о внешних данных, записать проскочивший дефект, разгрузить разросшуюся архитектуру. Раскладку и соответствие канону проверяет скилл canon.
|
||
---
|
||
|
||
# Ведение содержимого канона
|
||
|
||
Скилл владеет **содержимым** документов канона; раскладкой владеет `canon`.
|
||
Определение канона и роли документов — [канон](../canon/references/canon.md),
|
||
здесь не пересказывается.
|
||
|
||
Главный вызывающий — **шаг синка документации в пайплайне задачи**. Пайплайн
|
||
живёт в другом плагине и зовёт этот скилл по имени; проект без пайплайна ведёт
|
||
документацию тем же скиллом вручную.
|
||
|
||
## Правило, из которого всё следует
|
||
|
||
**Принуждённое отрицание.** Синк обязан назвать **каждый** документ канона: либо
|
||
чем он обновлён, либо «не требуется, потому что…». Нетронутые группируются одной
|
||
строкой с общей причиной.
|
||
|
||
Причина, по которой правило именно такое, измерена: у ADR был список триггеров
|
||
прозой — и он дал **6 записей на 43 изменения**. Прозаический триггер, который
|
||
некому проверить, не срабатывает. Отличить «не написал» от «написал, что не
|
||
требуется» можно только тогда, когда отрицание обязательно.
|
||
|
||
Это тот же приём, что «границы покрытия» в отчёте ревью и «пустое называется
|
||
пустым» в каноне.
|
||
|
||
## Чек-лист синка
|
||
|
||
Идёт сверху вниз; каждая строка попадает в доклад.
|
||
|
||
| Документ | Обновляется, когда | Проверка |
|
||
| --- | --- | --- |
|
||
| `openspec/specs/` | всегда при изменении поведения | вливает `opsx:archive` |
|
||
| `database.md` | тронуты миграции | `docs.py check --base` |
|
||
| `architecture.md` | новый компонент, граница, внешняя зависимость, изменилось окружение | `docs.py`: capability без упоминания |
|
||
| `adr/` | дорогой откат, намеренный отказ, пересмотр прежнего | нет — только этот чек-лист |
|
||
| `research/` | узнали новое о внешнем формате или данных | нет |
|
||
| `security.md` | новый недоверенный вход, токен, путь наружу, сдвиг периметра | нет |
|
||
| `conventions/` | находка принята и не специфична для одного места | промоут |
|
||
| `review.md` | дефект воспроизведён; сузили или расширили проверку | нет |
|
||
| `passport.md` | новый потребитель, сдвиг границы «чем не является» | нет |
|
||
| `CLAUDE.md` | изменился инвариант, гейт, запрет, необратимое | нет |
|
||
|
||
Пример доклада:
|
||
|
||
```
|
||
Синк документации:
|
||
- architecture.md — добавлен воркер свёртки, ссылка на capability reindex
|
||
- database.md — миграция 00006, таблица bucket
|
||
- adr/ — заведён ADR-2026-08-03-queue-as-table: отказ от внешней очереди
|
||
- research/ — новое о формате не узнано
|
||
- passport, security, conventions, review — не требуется: изменение внутреннее
|
||
```
|
||
|
||
## Сверка — не здесь, а на сессии
|
||
|
||
Синк правит документы поодиночке, а расходятся они **между собой**: факт,
|
||
дописанный в `architecture.md`, уже живёт в `CLAUDE.md`; периметр в
|
||
`security.md` не знает про новый эндпоинт. Поймать это на своей же правке нельзя,
|
||
и судит это агент `doc-consistency`.
|
||
|
||
**Но синк его не зовёт.** Оба судьи документов — `doc-consistency` и
|
||
`doc-code-drift` — зовутся раз в спринт, шагом сессии, на весь канон разом.
|
||
Причина в цене: `doc-consistency` на `opus` по каждой сделанной задаче — самая
|
||
дорогая церемония процесса, а `doc-code-drift` хоть и на `sonnet`, но читает
|
||
репозиторий целиком. К тому же расхождение между двумя документами по определению
|
||
требует двух документов, а на большинстве задач синк правит один.
|
||
|
||
Что теряется: привязка находки к задаче, которая её породила. Что выигрывается,
|
||
кроме денег: синк перестаёт отбирать пачку, и в неё попадают документы,
|
||
которых работа не касалась, — расхождение, внесённое правкой в одном месте, там
|
||
и живёт.
|
||
|
||
## ADR — промоут, а не второе сочинение
|
||
|
||
Обоснование уже написано: `opsx:propose` кладёт `design.md` в каждый change, и
|
||
после архивации он лежит в `openspec/changes/archive/<id>/design.md` с разделами
|
||
`Context` / `Goals / Non-Goals` / `Decisions` / `Risks / Trade-offs`.
|
||
|
||
**ADR цитирует решение оттуда и ссылается на источник.** Не пересказывает и не
|
||
сочиняет заново.
|
||
|
||
**Триггер заведения, форма имени и правило замены — в
|
||
[каноне](../canon/references/canon.md), раздел `adr/`.** Здесь они не
|
||
повторяются: копия правила расходится с оригиналом на первой же смене версии
|
||
канона, а расходится незаметно.
|
||
|
||
Твоя часть — **применить триггер к этой задаче и сказать вслух, сработал он или
|
||
нет**. Строка «adr/ — не требуется: решение рутинное» и есть то, ради чего
|
||
чек-лист существует; её отсутствие неотличимо от «забыл посмотреть».
|
||
|
||
Порядок работы: открой архивный `design.md` change, найди в `Decisions` то, что
|
||
проходит триггер, процитируй решение и его причину, сошлись на источник, добавь
|
||
строку в индекс `docs/adr/README.md` сверху.
|
||
|
||
## Чистка `architecture.md`
|
||
|
||
Обзор не держит поведение — его нормативный дом `openspec/specs/`. **Форма
|
||
маркера долга и правило «гейт от них не краснеет» — в
|
||
[каноне](../canon/references/canon.md), раздел `architecture.md`.**
|
||
|
||
Разбирается порциями: раздел вычищает та задача, которая его касается.
|
||
Содержимое не выбрасывается, а переезжает — требования в дельта-спеку change,
|
||
обоснование в ADR, обзор остаётся строкой со ссылкой на capability.
|
||
|
||
## Запись в `research/`
|
||
|
||
Наблюдение о внешнем мире: что реально шлёт источник, чем документация формата
|
||
расходится с практикой. **Требование провенанса и правило про расходящееся
|
||
число — в [каноне](../canon/references/canon.md), раздел `research/`.**
|
||
|
||
Твоя часть — заметить, что по ходу задачи узналось новое о внешних данных, и не
|
||
дать этому остаться в контексте. Признак: ты правил разбор, опираясь на то, чего
|
||
нет ни в одном документе.
|
||
|
||
## Запись в `review.md`
|
||
|
||
Файл держит два раздела с разными сроками жизни — журнал дефектов и настройку
|
||
конвейера. **Что в каком и в какой форме — в
|
||
[каноне](../canon/references/canon.md), раздел `review.md`**; подробности формы
|
||
записи и выбор адреса, куда она ведёт, — у конвейера ревью проекта (при
|
||
`av-dev-pipeline` — `Skill av-dev-pipeline:review-pipeline`, его
|
||
`references/review-journal.md`). **Конвейера в проекте нет** — пиши по форме из
|
||
скелета `review.md`, которую положил канон, и скажи в докладе, что подробностей
|
||
формы взять негде.
|
||
|
||
Твоя часть на синке: **дефект пишется сразу**, а не «потом, когда починим».
|
||
Со временем теряется не факт, а то, почему дефект не поймали, — единственное,
|
||
ради чего журнал есть. И решение сузить проверки (перестали звать проход, понизили
|
||
метка) обязано попасть в раздел настройки, а не остаться в отчёте ревью.
|
||
|
||
## Промоут в конвенции
|
||
|
||
Находка → конвенция → правило линтера → **удаление из прозы**. Процедура целиком
|
||
принадлежит конвейеру ревью проекта (при `av-dev-pipeline` — его
|
||
`references/promote.md`, читается через `Skill av-dev-pipeline:review-pipeline`);
|
||
роль каталога конвенций — в [каноне](../canon/references/canon.md). **Конвейера
|
||
нет** — три шага всё равно твои, просто без его процедуры: сформулируй правило,
|
||
поищи, чем оно механизируется, и вычеркни прозу, если механизировалось.
|
||
|
||
Твоя часть — **третий шаг, который пропускают чаще всего**: правило заработало,
|
||
а формулировка осталась в прозе, и проход продолжает проверять уже проверенное.
|
||
На синке это отдельная строка: «conventions/ — правило X механизировано,
|
||
формулировка удалена» либо «не требуется».
|
||
|
||
## Чего этот скилл не делает
|
||
|
||
- **Не проверяет раскладку** — это `canon`.
|
||
- **Не заводит недостающие документы** — их скелет кладёт `canon adopt` или
|
||
`init`.
|
||
- **Не сочиняет содержание.** Нечего записать — так и пишется, честной строкой.
|
||
- **Не переоформляет документы «заодно»**: правится то, чего коснулась работа.
|