Я пишу спецификацию до того, как прошу AI написать код. Вот почему
Я замерил. Когда я пишу спецификацию перед тем, как открыть Claude Code, итерация занимает в среднем 40 минут. Когда сажусь сразу писать промпт — около двух с половиной часов и три откатa.
Это не формализм. Это способ сделать AI-сессию предсказуемой.
Почему «напиши мне функцию» — это промпт архитектора, а не разработчика
Когда я говорю Claude Code «напиши функцию экспорта заказов в CSV», я звучу как разработчик. Но это ложное ощущение.
Я только что принял как минимум пять решений, которые в нормальном рабочем процессе требовали бы обсуждения: откуда берутся данные, какой формат CSV (разделитель, кодировка, заголовки), что делать с пустыми полями, как обрабатывать ошибки, куда идёт результат. Я не принял их явно. Я позволил Claude принять их за меня.
Иногда он угадывает. Чаще — угадывает не так, как мне нужно.
Отсюда и берётся цикл «переделай-переделай-ещё раз». Не потому что Claude плохо пишет код. А потому что задача была недоопределена с самого начала — и я это скрыл за иллюзией понятного запроса.
Что я называю spec: не RFC на 10 страниц
Спецификация в моём понимании — это не документ с заголовками и разделами. Это ответы на пять конкретных вопросов, которые я пишу в обычном markdown-файле или прямо в начале сессии.
Занимает 10–15 минут. Иногда меньше.
Сам процесс написания spec раньше находил у меня 30–40% ошибок до того, как я открывал Claude Code. Начинаю отвечать на вопрос «какой контракт у функции» — и понимаю, что не знаю ответа. Это означало, что задача была ещё не готова к реализации. Без spec я бы узнал об этом только после второго или третьего отката.
Это — главный эффект спецификации. Не контроль над AI. А ранний фиддбек самому себе.
Формат, который работает: пять вопросов до открытия Claude Code
Вот конкретный шаблон, который я использую. Не придуманный — выработанный за несколько месяцев работы с автономными задачами.
Первый вопрос — что входит в задачу. Один абзац: какие данные на входе, какое поведение на выходе. Если не могу написать это одним абзацем, задача ещё не готова.
Второй — что не входит. Явный список того, что мы намеренно не делаем. Это анти-scope, и он важнее scope'а. Claude по умолчанию старается быть полезным: без явного ограничения добавит обработку edge-кейсов, которые я не просил, и сделает функцию втрое сложнее нужного.
Третий — какие ограничения. Технологический стек, версии, существующие конвенции. В проекте на Bitrix + Next.js это критично: Claude знает React, но не знает, как устроен наш компонентный слой. Без этого пункта он напишет правильный React, но неправильный наш React.
Четвёртый — как проверить, что работает. Один или два конкретных сценария. Не unit-test, просто: «при входе X ожидаю Y». Это заставляет думать о поведении, а не о реализации.
Пятый — что сделано рядом. Ссылки на существующие файлы или функции, которые уже решили похожую задачу. Самый дешёвый способ передать контекст: вместо объяснения архитектуры в тексте — показываю готовый образец.
Без spec и со spec: два примера из одного проекта
В прошлом году я делал систему автоматизации для ivanpin.com — 13 автономных cron-задач на Claude Code. Каждая задача пишет в JSONL-лог, каждая имеет stop-условие, каждая работает без моего участия.
Первые три задачи я писал без spec. Каждая требовала в среднем четырёх итераций с Claude: код работал, но не вписывался в систему. Структура логов была разной. Обработка ошибок — разной. Имена переменных — разными. Технически корректный код. Архитектурно — хаос.
Начиная с четвёртой задачи я начал писать spec. Формат оказался простым: markdown-файл с пятью разделами, в каждом — два-три предложения. Последние девять задач потребовали в среднем одной итерации.
Разница — не в качестве промпта. Разница в том, что я сформулировал контракт задачи до того, как написал первый символ промпта.
Второй пример — на том же проекте — был обратным. Я написал spec для задачи публикации статей. Посередине написания понял, что в разделе «что не входит» нет явного запрета на автоматическую публикацию в LinkedIn. Я остановился, добавил запрет, и это предотвратило потенциально неприятную ситуацию. Без spec я бы этот пункт не проговорил.
Когда spec избыточен — и как понять за две минуты
Spec не нужен для одноразовых скриптов, которые не войдут в систему. Если я прошу Claude написать скрипт для разовой миграции данных — мне достаточно хорошего промпта.
Spec нужен, когда:
- результат будет использоваться повторно;
- код будет взаимодействовать с существующей архитектурой;
- задача связана с внешними данными или внешними системами.
Проверка занимает две минуты: я спрашиваю себя, «войдёт ли этот код в кодовую базу проекта или это одноразовый инструмент?» Если первое — пишу spec. Если второе — просто хороший промпт с контекстом.
Итог
Спецификация — это не документация ради документации. Это ранний фиддбек себе: часть ошибок я нахожу ещё до открытия Claude Code, а не после третьей итерации.
Формат простой: пять вопросов, 10–15 минут, обычный markdown. Код после этого вписывается в систему с первого раза заметно чаще.
Я не советую делать spec для каждого промпта. Я советую делать его для каждой задачи, которая войдёт в production.
*Смежные материалы: Я дал Claude писать тесты. Я не даю ему выбирать архитектуру · Как я доверяю AI-агенту в продакшне*