Последнее время перестал смотреть глазами на код, который пишут агенты. Хотел написать, что "Не из лени, а просто арифметика перестала сходиться", но, если честно, то и из лени тоже. За последнюю неделю в семь репозиториев одного из проектов влилось 157 пулл-реквестов, - больше двадцати в день (у нас правило "один PR = один логический шаг, с тестами в том же PR", поэтому они мелкие, но их много). Вычитывая каждый, я стал тем самым боттлнеком - пока я читаю диф одной сессии, три-четыре других простаивают.
Поэтому ориентируюсь теперь не на свои глаза, а на обвязку, которую мы вокруг процесса строили последние месяцы. Слоёв несколько, и они ловят разное:
• CI на каждый PR - на своём железе, 5–11 минут: проверка типов, три линтера, проверка форматирования, отдельный линтер доступности, 321 файл юнит-тестов, сборка и бюджет размера бандла. Отдельным шагом CI выкачивает канон контрактов из соседнего репозитория и сверяет, что клиент зовёт эндпоинты, которые там реально описаны.
• Локальный прогон перед пушем, включающий то, чего в CI на PR нет: 89 браузерных спеков Playwright. Их пришлось убрать из PR-прогона - шесть раннеров живут на той же 12-ядерной машине, где идёт работа, и браузерные проверки съедали половину времени. То есть сейчас локальный прогон - единственное место, где браузер запускается до мержа.
• Проверка мутацией. Зелёные тесты значат либо "код верный", либо "никто не спросил", и различить это можно только одним способом - сломать в своей же правке то, ради чего тест написан, и убедиться, что он краснеет. У нас это одна команда. Она берёт строки, добавленные веткой, делает по одной неверной правке и смотрит, заметят ли тесты.
• Аудиты по факту - ручные прогоны на проде и разборы телеметрии. Тут и я смотрю глазами и агент анализирует.
Первое изменение. Теперь PR открывает агент. Раньше он готовил ветку, коммит, пуш и отдавал мне ссылку с предзаполненным заголовком и описанием, а PR открывал я, посмотрев код. Выигрыш в том, что пока я работаю с одной сессией, вторая уже открыла PR, на нём автоматически стартовал CI, и к моменту, когда я до неё дойду, прогон с большой вероятностью зелёный - останется только смержить. А если покраснеет, то агент сам разберётся, почему, и починит, не дожидаясь моего внимания. Раньше эти 5–11 минут начинали течь только после того, как я переключусь в сессию, которая прислала compare-ссылку.
Чтобы "готово" не приходилось выяснять по переписке, PR открывается черновиком и переводится в обычное состояние, когда CI зелёный. Сигнал живёт в самом пулл-реквесте: вижу готовый - мержу, вижу черновик - агент ещё работает.
Порядок при этом такой. Полный локальный прогон до пуша, а не параллельно с CI. Раннеры и работа делят 12 ядер, и под нагрузкой браузерный прогон растягивается вдвое и роняет 2–3 случайных теста, каждый раз разных.
Второе изменение. Контракты теперь агент мержит сам. У нас есть отдельный репозиторий-канон - там лежит описание REST-контракта (выгрузка OpenAPI), схемы событий шины данных и проза, объясняющая правила, которые по схемам не прочитать. Главное правило работы, появившееся с самых первых дней - "контракт первым". Сначала меняется канон, потом консьюмер, потом продюсер. А значит PR потребителя законно красный, пока контрактный не влит - его проверка читает канон из основной ветки в момент прогона. Получалось, что один мой человеческий шаг блокировал два машинных, и держал ровно столько, сколько я шёл до этой сессии.
Границу провели по тому, где есть механическое доказательство. Агент мержит сам генерируемое (выгрузку OpenAPI, JSON-схемы) и прозу, сопровождающую ту же правку формы. Форму можно доказать прогоном продюсера против ветки-канона. Мне остаются два случая, где ошибка молчаливая - это удаление поля из канона (ничего не падает - канон просто перестаёт описывать то, что живой сервис ещё читает) и правки архитектурных и процессных документов, то есть правил работы, которые агент сам себе утверждать не должен.