SDD -- инструмент-агностик
Spec-Driven Development -- это методология, а не продукт. Она работает с любым AI-инструментом, который умеет принимать текстовые инструкции и генерировать код. Но степень интеграции и удобство работы сильно различаются в зависимости от инструмента.
Уровни интеграции SDD:
Уровень 1: Копировать спеку → вставить в чат AI
(работает с любым AI)
Уровень 2: AI читает спеку из файловой системы
(Claude Code, Cursor, Windsurf)
Уровень 3: AI использует спеку как контекст между сессиями
(Claude Code с Memory, AGENTS.md)
Уровень 4: CI/CD валидирует спеку автоматически
(любой CI + OpenAPI/JSON Schema)
В этой статье рассмотрим практическую настройку SDD для основных AI-инструментов разработки.
Claude Code
Claude Code -- это терминальный AI-агент от Anthropic. Он работает непосредственно в файловой системе проекта и может читать, создавать и модифицировать файлы. Это делает его идеальным инструментом для SDD.
CLAUDE.md как контекст проекта
Файл CLAUDE.md в корне проекта -- это первое, что Claude Code читает при запуске. Он задаёт контекст: архитектуру, конвенции, запрещённые паттерны.
# CLAUDE.md
## Project: IT Crib Learning Platform
### Architecture
- Backend: Symfony 7.4 + PHP 8.4 (api/)
- Frontend: Nuxt 3 SPA (app/)
- DB: PostgreSQL 18
- Cache: Redis 7
- Search: Meilisearch
- Queue: RabbitMQ via Symfony Messenger
### Conventions
- PHP: final classes, strict_types, constructor promotion
- All IDs: UUID v7
- All tables: created_at/updated_at TIMESTAMPTZ
- Pagination: keyset only (no OFFSET)
- Tests: PHPUnit 11, PHPStan level 9
### Specs Directory
All feature specifications are in specs/ directory.
Before implementing any feature, check if a spec exists.
If no spec exists, create one first.
### Forbidden Patterns
- No raw SQL (use Doctrine QueryBuilder)
- No service locator (constructor injection only)
- No hard deletes (soft delete with deleted_at)
- No OFFSET pagination
- No @phpstan-ignore annotations
Использование спецификаций с Claude Code
Спецификации хранятся в проекте и Claude Code читает их как обычные файлы.
# Start Claude Code in project root
claude
# Ask Claude to read the spec first
> Read specs/features/user-registration.md and implement
Task 4.1: RegistrationService according to the specification.
Follow all conventions from CLAUDE.md.
Claude Code автоматически:
- Прочитает
CLAUDE.mdдля контекста проекта - Прочитает указанную спецификацию
- Проверит существующие файлы проекта
- Сгенерирует код, соответствующий спеке и конвенциям
- Может запустить тесты и линтер для верификации
Агентный режим для автономной реализации
В агентном режиме Claude Code может выполнять полную фазу Implement автономно.
# Autonomous implementation of a task
> Implement all tasks from specs/features/rate-limiting.md
For each task:
1. Create the necessary files
2. Run PHPStan to verify
3. Run related tests
4. Report status before moving to next task
Stop and ask me if:
- A task fails after 3 attempts
- You need to modify the spec
- You encounter an architectural decision
Memory для эволюции спецификаций
Claude Code с MCP Memory сохраняет знания между сессиями. Это позволяет спецификациям эволюционировать.
## Workflow с Memory
Сессия 1: Написали спеку для регистрации
→ memory_save: "User registration spec completed, stored in specs/features/"
Сессия 2: Реализация показала gap в спеке
→ memory_save: "Registration spec updated: added re-registration
flow for pending users. Pattern: always handle existing entity states."
Сессия 3: Новая фича использует те же паттерны
→ memory_recall: "registration spec patterns"
→ AI знает про re-registration pattern и применяет его
| Что сохранять | Пример | Зачем |
|---|---|---|
| Spec gaps | "Spec didn't cover blocked users re-registration" | Улучшить шаблоны |
| Conventions discovered | "DTO validation via Symfony attributes works better" | Стандартизировать |
| AI failure patterns | "AI generates raw SQL when not reminded about QueryBuilder" | Предотвратить |
| Successful patterns | "State machine spec produced 100% first-attempt success" | Повторить |
Cursor
Cursor -- это fork VS Code с встроенным AI. Его отличие -- глубокая интеграция с кодовой базой: AI "видит" весь проект и может работать с несколькими файлами одновременно.
.cursorrules для конвенций проекта
Файл .cursorrules в корне проекта -- аналог CLAUDE.md для Cursor. Он задаёт правила, которые AI должен соблюдать.
# .cursorrules
## PHP Conventions
- Always use declare(strict_types=1)
- Classes are final by default
- Use constructor property promotion
- All parameters and return types must have type hints
- Use readonly for DTOs and Value Objects
## Database Conventions
- UUID v7 for all primary keys
- Always include created_at/updated_at TIMESTAMPTZ
- Keyset pagination only (no OFFSET)
- Index all foreign keys
- CREATE INDEX CONCURRENTLY in migrations
## Testing Conventions
- PHPUnit 11 with attributes (#[Test], #[DataProvider])
- PHPStan level 9
- Integration tests extend WebTestCase
- Test method names describe behavior
## Architecture
- Thin controllers: validate input, call service, return response
- Services contain business logic
- Repositories contain data access logic
- Async operations via Messenger (RabbitMQ)
## Forbidden
- No raw SQL queries
- No service locator pattern
- No @phpstan-ignore annotations
- No hard deletes of user data
- No OFFSET pagination
Composer для мульти-файловой реализации
Cursor Composer позволяет AI работать с несколькими файлами одновременно -- идеально для реализации задач из спецификации.
Composer prompt:
@specs/features/user-registration.md
Implement Task 4.1 (RegistrationService) from this specification.
Create these files:
1. src/Service/RegistrationService.php
2. src/Exception/EmailAlreadyExistsException.php
Use existing files for context:
- src/Repository/UserRepository.php
- src/Entity/User.php
- src/Entity/ConfirmationToken.php
@docs для ссылок на спецификации
Cursor позволяет ссылаться на файлы прямо в чате с помощью @.
Chat prompt:
Looking at @specs/api/openapi.yaml, generate the RegistrationController
that handles POST /api/v1/auth/register endpoint.
Also check @src/Service/RegistrationService.php for the service interface
that the controller should call.
GitHub Copilot
GitHub Copilot работает иначе -- это прежде всего инструмент автодополнения и чата внутри IDE. Он не имеет агентного режима (на момент написания), но всё равно можно интегрировать SDD.
.github/copilot-instructions.md
GitHub Copilot поддерживает файл инструкций на уровне репозитория.
# .github/copilot-instructions.md
## Project Context
This is a PHP 8.4 / Symfony 7.4 learning platform.
Feature specifications are stored in specs/ directory.
## Code Style
- Always declare(strict_types=1)
- Final classes by default
- Constructor property promotion
- Full type hints everywhere
- PHPStan level 9 compatible
## Patterns
- Thin controllers (validate → service → response)
- Services for business logic
- Repositories for data access
- Async via Symfony Messenger
## Never Do
- Raw SQL queries (use Doctrine)
- Service locator pattern
- @phpstan-ignore annotations
- OFFSET pagination (use keyset)
Copilot Chat со спецификациями
Copilot Chat:
/file specs/features/user-registration.md
Based on this specification, implement the RegistrationService.
Focus on the register() method described in Task 4.1.
Copilot CLI для исполнения задач
GitHub Copilot CLI может помочь с отдельными командами в рамках SDD.
# Ask Copilot for a command to verify implementation
gh copilot suggest "run phpstan on RegistrationService"
# → docker compose exec php vendor/bin/phpstan analyse src/Service/RegistrationService.php --level=9
# Ask for test command
gh copilot suggest "run phpunit tests for registration"
# → docker compose exec php vendor/bin/phpunit --filter=Registration
Стандарт AGENTS.md
Универсальный файл контекста
AGENTS.md -- это формирующийся стандарт для предоставления контекста AI-инструментам. Он не привязан к конкретному инструменту (как CLAUDE.md к Claude Code или .cursorrules к Cursor). Идея: один файл, который работает везде.
# AGENTS.md
## Project Overview
IT Crib — educational platform for developers.
6 sections, 100+ topics, 500+ articles, quizzes, code challenges.
## Technology Stack
- **Backend**: PHP 8.4 / Symfony 7.4
- **Frontend**: Vue 3.6 / Nuxt 4 with TypeScript
- **Database**: PostgreSQL 18
- **Cache**: Redis 7
- **Search**: Meilisearch
- **Queue**: RabbitMQ via Symfony Messenger
- **Container**: Docker Compose v2
## Project Structure
api/ # Symfony backend ├── src/ │ ├── Controller/ # Thin HTTP controllers │ ├── Entity/ # Doctrine entities │ ├── Repository/ # Data access layer │ ├── Service/ # Business logic │ ├── Message/ # Async message DTOs │ └── MessageHandler/ # Async message processors ├── tests/ │ ├── Unit/ │ └── Integration/ └── specs/ # Feature specifications ├── features/ # Feature specs ├── api/ # OpenAPI specs └── templates/ # Spec templates
app/ # Nuxt frontend ├── components/ ├── composables/ ├── pages/ └── stores/
## Conventions
### PHP
- `declare(strict_types=1)` always
- `final` classes by default
- Constructor property promotion
- Type hints on ALL parameters and returns
- `readonly` for DTOs and Value Objects
### Database
- UUID v7 for primary keys
- `created_at`/`updated_at` TIMESTAMPTZ
- Keyset pagination (no OFFSET)
- `CREATE INDEX CONCURRENTLY`
### Testing
- PHPUnit 11 with attributes
- PHPStan level 9
- Integration tests: WebTestCase
## Forbidden Patterns
- Raw SQL queries (use Doctrine QueryBuilder)
- Service locator (use constructor injection)
- @phpstan-ignore annotations
- OFFSET pagination
- Hard deletes of user data
- Storing secrets in code
## Specification-Driven Development
This project uses SDD. Before implementing any feature:
1. Check specs/ for existing specification
2. If none exists, create one using specs/templates/
3. Follow the 4-phase process: Specify → Plan → Tasks → Implement
4. All specs are reviewed before implementation begins
Связь AGENTS.md и спецификаций
AGENTS.md -- это постоянный контекст проекта. Спецификации -- это временные контексты отдельных фич. Вместе они дают AI полную картину.
AGENTS.md (постоянный)
├── Архитектура проекта
├── Конвенции кода
├── Запрещённые паттерны
└── Ссылка на specs/ директорию
specs/ (временные)
├── features/user-registration.md (текущая фича)
├── features/order-system.md (следующая фича)
└── templates/feature-spec-template.md (шаблон)
Version control для спецификаций
Спецификации -- часть кода
Спецификации живут в репозитории наравне с кодом. Они версионируются, ревьюятся и обновляются.
# Directory structure
specs/
├── features/
│ ├── user-registration.md # Feature spec
│ ├── order-system.md # Feature spec
│ └── rate-limiting.md # Feature spec
├── api/
│ └── openapi.yaml # API specification
├── architecture/
│ ├── system-overview.md # Architecture decisions
│ └── data-model.md # Database design
└── templates/
├── feature-spec-template.md # Template for new features
└── api-endpoint-template.md # Template for API endpoints
Traceability: связь спеки с кодом
Каждый PR ссылается на спецификацию, которую он реализует.
# Pull Request Template
## Specification
Link: [specs/features/user-registration.md](specs/features/user-registration.md)
## Tasks Implemented
- [x] Task 1.1: Migration (users table)
- [x] Task 1.2: Migration (confirmation_tokens table)
- [x] Task 2.1: Entity (User)
- [x] Task 2.2: Entity (ConfirmationToken)
- [ ] Task 3.1: Repository (UserRepository) — next PR
## Spec Changes
- Added edge case: re-registration of pending users
(see commit abc123)
## Verification
- [ ] PHPStan level 9 clean
- [ ] All tests pass
- [ ] Spec requirements covered
Ревью спецификаций в PR
Спецификации ревьюятся отдельно от кода -- и до него.
# Workflow
git checkout -b spec/user-registration
# Write specification
vim specs/features/user-registration.md
# Create spec-only PR
git add specs/
git commit -m "docs(specs): add user registration specification"
git push origin spec/user-registration
# PR review: only spec, no code
# After approval: create implementation branch from spec branch
git checkout -b feat/user-registration
# Implement...
| Этап | Что ревьюится | Кто ревьюит |
|---|---|---|
| Spec PR | Полнота, однозначность, реализуемость | Архитектор / тимлид |
| Implementation PR | Соответствие спеке, качество кода | Разработчик / code review |
| Spec Update PR | Изменения спеки по итогам реализации | Автор спеки |
CI/CD интеграция
Валидация спецификаций в CI
# .github/workflows/spec-validation.yml
name: Spec Validation
on:
pull_request:
paths:
- 'specs/**'
- 'api/specs/**'
jobs:
validate-openapi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Validate OpenAPI spec syntax
- name: Validate OpenAPI
uses: char0n/swagger-editor-validate@v1
with:
definition-file: specs/api/openapi.yaml
validate-spec-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Check that specs follow template structure
- name: Check required sections
run: |
for spec in specs/features/*.md; do
echo "Checking $spec..."
grep -q "## Problem" "$spec" || \
(echo "Missing: Problem section in $spec" && exit 1)
grep -q "## Success Criteria" "$spec" || \
(echo "Missing: Success Criteria in $spec" && exit 1)
grep -q "## Functional Requirements" "$spec" || \
(echo "Missing: Functional Requirements in $spec" && exit 1)
done
check-spec-links:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Verify that implementation PRs reference specs
- name: Check spec reference
if: contains(github.event.pull_request.title, 'feat')
run: |
# Check PR body contains link to spec
echo "${{ github.event.pull_request.body }}" | \
grep -q "specs/" || \
(echo "Feature PRs must reference a specification" && exit 1)
Автогенерация документации из OpenAPI
# Generate API docs from OpenAPI spec on merge
generate-api-docs:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Generate API documentation
run: |
npx @redocly/cli build-docs specs/api/openapi.yaml \
--output docs/api/index.html
- name: Deploy docs
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/
Маппинг покрытия тестов на требования
<?php
declare(strict_types=1);
namespace Tests\Integration;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\CoversClass;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* Spec coverage: specs/features/user-registration.md
*
* FR-1.1: ✅ test_register_with_valid_data
* FR-1.2: ✅ test_register_rejects_invalid_email
* FR-1.3: ✅ test_register_rejects_duplicate_email
* FR-1.4: ✅ (verified by checking password_hash format in DB)
* FR-1.5: ✅ test_new_user_has_pending_status
* FR-1.6: ✅ test_confirmation_email_dispatched
*/
#[CoversClass(RegistrationController::class)]
final class RegistrationControllerTest extends WebTestCase
{
#[Test]
public function register_with_valid_data(): void
{
// FR-1.1: System accepts email and password for registration
$client = static::createClient();
$client->jsonRequest('POST', '/api/v1/auth/register', [
'email' => '[email protected]',
'password' => 'SecurePass1',
'password_confirmation' => 'SecurePass1',
]);
$this->assertResponseStatusCodeSame(201);
}
#[Test]
public function register_rejects_invalid_email(): void
{
// FR-1.2: System validates email format
$client = static::createClient();
$client->jsonRequest('POST', '/api/v1/auth/register', [
'email' => 'not-an-email',
'password' => 'SecurePass1',
'password_confirmation' => 'SecurePass1',
]);
$this->assertResponseStatusCodeSame(400);
}
// ... remaining tests mapping to FR requirements
}
Практическая структура проекта с SDD
Объединяя все инструменты, вот как выглядит проект, полностью настроенный для SDD:
project/
├── CLAUDE.md # Claude Code context
├── AGENTS.md # Universal AI context
├── .cursorrules # Cursor conventions
├── .github/
│ ├── copilot-instructions.md # GitHub Copilot context
│ ├── PULL_REQUEST_TEMPLATE.md # PR template with spec link
│ └── workflows/
│ ├── spec-validation.yml # CI: validate specs
│ ├── tests.yml # CI: run tests
│ └── api-docs.yml # CI: generate API docs
├── specs/
│ ├── features/
│ │ ├── user-registration.md # Feature specification
│ │ ├── order-system.md # Feature specification
│ │ └── rate-limiting.md # Feature specification
│ ├── api/
│ │ └── openapi.yaml # API specification
│ ├── architecture/
│ │ ├── system-overview.md # Architecture decisions
│ │ └── data-model.md # Database design
│ └── templates/
│ ├── feature-spec.md # Template: feature spec
│ ├── api-endpoint.md # Template: API endpoint
│ └── task.md # Template: implementation task
├── api/ # Backend
│ ├── src/
│ ├── tests/
│ └── composer.json
├── app/ # Frontend
│ ├── components/
│ ├── pages/
│ └── nuxt.config.ts
├── docker-compose.yml
└── Makefile
Шаблон спецификации
# specs/templates/feature-spec.md
# Feature: [Name]
## Problem Statement
[What problem are we solving? Who is affected? What is the impact?]
## Success Criteria
1. [Measurable criterion 1]
2. [Measurable criterion 2]
3. [Measurable criterion 3]
## Functional Requirements
### FR-1: [Requirement Group]
- FR-1.1: [Specific requirement]
- FR-1.2: [Specific requirement]
## Non-Functional Requirements
### NFR-1: Performance
- [Specific performance requirement]
### NFR-2: Security
- [Specific security requirement]
## API Contract
[OpenAPI snippet or reference to specs/api/openapi.yaml]
## Data Models
[Entity definitions with fields, types, constraints]
## Edge Cases
1. [Edge case and expected behavior]
2. [Edge case and expected behavior]
## Testing Strategy
- Unit tests: [what to test]
- Integration tests: [what to test]
- Edge case tests: [what to test]
## Implementation Plan
[High-level steps with dependencies]
## Tasks
[Atomic tasks with verification criteria]
Рекомендации по инструментам
Какой инструмент для какой фазы SDD
| Фаза SDD | Лучший инструмент | Почему |
|---|---|---|
| Specify | Claude Code / Chat | Генерация спеки через диалог |
| Plan | Claude Code | Читает спеку, генерирует план |
| Tasks | Claude Code | Декомпозирует план на задачи |
| Implement | Claude Code / Cursor | Автономная реализация с верификацией |
| Verify | CI/CD + линтеры | Автоматическая проверка |
Миграция между инструментами
Благодаря AGENTS.md и стандартной структуре specs/ -- переключение между инструментами безболезненно:
Утро: Claude Code (терминал, агентный режим)
→ Реализация задач из спеки автономно
День: Cursor (IDE, визуальный режим)
→ Код-ревью, рефакторинг, отладка
Вечер: Copilot (IDE, автодополнение)
→ Мелкие правки, документация
Спецификации и контексты (.cursorrules, CLAUDE.md, AGENTS.md) -- это портативные артефакты. Они не привязаны к инструменту. Это ваша инвестиция в процесс, а не в продукт.
Итоги
Интеграция SDD с инструментами -- это не про конкретный AI. Это про систему, в которой:
- Контекст хранится в файлах проекта (CLAUDE.md, AGENTS.md, .cursorrules)
- Спецификации живут в specs/ и версионируются вместе с кодом
- CI/CD валидирует спеки и код автоматически
- AI-инструменты читают контекст и спеки из файловой системы
Результат: любой разработчик (или AI) может взять проект и понять -- что строится, почему, какие правила, и где спецификации. Это масштабируется. Это воспроизводимо. Это SDD.