Files
dev-skills/av-dev-pipeline/skills/openspec/SKILL.md
T
av c5e6883461 task-pipeline переписан в resolve: два плановых стопа
Автоматическое решение задач агентом работает плохо, и хуже того — в
процессе перестаёт ориентироваться автор. В цикл возвращается человек,
но не согласованием на каждом шаге: доктрина «делать, а не спрашивать»
не отменена, а ограничена местом. Развилка до ближайшего чекпоинта
копится в него, после последнего — уходит вопросом в запись.

Чекпоинтов два. «Варианты» — у исследовательской задачи, до первого
требования: 2-4 способа с ценой каждого и рекомендацией, выбор оседает
по адресу, который назвала сама запись. «Объяснение» — у всякой, после
ревью дизайна: человек читает просеянное машиной.

Объяснение не завело своего артефакта — оно собирается из proposal.md и
design.md, а требование к их форме уехало в openspec/config.yaml
(rules.proposal, rules.design), то есть применяется в момент написания.
Отдельный раздел был бы третьим домом одного объяснения.

Закрыт открытый вопрос: находка ревью, меняющая дельта-спеки, отменяет
одобрение — разметка пересчитывается, чекпоинт повторяется.
2026-08-09 15:34:13 +03:00

163 lines
14 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.
---
name: openspec
description: "Завести и настроить OpenSpec в проекте — openspec init --tools claude, замена закомментированного примера в openspec/config.yaml на настройку канонической формы (язык, правила именования capability, придирки валидатора, адреса паспорта и CLAUDE.md), проверка формы своим скриптом openspec.py (имя файла, схема, незаменённый пример, адреса документов, ключи rules против артефактов схемы) и сверка слепка с живой версией инструмента. Использовать, когда в проекте нет каталога openspec/, когда config.yaml остался примером из коробки, когда заводят новый проект или переводят чужой и дошли до шага OpenSpec, а также когда конвейер отказался работать без источника требований. Каталог openspec нужен именно конвейеру: без него не работают ни opsx:propose, ни ревью дизайна, ни сверка требований."
---
# OpenSpec в проекте
Каталог `openspec/`**предпосылка конвейера**, а не канона документов. Без него
не работают ни `opsx:propose`, ни ревью дизайна, ни `review-specs`: у требований
не остаётся дома. Поэтому заводит и настраивает его этот плагин — тот, кто по
OpenSpec и работает.
Канон документов о файле не высказывается вовсе: `docs.py` его не открывает и об
его отсутствии молчит. Проект без конвейера живёт без OpenSpec законно, и
проверять там нечего. За каноном остаётся одно — **единственный дом**: не
пересказан ли в `context` документ, у которого есть свой файл. Это суждение, а не
форма, и смотрит его агент.
## Два шага, и второй важнее первого
**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, придирки валидатора и **адреса** документов
проекта.
Сюда же — **требования к форме `proposal` и `design`**, на которых стоит чекпоинт
скилла `av-dev-pipeline:resolve`: объяснение человеку собирается из этих двух
артефактов, и требование к ним обязано применяться в момент, когда их пишут, а не
вспоминаться шагом позже. Образец их содержит.
Пересказ паспорта, инвариантов, конвенций и правил ревью сюда **не переносится**.
Место для второго дома здесь самое частое: `context` читается при порождении
каждого артефакта, туда удобно дописать «чтобы агент знал», и так заводятся копии
инвариантов, состава гейта и правил выбора метки. Расходятся они молча, а
замечают это в уже написанном предложении.
Разрез, по которому отличают одно от другого: **утверждение, которое можно
опровергнуть, открыв другой файл проекта, — пересказ; строка, которая говорит,
какой файл открыть, — ссылка.** Машина этот разрез не проверяет; его смотрит
агент `doc-consistency` из плагина канона, когда тот подключён.
Два адреса обязательны — `docs/passport.md` и `CLAUDE.md`: предложение пишется до
того, как кто-либо откроет `docs/`, и без них его пишут, не зная ни границы
домена, ни инвариантов. Отсутствие адреса к **существующему** документу
`openspec.py check` называет отказом; документа нет в проекте — нет и требования.
## Инструмент
```
os="$CLAUDE_PLUGIN_ROOT/skills/openspec/scripts/openspec.py"
python3 $os check --dir <корень> # форма config.yaml в проекте
python3 $os form # слепок формы против живого OpenSpec
```
**Коды выхода — общий словарь скриптов av-dev:** 0 сошлось, 1 дрейф, 2 ошибка
употребления, 3 окружение, 4 внутренний сбой. Ветвись на коде, а не на тексте.
Различать 1 и 3 обязательно: «форма разошлась» — рабочая ситуация, «openspec не
отвечает» — нерабочая.
`check` проверяет пять вещей, и каждая — про молчащий пробел, а не про вкус:
каталог есть; имя именно `config.yaml` (`config.yml` OpenSpec не читает и об этом
не сообщает); `context` и `rules.specs` не остались примером, а правила называют
`SHALL`; `context` называет паспорт и `CLAUDE.md`; ключи под `rules:` — имена
артефактов схемы, а не свободные слова.
**Адреса требуются только к тем документам, которые в проекте есть.** Канон
документов ставится отдельным плагином и может быть не подключён; требовать
ссылку на несуществующий файл значит требовать битую ссылку. Нет
`docs/passport.md` — проверка по нему идёт строкой «не проверялось», и там же
сказано, что без канона конвейер работает вслепую.
### Форма сверяется с живым инструментом
Схема (`spec-driven`) и перечень артефактов (`proposal`, `specs`, `design`,
`tasks`) — **состояние чужого инструмента**, а не наше решение. OpenSpec
переименует артефакт: правила под прежним именем перестанут применяться, конфиг
останется выглядеть написанным, и молчат при этом все три стороны.
Сторож — сравнение версий. `check` каждым прогоном спрашивает `openspec
--version` (десятые доли секунды) и сравнивает `major.minor` с той версией, на
которой форма сверялась; разошлось — **замечание**, не отказ, с именем команды.
Патч-версия в сравнение не берётся намеренно: формы она не меняет, а нагоняй на
каждый багфикс приучает пролистывать весь блок.
Перепроверяет `openspec.py form`: он спрашивает `openspec templates --json`, то
есть перечень артефактов текущей схемы, и печатает, что разошлось с константами.
Дорогой вызов вынесен из `check` сознательно — он стоит втрое дороже опроса
версии, а ответ меняется только вместе с версией. **Чинится расхождение в
плагине, а не в проекте:** константы скрипта, образец
[references/config-skeleton.md](references/config-skeleton.md) и запись в журнал
версий канона.
## Кто зовёт этот скилл
- `av-dev-docs:init` — шагом заведения нового проекта, до первого документа;
- `av-dev-docs:canon` в режиме `adopt` — если на переводимом проекте каталога нет
или `config.yaml` остался примером;
- человек — когда конвейер отказался работать без источника требований.
**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов.
Правится дом, а не этот файл.
<!-- копия: граница-плагинов из shared/plugin-boundary.md -->
Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на
месте.
**Чужой скилл зовётся полным именем**`av-dev-docs:canon`,
`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может
разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет
видно ни в докладе, ни в поведении.
**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт
только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо
откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он
прочитает его сам.
**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови
строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя,
пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже.
**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня
установленных плагинов проект не ведёт — он разошёлся бы с действительностью
молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json`
канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер.
<!-- /копия: граница-плагинов -->
Здесь это значит: вызов не разрешился — плагина конвейера в проекте нет, и тогда
OpenSpec заводит человек командой выше.
## Чего этот скилл не делает
- **Не пишет спеки и предложения.** Это `opsx:propose` и пайплайн задачи.
- **Не ведёт документы канона** — их дом плагин `av-dev-docs`, и адреса в
`context` только на них ссылаются.
- **Не чинит расхождение формы с версией OpenSpec в проекте.** Оно чинится в
плагине: константы скрипта, образец здесь, запись в журнал версий канона.
- **Не судит, ссылается `context` на документы или пересказывает их.** Машине
этот разрез не виден; его смотрит агент `doc-consistency` из плагина канона.
Плагина нет — эту проверку не делает никто, и так и скажи.