--- name: openspec description: "Завести и настроить OpenSpec в проекте — openspec init --tools claude, замена закомментированного примера в openspec/config.yaml на настройку канонической формы (язык, правила именования capability, придирки валидатора, адреса паспорта и CLAUDE.md), проверка, что форма не разошлась с живой версией инструмента. Использовать, когда в проекте нет каталога openspec/, когда config.yaml остался примером из коробки, когда заводят новый проект или переводят чужой и дошли до шага OpenSpec, а также когда конвейер отказался работать без источника требований. Каталог openspec нужен именно конвейеру: без него не работают ни opsx:propose, ни ревью дизайна, ни сверка требований." --- # OpenSpec в проекте Каталог `openspec/` — **предпосылка конвейера**, а не канона документов. Без него не работают ни `opsx:propose`, ни ревью дизайна, ни `review-specs`: у требований не остаётся дома. Поэтому заводит и настраивает его этот плагин — тот, кто по OpenSpec и работает. Канон документов о файле всё ещё высказывается, но односторонне: `docs.py check` проверяет форму `config.yaml`, **если каталог есть**, и молчит, если его нет. Проект без конвейера живёт без OpenSpec законно. ## Два шага, и второй важнее первого **1. Завести.** ``` openspec init --tools claude ``` Команда кладёт ещё `.claude/skills/openspec-*` и `.claude/commands/opsx/*` — это её нормальная работа, не трогай их. **2. Заменить пример.** `openspec init` кладёт `config.yaml`, где `context` и `rules` — закомментированный пример на английском. **Файл из коробки хуже отсутствующего:** он есть, он валиден, имя правильное, — и читается как настроенный, работая как пустой. Узнаётся это по уже написанному предложению: на другом языке, с capability по имени пакета, без единого `SHALL`. Пример **заменяется целиком** по образцу: [references/config-skeleton.md](references/config-skeleton.md). ## Что туда пишут, а что нет **Это маршрутизатор, а не второй дом фактов.** Внутрь идёт ровно то, что нужно **в момент порождения артефакта** и чего в этот момент ещё никто не открыл: язык, правила именования capability, придирки валидатора и **адреса** документов проекта. Пересказ паспорта, инвариантов, конвенций и правил ревью сюда **не переносится**. Место для второго дома здесь самое частое: `context` читается при порождении каждого артефакта, туда удобно дописать «чтобы агент знал», и так заводятся копии инвариантов, состава гейта и правил выбора метки. Расходятся они молча, а замечают это в уже написанном предложении. Разрез, по которому отличают одно от другого: **утверждение, которое можно опровергнуть, открыв другой файл проекта, — пересказ; строка, которая говорит, какой файл открыть, — ссылка.** Машина этот разрез не проверяет; его смотрит агент `doc-consistency` из плагина канона, когда тот подключён. Два адреса обязательны — `docs/passport.md` и `CLAUDE.md`: предложение пишется до того, как кто-либо откроет `docs/`, и без них его пишут, не зная ни границы домена, ни инвариантов. Их отсутствие `docs.py check` называет отказом. ## Форма сверяется с живым инструментом Схема (`spec-driven`) и перечень артефактов (`proposal`, `specs`, `design`, `tasks`) — **состояние чужого инструмента**, а не наше решение. OpenSpec переименует артефакт: правила под прежним именем перестанут применяться, конфиг останется выглядеть написанным, и молчат при этом все три стороны. Сторож — сравнение версий, и живёт он пока в `docs.py` плагина канона: ``` python3 <канон>/skills/canon/scripts/docs.py openspec-form ``` `check` каждым прогоном сравнивает `major.minor` установленного OpenSpec с той версией, на которой форма сверялась, и при расхождении просит эту команду. Она ничего не правит — спрашивает инструмент и печатает, что разошлось. **Чинится расхождение в плагине, а не в проекте.** Плагина канона в проекте нет — сторожа тоже нет, и это надо назвать строкой, а не считать, что форма верна. ## Кто зовёт этот скилл - `av-dev-docs:init` — шагом заведения нового проекта, до первого документа; - `av-dev-docs:canon` в режиме `adopt` — если на переводимом проекте каталога нет или `config.yaml` остался примером; - человек — когда конвейер отказался работать без источника требований. Вызов идёт **через пространство имён**, а не путём в дерево плагина. Не разрешился — плагина конвейера в проекте нет, и тогда OpenSpec заводит человек командой выше; скажи это строкой, а путь не выдумывай. ## Чего этот скилл не делает - **Не пишет спеки и предложения.** Это `opsx:propose` и пайплайн задачи. - **Не ведёт документы канона** — их дом плагин `av-dev-docs`, и адреса в `context` только на них ссылаются. - **Не чинит расхождение формы с версией OpenSpec в проекте.** Оно чинится в плагине: константы скрипта, образец здесь, запись в журнал версий канона.