Код дешёв. Покажите спецификацию

Код дешёв. Покажите спецификацию

Времена меняются, и известное изречение Линуса Торвальдса «Talk is cheap. Show me the code» сегодня можно переформулировать: «Code is cheap. Show me the spec». Меня зовут Алекс Гусев, и я хочу объяснить, почему теперь именно спецификация, а не код, становится главным артефактом разработки.

Agent Driven Software Management и Spec-Driven Development

Я разрабатываю подход под названием ADSM (Agent Driven Software Management), который формализует мой личный опыт в методологию Spec-Driven Development (SDD). В рамках этой публикации я покажу, как SDD в виде ADSM применяется к созданию простого приложения — помощника по формированию плейлистов в Spotify.

Также я продемонстрирую, что происходит, когда один и тот же агент (Codex, GPT-5.4) генерирует код на основе одной и той же спецификации, но с разным уровнем reasoning: high, medium и low.

Предыстория: от идеи к автоматизации

Для семейного мероприятия понадобился плейлист на 4–5 часов. ChatGPT успешно составил список из 100 треков — с названиями и исполнителями. Оставалось только перенести их в Spotify. Раньше это делалось вручную, но теперь такие задачи легко автоматизировать с помощью ИИ-агентов.

Я не пишу «вайбкод», но зато практикую SDD. На создание первой версии приложения ушло чуть больше двух часов чистого времени.

До начала проекта я не знал о возможностях API Spotify. ChatGPT подсказал ссылку developer.spotify.com и объяснил, как зарегистрировать приложение.

Оказалось, что аутентификация реализуется через OAuth. Для этого нужен домен и TLS-сертификат. Домен был, сертификат — через Let’s Encrypt. Я пишу только на JavaScript, поэтому выбор языка и платформы был очевиден: TeqFW.

Разработка с агентом

Я создал приватный репозиторий на GitHub, склонировал его локально и добавил в контекст (./ctx/spec/) типовые шаблоны для node.js-приложений на основе библиотеки @teqfw/di.

Час я провёл в диалоге с Codex-агентом в VSCode: обсуждали запуск, конфигурацию, зависимости. Агент фиксировал всё в контексте проекта (./ctx/docs/).

Затем я попросил агента создать:

  • package.json;
  • bootstrap-файл ./bin/cli.mjs;
  • головной скрипт ./src/Main.mjs.

После этого — две итерации:

  1. Интеграционные тесты и код для получения и сохранения токена аутентификации через веб-сервер.
  2. Загрузка и парсинг текстового файла с треками, поиск в Spotify и создание плейлиста (всё с интеграционными тестами).

Соответствие формату ES6-модулей я проверял с помощью скилла teq-esm-validator.

Приложение проверялось по частям: запуск, аутентификация, разбор файла, поиск треков, создание плейлиста. Через два часа в Spotify был создан плейлист из 80+ композиций. Остальные треки не нашлись.

Детерминированность: не кода, а функционала

В комментариях на Хабре часто звучит мнение, что LLM-агенты неприменимы, потому что не дают детерминированного результата. Но программирование всегда было отчасти искусством.

«Детерминированность результата» ≠ «Детерминированность кода»

Если Леонардо да Винчи рисовал бы «Джоконду» десять раз, у него получилось бы десять разных картин одной и той же женщины. Так и с кодом: десять реализаций одного функционала — это десять разных приложений.

Эксперимент: три версии, один контекст

Я опубликовал код, созданный агентом (GPT-5.4, high reasoning) — версия 1.0.0. Контекст я намеренно удалил.

Затем попросил того же агента (но с уровнем reasoning medium) удалить папки ./src/ и ./test/ и, на основе неизменного контекста из ./ctx/, сгенерировать код с нуля — версия 2.0.0.

То же самое — с low reasoning: версия 3.0.0.

Агенту давался чёткий промпт: не восстанавливать прошлую реализацию из git, проектировать с нуля. В этом и был смысл итерации.

Результат: код во всех трёх версиях разный. Но приложение работает одинаково.

Ошибки и их детерминированность

Все три версии «затупили» при добавлении треков в плейлист. Dry-запуск проходил успешно, треки находились, но при добавлении агент использовал устаревший API Spotify. Пришлось вручную указывать на ошибку — трижды.

Если бы я не стремился к чистоте эксперимента, я бы добавил в контекст требование использовать новый API. Но я сознательно оставил контекст неизменным. Это показало: ошибки в прочтении контекста тоже детерминированы.

Третья версия (low reasoning) не смогла корректно запустить веб-сервер: он стартовал, но приложение сразу его останавливало, не дожидаясь получения токена. На уровнях high и medium такой проблемы не было.

Объём контекста vs объём кода

Я потратил месяцы на создание спецификаций для своего стиля разработки (./ctx/spec/code/platform/teqfw/). Эта документация переиспользуется во всех моих проектах.

На описание конкретного продукта ушло пара часов. А на генерацию кода каждой версии — около 10 минут. При этом на каждую версию уходило примерно 4% недельной квоты plus-подписки ChatGPT.

Соотношение объёма контекста и кода впечатляет:

  • Файлы в ctx: 53
  • Каталоги в ctx: 15
  • Строк в ctx: ~10 000
  • Файлы в src (v1–v3): 18–23
  • Строк в src: ~1 500

Да, это моя осознанная позиция: документы контекста должны быть в разы больше результирующего кода.

Скиллы как корректоры поведения агента

Моя платформа TeqFW использует позднее связывание: все зависимости внедряются через конструктор. В ./src/ нет ни одного статического импорта — это нетрадиционный подход, и агенты с ним справляются плохо.

Когда агенты упорно генерировали код со статическими импортами, я создал скилл teq-esm-validator — тоже с помощью Codex по методологии ADSM. Теперь достаточно указать в промпте: «используй скилл» — и проблема почти исчезает.

Заключение: код как производный артефакт

Я сравниваю поведение LLM-агентов с дождевой водой: она течёт по рельефу, собирается в ручьи и стремится к океану. Агент идёт по пути наименьшего сопротивления.

В этой аналогии:

  • Контекст — плотины и каналы;
  • Скиллы и тесты — насосы и шлюзы, поднимающие воду на новый уровень.

Основные затраты — на построение инфраструктуры. Но зато потом вода (код) почти всегда попадает туда, куда нужно.

Код — не конечный продукт. Это производный артефакт взаимодействия когнитивного контекста и агента.

Именно поэтому контекст проекта (53 файла в ./ctx/) важнее кода (18–23 файла в ./src/). Когда есть контекст, агент сгенерирует нужный код за минуты — даже для экзотической платформы вроде TeqFW.

Код всех трёх версий — дешёв. Изучайте его. А если хотите увидеть контекст — пишите в личку. Дам бесплатно, в обмен на обратную связь о применимости подхода в ваших проектах.

И немного прекрасного

ИИ-агенты легко генерируют «бойлерплейт» и делают ненужными тонны зависимостей в node_modules.

Они спокойно хардкодят Web API и перехардкодят при изменениях. В моём приложении всего:

  • 2 зависимости для runtime (мои библиотеки);
  • 2 зависимости для dev-режима (типы Node.js).
Читать оригинал