10 KiB
Design: OpenSpec в DSH
Issue: #42. Спека: openspec/changes/dsh-openspec/specs/dsh-openspec/spec.md.
Спайк: 24.10.2026, temp-проект /tmp/openspec-spike-dPkz, openspec 1.13.1.
1. Что показал спайк
| Проверка | Результат |
|---|---|
openspec init --tools agents в пустом git-проекте |
6 скиллов в .agents/skills/, openspec/config.yaml, openspec/{specs,changes/archive}; AGENTS.md не создаётся |
| Команды | Commands skipped for: agents (no adapter) — слэш-команд адаптер не ставит |
--tools claude, затем --tools agents |
.claude/skills и .claude/commands/opsx остаются нетронутыми, .agents/skills добавляется рядом |
| Отличие agents-скиллов от claude-скиллов | одна строка подсказки (/opsx:apply → /openspec-apply-change) и allowed-tools: Bash(openspec:*) в frontmatter |
openspec new change → instructions → validate --strict → archive -y |
весь цикл без интерактивных вопросов; спека probe создалась, change ушёл в openspec/changes/archive/2026-10-24-spike-test/ |
openspec change new |
команды нет; группа new скрыта из верхнего --help, но openspec new change <name> работает |
DSH видит .agents/skills |
да: сабагент, запущенный с cwd в worktree после openspec init --tools agents, получил в каталоге скиллов все шесть openspec-* |
Последняя строка — главная: проектный корень скиллов DSH действительно читает
.agents/skills, поэтому отдельный слой совместимости не нужен.
2. Решения
R-1 (решение владельца). Скиллы живут в проекте, не глобально
openspec init --tools agents пишет .agents/skills в проект; в ~/.dsh/skills
копии нет. Обоснование:
- версия скиллов совпадает с версией CLI проекта,
openspec updateих обновляет; - глобальная копия стареет молча и не знает про
--storeи профили конкретного проекта; - если проект сделал init сам, глобальная копия даёт два скилла с одним именем; поведение DSH при дублях не проверено, и проверять его незачем.
Цена: новый проект нужно один раз подключить (--openspec или openspec init).
Это осознанно: OpenSpec — свойство проекта, а не машины.
R-2 (решение владельца). Слэш-команды нет
Вход — model-invocable скиллы: их description содержит «openspec propose»,
«openspec archive» и т.п., поэтому фраза владельца запускает воркфлоу без
команды. /role остаётся единственной командой бандла. Цена: в DSH нет
аналога /opsx:*, набирать команды вручную нельзя — только просить модель.
Это укладывается в то, как DSH уже работает с ролями.
R-3. --openspec не создаёт OpenSpec-корень
Флаг добавляет agents-адаптер к проекту, который уже использует OpenSpec: если
openspec/ нет, скрипт отказывается и печатает готовую команду. Иначе
--openspec в чужом каталоге молча завёл бы openspec/, config.yaml и
changes-каталог — побочный эффект, который не читается из названия флага.
R-4. --check предупреждает, а не падает
Отсутствие openspec в PATH — WARN: guard, bootstrap, роли и SDD от него не
зависят. Код возврата --check меняют только FAIL-пункты (python3, git,
node, хуки, бандл).
R-5. Проверка «DSH видит скиллы» — живая, не в тестах
Юнит-тест может проверить наличие и frontmatter файлов, но не то, что DSH
подхватил каталог. Поэтому в тестах — файлы и поведение install.sh, а
видимость проверяется один раз живой сессией (сабагент с cwd в проекте) и
фиксируется здесь.
3. Отличия от Claude Code
| Что | Claude Code | DSH |
|---|---|---|
Куда ставит openspec init |
.claude/skills + .claude/commands/opsx/* |
.agents/skills, без команд |
| Вход | /opsx:propose, /opsx:apply, … |
скиллы по имени/фразе; команды нет |
| Обновление | openspec update |
openspec update, тот же генератор |
| Глобальная копия | нет | нет (R-1) |
Обе копии в одном репозитории — не дублирование ради дублирования: это два
клиента одного генератора. Расхождение ловится повторным openspec init /
openspec update, а не ручной синхронизацией.
4. Решения, принятые без обсуждения
- 2026-10-24. Скиллы
.agents/skillsкоммитятся в репозиторий обвязки. Обвязка сама ведёт спеки через OpenSpec, а dogfooding — единственный способ держать слой проверенным. Обоснование: если скиллы не закоммичены, первый же DSH-прогон в этом репозитории их не увидит. Цена ошибки: лишние 6 каталогов в диффе при обновлении openspec; лечитсяopenspec updateи отдельным коммитом. - 2026-10-24.
.openspec-target(agents) коммитится вместе со скиллами. Это маркер адаптера, который пишет генератор; без негоopenspec updateне знает, какой адаптер обновлять. Цена ошибки: одна строка в диффе. - 2026-10-24. Тест
--openspecподставляет фейковый бинарьopenspecв PATH. Тесты DSH-порта идут без внешних CLI (см.dsh/tests/run.sh); живой openspec в тесте сделал бы набор зависимым от машины. Цена ошибки: тест не проверяет настоящий генератор — это делает живая приёмка. - 2026-10-24. Проверка скиллов в
--checkсмотрит репозиторий обвязки ($ROOT), а не cwd.install.sh— скрипт установки обвязки, его--checkотвечает за состояние обвязки; проект проверяется флагом--openspec. Цена ошибки: из чужого проекта--checkпокажетWARNо скиллах обвязки — сообщение говорит, что делать.
5. Риски
- Версия скиллов против CLI. Скиллы генерирует CLI; если проект обновит
openspecи не выполнитopenspec update, скиллы отстанут от CLI.--checkсравнивать версии не будет: он не знает, какой CLI у проекта. Признак —metadata.generatedByво frontmatter. .claude/commands/opsxв DSH не работают и остаются в репозитории для Claude Code. Это не мёртвый груз, а второй клиент; в PORT.md написано явно.- DSH при дублях скиллов. Не проверено и не проверяется, потому что
глобальной копии нет (R-1). Если кто-то поставит
openspec init --tools agentsпри уже скопированных вручную скиллах, поведение определит DSH. openspec initпишет в проект. Флаг--openspecзапускается только по явной команде и только при существующемopenspec/;adopt-project.shиnew-project.shего не вызывают.
6. Приёмка
openspec validate dsh-openspec --strict— change валиден.bash dsh/tests/run.sh— зелёный, включая новыйopenspec.test.mjs.- Живая проверка DSH: сессия/сабагент с cwd в проекте после
openspec init --tools agentsвидит шестьopenspec-*в каталоге скиллов; полный циклnew change → validate --strict → archive -yпроходит без Claude Code (спайк 24.10.2026, транскрипт — в отчёте задачи). /roleи bootstrap не изменились: тестыrole-skill.test.mjs,bootstrap.test.mjsиsdd-skill.test.mjsзелёные.
Приёмка: прогон 24.10.2026
- CLI: openspec 1.13.1, temp-проект
/tmp/dsh-openspec-accept, веткаfeat/probe. openspec init --tools agents: шесть скиллов в.agents/skills; повторный прогон идемпотентен, файлы не задвоились.openspec new change probe→status→instructions proposal→ написаныproposal.mdи дельтаspecs/probe/spec.md.openspec validate probe --strict→Change 'probe' is valid.openspec archive probe -y→Specs updated successfully./Change 'probe' archived as '2026-10-24-probe'., основная спекаopenspec/specs/probe/spec.mdсоздана.- Видимость скиллов в DSH-сессии проверяет контроллер отдельным сабагентом; результат дописывается сюда после прогона.