--- 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-ochered-tablicej: отказ от внешней очереди - research/ — новое о формате не узнано - passport, security, conventions, review — не требуется: изменение внутреннее ``` ## ADR — промоут, а не второе сочинение Обоснование уже написано: `opsx:propose` кладёт `design.md` в каждый change, и после архивации он лежит в `openspec/changes/archive//design.md` с разделами `Context` / `Goals / Non-Goals` / `Decisions` / `Risks / Trade-offs`. **ADR цитирует решение оттуда и ссылается на источник.** Не пересказывает и не сочиняет заново. Заводится, когда верно одно из трёх: - **дорогой откат** — переделка стоит дороже переписывания одного файла; - **намеренный отказ** от очевидного подхода — чтобы не переоткрывать «а почему мы не сделали X»; - **пересмотр прежнего решения** — тогда у старой записи обязателен статус `заменено на ADR-…`, а у новой в контексте строка «Заменяет ADR-…». Не заводится для рутины и для того, что видно из кода и `git log`. Порядок: имя `ADR-ГГГГ-ММ-ДД-slug.md`, дата — когда решение **принято**, слаг английский; тело по `docs/adr/template.md`; строка в индексе `docs/adr/README.md` сверху. Активная запись статуса не имеет. ## Чистка `architecture.md` Обзор не держит поведение — его нормативный дом `openspec/specs/`. Раздел, где поведение осталось, помечается маркером долга: ``` ``` `docs.py` считает маркеры и печатает числом; **гейт от них не краснеет** — это долг, а не отказ, иначе постепенный переезд стал бы невозможен. Разбирается порциями: раздел вычищается той задачей, которая его касается. Содержимое не выбрасывается, а переезжает — требования в дельта-спеку change, обоснование в ADR, обзор остаётся строкой со ссылкой на capability. ## Запись в `research/` Наблюдение о внешнем мире: что реально шлёт источник, чем документация формата расходится с практикой. **Число — с провенансом**: команда или условия, которыми получено, чтобы его можно было перепроверить. Число без источника проход обязан читать как условие. Число, чей источник по ссылке не подтвердился, **не переписывается по догадке** — остаётся с пометкой «расходится с источником: там <что нашли>». Молча подставить «правильное» число хуже всего: расхождение перестанет быть видно, а причина останется. ## Запись в `review.md` Два раздела с разными сроками жизни, и путать их нельзя. **Журнал дефектов.** Запись на каждый воспроизведённый дефект с пометкой **проскочил / пойман ревью**. Пишется сразу, а не ретроспективно: со временем теряется не факт, а причина непоймания — единственное, ради чего журнал есть. Форма: где, симптом, чем воспроизведён, почему не поймали (для проскочивших), что меняем. Вывод «ничего не меняем, цена поимки выше цены дефекта» — законный исход. **Настройка конвейера.** Типовые узлы; типовые ложноположительные; вопросы к проходам поимённо с провенансом; недоступно проверке. Последний раздел делится на «не проверит ни один проход» (принципиальная граница, по факту промаха не пересматривается) и «перестали проверять сознательно» — этот **пересматривается первым**, как только что-то проскочило. ## Промоут в конвенции Находка → конвенция → правило линтера → **удаление из прозы**. Процедура принадлежит конвейеру ревью и живёт в его `references/promote.md`; здесь только то, что касается документа: - формулировка — **проверяемое свойство**, а не совет; - в прозе остаётся только то, что принципиально не выражается правилом; - как только правило работает, формулировка из `conventions/<тема>.md` **удаляется**, а правило попадает в перечень механизированного в `conventions/README.md` со ссылкой на место механизации. Непойманное место механизации означает, что проход по конвенциям будет добросовестно проверять уже проверенное. ## Чего этот скилл не делает - **Не проверяет раскладку** — это `canon`. - **Не заводит недостающие документы** — их скелет кладёт `canon adopt` или `init`. - **Не сочиняет содержание.** Нечего записать — так и пишется, честной строкой. - **Не переоформляет документы «заодно»**: правится то, чего коснулась работа.