test(plugins): тесты мода /feature в наборе обвязки, plugins/ — каталог кода (#7)

Агент, который правит обвязку, должен видеть мод частью проекта:
- tests/test-feature-plugin.sh — манифест, README и `claude plugin test`
  /`validate` мода в составе bash tests/run.sh; без claude в PATH — пропуск
  с пометкой. Правка формата ledger/Findings/Decisions без правки мода
  теперь роняет набор (проверено: испорченное ожидание → FAIL).
- .claude/code-paths: plugins/ — правки мода под require-plan, как hooks/
  и skills/.
- CLAUDE.md: команды тестов мода и запуск из worktree (--plugin-dir),
  правило «меняешь формат — правь мод в том же PR».

bash tests/run.sh — 162/162.

Refs #7

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-15 11:56:20 +04:00
parent 069c5643b1
commit 3aa34db5f0
3 changed files with 24 additions and 1 deletions

View File

@ -1,2 +1,3 @@
hooks/
skills/
plugins/

View File

@ -24,6 +24,7 @@
## Команды
- `bash tests/run.sh [имя]` — весь набор тестов. Зелёным считается только весь набор.
- `claude plugin test plugins/feature`, `claude plugin validate plugins/feature` — тесты и манифест мода `/feature` (входят в `tests/run.sh`). Попробовать мод из worktree: `claude --plugin-dir <worktree>/plugins/feature`.
- `bash install.sh --check` — проверка окружения: бинарники, плагины, конфликты.
- `bash install.sh` — установка глобальной части, идемпотентно.
- `bash skills/harness-doctor/scripts/doctor.sh [проект]` — отчёт и самотест хуков. Только чтение.
@ -35,6 +36,7 @@
- `tests/run.sh` — автоматические тесты источников (хуки через фиктивный JSON, скрипты во временных каталогах, размеры). Самотест хуков в `doctor.sh` проверяет установленные копии; перед ним `bash install.sh`.
- Ручная проверка хука: на main в любом репозитории попросить агента создать файл, ожидается `BLOCKED`.
- `tests/` покрывает `role-hint` и скрипты `install.sh`, `doctor.sh`, `link-roles.sh`; регрессионные тесты `guard-main` и `require-plan` на реальных командах из транскриптов (бэклог ретро B2) пока не сделаны.
- `tests/test-feature-plugin.sh` прогоняет тесты мода `/feature` через `claude plugin test` (нужен `claude` в PATH, иначе пропуск с пометкой). Мод читает форматы обвязки — ledger, таблицу `## Findings`, `Decisions made without discussion`, планы; меняешь формат — правь мод и его тесты в том же PR (контракт — `plugins/feature/README.md`).
## Текущая работа
Бэклог обвязки — `docs/retro/2026-10-11.md`, раздел 4 (B1–B12), решения владельца — раздел 5. Порядок: B1+B2 (guard-main по цели записи, тесты хуков), затем B5+B6 (роли и память, спека `docs/superpowers/specs/2026-10-11-roles-and-memory-design.md`), затем B3/B4/B10. Находки ретро маркируются `RT-n`.
@ -44,4 +46,4 @@
- Когда brainstorming классифицировал задачу как architectural, структуру change создать через `openspec new change <id>` (или `/opsx:propose <id>`), а содержимое proposal.md, specs/ и design.md написать по итогам brainstorming. tasks.md из OpenSpec не заполнять — задачи живут в плане superpowers.
- `/opsx:apply` не использовать: исполнение идёт через writing-plans и SDD/executing-plans.
- `openspec archive <id>` — после merge PR, как часть чеклиста закрытия.
- Хук require-plan защищает любой каталог `src/` на любой глубине. Если код лежит иначе — перечислить каталоги (префиксы от корня, по одному в строке) в `.claude/code-paths`. В этом репозитории код — `hooks/` и `skills/`, они перечислены в `.claude/code-paths`.
- Хук require-plan защищает любой каталог `src/` на любой глубине. Если код лежит иначе — перечислить каталоги (префиксы от корня, по одному в строке) в `.claude/code-paths`. В этом репозитории код — `hooks/`, `skills/` и `plugins/`, они перечислены в `.claude/code-paths`.

View File

@ -0,0 +1,20 @@
# Мод /feature (plugins/feature): его тесты и проверка манифеста — часть набора обвязки.
# Мод читает форматы обвязки (ledger, ## Findings, Decisions в design.md, планы): правка формата
# без правки мода должна ронять этот набор. Нужен `claude` в PATH; без него — пропуск с пометкой.
P="$ROOT/plugins/feature"
assert_file "мод: манифест" "$P/.claude-plugin/plugin.json"
assert_grep "мод: имя feature" '"name": "feature"' "$P/.claude-plugin/plugin.json"
assert_file "мод: README с контрактом" "$P/README.md"
if command -v claude >/dev/null 2>&1; then
# claude читает свою конфигурацию из настоящего HOME, не из временного
out=$(HOME="$REAL_HOME" claude plugin test "$P" 2>&1); code=$?
if [ "$code" = 0 ] && printf '%s' "$out" | grep -qE '(^| )0 fail'; then
ok "мод: claude plugin test ($(printf '%s' "$out" | grep -oE '[0-9]+ pass' | head -1))"
else
fail "мод: claude plugin test" "exit $code; $(printf '%s' "$out" | grep -E 'fail|Error' | head -3 | tr '\n' ' ')"
fi
out=$(HOME="$REAL_HOME" claude plugin validate "$P" 2>&1); code=$?
[ "$code" = 0 ] && ok "мод: claude plugin validate" || fail "мод: claude plugin validate" "exit $code; $(printf '%s' "$out" | tail -3 | tr '\n' ' ')"
else
printf ' skip мод: claude не найден в PATH — тесты мода не запускались\n'
fi