← Статьи Harupa
2026-08-02RU EN UA BY PL

My Architect, часть 11: восемьсот коммитов, которые писал не я

Второго августа утром я посчитал коммиты в своём видеогенераторе. Вышло 795. Пока я писал эту статью, счётчик дошёл до 802. Кода за это время я не написал ни строчки — отвечал на вопросы и смотрел, что получается.

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

Все цифры ниже сняты с живого проекта 2 августа 2026 года. Где цифра меряет не то, что кажется на первый взгляд, — я так и пишу.

Проект, который не помещается в голову

Видеогенератор — он же Vini Studio — начался 16 мая 2026 года коммитом с сообщением init. На второе августа это 802 коммита за 78 суток, 920 файлов под гитом, 85 тысяч строк кода и ещё 70 тысяч строк документации и конфигов.

Разнородность там неприличная для одного человека. Фронт: React 18 поверх litegraph, нодовый холст на 25 типов нод. Бэк: Node без фреймворка, 2771 строка в одном роутере, SQLite на 16 таблиц. Рендер идёт через Remotion, а тот поднимает Chrome Headless Shell. Рядом живут два питоновских сайдкара на Flask: первый обёрнут вокруг ffmpeg и держит 17 эндпоинтов, второй разделяет дорожки через Demucs на торче. Моделей пять вендоров — fal.ai, Anthropic, OpenAI, Groq, ElevenLabs, и два реестра по шесть моделей в каждом, для видео и для картинок. Есть ещё исследовательский слой: девятнадцать research-документов, трёхслойные эвалы поведений, слепая кросс-вендорная оценка сценаристов и пять A/B-замеров, где решение принималось по цифрам.

А 24 июля проект вообще сменил архитектуру целиком. Первый путь сборки, телеграм-бот на n8n, ушёл в архив решением RFC-055, каноническим стал нодовый холст. Девятнадцать n8n-воркфлоу остались в гите только как история.

Про заголовок сразу, чтобы не было спекуляций. Автором всех 802 коммитов гит считает меня, и жму коммит тоже я. Формальный след агентского соавторства — трейлер Co-Authored-By, он стоит в 256 коммитах, это 31,9%, и там пять разных версий моделей. Это нижняя граница, потому что трейлер ставится не всегда.

Зато режим работы по репозиторию виден хорошо. Семь рабочих деревьев, три из них агентские и созданы 19 июля с разницей в семь минут. А четвёртого июля есть серия из 43 коммитов за 33 минуты: механическая миграция тестов на общий стенд, по коммиту на файл. Руками я так не умею.

Я не помню этот проект. Я помню направление. Всё остальное лежит в архитекторе.

Что там на самом деле лежит

Дамп проекта из my_architect на второе августа — 650 узлов. Тридцать один эпик верхнего уровня, 237 фич, 33 истории, 324 задачи и 25 багов заведены отдельным типом. Из них 527 закрыты — это 81%. Четыре уровня иерархии, шесть релизных корзин, самая старая — MVP, закрытая целиком, 38 из 38.

Требований — 296. Не только функциональных: 241 FR, 26 NFR, 20 ограничений, пять архитектурно значимых, три системных и один открытый вопрос — тот самый, который я подкинул в обсуждении и который заведён именно для того, чтобы не потеряться. Документов на узлах — 29, диаграмм — четыре, включая доску Event Storming.

Масштаб проще всего почувствовать так. Когда я попросил выгрузить контекст проекта одним вызовом, ответ занял 258 тысяч символов — и это ещё урезанный вид, без описаний узлов. А список требований целиком не влез вообще: инструмент вернул ошибку «385 тысяч символов, превышен лимит» и положил ответ на диск.

Это и есть ответ на вопрос, зачем внешняя память. Не потому что агент глупый. Потому что проект физически больше любого контекстного окна — и моего в том числе.

Требование, коммит и тест держатся за руки

В корне проекта лежит CLAUDE.md на 488 строк с одиннадцатью жёсткими правилами. Одно из них устроено так:

