Фича для прогона
Установка Spec Kit позади — теперь самое интересное: пройти весь цикл на живом примере. Возьмём небольшую, но ёмкую фичу: CSV-экспорт данных пользователя. Звучит тривиально, но в ней ровно столько неоднозначностей, чтобы увидеть, где clarify реально спасает от переделки.
flowchart TD
A["/speckit.constitution"] --> B["/speckit.specify"]
B --> C["/speckit.clarify"]
C --> D["/speckit.plan"]
D --> E["/speckit.tasks"]
E --> F["/speckit.analyze"]
F --> G["/speckit.implement"]
style C fill:#fff8e1,stroke:#f59e0b
style F fill:#e8f5e9,stroke:#4caf50Шаг 0: constitution.md
Конституция — «нулевой шаг», который задаёт тон всему циклу. После specify init файл уже существует, но пустой. Заполняем:
/speckit.constitutionClaude Code задаст несколько вопросов о проекте и запишет принципы в .specify/memory/constitution.md. Реальный результат выглядит примерно так:
# Project Constitution
## Code Quality
- TypeScript strict mode, no `any`
- All business logic covered by unit tests
## Performance
- API responses < 200ms at p95
## Security
- All endpoints require valid session token by defaultКонституция живёт один раз на проект. Все последующие спеки ей подчиняются автоматически — не надо повторять эти принципы в каждом spec.md.
Шаг 1: /speckit.specify
/speckit.specify Экспорт данных пользователя в CSV-файлClaude Code читает кодовую базу, находит существующие модели и генерирует specs/001-csv-export/spec.md. Упрощённый результат:
# CSV Export — spec.md
::widget{id="rc-3"}
## Goal
Allow users to download their personal data as a CSV file.
## Acceptance Criteria
- Export includes all user fields
- File is available immediately on request
- Download does not require authenticationЗаметьте три допущения: «все поля», «сразу», «без аутентификации». Каждое из них — потенциальная бомба.
Шаг 2: /speckit.clarify — где экономится время
/speckit.clarifyClaude Code задаёт уточняющие вопросы. Вот как это выглядит в диалоге:
Claude: Какие именно поля должны попасть в экспорт? Все, включая хешированный пароль и внутренние флаги?
Вы: Только публичные: имя, email, дата регистрации. Пароль — никогда.
Claude: Ссылка на скачивание должна требовать авторизации?
Вы: Да, только через валидную сессию.
После этого spec.md обновляется:
## Acceptance Criteria
- Export includes ONLY: name, email, created_at
- Passwords, roles, internal flags — EXCLUDED
- Synchronous download, response < 200ms
- Download requires valid session tokenБез clarify план включал бы все поля, архитектура строилась бы без auth-middleware, и к моменту code review пришлось бы переписывать половину.
Шаг 3: /speckit.plan
/speckit.planНа вход — обновлённая спека, на выходе — specs/001-csv-export/plan.md:
# CSV Export — plan.md
## Architecture
- New route: GET /api/users/me/export
- Middleware: requireAuth (existing)
- CsvExportService.generate(userId) → Buffer
- Allowed fields: ['name', 'email', 'created_at']
- Headers: Content-Disposition, Content-Type: text/csv
## Dependencies
- csv-stringify (already in package.json)
- Existing UserRepositoryВажная деталь: план ссылается на requireAuth — middleware, которое уже есть в кодовой базе. Это работает потому, что Claude Code читал проект перед генерацией спеки.
Шаг 4: /speckit.tasks
/speckit.tasksЗадачи разбиваются с зависимостями и маркерами параллельности:
- [ ] T1: Add GET /api/users/me/export route with requireAuth
- [ ] T2: Implement CsvExportService.generate(userId)
- [ ] T3 [P]: Unit tests for CsvExportService
- [ ] T3 [P]: Integration test for the export route
- [ ] T4: Update API docs[P] — параллельные задачи: юнит-тесты сервиса и интеграционный тест роута можно писать одновременно, у них нет зависимости друг от друга.
Шаг 5: /speckit.analyze
/speckit.analyzeПроверяет согласованность между тремя артефактами — spec.md, plan.md и tasks.md:
✓ AC-1 (field whitelist) → covered in plan.md
✓ AC-2 (auth) → covered via requireAuth middleware
⚠ AC-3 (< 200ms) → no performance test in tasks.mdПредупреждение реальное: конституция требует p95 < 200ms, но в задачах нет перформанс-теста. Добавляем строчку в tasks.md вручную — прямо сейчас, пока это просто текст, а не переделка уже написанного кода.
Шаг 6: /speckit.implement
/speckit.implement T1Claude Code берёт задачу T1 и пишет код строго по артефактам:
// src/routes/export.ts
import { Router } from 'express';
import { requireAuth } from '../middleware/auth';
import { CsvExportService } from '../services/CsvExportService';
const router = Router();
router.get('/me/export', requireAuth, async (req, res) => {
const buffer = await CsvExportService.generate(req.user.id);
res.setHeader('Content-Disposition', 'attachment; filename=my-data.csv');
res.setHeader('Content-Type', 'text/csv');
res.send(buffer);
});
export default router;Затем T2, T3, T4 — каждый раз с кратким ревью перед следующим шагом.
Human-in-the-loop: ревью на каждом переходе
SDD не означает «запустил и забыл». На каждом переходе между фазами — краткая проверка:
| Переход | Вопрос для ревью |
|---|---|
После specify | Спека описывает именно то, что нужно? |
После clarify | Все неоднозначности сняты? |
После plan | Архитектура не противоречит кодовой базе? |
После analyze | Нет красных флагов? |
После implement | Код соответствует задаче в tasks.md? |
Пять минут ревью plan.md стоят дешевле, чем переписывать готовый код. Это и есть «человек в контуре» — не бюрократия, а точка, где цена ошибки ещё минимальна.
Практическое задание
Возьмите одну небольшую фичу из реального проекта — или придумайте: «смена пароля», «уведомления по email», «пагинация списка». Пройдите цикл до /speckit.clarify включительно. Сравните spec.md до и после: что изменилось? Найдите хотя бы одно допущение, которое clarify заставил вас явно прояснить. Именно это место — то, где SDD защищает от переделки.