Files
dev-skills/av-dev-pm/skills/canon/references/skeletons.md
T
avandClaude Opus 5 885981ca39 проверка копий правил: маркеры дома и копии, побайтовая сверка
Разделение плагинов оставлено, цена названа: пять симметричных контрактов в двух
домах, два уже разошлись — форма журнала дефектов потеряла в копии поле
«Причина», список читателей docs/research/ потерял specs. Оба раза копия
выглядела актуальной и прошла мимо трёх ревью.

scripts/copies.py требует побайтового совпадения текста между маркерами.
Комментарии, а не манифест копий: маркер уезжает в репозиторий проекта вместе со
скелетом и там полезен — говорит, что у текста есть дом.

Идентификатор строгий и повторяется в закрывающем маркере. Иначе документация о
самом механизме объявляет дом и роняет проверку: это случилось на первом же
прогоне, README объявил дом примером.

Ограда блока кода в сверку не входит: в доме текст обрамлён своей оградой, в
скелете лежит внутри чужой, объемлющей.

Помечены два контракта. Второй пришлось сперва сделать дословным: копия говорила
«обязателен статус», дом — «обязателен статус „заменено на“».

Проверка не ловит копию, которую забыли пометить, — это сказано вслух, иначе
зелёный прогон читался бы как «копий больше нет». И не заменяет запись в журнал
версий канона: она видит, что копия отстала, но не что проект унёс старую версию.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 16:23:03 +03:00

