name: spec-driven
description: "Success-Oriented Software Architecture & Logic Spec Driven. Produces a spec document that defines what success looks like (observable, measurable), then the architecture and per-component logic contracts that guarantee it, then a verification plan that checks each success criterion. Use before implementing any non-trivial system: fuzzy requirements, multi-component features, behavior others must build/verify against, risky design with real failure modes. Turns 'build X' into a verifiable contract before a line of code is written."


spec-driven — методология, а не бинарник. Твоя роль: собрать контекст, провести reasoning по схеме ниже и записать результат в spec-файл. Не начинай реализацию, пока spec не сформулирован и не подтверждён пользователем (если он участвует).

Core idea

Обычный подход: «опиши фичи → построй → почини». Success-oriented подход идёт с обратного конца:

  1. Что значит «работает»? — наблюдаемые, проверяемые критерии успеха. Не список фич, а контракт с внешним миром.
  2. При каких ограничениях? — реальные пределы: latency, бюджет, совместимость, operational constraints.
  3. Какая архитектура гарантирует успех в этих границах? — компоненты, границы, потоки данных. Решения с rationale и отвергнутыми альтернативами.
  4. Какая логика у каждого компонента? — контракты, инварианты, состояния, ошибки. Достаточно точно, чтобы реализация стала механической.
  5. Как мы проверим каждый критерий успеха? — verification plan, привязанный к п.1, а не «напишем тесты».

Spec — это контракт. Реализация — это заполнение контракта. Если реализация расходится со spec'ом, чинят spec (если он был неправ) или реализацию (если она не дотянула). Без spec'а непонятно, кто неправ.

When to use

  • Требования размыты. Пользователь сказал «сделай X», но X имеет 5 разумных трактовок. Spec фиксирует трактовку ДО реализации.
  • Много компонентов / несколько исполнителей. Нужен общий контракт, иначе компоненты не состыкуются.
  • Реальные failure modes. Система может упасть 10 способами — success criteria определяют, какие из них допустимы, какие нет.
  • Дизайн с риском. Архитектурное решение, которое дорого менять потом. Spec заставляет подумать о границах и rationale сейчас.
  • Кто-то будет верифицировать. Spec даёт проверяющему checklist, привязанный к успеху, а не к «как написано».

When NOT to use

  • Однофайловая утилита, поведение очевидно из задачи — spec будет длиннее кода.
  • Чистый рефакторинг без изменения контракта — контракт уже есть, меняется реализация.
  • Спайк / прототип, который выкинут — успех = «узнали ответ», spec не нужен.
  • Задача сводится к одной bash-команде или одной функции.

How to run

1. Собери контекст

Прежде чем писать spec, найди:

  • Реальные требования. Что пользователь сказал дословно — сохрани как секцию ## Исходный запрос (как в deep-analyze). Тон и контекст важны, не только формальная формулировка.
  • Ограничения. Что уже зафиксировано: стек, бюджет, совместимость, deadlines, существующий код. Читай файлы проекта, не додумывай.
  • Существующие решения. Если в проекте уже есть похожий код / архитектура — spec должен с ней стыковаться, а не изобретать параллельную вселенную.

Если контекста мало — задай конкретные вопросы пользователю. Не выдумывай требования. Лучше 3 вопроса, чем spec на основе галлюцинации.

2. Reasoning по схеме (внутренний шаг)

Пройди сверху вниз. На каждом уровне проверяй совместимость с предыдущим:

  • Успех должен быть наблюдаемым («p99 latency < 50ms под 1k RPS на reference-железе»), а не свойством («быстрый»).
  • Архитектура должна выводиться из успеха + ограничений, а не из «модно». Для каждого ключевого решения — rationale и хотя бы одна отвергнутая альтернатива с причиной отказа.
  • Логика должна быть достаточно точной, чтобы второй человек (или свежий подагент) реализовал её без дополнительных вопросов. Контракты, инварианты, состояния, ошибки — явно.
  • Verification должен проверять критерии успеха из п.1, а не «код работает». Каждый критерий → конкретная проверка.

3. Запиши spec

Пиши в markdown-файл. Структура ниже — canonical, отклоняйся только если задача явно требует иного.

# Spec: <название>

## Исходный запрос
<дословно, как было задано>

## Success criteria
<Наблюдаемые, измеримые, проверяемые. Каждый — отдельно, с метрикой и порогом.>
- SC1: ...
- SC2: ...

## Context & constraints
- Что зафиксировано (стек, совместимость, бюджет, железо)
- Что запрещено / out of scope
- Существующий код, с которым стыкуемся