Любое архитектурное решение, decision, status-change или scope-shift ОБЯЗАТЕЛЬНО отражается в ДВУХ местах: RFC в docs/rfc/RFC-NNN-*.md и my_architect MCP. Если изменение не отражено в обоих — оно потеряется при /compact или новой сессии. Не делай работу не записав. Не записывай работу не сделав.

Последняя фраза не мой пересказ, а дословная строка из репозитория. И она работает: 456 коммитов из 802, то есть 56,9%, несут в теме или теле ссылку на конкретный FR или RFC. RFC-файлов в проекте 63, от первого до шестьдесят четвёртого, с одной дырой на сорок шестом.

Но одна дисциплина ссылок ничего не стоит без второго конца. Второй конец — тесты. Правило звучит так: каждая починка регрессии приезжает с постоянным тестом, помеченным // covers: FR-NNN против требования в архитекторе, и если требования ещё нет, его сначала заводят.

Дальше начинается механика. Скрипт вытаскивает требования из архитектора и сверяет их с тегами в тестах. Второй скрипт роняет сборку, если у какого-то требования нашлось ноль покрывающих тестов. Я запустил его прямо сейчас: ALL 203 requirements covered. Тегов // covers: в тестовой папке — 290 штук на 221 уникальный идентификатор. Идентификаторы требований живут и в продуктовом коде тоже: 145 разных FR встречаются в исходниках холста.

Как это выглядит в конкретной цепочке. Есть RFC-052 про удаление проекта. В его шапке — узел feature-211-adwcry в архитекторе. У узла пять требований. По ним два коммита от 23 июля, по коммитам — функции deleteProject и renameProject в сторе, а по функциям — три теста с тегами. И тело первого коммита заканчивается строкой Architect: feature-211-adwcry → done; NFR-122/FR-143/FR-144/FR-145 → approved. Цепочка замкнута в обе стороны, и пройти её можно с любого конца.

До кода — картинка, а не текст

Есть техника, которую я недооценивал, пока не начал ей пользоваться постоянно: перед тем как что-то строить, нарисовать это и дать себе выбрать.

С 28 июня по 3 июля агент нарисовал мне четырнадцать интерактивных HTML-вайрфреймов в шести брейншторм-сессиях — примерно 94 килобайта рукописной вёрстки. Не картинки: локальный сервер поднимал их в браузере по одному, а я кликал вариант. Раскладка оболочки — рельс с доком против всего в верхней панели. Три варианта статус-бара. Куда вешать иконки над нодой и сколько их. Как выглядят состояния индикатора сохранения. Панель истории.

Проверить порядок «сначала картинка, потом код» просто. Вайрфрейм концепта холста датирован 28 июня, первый коммит самого холста — 29-м. Спека от 1 июля говорит дословно: «варианты ниже отражают реальный выбор пользователя в браузере, а не предположения». Спека от 3 июля указывает, что взят макет C, а макет B отклонён.

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

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

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

Про ночь

Я отдаю задачу в десять вечера, а утром прихожу к готовому результату. В последние месяцы — к крупному: не «поправь отступ», а собранный кусок системы.

Сначала я решил проверить это по коммитам и чуть не сделал неверный вывод. В окно с десяти вечера до восьми утра попадают 75 коммитов из 802, а с часу ночи до шести утра — ровно ноль. Выглядит как опровержение.

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

Зато форма суток меряется, и она говорит ровно то, что я и описываю. У дня два горба, и ночь лежит между ними. Девять вечера — второй по загрузке час за всё время проекта, 75 коммитов. Девять утра — третий, 70. На вечернюю сдачу с девяти до полуночи приходится 122 коммита, на утренний разбор с семи до десяти — 115.

И утренние коммиты самые крупные за сутки: в среднем 361 вставленная строка против 179 днём, вдвое. Днём идёт мелкая итерация. Утром в репозиторий приезжает большой кусок, сделанный целиком.

Так что фраза не про часы. Она про то, откуда берётся уверенность отдать большой кусок и не сидеть над ним, — и вот это меряется напрямую.

