Научитесь создавать спецификации фич Claude Code из кода: извлекать реальное поведение из маршрутов и компонентов, затем формировать живую спецификацию и список разрывов.

Люди по-разному помнят, что делает приложение, потому что они помнят разные версии. Саппорт помнит последний злой тикет. Продажи помнят путь из демо. Инженеры помнят, что фича должна была делать. Спросите трёх человек — получите три уверенных ответа, и ни один не совпадёт с текущей сборкой.
Со временем код становится единственным актуальным источником правды. Документация устаревает, тикеты закрываются, быстрые фиксы накапливаются. У маршрута появляется новое правило валидации. В UI переключатель меняет значение по умолчанию. Хендлер начинает возвращать другие ошибки. Никто не обновляет спецификацию, потому что это кажется необязательным, а каждое изменение кажется слишком мелким, чтобы его документировать.
Это создаёт предсказуемые проблемы. Команды выпускают изменения, которые ломают редкие сценарии, о существовании которых они не знали. QA тестирует счастливый путь и пропускает правила, спрятанные в хендлерах. Новые члены команды копируют поведение из UI, не понимая реальных ограничений. Заинтересованные лица спорят мнениями вместо того, чтобы ссылаться на согласованное поведение.
Хороший результат — это не идеальный документ. Это общая ясность. Каждый должен уметь ответить: "Что произойдёт, если я сделаю X?" и "Какие гарантии даёт система?" без домыслов. Меньше сюрпризов, короче ревью и меньше моментов «Стоп, но оно же уже это делает», потому что команда смотрит на одну и ту же правду.
Когда спецификация соответствует коду, планировать изменения становится безопасно. Видно, что стабильно, что случайно, и чего не хватает до релиза.
Живая спецификация — это короткое, редактируемое описание того, что приложение реально делает сегодня. Это не одноразовый документ. Оно меняется при каждом изменении поведения, чтобы команда могла ему доверять.
Когда говорят о спецификациях фич, написанных из кода (например, с использованием Claude Code), цель проста: прочитать реальное поведение из маршрутов, хендлеров и экранов, а затем записать его простым языком.
Полезная живая спецификация фокусируется на том, что видит пользователь и что система обещает. Она должна покрывать:
То, что не следует покрывать — как организован код. Если вы начинаете называть файлы и планы по рефакторингу, вы уходите в детали реализации. Избегайте:
Список разрывов — это отдельное небольшое перечисление несоответствий и неизвестностей, которые вы обнаружили при написании спецификации.
Пример: один маршрут отклоняет файлы больше 10 МБ, а UI говорит 25 МБ. Это gap, пока команда не решит, какое правило истинно, и не обновит либо код, либо спецификацию.
Начните с малого. Если пытаться документировать всё приложение, вы получите свалку заметок, которым никто не доверяет. Выберите один срез, который пользователь может описать одним предложением, например "пригласить коллегу", "оформить заказ" или "сброс пароля". Хорошие масштабы — одна область фичи, один модуль или одно пользовательское путешествие от входа до результата.
Выберите точку входа в зависимости от того, где живёт правда:
Перед чтением кода соберите несколько входных данных, чтобы несоответствия было видно сразу: существующая API-документация, старые заметки продукта, тикеты саппорта и «известные боли», на которые жалуются люди. Они не отменяют код, но помогают замечать пропущенные состояния: ошибки, крайние случаи и правила доступа.
Делайте формат спецификации скучным и последовательным. Команды быстрее сходятся во мнении, когда каждая спецификация читается одинаково.
Повторяйте эту структуру, и ваши спецификации останутся читаемыми, сопоставимыми и простыми в обновлении.
Начните с серверных точек входа. Маршруты и хендлеры показывают «что приложение делает» в конкретных терминах: кто может вызывать, что нужно отправить, что возвращают и что меняется в системе.
Перечислите маршруты в области и сопоставьте каждый с пользовательским намерением. Не пишите «POST /api/orders.» Пишите «Оформить заказ» или «Сохранить черновик». Если вы не можете назвать намерение простыми словами — это уже gap спецификации.
Читая каждый хендлер, фиксируйте входные данные и правила валидации как требования для пользователя. Включайте обязательные поля, допустимые форматы и правила, которые приводят к реальным ошибкам. Например: "Email должен быть валидным", "Количество должно быть не менее 1", "Дата начала не может быть в прошлом."
Пишите проверки авторизации и ролей так же. Вместо "middleware: requireAdmin" документируйте: "Только админы могут отменять любой заказ. Обычные пользователи могут отменять только свои заказы в течение 10 минут." Если код проверяет принадлежность, feature flags или границы арендатора, включите и это.
Затем отметьте выводы и исходы. Что возвращает успех (созданный ID, обновлённый объект)? Какие типичные ошибки (401 не авторизован, 403 нет доступа, 404 не найдено, 409 конфликт, 422 ошибка валидации)?
Наконец, зафиксируйте побочные эффекты — они тоже часть поведения: созданные или обновлённые записи, отправленные письма/уведомления, опубликованные события, поставленные в очередь фоновые задания и всё, что запускает другие потоки. Эти детали предотвращают сюрпризы, когда позже на спецификацию будут опираться другие команды.
Маршруты говорят, что приложение может делать. Компоненты показывают, что пользователи реально испытывают. Рассматривайте UI как часть контракта: что отображается, что блокирует действия и что происходит при ошибках.
Начните с поисков точек входа в фичу: страницу, обёртку layout и несколько «решающих» компонентов, которые контролируют фетчинг, права доступа и навигацию. Именно там обычно живёт реальное поведение.
Читая компоненты, фиксируйте правила, которые чувствует пользователь: когда кнопки отключены, обязательные шаги, условные поля, состояния загрузки и как отображаются ошибки (инлайн-подполе против тоста, автоповтор, кнопки «повторить попытку»). Также отметьте поведение состояния и кэширования: сначала показывается устаревшая информация, оптимистичные обновления или отметки "последнее сохранение".
Ищите скрытые потоки, которые тихо меняют то, что видит пользователь. Ищите feature flags, экспериментальные корзины и гейты только для админов. Зафиксируйте тихие редиректы, например отправку неавторизованных пользователей на страницу входа или отправку пользователей без доступа на страницу апгрейда.
Конкретный пример: на экране "Сменить email" задокументируйте, что кнопка Сохранить остаётся отключённой, пока email не пройдет валидацию, отображается спиннер во время запроса, успех вызывает баннер подтверждения, а ошибки валидации от бэкенда рендерятся под полем ввода. Если код показывает флаг newEmailFlow, отметьте оба варианта и в чём их различие.
Опишите каждый UI-поток короткими шагами (что делает пользователь, что UI делает в ответ) и держите условия и ошибки рядом со шагом, на который они влияют. Это делает спецификацию читаемой и упрощает выявление разрывов.
Сырые заметки из маршрутов и компонентов полезны, но трудно обсуждаемы. Перепишите наблюдения в спецификацию, которую может прочитать и согласовать PM, дизайнер, QA и инженер.
Практичный подход — одна user story на маршрут или экран. Держите её маленькой и конкретной. Например: "Как вошедший пользователь, я могу сбросить пароль, чтобы восстановить доступ." Если код показывает разное поведение по ролям (админ vs пользователь), разделите это на отдельные истории, а не прячьте в сносках.
Пишите acceptance criteria, которые отражают реальные пути кода, а не идеальный продукт. Если хендлер возвращает 401 при отсутствии токена, это критерий. Если UI блокирует отправку до валидности поля — это критерий.
Включайте правила данных простым языком, особенно те, которые вызывают сюрпризы: лимиты, порядок, уникальность, обязательные поля. "Имена пользователей должны быть уникальными (проверяется при сохранении)" понятнее, чем "уникальный индекс".
Крайние случаи часто отличают приятный документ от полезного. Выделяйте пустые состояния, null-значения, повторы, таймауты и то, что видит пользователь при ошибке API.
Если встречаете неизвестные вещи, помечайте их, а не догадывайтесь:\n
Список разрывов — не вторая Jira. Это короткий, основанный на доказательствах список мест, где код и ожидаемое поведение не совпадают или где никто не может чётко объяснить, что правильно. Хорошо сделанный, он служит инструментом для согласования, а не предметом планировочной ссоры.
Строго определите, что считается разрывом:\n
Когда вы записываете разрыв, включайте три части, чтобы он оставался привязанным к фактам:\n
Доказательства не дают списку превратиться в набор мнений. Пример: "POST /checkout/apply-coupon принимает просроченные купоны, но CouponBanner.tsx блокирует их в UI. Влияние: доходы и путаница пользователя. Тип: баг или отсутствие решения (подтвердить желаемое правило)."
Держите список коротким. Установите жёсткий лимит, например 10 пунктов на первый проход. Если вы нашли 40 проблем, сгруппируйте их по паттернам (несоответствия в валидации, проверки прав, пустые состояния) и оставьте только ключевые примеры.
Не добавляйте даты и планирование в сам список разрывов. Если нужна ответственность, укажите, кто должен принять решение (product) или кто может проверить поведение (engineering), а планирование перенесите в основной бэклог.
Выберите маленький, но часто используемый срез: оформление заказа с промокодами и вариантах доставки. Цель — не переписать весь продукт, а зафиксировать, что приложение делает сегодня.
Начните с бэкенд-маршрутов. Часто правила проявляются сначала там. Вы можете найти маршруты вроде POST /checkout/apply-promo, GET /checkout/shipping-options и POST /checkout/confirm.
Из хендлеров запишите поведение простыми словами:\n
restricted.\n- Подтверждение падает, если запас по позиции изменился с момента загрузки корзины.\n- Налог считается после выбора доставки (не при применении промо).Затем проверьте UI-компоненты. PromoCodeInput может показывать обновлённые суммы только после успешного ответа, а ошибки рендерятся под полем ввода. ShippingOptions может автоматически выбирать самый дешёвый вариант при загрузке и триггерить обновление разбивки цен при смене пользователем.
Теперь у вас есть читаемая спецификация и небольшой список разрывов. Например: сообщения об ошибках различаются между промо-маршрутом и UI ("Invalid code" vs "Not eligible"), и никто не знает точное правило округления налогов (по строке или по сумме заказа).
При планировании команда сначала соглашается с реальностью, потом решает, что менять. Вместо споров вы просматриваете задокументированное поведение, выбираете одно несоответствие для исправления и оставляете остальное помеченным как "текущее поведение" до следующего ревью.
Спецификация помогает только если команда согласна, что она отражает реальность. Проведите короткий прогон с одним инженером и одним продуктовым. Держите его в пределах: 20–30 минут, сосредоточившись на том, что пользователь может сделать и как система отвечает.
Во время проверки превращайте утверждения в вопросы да/нет. "Когда пользователь попадает на этот маршрут, мы всегда возвращаем 403 без сессии?" "Это пустое состояние — намеренно?" Так вы отделяете намеренное поведение от случайных изменений, которые накопились со временем.
Согласуйте словарь до редактирования. Используйте слова, которые видны в UI (названия кнопок, заголовки страниц, сообщения). Добавляйте внутренние имена только когда они помогают инженерам найти код (имена маршрутов, компонентов). Это предотвращает несоответствия вроде того, что продукт говорит "Workspace", а спецификация — "Org".
Чтобы держать спецификацию актуальной, сделайте явными владение и ритм обновлений:
Если вы используете инструмент вроде Koder.ai, снапшоты и откаты помогут сравнить "до" и "после" при обновлении спецификации, особенно после больших рефакторингов.
Самый быстрый путь потерять доверие к спецификации — описывать продукт, каким вы хотите его видеть, а не тем, какой он есть. Жёсткое правило: каждое утверждение должно подтверждаться тем, на что вы можете указать в коде или на реальном экране.
Ещё одна ловушка — копирование структуры кода в документ. Спецификация, читающаяся как "Controller -> Service -> Repository", не является спецификацией, это карта папок. Пишите на языке, понятном пользователю: что запускает действие, что видит пользователь, что сохраняется и как выглядят ошибки.
Права доступа и роли часто игнорируют до финала, а потом всё ломается. Добавляйте правила доступа с самого начала, даже если они запутаны. Отмечайте, какие роли могут просматривать, создавать, редактировать, удалять, экспортировать или утверждать, и где правило применяется (только UI, только API или и там, и там).
Не пропускайте не-хэппи-пати. Реальное поведение скрыто в повторах, частичных сбоях и правилах по времени: истечения, кулдауны, планировщики или лимиты типа "только раз в день". Рассматривайте их как поведение первого порядка.
Быстрый способ выявить разрывы — проверить:\n
Наконец, двигайте список разрывов вперёд. Каждому разрыву присвоьте статус из: "unknown/needs decision", "bug/fix" или "missing feature/plan". Если список не помечается, он застывает и спецификация перестаёт быть "живой".
Сделайте быструю проверку на ясность, покрытие и пригодность к действию. Тот, кто не писал спецификацию, должен понять, что фича делает сегодня и что ещё неясно.
Прочитайте спецификацию как новый человек в команде в первый день. Если он может пересказать фичу за минуту — вы близки к цели. Если он всё время спрашивает: "Откуда начинается поток?" или "Каков счастливый путь?" — усилите начало.
Проверьте:\n
Каждый gap должен быть конкретным и проверяемым. Вместо общего "неясна обработка ошибок" напишите: "Если платёжный провайдер возвращает 402, UI показывает общий тост; подтвердить желаемое сообщение и стратегию повтора." Добавьте одно следующее действие (спросить продукт, добавить тест, посмотреть логи) и укажите, кто должен ответить.
Выберите одну область фич и ограничьте время до 60 минут. Возьмите что-то небольшое, но реальное (логин, оформление заказа, поиск, админ-экран). Напишите одно предложение масштаба: что включено и что исключено.
Пройдите workflow один раз целиком: пробегитесь по ключевым маршрутам/хендлерам, проследите основной UI-поток и выпишите наблюдаемое поведение (входы, выходы, валидация, ошибки). Если застряли — зафиксируйте вопрос как gap и идите дальше.
Когда закончите, поделитесь спецификацией там, где команда может комментировать, и установите одно правило: любое поведение, отправленное в релиз, должно обновить спецификацию в том же окне доставки, даже если это пять строк.
Держите gaps отдельно от бэклога. Группируйте их в "неизвестное поведение", "несогласованное поведение" и "недостающие тесты" и кратко пересматривайте каждую неделю, чтобы решить, что важно сейчас.
Если набрасывание и итерация идут медленно, чат-базированный билдeр вроде Koder.ai может помочь получить первоначальную версию быстро. Опишите фичу, вставьте ключевые фрагменты или имена маршрутов, уточняйте формулировки в разговоре и экспортируйте исходники при необходимости. Смысл — скорость и общая ясность, а не громоздкий процесс.
Начните с одной небольшой видимой пользователю части (например, “сброс пароля” или “пригласить коллегу”). Прочтите routes/handlers, чтобы зафиксировать правила и результаты, затем изучите UI-поток, чтобы описать, что реально видит пользователь (заблокированные кнопки, ошибки, редиректы). Оформите результат по постоянному шаблону и зарегистрируйте неизвестные моменты в отдельном списке gaps.
По умолчанию: документируйте текущее поведение кода как источник истины.\n\nЕсли поведение похоже на случайность или несогласованность, не «исправляйте» это в спецификации — отметьте как gap с доказательством (где вы это увидели и что происходит), затем получите решение: обновлять код или спецификацию.
Делайте шаблон скучным и повторяемым. Практичный формат:\n\n- Purpose (цель)\n- Entry points (точки входа)\n- Preconditions (авторизация/роли/данные)\n- Main flow (5–10 шагов)\n- Data and side effects\n- Errors and edge cases\n- Open questions\n\nТак спецификации остаются читаемыми и несут явную пользу при сравнении.
Пишите правила с точки зрения пользователя, а не как заметки к коду.\n\nПримеры:\n\n- “Email должен быть валиден”\n- “Количество должно быть не менее 1”\n- “Только админы могут отменять любой заказ; обычные пользователи могут отменить свой заказ в течение 10 минут”\n\nЗафиксируйте, что вызывает ошибку и что видит пользователь в этом случае.
Фокусируйтесь на наблюдаемом поведении:\n\n- Результат успеха (что изменяется, что видит пользователь)\n- Частые ошибки (неавторизован, нет доступа, не найдено, ошибка валидации)\n- Побочные эффекты (обновлённые записи, отправленные письма/уведомления, фоновые задачи)\n\nПобочные эффекты важны, потому что они влияют на другие фичи и ожидания поддержки/операций.
Если UI блокирует то, что API разрешает (или наоборот), зафиксируйте это как gap до принятия решения.\n\nУкажите:\n\n- Что показывает/делает UI\n- Что применяет бэкенд\n- Влияние (путаница, безопасность, проблемы с данными)\n\nЗатем согласуйте одно правило и обновите и код, и спецификацию.
Держите gaps маленькими и основанными на доказательствах. Каждый пункт должен содержать:\n\n- Тип: баг или отсутствие решения\n- Влияние: от мелкого до серьёзного (путаница, безопасность, потеря данных)\n- Доказательство: где вы это увидели (route/handler/component) и точное поведение\n\nИзбегайте превращать их в планирование или вторую Jira.
Явно фиксируйте их, а не прячьте.\n\nВключите:\n\n- Пустые состояния (нет результатов, нет доступа)\n- Повторы/таймауты и что пользователь может сделать дальше\n- Дублированные отправки (двойной клик, обновление)\n- Конкуренция (два человека редактируют одну запись)\n- Правила по времени (истечение, кулдаун)\n\nИменно эти сценарии чаще всего приводят к сюрпризам и багам.
Короткая проверка: 20–30 минут с одним инженером и одним продуктовым менеджером.\n\nПреобразуйте утверждения в вопросы «да/нет» (например, “Всегда ли возвращаем 403, когда доступ запрещён?”). Согласуйте словарь, используя термины интерфейса (лейблы, сообщения), чтобы все понимали друг друга.
Держите спецификацию рядом с кодом и делайте обновления частью релиза.\n\nПрактические по умолчанию:\n\n- Ясный владелец, который принимает изменения спецификации\n- Триггер обновления: любое изменение поведения вмерже или каждый релиз\n- Чеклист PR: “Спецификация обновлена?”\n- Отдельный список gaps и краткий обзор по расписанию\n\nЦель — небольшие и частые правки, а не глобальный редизайн.