Контракты, а не задачи

Я замерил, куда на самом деле уходит моя неделя. Декомпозиция одной фичи на точные задачи — какие файлы, какие методы, в каком порядке — стоит мне часов. Потом я посмотрел, что разработчик сделал с моей декомпозицией.

Он вставил её в Claude.

Задержись на этом на секунду — мне понадобилось стыдно долго. Подробный список задач — это, по функции, промпт. Я руками писал промпты самыми дорогими часами в команде — для модели, которая сидит рядом с кодом и перегенерирует тот же план за минуты.

Дубль

У репозитория, из которого релизится моя команда, есть собственный агентный тулинг: по хорошо оформленному требованию он в порядке вещей выдаёт план имплементации — файлы, слои, порядок.

Так что каждая моя пофайловая задача была дублем: моей догадкой о плане имплементации, произведённой дальше от кода, чем инструмент, который всё равно его переделает.

Два прохода по одной работе. И из двух дорогим был мой.

Математика горлышка

Вот почему это не косметическая неэффективность:

ШагКто платитТипичная цена
Мелкозернистая декомпозициявладелецчасы на фичу
Реализация по нейразработчик + агентчасто меньше

Когда постановка стоит дороже производства, очередь выстраивается перед владельцем. Не изредка — структурно. Фичи перестают ждать рук и начинают ждать моей писанины.

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

Значит, лечение не может быть «декомпозируй лучше». Оно обязано быть «декомпозируй меньше — и всё равно оставайся в безопасности». Вот как это выглядит.

Одна фича, две передачи

Как список задач: добавь колонку, поправь хэндлер, расширь валидацию, не забудь миграцию, обнови вызов на клиенте. Пять прогнозов о том, как, — каждый из них тулинг рядом с кодом выведет заново, и ни один я не могу проверить.

Как контракт: операция переименования существует; дубль имени отклоняется отдельной ошибкой; вызвать может только владелец scope; когда родительский объект умирает, запись умирает с ним; «готово» — это три проходящие проверки.

Пять обещаний о том, что должно стать истинным, — каждое проверяемо, и ни одно не является моей догадкой о чужом файле.

В этом вся замена. Единица передачи — больше не изменение, которое надо сделать, а обещание, которое надо сдержать. Из чего оно состоит:

СекцияНа какой вопрос отвечаетПочему переживает встречу с реальностью
ИнтерфейсЧто существует, когда ты закончил?Абстрактная схема, именованная конвенциями самого API — ничего выдуманного
ПоведениеЧто происходит при успехе, при отказе, на границах?Текстом, не кодом — перевод берёт на себя имплементатор
ДоступКто может вызвать, под какой привилегией и в каком scope?Включая случаи, о которых забывают: обход админа, машинная идентичность
Жизненный циклЧто происходит при удалении / обновлении / отвязке родителя?«Мы забыли про каскад» — самый скучный продакшн-инцидент на свете
ПриёмкаЧто значит «готово»?Прогоняемо без вопросов автору, что он имел в виду
Радар воздействияЧто нельзя сломать и что от этого зависит?Порядок становится данными, а не племенным знанием

Что контракт намеренно опускает: пути к файлам, имена методов, SQL, пошаговые инструкции. Это юрисдикция имплементатора, это лучше перегенерируется ближе к коду — и каждая такая строка в спеке — строка, за которую я заплатил дважды.

Страх — и закон, который на него отвечает

Отдать крупное обещание вместо пяти прожёванных шагов — страшно, похоже на безрассудство. Страх легитимен — и у него есть точный ответ:

Гранулярность декомпозиции должна быть обратно пропорциональна силе твоего приёмочного gate.

Если gate исполнителя силён — ревью против контракта, тесты, которые пишет автор как норму, скрипт, проверяющий саму структуру контракта, — крупные единицы безопасны: один контракт упаковывает то, что было бы шестью задачами, а gate ловит, что пошло не так.

Если gate слаб, крупные куски и правда безрассудство. Приходится мельчить — не навсегда, а пока gate не вырастет.

Я гоняю оба режима одновременно, поэтому и знаю, что закон держится:

ТрекGate сегодняРазмер единицы сегодня
BackendСилён: сеньор ревьюит против контракта, автор пишет тесты, скрипт проверяет структуруКрупный — один контракт вместо шести задач
FrontendСлабее, ещё растётМелкозернистый, послойный

Backend-контракты со временем стали жёстче, а не мягче: сеньор, который их потребляет, раз за разом возвращал их — недостающий пункт жизненного цикла, имя поля, уплывшее от API-дока, строка доступа без админского случая. Каждый его рулинг становился постоянной проверкой. Это gate буквально усиливается — и каждый раз, когда это происходило, я мог позволить себе отдать кусок чуть крупнее.

Frontend остаётся мелкозернистым не потому, что фронтенд сложнее, а потому, что тот gate моложе. Тот же закон, другой конец шкалы.

Куда делись часы

Выигрыш замыкает петлю, с которой этот текст начался:

БылоСтало
Мои часы на фичупрожёвывание плана имплементациинаписание обещаний + суждение по приёмке
Разработчик получаетмой прогноз, чтобы вставить его в модельправо владеть «как» — с gate, который ловит провал
Очередьвыстраивается передо мнойвыстраивается перед gate — а он масштабируется

Два контракта, делящие граничный интерфейс, могут даже идти параллельно — фронтенд против схемы, бэкенд против поведения, — потому что источник истины на границе — контракт, а не совещание. Прожёванные задачи так не умеют: они сериализуются на общих файлах, даже когда обещания независимы.

Честный prior art, с датой: design-by-contract существует сорок лет — предусловия и постусловия принадлежат Мейеру, не мне, — а работы 2026-го оживляют его под задачной декомпозицией, чтобы верифицировать кодогенерацию. Ход здесь другой: контракт заменяет задачу как единицу передачи на границе человек↔агент, и приходящего с ним закона гранулярности я нигде сформулированным не видел. По состоянию на середину июля 2026-го — сверься с датой, прежде чем цитировать.

Неуютное следствие — дальше в серии возьмусь за него всерьёз: если гранулярность — функция силы gate, то улучшение твоих gate — а не промптов и не моделей — самая рычажная инвестиция в команде, работающей с AI. Gate — это и есть продукт.

Владелец перестаёт быть горлышком в тот день, когда единица передачи — обещание, которое может проверить gate исполнителя, а не план, который владелец был вынужден написать дважды.

Дальше: The Two-Layer Compiler — почему тупой процедурный слой плюс обучающийся слой компаундятся, а ручная сообразительность — нет.