Анатомия рабочей спеки
Из чего состоит спека, по которой агент реально может писать код: цель и не-цели, требования, граничные случаи, ограничения по стеку, критерии готовности. Разделяем «что» (requirements) и «как» (design), чтобы не смешивать продуктовую и техническую части. Пишем первую спеку для своей фичи и фиксируем «конституцию» проекта — неизменные принципы и договорённости по стеку.
Анатомия рабочей спеки
В прошлом подмодуле мы разобрались, почему промпт не масштабируется на проект, и завели CLAUDE.md как постоянный контекст для агента. Теперь следующий слой: как написать спеку конкретной фичи, по которой агент сможет работать, а не заполнять пробелы угадками.
Почему «короткое описание» не работает
Большинство первых спек страдают одним из двух дефектов.
Слишком коротко. «Добавь авторизацию через JWT» — это одна строчка, не спека. Всё, что не написано явно, агент придумает сам. На третьем запросе вы обнаружите, что у вас появился cookie-session, о котором вы не просили.
Всё перемешано. В одном абзаце — что должна делать фича, как хранить токены, какой флоу ошибок, что рисует UI. Такую спеку сложно согласовать с продактом и сложно менять — технические и продуктовые решения переплетены.
Рабочая спека — не длинный документ. Это структурированный.
Шесть блоков рабочей спеки
flowchart TD
S["specs/feature.md"]
S --> A["Цель: что и для кого"]
S --> B["Не-цели: исключения скоупа"]
S --> C["Требования — ЧТО"]
S --> D["Дизайн — КАК"]
S --> E["Граничные случаи"]
S --> F["Критерии готовности"]
style C fill:#dbeafe,stroke:#3b82f6,color:#1e3a8a
style D fill:#fef3c7,stroke:#d97706,color:#78350fЦель — одна-две строки: что делаем и для кого. Агент читает это первым и получает контекст для всей задачи.
*Пример:* пользователь может войти в приложение с email и паролем и получить JWT-токен для авторизации последующих запросов.
Не-цели — явный список того, что выходит за рамки этой фичи. Один из самых ценных блоков: защищает от разрастания скоупа прямо во время реализации.
*Пример:* не входит — OAuth, сброс пароля, 2FA, «запомнить меня».
Требования — список «что»: поведение системы с точки зрения пользователя, без деталей реализации.
- При успешном входе возвращается токен сроком 7 дней.
- При неверном пароле — 401 и сообщение «Invalid credentials».
- После 5 ошибок подряд — блокировка на 15 минут.
Дизайн — технические решения: эндпоинты, структуры данных, алгоритм. Заполняется разработчиком, иногда вместе с агентом.
POST /auth/loginпринимает{email, password}, возвращает{token, expiresAt}.- Токен — JWT HS256, payload:
{userId, email, exp}. - Счётчик ошибок: колонки
failed_attemptsиlock_untilв таблицеusers.
Граничные случаи — самый часто пропускаемый блок. Агент не спросит про edge case, если вы его не написали.
User@Example.comиuser@example.com— один пользователь или разные?- Верный пароль введён во время блокировки — что происходит?
- Просроченный токен возвращает 401 или 403?
Критерии готовности — чеклист, по которому однозначно видно «сделано». Эти же пункты используются при приёмке (об этом — в пятом подмодуле).
- [ ]
POST /auth/loginвозвращает токен при верных данных. - [ ] Неверный пароль → 401, правильное сообщение.
- [ ] Блокировка после 5 ошибок — покрыта тестом.
- [ ] Email регистронезависим — есть тест.
«Что» и «Как»: зачем разделять
Блоки «Требования» и «Дизайн» легко перепутать, но их разделение даёт конкретную практическую выгоду.
Если вы работаете с продактом, он видит раздел «Требования» и проверяет поведение без необходимости понимать JWT или структуру базы. Разработчик работает с «Дизайном» и предлагает технические решения, не трогая продуктовые условия. Когда они смешаны, правка в одной части ломает понимание другой.
С агентом та же история. Если требование и реализация записаны в одном предложении — «хранить сессии в Redis» — агент трактует Redis как обязательный выбор в любом контексте. Разделите «что» и «как» — и сможете менять одно, не переписывая другое.
<!-- ❌ смешано: реализация вписана в требование -->
## Требования
- Хранить сессии в Redis с TTL 7 дней.
<!-- ✅ разделено -->
## Требования
- Сессия остаётся активной 7 дней после входа.
## Дизайн
- Хранить сессии в Redis, ключ `session:{userId}`, TTL 604 800 с.Простой тест: «Если реализация изменится, этот пункт всё равно останется верным?» Да — требование. Нет — дизайн.
Шаблон для копирования
Сохраните в specs/_template.md и используйте для каждой новой фичи:
# [Название фичи]
## Цель
[Что и для кого — одна-две строки]
## Не-цели
- [Явные исключения скоупа]
## Требования
- [ ] [Поведение с точки зрения пользователя / системы]
## Дизайн
[Эндпоинты, структуры данных, алгоритмы]
## Граничные случаи
- [Edge case]
## Критерии готовности
- [ ] [Проверяемый пункт]Каждая фича — отдельный файл: specs/auth-login.md, specs/user-profile.md. Имена в kebab-case, совпадают с названием задачи.
Конституция и спека фичи: два разных инструмента
CLAUDE.md — про весь проект: стек, соглашения, неизменные принципы. Меняется редко, агент читает его при каждом запуске автоматически.
Спека фичи — про один конкретный скоуп. Вы кладёте её в контекст явно, когда начинаете работу над фичей. Оба файла работают в паре: конституция задаёт правила, спека — цель.
Если в процессе написания спеки вы понимаете, что правило относится ко всему проекту — например, «все эндпоинты требуют авторизации, кроме /auth/*» — это место в CLAUDE.md, не в спеке фичи.
Задание
Возьмите одну фичу из своего pet-проекта — небольшую: один эндпоинт, одна форма. Заполните шаблон выше. Правило: не тратьте на это больше 30 минут. Пропуски — нормально; в следующем подмодуле вы прогоните спеку через агента, и он сам найдёт дыры.
Самопроверка
- Статья определяет две основные проблемы коротких спек: «слишком коротко» и «всё перемешано». В чём ключевое различие между ними с точки зрения работы агента?
- Как правильно применить тест из статьи для разделения требования и дизайна: «Если реализация изменится, этот пункт всё равно останется верным?»
- Почему статья называет раздел «Не-цели» одним из самых ценных блоков спеки?
- В статье говорится, что разделение требований и дизайна даёт практическую выгоду. Какой из примеров наиболее точно иллюстрирует эту выгоду?
- Статья говорит, что граничные случаи — самый часто пропускаемый блок спеки. Почему?
- Во время написания спеки для новой фичи вы формулируете правило: «Все эндпоинты требуют авторизации, кроме /auth/*». Где должно быть это правило?
- Что произойдёт, если в спеке написать дизайн вместо требования, например: «Хранить сессии в Redis»?
- Когда вы описываете требование про блокировку: «После 5 ошибок подряд — блокировка на 15 минут», какой из этих вопросов ТОЧНО должен быть описан как граничный случай?
Домашние задания
Разобрать спеку на компонентыtext
Перед вами такое описание: «Нужна авторизация через JWT. Хранить токены в Redis, срок 7 дней. После 5 ошибок юзер блокируется на 15 минут. POST /auth/login принимает {email, password}, возвращает {token, expiresAt}. Не входит: OAuth, восстановление пароля, 2FA. Токены проверяются на каждом запросе.» Это хаос — требования смешаны с дизайном, не-цели потеряны в тексте. Ваша задача: выпишите каждое предложение или фразу и распределите по 6 блокам спеки (цель, не-цели, требования, дизайн, граничные случаи, критерии готовности). Если какого-то блока нет — напишите, какая информация там должна быть.
• Все 6 блоков идентифицированы, предложения корректно распределены • Требования (поведение системы) явно отделены от дизайна (техдетали) • Указано минимум 2 отсутствующих блока или информации, которую надо добавить • Объяснено, почему определённое предложение попало именно туда, а не в другой блок
Написать спеку для фичиdocument
Возьмите небольшую фичу из своего проекта — достаточно небольшую, чтобы уложиться в 30 минут. Один эндпоинт, одна форма, функция с чётким скоупом. Сохраните файл `[название-фичи].md` и заполните шаблон: # [Название] ## Цель [Что и для кого — одна-две строки] ## Не-цели [Явные исключения из скоупа] ## Требования [Поведение с точки зрения юзера, без деталей реализации] ## Дизайн [Эндпоинты, структуры, алгоритмы] ## Граничные случаи [Edge cases — не просто список, а 'когда X, система делает Y'] ## Критерии готовности [Чеклист проверяемых пунктов] Ключевой момент: если вы завтра переделаете реализацию, требование должно остаться актуальным. Если нет — это не требование, это дизайн.
• Все 6 блоков присутствуют и содержат информацию (не шаблонный текст) • Требования описывают 'что', без слов вроде 'хранить в Redis' или 'POST /api' • Дизайн содержит технические решения, не в требованиях • Не-цели исключают минимум 2 реальных расширения (не абстрактные) • Граничные случаи конкретны: 'email не регистронезависим', а не 'обработать ошибки' • Критерии готовности можно проверить тестом или вручную — они измеримые
Проверить спеку через глаза кодировщикаtext
Вернитесь к спеке, которую только что написали. Прочитайте её как будто вы — агент, который будет её кодить. Ответьте честно на каждый вопрос: 1. **Требования и дизайн:** есть ли в требованиях слова 'эндпоинт', 'таблица', 'Redis', 'JWT'? Если да — переместите в дизайн или переформулируйте. 2. **Граничные случаи:** для каждого перечисленного edge case ясно, что система должна делать? Или это просто список ситуаций? Переформулируйте в чеклист: 'Когда... → система...' 3. **Двусмысленность:** может ли другой разработчик прочитать эту спеку и понять её иначе? Найдите минимум одно слово или фразу, которая неоднозначна. 4. **Что забыли:** выпишите 3-4 граничных случая, которые вы первый раз не заметили. Добавьте их в спеку. Напишите короткий отчёт: что нужно доработать и почему это важно.
• Ответы на все 4 пункта, не просто 'да'/'нет', а с примерами • Минимум 3 новых граничных случая добавлены в спеку, описаны поведением • Указаны конкретные фразы из спеки, где видна двусмысленность • Отчёт показывает, что вы честно смотрели критически, нашли реальные дыры • Правки внесены в файл спеки (или описаны, как их внести)
Сдача и проверка заданий — в приложении Learn (Almost) Anything.