388 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Скелеты документов канона
Что кладут `init` и `canon adopt` в незаполненный слот. Правило одно:
**честная информативная строка вместо заглушки**. Проход читает строку как факт;
`<!-- заполнить: … -->` он читает как пробел, и `docs.py check` о таком
плейсхолдере напоминает.
Плейсхолдер ставится только там, где ответ **обязан** быть и его не спросили.
Всё, чего в проекте пока просто нет, описывается словами, а не плейсхолдером.
**Шаблоны — единственное место, где правило канона копируется намеренно.**
`adr/README.md` и `review.md` уезжают в репозиторий проекта и обязаны там что-то
говорить; определение при этом остаётся в [canon.md](canon.md). Отсюда
обязанность: **правка такого правила в каноне тянет запись в
[changelog.md](changelog.md)** с указанием, какой файл проекта поднимает
`upgrade`. Без этого копия в проекте останется на старой версии молча.
**Каждая такая копия помечена и сверяется машиной.** Дом обрамляется
`<!-- дом: <id> -->``<!-- /дом: <id> -->`, копия —
`<!-- копия: <id> из <путь> -->``<!-- /копия: <id> -->`;
`scripts/copies.py` маркетплейса требует дословного
совпадения. Комментарии невидимы в отрендеренном markdown и уезжают в проект
вместе со скелетом — там они говорят читателю, что у текста есть дом. Правишь
текст внутри маркеров — правь дом, а не копию.
## `docs/passport.md`
```markdown
# Паспорт проекта
Зачем это и для кого. [architecture.md](architecture.md) отвечает «как
устроено», [tasks/PLAN.md](tasks/PLAN.md) — «в каком порядке», паспорт —
«зачем и для кого».
## Цель
<!-- заполнить: одна фраза без технических деталей -->
**Потребители** — список закрытый: он определяет, что считать нужным, а что
интересным.
| Кто | Что ему нужно от нас |
| --- | --- |
Цель достигнута, когда:
## Что целью не является
Граница домена. По ней архитектурный проход судит, не перенесено ли понятие
через границу.
## Типовые сценарии
## Референсы
Где смотреть prior art, когда упёрлись.
```
## `docs/architecture.md`
```markdown
# Архитектура
Обзор: как сложено и где что работает. **Поведение системы здесь не
описывается** — его нормативный дом `openspec/specs/`.
## Принципы
## Компоненты
Каждый — строкой со ссылкой на capability, а не пересказом её требований.
## Внешние границы и форматы
## Эксплуатация
- Где работает, что рядом, кто перезапускает:
- Внешние зависимости поимённо и чем каждая отказывает (падает, отвечает
медленно, молчит, отдаёт мусор):
- Кто заметит отказ и когда:
- Характер потока (непрерывный, по запросу, по расписанию):
## Единые точки проекта
Где генерируются идентификаторы и время; где единственный парсер входного
формата; где маппинг доменной ошибки в код ответа; где общий путь приёма.
Материал для вопроса «не появился ли второй способ делать то, что уже делается».
## Деплой
## Открытые вопросы
```
Пустой проект: «Архитектуры пока нет: кода нет. Наполняется первой задачей.»
Нет внешних зависимостей: «Внешних зависимостей нет — смотри на диск и на СУБД.»
## `docs/database.md`
```markdown
# Схема хранилища
СУБД, миграции, правило времени и идентификаторов.
## Таблицы
## Представление данных
Чем физически лежит запись и что происходит при чтении и записи.
## Настройки с числовым значением
Таймаут занятости, режим журналирования, лимит тела, размер пула, ретеншен.
Без них замер не превращается в находку: пик памяти — аномалия только рядом
со строкой «запись лежит сжатой и распаковывается целиком».
```
Нет БД — файла нет, и в `docs/.pm.json` нет ключа `migrations`.
## `docs/security.md`
```markdown
# Модель угроз
## Периметр
<!-- заполнить: первой строкой, против кого защищаемся -->
Контур не развёрнут — назови оба периметра, целевой и сегодняшний, и скажи
прямо, против какого строятся находки.
## Недоверенный вход
Что приходит извне и каким каналом: тело запроса, файл, аргумент команды,
ответ внешней системы, содержимое архива.
## Из чего строятся пути и ключи
Раскладка файлов на диске, состав координатного ключа записи, имя каталога.
Отсюда строится выход за пределы песочницы.
## Что разграничивает доступ
## Что чувствительнее чего
## Что вне модели
Перечислить явно. Пустой пункт означает, что враждебный проход выдумает угрозу
сам, и находка никогда не будет исправлена.
```
## `docs/conventions/README.md`
```markdown
# Конвенции кода
Как мы пишем код — в отличие от `openspec/specs/`, который описывает, что
система делает.
**Прозой остаётся только то, что не выражается правилом.** Свойство, ставшее
правилом линтера, отсюда удаляется и переезжает в перечень ниже.
## Записи
## Механизировано
| Правило | Где механизировано |
| --- | --- |
Непойманное место механизации означает, что проход по конвенциям будет
добросовестно проверять уже проверенное.
```
Пустой проект: «Конвенций пока нет: код не написан. Наполняется по мере
реального трения, а не вперёд.»
## `docs/research/README.md`
```markdown
# Разведка
Наблюдения за внешним миром: что реально шлёт источник, чем документация
формата расходится с практикой. Источник истины — этот каталог, а не чужая
документация.
**Каждый вывод — с числами и командой, которой получен**, чтобы его можно было
перепроверить.
## Как снималось
## Записи
```
Нет внешних источников: «Внешних источников данных нет — разведка неприменима.»
## `docs/adr/README.md`
```markdown
# Журнал решений
Одна запись — одно решение. **ADR это промоут поверх архивного `design.md`**,
а не второе сочинение: запись цитирует решение и ссылается на
`openspec/changes/archive/<id>/design.md`.
## Когда заводить
Верно одно из трёх:
<!-- копия: adr-когда-заводить из av-dev-pm/skills/canon/references/canon.md -->
- **дорогой откат** — переделка стоит дороже переписывания одного файла;
- **намеренный отказ** от очевидного подхода;
- **пересмотр прежнего решения** — тогда у старой записи обязателен статус
«заменено на».
<!-- /копия: adr-когда-заводить -->
Не заводить для рутины и для того, что видно из кода и `git log`.
## Соглашения
- Имя файла — `ADR-ГГГГ-ММ-ДД-slug.md`, слаг английский, дата — когда решение
реально принято.
- Записи неизменяемы: передумали — новая запись, старой ставится статус.
- Активная запись статуса не имеет. Значений два: `заменено на ADR-…` и
`устарело`.
## Записи
Новые сверху.
| Дата | Запись | Статус |
| --- | --- | --- |
```
## `docs/adr/template.md`
```markdown
# Краткий заголовок решения
- Дата: ГГГГ-ММ-ДД
- Источник: openspec/changes/archive/<id>/design.md
## Решение
Что именно решено — одной фразой.
## Почему
Намерение и причина. Цитата из источника, а не пересказ. Пиши так, чтобы через
год было понятно без чтения переписки.
## Последствия
- `+` что стало лучше.
- `` чем платим: ограничения, риски, нагрузка на поддержку.
```
## `docs/review.md`
```markdown
# Ревью: настройка и журнал
## Как настроен конвейер
### Типовые узлы
Рода узлов проекта и 3–5 проверяемых свойств к каждому. Рода, а не инвентарь
пакетов: род, который проект задумал, но ещё не написал, включать полезно.
### Типовые ложноположительные
Находки, которые здесь выглядят убедительно и всегда неверны. Каждая — с одной
строкой «почему здесь это не дефект».
### Вопросы к проходам
Форма: `<имя прохода>: <вопрос> (<провенанс>)`. Главный источник — журнал ниже.
Проход, увидев свой блок, задаёт эти вопросы дополнительно к обязательным.
### Триггеры профиля
Проектная конкретизация правила выбора профиля: какие пути и контракты означают
`deep`, что здесь считается «поведением, видимым снаружи», при каком изменении
запускается независимая реализация. Уточняет умолчания конвейера, не отменяет их.
### Недоступно проверке
**Не проверит ни один проход** — принципиальная граница; по факту промаха не
пересматривается.
**Перестали проверять сознательно** — что, когда и почему, со ссылкой на запись
журнала. Пересматривается **первым**, как только что-то проскочило.
## Журнал дефектов
Запись на каждый воспроизведённый дефект, сразу, а не ретроспективно: со
временем теряется не факт, а причина непоймания.
Форма:
<!-- копия: журнал-дефектов-форма из av-dev-pipeline/skills/review-pipeline/references/review-journal.md -->
## ГГГГ-ММ-ДД — <краткое последствие> [проскочил|пойман]
- **Где:** путь:строка либо «конвейер, а не код»
- **Симптом:** как обнаружилось, кем и когда
- **Причина:** что на самом деле было не так
- **Чем воспроизведён:** тест, команда, замер — с числами
- **Почему не поймали:** только для проскочивших — какой проход обязан был найти
и что ему помешало
- **Что меняем:** правило прохода, шаг гейта, конвенция, факт в документе
проекта — либо «ничего, цена поимки выше цены дефекта»
<!-- /копия: журнал-дефектов-форма -->
```
Новый проект: «Дефектов пока не было. Настройка конвейера появится с первым
ревью.»
## `CLAUDE.md`
Лежит в корне, не в `docs/`. Единственный файл канона, который агент читает
**всегда**, поэтому в нём то, без чего нельзя сделать ни шага.
```markdown
# CLAUDE.md
Памятка для работы над <проект>. Перед задачей прочитай также
[docs/passport.md](docs/passport.md), [docs/architecture.md](docs/architecture.md)
и [docs/conventions/](docs/conventions/README.md).
## Что это
Абзац: что делает и чего **не** делает.
## Стек
## Инварианты
Что нарушать нельзя. Каждый пункт — три вещи: формулировка **как проверяемое
свойство**, а не лозунг; последствие нарушения и его обратимость; **severity**
рядом. По этим формулировкам проходы ревью присваивают `critical`, поэтому
severity стоит здесь, а не выводится каждым проходом заново.
## Команды
## Гейт
- Команда целиком и как определяется база диффа:
- Где логи шагов:
- Что означает каждый исход:
- **Что красит безусловно и почему:**
- Чего в гейте намеренно нет и **кто тогда обязан это гонять:**
## Запреты
Что запускать нельзя, **с путями**: рабочая БД, боевой каталог данных, внешние
сервисы. Плюс где `testdata` и куда писать временное.
## Работа
- **Основная ветка:** <имя>
- **Необратимое** (спрашивается у человека всегда):
- **Общий станок** — какая проверка, покраснев, врывается в замороженный спринт:
- **Ориентир по размеру спринта:** 5–8 задач, ориентир а не закон
- **Что такое «сделана»:** пайплайн проекта пройден + критерии приёмки проверены
поимённо
## Язык
- Документация, комментарии, сообщения коммитов — русский.
- Код и идентификаторы — английский.
```
Имя основной ветки, запреты с путями и «что необратимо» — не украшение: без
первого падают git-операции батча и расчёт базы диффа, без второго проход может
тронуть рабочие данные, без третьего вся шкала ранжирования триажа держится на
догадке.
## `docs/.pm.json`
```json
{
"canon": 1
}
```
Плюс `"migrations": "<путь>"`, если есть БД. Ключ `"tasks"` заводится **только**
когда имя файла или заголовка отличается от умолчания (`{"backlog":
"INDEX.md"}`); секций беклога в нём нет — их дом заголовки `##` индекса. Состав
ключей — [canon.md](canon.md).