Назад в блог

Я пишу спецификацию до того, как прошу 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-агенту в продакшне*