Версия 7 объявила openspec/ слотом канона: init его заводил, adopt тоже, образец config.yaml лежал в скелетах, отсутствие каталога docs.py считал отказом. Разрез был проведён не там. По OpenSpec работает конвейер — без каталога не запускаются ни opsx:propose, ни ревью дизайна, ни сверка требований, — а канон документов о нём только высказывался. Проект, которому конвейер не нужен, получал отказ за отсутствие того, чем не пользуется. Появился скилл av-dev-pipeline:openspec: заводит каталог, заменяет закомментированный пример в config.yaml настройкой, объясняет разрез между ссылкой и пересказом — утверждение, опровергаемое открытием другого файла, это пересказ; строка, говорящая какой файл открыть, это ссылка. Образец переехал туда же, в references/config-skeleton.md, а в скелетах канона остался указатель. init и canon adopt OpenSpec больше не заводят, а зовут скилл конвейера через пространство имён. Вызов не разрешился — плагина конвейера нет, и это строка доклада, а не поломка: docs.py о каталоге тогда тоже молчит. Отсутствие openspec/ стало неприменимостью вместо отказа, остальные четыре проверки формы идут только при живом каталоге. На фикстуре без openspec дрейф упал с 10 пунктов до 9. Что осталось на месте и названо честно: проверка формы config.yaml и сторож версии (docs.py openspec-form) пока живут в скрипте канона. Перенести их значит завести в конвейере свой скрипт, а этого у него нет ни одного. У файла сейчас два плагина — один заводит, другой проверяет, — и это временное состояние, а не задуманное; в журнале версий оно записано так же. Канон повышен до версии 9. Запись не двигает ни одного файла проекта: меняется только то, кто их заводит. Но в ней названа потеря, которую легко не заметить — проект по OpenSpec без установленного пайплайна теперь не услышит от docs.py ничего про свою настройку, и молчание это законное. Гейт зелёный, скиллов стало десять. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
98 lines
7.7 KiB
Markdown
98 lines
7.7 KiB
Markdown
---
|
||
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 в проекте.** Оно чинится в
|
||
плагине: константы скрипта, образец здесь, запись в журнал версий канона.
|