Files
dev-skills/av-dev-pm/skills/canon/references/skeletons.md
T
avandClaude Opus 5 cc173b6b94 ступень ревью поднимает проход, а не риск
Полный набор гонялся чаще, чем оправдано, и размер задач тут вторая причина,
не первая. Первая — триггеры: миграция схемы, публичный контракт и инвариант
поднимали ступень, не добавляя ни одного прохода. Миграцию гоняет gate шагом
миграций и разбирает ops, контракт сверяет specs направлением code→spec,
инвариант даёт основание для critical любому проходу — все трое уже в
standard. На проекте с базой и эндпоинтами верхняя ступень оказывалась не
исключением, а умолчанием: правило объявляло исключением то, что происходит
всегда.

Теперь ступень поднимает то, что даёт работу новому проходу. wide означает
ровно одно — изменение вводит новое понятие или структурную единицу; добавить
поле в существующий ответ это не концепт. standard стал рабочим умолчанием.
Проект, где изменение контракта и правда архитектурное, поднимает его сам в
docs/review.md — уточнением, а не возвратом прежнего умолчания.

Чекпоинт design получил то же условие: specs идёт всегда, rubric и
architecture — только при новом понятии. Он стоит на каждой задаче, поэтому
при мелкой нарезке три прохода умножаются на число задач.

Со стороны задач — шов нарезки: тест декомпозиции отвечает, допустим ли
разрез, шов отвечает, где его провести. Резать по границе, за которой падает
ступень; не резать, когда обе половины остаются в одной — костяк из четырёх
проходов платится за каждую задачу, и такой разрез делает ревью дороже.
Порога в числе границ нет по тому же принципу, что в теме 16: размер не
триггер. Дешёвое место заметить разнородную задачу — показ набора спринта,
там «Затрагивает» уже написан, а предложение ещё не заведено.

Правило выведено из состава проходов, а не из статистики прогонов — замер
остаётся за обкаткой. DECISIONS 18, RRR–WWW и следствия 72–75; JJJ темы 17
помечен как пересмотренный. Шаг про «Триггеры профиля» дописан в ещё не
выкаченную версию 3 канона, а не отдельной версией.

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

395 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/ROADMAP.md](tasks/ROADMAP.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
Статус ставится тем же полем и только при пересмотре:
`- **Статус:** заменено на ADR-…` либо `- **Статус:** устарело`.
У активной записи поля нет.
## Решение
Что именно решено — одной фразой.
## Почему
Намерение и причина. Цитата из источника, а не пересказ. Пиши так, чтобы через
год было понятно без чтения переписки.
## Последствия
- `+` что стало лучше.
- `` чем платим: ограничения, риски, нагрузка на поддержку.
```
## `docs/review.md`
```markdown
# Ревью: настройка и журнал
## Как настроен конвейер
### Типовые узлы
Рода узлов проекта и 3–5 проверяемых свойств к каждому. Рода, а не инвентарь
пакетов: род, который проект задумал, но ещё не написал, включать полезно.
### Типовые ложноположительные
Находки, которые здесь выглядят убедительно и всегда неверны. Каждая — с одной
строкой «почему здесь это не дефект».
### Вопросы к проходам
Форма: `<имя прохода>: <вопрос> (<провенанс>)`. Главный источник — журнал ниже.
Проход, увидев свой блок, задаёт эти вопросы дополнительно к обязательным.
### Триггеры профиля
Проектная конкретизация правила выбора профиля: что здесь считается **новым
понятием или структурной единицей** (поднимает прогон до `wide` и запускает
архитектурный проход) и что — правилом идентичности, слияния или разбора
(до `deep`, запускает независимую реализацию). Уточняет умолчания конвейера, не
отменяет их; рабочее умолчание — `standard`.
### Недоступно проверке
**Не проверит ни один проход** — принципиальная граница; по факту промаха не
пересматривается.
**Перестали проверять сознательно** — что, когда и почему, со ссылкой на запись
журнала. Пересматривается **первым**, как только что-то проскочило.
## Журнал дефектов
Запись на каждый воспроизведённый дефект, сразу, а не ретроспективно: со
временем теряется не факт, а причина непоймания.
Форма:
<!-- копия: журнал-дефектов-форма из 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": 2
}
```
Плюс `"migrations": "<путь>"`, если есть БД. Ключ `"tasks"` заводится **только**
когда имя файла или заголовка отличается от умолчания (`{"backlog":
"INDEX.md"}`); секций беклога в нём нет — их дом заголовки `##` индекса. Состав
ключей — [canon.md](canon.md).