# Скелеты документов канона Что кладут `init` и `canon adopt` в незаполненный слот. Правило одно: **честная информативная строка вместо заглушки**. Проход читает строку как факт; `` он читает как пробел, и `docs.py check` о таком плейсхолдере напоминает. Плейсхолдер ставится только там, где ответ **обязан** быть и его не спросили. Всё, чего в проекте пока просто нет, описывается словами, а не плейсхолдером. **Шаблоны — единственное место, где правило канона копируется намеренно.** `adr/README.md` и `review.md` уезжают в репозиторий проекта и обязаны там что-то говорить; определение при этом остаётся в [canon.md](canon.md). Отсюда обязанность: **правка такого правила в каноне тянет запись в [changelog.md](changelog.md)** с указанием, какой файл проекта поднимает `upgrade`. Без этого копия в проекте останется на старой версии молча. ## `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//design.md`. ## Когда заводить Верно одно из трёх: - **дорогой откат** — переделка стоит дороже переписывания одного файла; - **намеренный отказ** от очевидного подхода; - **пересмотр прежнего решения** — тогда у старой записи обязателен статус. Не заводить для рутины и того, что видно из кода и `git log`. ## Соглашения - Имя файла — `ADR-ГГГГ-ММ-ДД-slug.md`, слаг английский, дата — когда решение реально принято. - Записи неизменяемы: передумали — новая запись, старой ставится статус. - Активная запись статуса не имеет. Значений два: `заменено на ADR-…` и `устарело`. ## Записи Новые сверху. | Дата | Запись | Статус | | --- | --- | --- | ``` ## `docs/adr/template.md` ```markdown # Краткий заголовок решения - Дата: ГГГГ-ММ-ДД - Источник: openspec/changes/archive//design.md ## Решение Что именно решено — одной фразой. ## Почему Намерение и причина. Цитата из источника, а не пересказ. Пиши так, чтобы через год было понятно без чтения переписки. ## Последствия - `+` что стало лучше. - `−` чем платим: ограничения, риски, нагрузка на поддержку. ``` ## `docs/review.md` ```markdown # Ревью: настройка и журнал ## Как настроен конвейер ### Типовые узлы Рода узлов проекта и 3–5 проверяемых свойств к каждому. Рода, а не инвентарь пакетов: род, который проект задумал, но ещё не написал, включать полезно. ### Типовые ложноположительные Находки, которые здесь выглядят убедительно и всегда неверны. Каждая — с одной строкой «почему здесь это не дефект». ### Вопросы к проходам Форма: `<имя прохода>: <вопрос> (<провенанс>)`. Главный источник — журнал ниже. ### Недоступно проверке **Не проверит ни один проход** — принципиальная граница; по факту промаха не пересматривается. **Перестали проверять сознательно** — что, когда и почему, со ссылкой на запись журнала. Пересматривается **первым**, как только что-то проскочило. ## Журнал дефектов Запись на каждый воспроизведённый дефект, сразу, а не ретроспективно: со временем теряется не факт, а причина непоймания. Форма: ## ГГГГ-ММ-ДД — краткое последствие [проскочил|пойман] - **Где:** файл:строка - **Симптом:** как обнаружилось - **Чем воспроизведён:** тест, команда, замер - **Почему не поймали:** только для проскочивших - **Что меняем:** правило прохода, шаг гейта, конвенция — либо «ничего, цена поимки выше цены дефекта» ``` Новый проект: «Дефектов пока не было. Настройка конвейера появится с первым ревью.» ## `docs/.pm.json` ```json { "canon": 1 } ``` Плюс `"migrations": "<путь>"`, если есть БД, и `"tasks": {"sections": [...]}`, если секции беклога отличаются от умолчания.