diff --git a/docs/superpowers/specs/2026-05-16-regression-skill-design.md b/docs/superpowers/specs/2026-05-16-regression-skill-design.md index def5c8a5..7e96c60e 100644 --- a/docs/superpowers/specs/2026-05-16-regression-skill-design.md +++ b/docs/superpowers/specs/2026-05-16-regression-skill-design.md @@ -3,9 +3,10 @@ **Дата:** 2026-05-16 **Статус:** дизайн одобрен заказчиком (через `superpowers:brainstorming`, Q1–Q4 + полное согласование дизайна) **Экономия:** 0% (максимальное качество, без скипов) -**Связанные артефакты:** `.claude/skills/regression/SKILL.md` (создаётся), `.claude/skills/regression/run.mjs` (создаётся), `.claude/skills/q-item-add/SKILL.md` (образец), `.claude/skills/rls-check/SKILL.md` (образец), `package.json`, `app/package.json`, `app/composer.json`, `lefthook.yml` +**Связанные артефакты:** `.claude/skills/regression/SKILL.md` (создаётся), `.claude/skills/regression/run.mjs` (создаётся), `.claude/skills/regression/run.test.mjs` (создаётся), `.claude/skills/q-item-add/SKILL.md` (образец), `.claude/skills/rls-check/SKILL.md` (образец), `tools/ruflo-queen-hook.test.mjs` (образец теста), `package.json`, `app/package.json`, `app/composer.json`, `lefthook.yml` **Источник:** рекомендация №1 из `/claude-code-setup:claude-automation-recommender` (16.05.2026) **Следующий шаг:** `superpowers:writing-plans` → план реализации. +**Правка 1 (2026-05-16, при `writing-plans`):** §2/§3/§4/§10 — добавлен co-located `run.test.mjs` (`node:test`). Прежняя формулировка §10 (об отсутствии отдельных unit-тестов для `run.mjs`) опиралась на ложную предпосылку («`tools/*.mjs` тестов не имеют»); фактически все 3 `tools/*.mjs` имеют co-located `.test.mjs`. Скорректировано под economy-0% TDD-мандат + конвенцию проекта. --- @@ -39,7 +40,8 @@ - bundled-скрипт-оркестратор на Node ESM; - каноническая строка + per-check таблица + вердикт GREEN/RED; - правила инвокации (Both с self-restraint); -- caveats по проектным квиркам (Pest `--parallel` flake, ruflo daemon). +- caveats по проектным квиркам (Pest `--parallel` flake, ruflo daemon); +- co-located `run.test.mjs` (`node:test`) — unit-тесты pure-функций `run.mjs` + subprocess-тест `main`. **Не-цели (сознательно вне scope v1):** @@ -63,6 +65,7 @@ | U1 | Дефолт без аргумента | `/regression` ≡ `/regression full` | Headline use-case — свод перед закрытием. | | U2 | Состав `quick` | `quick` НЕ включает Larastan | Чистая граница «линт/формат/тип» vs «статанализ/прогон»; Larastan уже в `lefthook` pre-commit. | | U3 | Язык скрипта | Node `.mjs` | House-style проекта: `tools/ruflo-*.mjs`, `app/scripts/dev-indices-lookup.mjs`, `node -e` в хуках `.claude/settings.json`; кросс-платформенно для Linux/Mac CI. | +| P1 | Тестирование `run.mjs` | Co-located `run.test.mjs` (`node:test`): unit-тесты pure-функций + subprocess-тест `main` | Правка 1 — economy-0% TDD-мандат + конвенция проекта (все `tools/*.mjs` имеют `.test.mjs`, паттерн `tools/ruflo-queen-hook.test.mjs`). | ## 4. Компоненты @@ -71,7 +74,8 @@ | Файл | Назначение | |---|---| | `.claude/skills/regression/SKILL.md` | frontmatter (`name`, `description`, инвокация) + «Когда использовать» + «Workflow» + «Правила инвокации (self-restraint)» + «Caveats» + «Не использовать когда». Структура повторяет `q-item-add`/`rls-check`. | -| `.claude/skills/regression/run.mjs` | Оркестратор. Аргумент `quick` \| `full` (дефолт `full`). Чистый Node ESM — только `node:child_process`, `node:process`, `node:path`; без npm-зависимостей. | +| `.claude/skills/regression/run.mjs` | Оркестратор. Аргумент `quick` \| `full` (дефолт `full`). Чистый Node ESM — только `node:child_process`, `node:process`, `node:path`; без npm-зависимостей. Экспортирует pure-функции (`parse`-функции проверок, логика вердикта, сборка канонической строки, платформенная развилка) для unit-тестирования. | +| `.claude/skills/regression/run.test.mjs` | Co-located тесты (`node:test` + `node:assert/strict`), паттерн `tools/ruflo-queen-hook.test.mjs`: unit-тесты экспортированных pure-функций + subprocess-тесты `main` через `execFileSync`. | `SKILL.md` frontmatter (Both с self-restraint — `disable-model-invocation` НЕ ставится, в отличие от `q-item-add`/`rls-check`): @@ -199,14 +203,29 @@ Frontmatter разрешает инвокацию и Claude, и пользова ## 10. Тестирование скилла -Дисциплина `superpowers:writing-skills` — верифицировать скилл до объявления «готово»: +Проект тестирует `tools/*.mjs` co-located файлами `.test.mjs` на встроенном `node:test` (паттерн `tools/ruflo-queen-hook.test.mjs`: unit-тесты экспортированных pure-функций + subprocess-тест `main` через `execFileSync`). `run.mjs` следует той же конвенции — TDD по `superpowers:test-driven-development`. -1. **Happy path.** Прогон `/regression quick` и `/regression full` на чистом дереве — убедиться, что печатается каноническая строка и вердикт GREEN, exit-код 0. -2. **RED path.** Временно внести lint-ошибку (напр. в `.ts`-файл) → `/regression quick` обязан дать RED, exit 1, перечислить ESLint; откатить лом. -3. **RED-INCOMPLETE path.** Временно сделать недоступным один бинарь (напр. переименовать `bin\gitleaks.exe`) → `full` обязан дать `[⚠] SKIPPED` + вердикт RED-INCOMPLETE; вернуть бинарь. -4. **Парсеры.** Сверить count-токены канонической строки с реальным выводом каждой команды (Pest/Vitest/gitleaks/lychee/Vite build) — числа должны совпадать с тем, что печатают сами инструменты. +**`run.mjs` структурируется на два слоя:** -Отдельного unit-харнесса для `run.mjs` нет — сознательное решение, согласованное с тем, что существующие `tools/*.mjs` проекта unit-тестов не имеют. Верификация — функциональная, по пунктам 1–4 выше. +- **Pure-функции** (экспортируются, детерминированы, без I/O): `parse`-функция каждой проверки (вывод инструмента → count-токен), логика вердикта (массив результатов → GREEN/RED/RED-INCOMPLETE + exit-код), сборка канонической строки, платформенная развилка бинаря (`win32` → `bin\*.exe`). +- **Orchestrator** (`main`): парсинг аргумента, последовательный запуск проверок через `child_process`, печать таблицы/строки/вердикта. + +**`run.test.mjs`** (co-located, `node:test` + `node:assert/strict`): + +- unit-тест каждой `parse`-функции — на реальных фрагментах вывода Pest / Vitest / gitleaks / lychee / Vite build / Larastan (фикстуры-строки в тесте); +- unit-тест логики вердикта — GREEN (все exit 0), RED (≥1 ненулевой), RED-INCOMPLETE (≥1 SKIPPED) + сверка возвращаемого exit-кода; +- unit-тест сборки канонической строки (порядок токенов, число токенов = числу проверок уровня) и платформенной развилки бинаря; +- subprocess-тесты `main` через `execFileSync`: неизвестный аргумент → ошибка + ненулевой exit; `run.mjs quick` стартует и печатает заголовок уровня. + +Прогон: `node --test .claude/skills/regression/run.test.mjs` (Node ≥20, нулевые зависимости). + +**Дополнительная функциональная верификация** (внешние инструменты — вне unit-покрытия): + +1. **Happy path.** `/regression quick` и `/regression full` на чистом дереве → каноническая строка + вердикт GREEN, exit 0. +2. **RED path.** Временный lint-лом в `.ts` → `/regression quick` даёт RED, exit 1, перечисляет ESLint; откатить лом. +3. **RED-INCOMPLETE path.** Временно недоступный бинарь (переименовать `bin\gitleaks.exe`) → `full` даёт `[⚠] SKIPPED` + RED-INCOMPLETE; вернуть бинарь. + +Дисциплина `superpowers:writing-skills` — верификация скилла (unit `run.test.mjs` + функциональная 1–3) до объявления «готово». ## 11. Отклонённые альтернативы