Уверенность даёт не модель. Её даёт то, что агенту некуда соврать: у требования есть номер, у номера есть тест, у теста есть гейт, который роняет сборку.

Как выглядит проверка на прочность этого механизма, видно по истории первого августа. В холсте было 63 зелёных браузерных теста, создававших связи между нодами вызовом внутреннего API. Одновременно с этим жили два бага, воспроизводимых руками стопроцентно. Один тест вообще подделывал событие, которого в проде не бывает, и был зелёным именно потому, что чинил собой ровно то условие, которое сломано.

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

И раз уж я обещал честность, вот вторая половина картины. Машинного принуждения к синхронизации у меня нет: хуков нет, CI прогоняет только деплой, тесты и гейт покрытия я гоняю руками. Дисциплина держится текстом правил и тем, что агент их читает каждую сессию. Работает — но это не то же самое, что «невозможно нарушить».

Что я на этом выигрываю

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

За последнюю неделю июля и первые дни августа в студии появился редактор оформления, где превью физически не может разойтись с рендером, потому что это буквально одна и та же композиция. Появилась студия монтажа: с ревизии от 2 августа она собирает ролик прямо во вкладке браузера. И за два дня приехал весь голосовой контур: клон голоса, озвучка, изоляция, дубляж, липсинк. Три RFC подряд закрыты за трое суток.

Заодно там случился инцидент, который в отчёт о победах обычно не попадает: 20 июля неограниченный рендер уронил по памяти весь общий сервер, load дошёл до одиннадцати на четырёх ядрах. Лечится это скучно — потолком памяти и процессоров у контейнера, чтобы падал только свой рендер, а не хост. Комментарий с описанием инцидента я оставил прямо в конфиге, чтобы никто потом не снял лимиты «за ненадобностью».

Дальше — команда

Скажу прямо, чтобы меня не поняли наоборот. Это не история про то, что один человек заменяет команду. Посадить одного на большой командный проект и надеяться, что взлетит, сегодня нельзя, и я такого не предлагаю.

История про то, куда переехало узкое место. Раньше моим ограничением были руки. Теперь ограничение — насколько внятно сформулировано, что должно получиться, и насколько машина может проверить, что получилось именно оно.

И вот здесь для команды самое интересное. Вся дисциплина, из-за которой агенту можно отдать большой кусок, — это ровно те артефакты, которые команде нужны и без всяких агентов. Один источник правды о состоянии работы вместо треда в мессенджере. Требование с номером, до которого дотягиваешься из кода, и гейт, который роняет сборку, если это требование осталось без теста. В одиночку без такого ещё можно жить, в команде — нет.

Раньше такие артефакты приходилось продавать команде как накладные расходы: пишем требования, потому что так правильно. Теперь у них появился второй потребитель, который читает их каждую сессию и работает по ним буквально. Один и тот же документ обслуживает и человека, и агента. Я такого раньше не видел, и множитель именно в этом.

Что я на команде ещё не мерил и честно называю открытым: как расходится трекер, когда в него пишут пять человек и десять агентов; кто утверждает требование, если его автор — агент; сколько нужно ревью, когда объём кода в неделю вырастает кратно. Это следующая задача, а не решённая.

Дверь я открываю, а не закрываю.

Факты и ссылки

Замер сделан 2 августа 2026 года. Репозиторий видеогенератора: 802 коммита, первый 16 мая 2026, последний на момент замера — a2cc612 в 12:50. Данные архитектора — живой проект ai-video-generator на my-architect.app: 650 узлов, 296 требований, 29 документов, 4 диаграммы. Гейт покрытия — node test/check-coverage.mjs, вывод «ALL 203 requirements covered». Распределение коммитов по часам — git log --format='%ad' --date=format:'%H'; средний размер коммита по окнам суток — по git log --shortstat. Вайрфреймы лежат в .superpowers/ и в гит не попадают, даты взяты по файловой системе и сверены с датами спек.

Сам инструмент — my-architect.app, ставится в Claude Code двумя командами. Как устроена студия, про которую тут речь, я разбирал в статье «От холста к студии».

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