Слияние ничего из идей не тронуло, но сделало дешёвым дом для правила, натянутого между скиллами. Заведён shared/axes.md — дом перечня, а не значений: девять осей, их адреса и чего каждая не решает. Механика остаётся у владельца. Целиком сюда переехали две оси, у которых владельца не было. Коды выхода объявлялись общим словарём в одиннадцати местах, и каждое объявление называло свой набор соседей; машина их не сверяла, потому что copies.py смотрит markdown, а перечни лежали в docstring'ах. Теперь дом один, скрипты держат указатель, а три SKILL.md — помеченную копию, потому что на кодах они ветвятся. Режим прогона (с меткой, без метки) был размазан по четырём файлам и осью назван не был, хотя в уставе review-basics задаёт саму возможность запуска. Разведены два значения слова «стадия»: ступени 1-5 внутри прогона кода, стадии дизайна и кода снаружи. Карта нашла ошибку в себе: клетка «категория документа × метка» пустой не была — review-basics приёмник проектных тем при любой метке. Пустой оказалась соседняя: на прогоне без метки план фиксирован, и своих тем проекта в нём нет вовсе. Обе оставшиеся пустоты названы вслух, а не заполнены наугад.
16 KiB
name, description
| name | description |
|---|---|
| code-openspec | Завести и настроить 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 его не открывает и об
его отсутствии молчит. Проект, не ведущий задачи циклом SDD, живёт без 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.
Что туда пишут, а что нет
Это маршрутизатор, а не второй дом фактов. Внутрь идёт ровно то, что нужно в момент порождения артефакта и чего в этот момент ещё никто не открыл: язык, правила именования capability, придирки валидатора и адреса документов проекта.
Сюда же — требования к форме proposal и design, на которых стоит чекпоинт
скилла av-dev:code-resolve: объяснение человеку собирается из этих двух
артефактов, и требование к ним обязано применяться в момент, когда их пишут, а не
вспоминаться шагом позже. Образец их содержит.
Пересказ паспорта, инвариантов, конвенций и правил ревью сюда не переносится.
Место для второго дома здесь самое частое: context читается при порождении
каждого артефакта, туда удобно дописать «чтобы агент знал», и так заводятся копии
инвариантов, состава гейта и правил выбора метки. Расходятся они молча, а
замечают это в уже написанном предложении.
Разрез, по которому отличают одно от другого: утверждение, которое можно
опровергнуть, открыв другой файл проекта, — пересказ; строка, которая говорит,
какой файл открыть, — ссылка. Машина этот разрез не проверяет; его смотрит
агент doc-consistency, когда документы канона в проекте есть.
Два адреса обязательны — docs/passport.md и CLAUDE.md: предложение пишется до
того, как кто-либо откроет docs/, и без них его пишут, не зная ни границы
домена, ни инвариантов. Отсутствие адреса к существующему документу
openspec.py check называет отказом; документа нет в проекте — нет и требования.
Инструмент
os="$CLAUDE_PLUGIN_ROOT/skills/code-openspec/scripts/openspec.py"
python3 $os check --dir <корень> # форма config.yaml в проекте
python3 $os form # слепок формы против живого OpenSpec
Копия. Дом словаря — shared/axes.md в репозитории плагина: словарь общий
для всех скриптов, и ни один скилл им не владеет. Правится дом, а не этот файл.
Коды выхода — общий словарь всех скриптов av-dev. Ветвись на коде, а не на
тексте вывода.
| Код | Что случилось |
|---|---|
| 0 | сошлось |
| 1 | дрейф: рабочая ситуация, чинится |
| 2 | ошибка употребления: аргументы или нарушенное правило |
| 3 | окружение: не тот каталог, битый конфиг, нет инструмента |
| 4 | внутренний сбой — дефект скрипта, доложить |
Различать 1 и 3 обязательно. «Дрейф» — рабочая ситуация, и чинится она правкой предмета; «окружение» — нерабочая, и повтор той же командой не поможет. Одинаковая реакция на них неверна в обоих случаях.
Здесь это значит: «форма разошлась» — рабочая ситуация, «openspec не отвечает» — нерабочая.
check проверяет форму, и каждая проверка — про молчащий пробел, а не про вкус:
каталог есть; имя именно config.yaml (config.yml OpenSpec не читает и об этом
не сообщает); ключ schema называет ту схему, для которой форма описана;
context и rules.specs не остались примером, а SHALL назван именно внутри
rules.specs (в context он стоит и в образце, поэтому греп по файлу здесь
ничего не значит); 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 и запись в журнал
версий канона.
Кто зовёт этот скилл
av-dev:doc-init— шагом заведения нового проекта, до первого документа;av-dev:doc-canonв режимеadopt— если на переводимом проекте каталога нет илиconfig.yamlостался примером;av-dev:code-resolveиav-dev:code-review— не вызовом по ходу, а отсылкой: OpenSpec у обоих жёсткая предпосылка, и на проекте без каталога оба посылают сюда вместо того, чтобы заводить его руками;- человек — когда конвейер отказался работать без источника требований.
Копия. Дом правила — shared/absence.md в репозитории плагина.
Правится дом, а не этот файл.
Скилл не вправе считать раскладку проекта полной. Части заводятся порознь и живут порознь; каждая узнаётся своим следом:
| Чего нет | Как видно | Чего теперь не делает никто |
|---|---|---|
| настройки av-dev | нет .av-dev.toml в корне |
проект под процесс не заводился; версии нет, настроек нет |
| документы канона | нет docs/ |
проектную конкретику брать неоткуда — темы, инварианты, прецеденты |
| учёт работ | нет каталога задач | запись остаётся владельцу: назови её текстом в докладе |
| источник требований | нет openspec/config.yaml |
цикл SDD не запускается: спеки не с чем сверять |
Свой скилл зовётся полным именем — av-dev:doc-canon, av-dev:task-track,
av-dev:code-review. Короткое имя может разрешиться в устаревшую проектную
копию из .claude/skills/, и подмены не будет видно ни в докладе, ни в
поведении.
Внешний плагин может не стоять. Их два: opsx:* — цикл SDD, и
av-dev-git:commit — сообщения коммитов. Путь в дерево чужого плагина не
пишется никогда: $CLAUDE_PLUGIN_ROOT ведёт только в своё дерево, а
вычисленный от него путь к соседу либо не откроется, либо откроет чужую
установку. Нужен чужой справочник — зови владеющий им скилл, он прочитает его
сам.
Отсутствие — исход, а не поломка. Назови строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя: пропуск неотличим от сделанного. Выдумывать обходной путь нельзя тоже.
Присутствие узнаётся следом в проекте, а не объявлением. Перечня того, что здесь заведено, проект не ведёт — он разошёлся бы с действительностью молча.
Здесь это значит: документов канона в проекте может не быть, и тогда context
называет только те адреса, которые есть, — строкой доклада говорится, что без
паспорта предложение пишут, не зная границы домена.
Чего этот скилл не делает
- Не пишет спеки и предложения. Это
opsx:proposeи конвейер задачи. - Не ведёт документы канона — их дом скилл
av-dev:doc-canon, и адреса вcontextтолько на них ссылаются. - Не чинит расхождение формы с версией OpenSpec в проекте. Оно чинится в плагине: константы скрипта, образец здесь, запись в журнал версий канона.
- Не судит, ссылается
contextна документы или пересказывает их. Машине этот разрез не виден; его смотрит агентdoc-consistency. Документов канона в проекте нет — сверять пересказ не с чем, и так и скажи.