specward
v0.1.2
Published
CLI tool for spec-driven development: validates spec YAML files against test files using AST analysis (no test execution required)
Maintainers
Readme
specward
CLI-утилита для валидации spec YAML файлов против тестовых файлов. Анализирует тесты через AST (SWC) — без их запуска.
Зачем
Альтернатива spec-box — без внешней инфраструктуры (Postgres, Web UI). Работает локально, мгновенно, встраивается в CI как lint-шаг.
Как работает
- Находит
*.spec.yamlфайлы (спецификации) - Находит
*.spec.tsфайлы (тесты) - Парсит тесты через SWC AST — извлекает
describe/itиерархию - Сверяет: category + assert из YAML = последний describe + it title в тесте
- Выводит результат:
- ERROR — спек без теста (exit code 1)
- WARNING — тест без спека
Установка
npm install --save-dev specward
# или
yarn add -D specwardИспользование
# Весь проект
npx specward
# Один пакет
npx specward --cwd packages/feature-flags
# Кастомные паттерны
npx specward --specs "*.spec.yaml" --tests "src/__tests__/*.spec.ts"Опции
| Флаг | По умолчанию | Описание |
|------|-------------|----------|
| --specs <glob> | **/*.spec.yaml | Glob для spec-файлов |
| --tests <glob> | **/src/**/*.spec.ts | Glob для тестовых файлов |
| --cwd <path> | . | Рабочая директория |
| -h, --help | | Справка |
Формат spec YAML
feature: feature-flags module
code: feature-flags
description: Описание модуля
specs-unit:
Регистрация модуля:
- assert: forRoot регистрирует модуль и предоставляет Client через DI
- assert: forRootAsync с фабрикой регистрирует модуль
Кэширование:
- assert: Запросы кэшируются по flagKeys + entity
specs-e2e:
Полный сценарий:
- assert: Пользователь создаёт объект и видит его в спискеМаппинг на тесты
YAML Test file
───────────────────────────────── ──────────────────────────────────
specs-unit: (любая секция specs-*)
Регистрация модуля: → describe('Регистрация модуля', () => {
- assert: forRoot... → it('forRoot...', () => {});Ключ матчинга: "feature/code > path > assert" = "describes... > it title".
Программное использование
import { parseSpecFile, parseTestFile, match, report } from 'specward';
const spec = await parseSpecFile('feature.spec.yaml');
const tests = await parseTestFile('feature.spec.ts');
const result = match([spec], tests);
const passed = report(result, process.cwd());Архитектура
src/
├── cli.ts # Точка входа CLI
├── spec-parser.ts # Парсинг YAML → SpecFile[]
├── test-parser.ts # SWC AST → TestAssertion[]
├── matcher.ts # Кросс-сверка specs ↔ tests
├── reporter.ts # Вывод в консоль (chalk)
└── index.ts # Публичные экспортыПочему AST, а не test report
| | AST (SWC) | Test report (vitest --reporter=json) |
|---|---|---|
| Скорость | ~100ms на 200 файлов | Минуты (поднимает контейнеры, БД) |
| Зависимости | Не нужны | Нужна вся инфраструктура тестов |
| CI | Рядом с lint / check-types | Только после полного прогона |
| Точность | 100% для статических строк | 100% |
Контрибьютинг
Изменения версионируются через Changesets:
npx changeset # описать изменение
git commit -am "feat: ..."
# когда коммит улетит в main, бот откроет "Version Packages" PRLicense
MIT © Evgeny Paromov
