10 KiB
Spec Delta: dsh-install
Purpose
Слой установки DSH-обвязки: откуда берутся superpowers-скиллы и роли, что
делает dsh/install.sh --skills/--roles, какие пути попадают в установленные
инструкции. В Claude Code источником служит кэш плагина в ~/.claude; в DSH
источник задаётся установщиком явно (аргумент, переменная или пиннинг в
~/.dsh), а ~/.claude остаётся только legacy-fallback'ом с предупреждением.
Контракт нужен, чтобы свежая установка на машине без Claude Code проходила
полный цикл #48 и чтобы путь ~/.claude не возвращался в runtime незаметно.
ADDED Requirements
Requirement: Источник superpowers задаётся при установке
dsh/install.sh --skills SHALL разрешать источник superpowers-скиллов в
порядке приоритета и MUST NOT исполнять git clone и любые сетевые операции.
- Порядок:
--superpowers-from <dir>→$DSH_SUPERPOWERS_SOURCE→$DSH_HOME/superpowers/skills(пиннинг; допускается и корень$DSH_HOME/superpowersс подкаталогомskills/) → legacy-кэш Claude Code → legacy~/.claude/skills. - Для явного источника (
--superpowers-from,$DSH_SUPERPOWERS_SOURCE) допускаются обе формы: корень superpowers (естьskills/using-superpowers/SKILL.md) или сам каталогskills. - Явно заданный, но невалидный источник MUST приводить к
FAILи коду возврата 1: тихий откат на legacy запрещён. - Копирование MUST быть заменой каталога назначения (
rm -rf+cp -R), а не симлинком:~/.dsh/skillsне должен зависеть от каталога-источника.
Scenario: Явный источник без ~/.claude
- WHEN
HOME— пустой temp-каталог без~/.claude, а--superpowers-fromуказывает на каталог superpowers - THEN
--skillsкопирует скиллы в$DSH_HOME/skills, печатает источник и завершается кодом 0
Scenario: Переменная окружения вместо флага
- WHEN задан
DSH_SUPERPOWERS_SOURCE=<dir>и флаг--superpowers-fromне передан - THEN источник берётся из переменной; поведение совпадает с флагом
Scenario: Флаг важнее переменной
- WHEN заданы и
--superpowers-from, иDSH_SUPERPOWERS_SOURCE - THEN используется каталог из флага
Scenario: Невалидный явный источник
- WHEN
--superpowers-fromуказывает на каталог безusing-superpowers/SKILL.md - THEN
--skillsпечатаетFAILс ожидаемой структурой и завершается кодом 1, ничего не копируя из legacy-источников
Scenario: Пиннинг в ~/.dsh
- WHEN существует
$DSH_HOME/superpowers/skills/using-superpowers/SKILL.mdи флаг/переменная не заданы - THEN источником служит этот каталог,
--checkпечатаетok: superpowers source (<path>)
Requirement: Отсутствие источника не бывает тихим
Если источник superpowers не найден, --skills MUST различать первичную и
повторную установку и MUST NOT завершаться успехом молча.
- Если
$DSH_HOME/skills/using-superpowers/SKILL.mdуже существует —WARN«источник не найден, копии сохранены» и код 0 (идемпотентный повтор). - Если копий нет —
FAILс готовой командой получения источника (git clone --depth 1 https://github.com/obra/superpowers ~/.dsh/superpowers) и код возврата 1. - Локальные скиллы обвязки (
dsh/skills/*:role,sdd) MUST ставиться в обоих случаях: они не зависят от superpowers.
Scenario: Первая установка без источника
- WHEN
HOMEпуст,$DSH_HOME/skillsне существует, источника нет - THEN
--skillsпечатаетFAIL, код 1, но$DSH_HOME/skills/role/SKILL.mdи$DSH_HOME/skills/sdd/SKILL.mdна месте
Scenario: Повторная установка без источника
- WHEN
$DSH_HOME/skills/using-superpowers/SKILL.mdуже есть, источника нет - THEN
--skillsпечатаетWARN, код 0, установленные скиллы не удалены
Requirement: ~/.claude — только legacy-fallback с предупреждением
superpowers-скиллы и роли MUST иметь рабочий путь ~/.dsh; пути ~/.claude
SHALL оставаться fallback'ом для машин, где --skills --roles ещё не
перезапускали, и MUST сопровождаться предупреждением.
- Установка: legacy-кэш Claude Code и
~/.claude/skillsдопустимы как источник, но--skillsпечатаетWARN: legacy superpowers sourceс подсказкой перейти на пиннинг/флаг. --check: legacy-источник —WARN, явный/пиннинг —ok, отсутствие —WARNс подсказкой, невалидный явный источник —FAILи код 1 (пользователь задал его сам, подсказка «нет источника» здесь неверна).- Runtime: bootstrap и резолвер ролей сохраняют порядок
~/.dsh→~/.claude, но при выборе legacy-пути один раз за процесс пишут в лог предупреждение. - Удаление fallback'ов — отдельное изменение; в этом change они не удаляются.
Scenario: Legacy-кэш как источник установки
- WHEN в
HOMEесть только кэш Claude Code с superpowers,$DSH_HOMEпуст - THEN
--skillsкопирует скиллы и печатаетWARN: legacy superpowers source
Scenario: Runtime-предупреждение
- WHEN bootstrap резолвит
using-superpowersиз~/.claude/... - THEN в лог один раз за процесс попадает предупреждение с предложением
выполнить
dsh/install.sh --skills
Scenario: ~/.dsh приоритетнее
- WHEN существуют и
~/.dsh/skills/using-superpowers/SKILL.md, и legacy-копия - THEN используется
~/.dsh, предупреждения нет
Requirement: Установленные инструкции DSH не ссылаются на ~/.claude
dsh/install.sh --global MUST писать $DSH_HOME/AGENTS.md так, чтобы пути
ролей указывали на DSH-слой, а формат инструкций не выдавался за runtime
Claude Code.
- Строки
~/.claude/rolesв установленной копии MUST заменяться на~/.dsh/roles, а adapter-шапка MUST NOT называть пути~/.claude: в установленном файле не остаётся ни одного такого пути.global/CLAUDE.mdв репозитории MUST NOT меняться (его читает Claude Code). - Шапка установленного файла MUST говорить, что проектный
CLAUDE.md/AGENTS.md— это формат файлов инструкций DSH, а не запущенный Claude Code, и что роли лежат в~/.dsh/roles(--roles), а superpowers-скиллы — в~/.dsh/skills(--skills). - Повторный
--globalобязан делать бэкап прежнегоAGENTS.md(как сейчас).
Scenario: Пути ролей после установки
- WHEN выполнен
--globalво временныйDSH_HOME - THEN в
AGENTS.mdесть~/.dsh/roles/dev.mdи нет ни одного пути~/.claude
Scenario: global/CLAUDE.md не тронут
- WHEN выполнен
--global - THEN
global/CLAUDE.mdв репозитории побайтно не изменился
Requirement: Чистый HOME без ~/.claude проходит установку
Установка, bootstrap и skill role MUST работать на машине, где Claude Code
никогда не устанавливался.
--global --skills --rolesс явным источником superpowers в пустомHOMEMUST создавать$DSH_HOME/{AGENTS.md,skills/using-superpowers/SKILL.md,skills/role/SKILL.md,skills/sdd/SKILL.md,roles/dev.md}.- bootstrap MUST резолвить скилл из
$DSH_HOME/skillsприhomeэтого HOME и MUST NOT обращаться к~/.claude. - Резолвер ролей MUST находить
$DSH_HOME/rolesприhomeэтого HOME.
Scenario: Установка в чистый HOME
- WHEN
HOME— пустой temp-каталог,DSH_HOME=$HOME/.dsh,--superpowers-fromуказывает на каталог superpowers - THEN
--global --skills --rolesзавершается кодом 0, все перечисленные файлы на месте,--checkзелёный по skills и roles
Scenario: Bootstrap в чистом HOME
- WHEN
prepareBootstrap({ home: <temp HOME> })вызывается после установки - THEN выбранный путь —
$HOME/.dsh/skills/using-superpowers/SKILL.md, текст содержит маркер<!-- DSH-HARNESS-BOOTSTRAP:... -->, предупреждений о legacy нет