## Architecture
### Components & boundaries
<Что существует, кто с кем говорит, где границы>

### Data flow
<Как данные проходят через систему — последовательность или диаграмма текстом>

### Key decisions
| Решение | Почему | Отвергнутая альтернатива | Почему нет |
|---|---|---|---|

## Logic spec (per component)
### <Component A>
- **Контракт:** входы / выходы / типы
- **Инварианты:** что всегда верно
- **Состояния:** state machine если есть
- **Ошибки:** какие, когда, семантика
- **Последовательности:** ключевые сценарии (success path + главные failure paths)

### <Component B>
...

## Failure modes & tolerance
<Какие режимы отказа допустимы (degraded), какие — нет. Что система делает при каждом.>

## Verification plan
| Success criterion | Как проверяется | Уровень (unit/integration/e2e/manual) |
|---|---|---|
| SC1 | ... | ... |

## Open questions & risks
- Что ещё неизвестно и блокирует реализацию
- Риски, которые могут заставить пересмотреть spec

4. Самопроверка перед передачей

Прочти spec и ответь на 4 вопроса. Если хоть один провален — доработай:

  1. Каждый ли критерий успеха наблюдаем и имеет порог? «Надёжный» — нет. «99.9% сообщений доставляются за < 1s» — да.
  2. Выводится ли архитектура из успеха + ограничений? Если решение обосновано «так принято» — это не rationale.
  3. Может ли свежий исполнитель реализовать логику без вопросов? Найди двусмысленности: «обрабатывает ошибку» — как именно? Допиши.
  4. Покрывает ли verification каждый критерий успеха? Найди criterion без проверки — это дыра.

5. Подтверждение и итерация

Если пользователь участвует — покажи spec и запроси подтверждение до реализации. Spec дешевле менять, чем код.

Если нашли пробелы в ходе реализации — вернись к spec, обнови, потом чини реализацию. Spec — источник правды, не реализация.

Output expectations

Один spec-файл. Не код, не прототип. Документ, из которого реализация становится механической, а верификация — checklist'ом по критериям успеха.

Размер: пропорционален сложности. Простая фича — полстраницы. Распределённая система — несколько страниц. Не раздувай ради объёма, не сжимай ради краткости в ущерб точности.

Язык: следуй языку задачи. Русский запрос — русский spec, английский — английский. Термины оставляй в оригинале.

Good invocations

«Сделай очередь задач для воркеров: 10k задач/день, p99 < 5s, переживает рестарт воркера» → spec фиксирует success criteria (throughput, latency, durability), архитектуру (queue, workers, ack/nack), логику (state transitions задачи, семантика retry/dlq), verification (нагрузочный тест, kill-test воркера).

«Добавь кэш в API» → слишком размыто для spec'а? Нет — spec заставит определить: кэш чего, какой hit rate считается успехом, invalidation стратегия, что при cache stampede. Без spec'а «кэш» = 5 разных реализаций у 5 исполнителей.

«Перепиши импорт CSV на стриминг» → success: memory < 200MB на файл любого размера, throughput > 50k строк/с. Архитектура: streaming pipeline, backpressure. Логика: обработка ошибочной строки, частичный коммит. Verification: тест на 10GB файл, тест на malformed rows.

Bad invocations

«Напиши spec для hello world» — задача тривиальна, spec длиннее кода.

«Сделай рефакторинг этой функции» — контракт не меняется, spec не нужен. Если меняется — тогда да.

«Опиши архитектуру нашего проекта» — это аудит/обзор, а не success-oriented spec. Используй deep-analyze.

Common pitfalls

  • Success criteria как фичи. «Поддержка retry» — это фича, не критерий успеха. Критерий: «99% временно-недоступных зависимостей автоматически восстанавливается за < 30s без потери данных».
  • Architecture без rationale. «Используем Redis» — почему? Какая альтернатива (Memcached, in-process, Postgres LISTEN) и почему нет? Без этого решение не обосновано, а продиктовано привычкой.
  • Логика без ошибок. Описан только happy path. Реальные системы живут в failure modes. Специфицируй ошибки явно: какие, когда, семантика, что делает вызывающий.
  • Verification не привязан к успеху. «Напишем unit-тесты» — не план. План: «SC1 → интеграционный тест с 1k RPS на reference-железе, порог p99 50ms, запускать в CI на nightly».
  • Spec после кода. Если код уже есть и расходится со spec'ом — это не spec, это апология. Spec пишется до, либо честно фиксирует существующее как baseline.
Edit

Pub: 29 Aug 2026 11:47 UTC

Views: 13