Merge queue для ИИ-агентов: держите main зелёным

Почему ветки параллельных ИИ-агентов ломают main, даже если каждая проходит проверки, что такое merge queue и как AgentVera по порядку сливает, проверяет и вливает ветки.

Solviera Teknoloji 8 мин чтения

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

В этой статье: почему ветки параллельных агентов ломают main, как это исправляет merge queue и как шаг за шагом работает merge queue в AgentVera.

Зелёные поодиночке, красные вместе

Начнём с примера. В main есть функция formatPrice(amount). Вы запускаете двух агентов одновременно:

  • Агент A добавляет параметр валюты: formatPrice(amount, currency) — и обновляет все места вызова.
  • Агент B делает новый экран счетов, который вызывает formatPrice(amount).

Обе ветки начались от одного и того же main. Тесты A проходят, потому что в мире A экрана счетов нет. Тесты B проходят, потому что в мире B функция всё ещё принимает один аргумент. Git тоже не видит конфликта: ветки меняли разные файлы.

Вы сливаете A, затем B. Git молчит. Но теперь main вызывает функцию с двумя параметрами, передавая один аргумент, и проверка типов падает.

Это семантический конфликт: текстового конфликта нет, но изменения ломают друг друга. С параллельными агентами он встречается чаще, потому что:

  • Агенты не видят друг друга. Каждый работает в своём worktree и не знает, что делают остальные.
  • Ветки копятся быстро. К середине дня могут ждать пять-шесть веток.
  • Каждая ветка тестировалась на старой базе. Чем дольше ветка ждёт, тем устаревшее её база.
  • Сливать по порядку вручную утомительно. После каждого слияния нужно обновлять следующую ветку, снова запускать тесты и разбирать конфликты. Люди начинают это пропускать.

Что такое merge queue

Merge queue выстраивает в очередь ветки, ожидающие влития, сливает каждую с актуальной вершиной целевой ветки и тестирует получившийся результат. Идея проста: прежде чем ветка попадёт в main, проверь, как main будет выглядеть после этого на самом деле.

Сравнение со слиянием вручную:

Слияние вручнуюMerge queue
На чём запускается тестНа собственной базе веткиНа актуальной вершине main + ветка
Семантические конфликтыНаходятся после попадания в mainЛовятся до влития
ПорядокКто первым нажалПорядок очереди
Сломанная веткаЛомает mainОтклоняется, main остаётся чистым

У GitHub тоже есть merge queue на уровне репозитория: она ставит в очередь pull request’ы и тестирует их вместе с последней версией целевой ветки. Очередь AgentVera применяет ту же идею на вашем десктопе, для веток ваших агентов, и дополнительно подключает агентов, которые разрешают конфликты слияния и исправляют упавшие проверки.

Как работает merge queue в AgentVera

Очередь находится в десктопном приложении в разделе Details → Automation → Merge queue. У каждого проекта одна очередь; в проекте с несколькими репозиториями у каждого репозитория своя очередь и свои настройки. Ветки вливаются по одной.

1. Ветка попадает в очередь

Есть три способа:

  • Вручную: введите имя ветки в поле Branch, при желании задайте Title и нажмите Add to queue.
  • Из параллельной команды: когда параллельная команда закончила, нажмите Queue, чтобы отправить её интеграционную ветку.
  • Из автоматизации: выберите Add to the merge queue как способ доставки в правиле автоматизации, и ветка завершившего работу агента сразу попадёт в очередь.

Карточки в Review inbox тоже предлагают Send to the merge queue. Для каждого элемента показано, откуда он пришёл: вручную, из параллельной команды или из автоматизации.

2. Слияние с актуальной вершиной целевой ветки

Когда подходит очередь ветки, она сливается с текущей вершиной целевой ветки в отдельном worktree самой очереди. Ваша рабочая папка и папки ваших агентов остаются нетронутыми. Если у репозитория есть удалённый репозиторий, целевая ветка сначала подтягивается, и слияние выполняется поверх последней версии origin.

Стратегию вы выбираете в настройках: Merge commit или Squash. Если ветка уже содержится в целевой, элемент отмечается как влитый.

3. Конфликт получает агента

Если при слиянии возникает конфликт, очередь не останавливается. Она открывает агента-резолвера, а элемент переходит в состояние «resolving conflicts». Агенту велено сохранить намерения обеих сторон, не оставлять маркеров конфликта и закоммитить результат.

Когда агент сдаёт работу, AgentVera не принимает его слова на веру. Она проверяет, нет ли неслитых файлов, ищет маркеры <<<<<<< и >>>>>>> и убеждается, что ветка действительно слита. Если что-то из этого не выполнено, элемент завершается ошибкой и не вливается.

При включённом Automatic model модель резолвера выбирается по сложности задачи.

4. Проверка на слитом результате

Когда слитый результат готов, очередь запускает команду проверки. Оставьте Check пустым, и она возьмёт тестовую команду проекта, либо впишите свою, например pnpm typecheck && pnpm test.

Если проверка падает, агент-резолвер получает конец вывода и пытается её исправить. Раундов исправления не больше двух. Если проверка всё ещё красная, элемент отклоняется, а очередь идёт дальше. Сломанная ветка в main не попадает.

Именно так и происходит в примере с formatPrice: ветка B сливается с main, где уже есть A, проверка типов падает, резолвер обновляет вызов на экране счетов под новую сигнатуру, и проверка зеленеет.

5. Подтверждение и влитие

Прошедшая ветка готова. По умолчанию Land passing branches automatically выключено, поэтому элемент ждёт в статусе «ready, awaiting approval», а вы получаете уведомление. Посмотрите и нажмите Land, когда всё устраивает.

Влитие происходит так:

  • Если есть удалённый репозиторий, слитый результат отправляется в целевую ветку. Для репозиториев GitHub используется вход в GitHub на вашем компьютере.
  • Если удалённого репозитория нет, локальная целевая ветка перематывается вперёд (fast-forward). Её никогда не сдвигают из-под незакоммиченной работы.
  • Если целевая ветка за это время ушла вперёд, элемент пересобирается на новой вершине и проверяется снова. Это происходит не более трёх раз; если целевая ветка продолжает двигаться, элемент завершается ошибкой.

Если закрыть и снова открыть приложение, прерванная работа не пропадёт; она возвращается в очередь.

Настройки

Их немного, и все они в одной вкладке:

НастройкаЧто делаетПо умолчанию
Target branchВетка, в которую вливается работаПусто: ветка по умолчанию
MergeMerge commit или SquashMerge commit
CheckКоманда, запускаемая на слитом результатеПусто: тестовая команда проекта
Land passing branches automaticallyВливает прошедшие ветки без подтвержденияВыключено

Элементы в очереди можно переставлять кнопками Up и Down, останавливать через Cancel и перезапускать упавшие или отменённые через Retry. У каждого элемента свой лог и история, а у элементов с pull request есть кнопка, открывающая его на GitHub.

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

Параллельные команды и очередь вместе

Больше всего пользы merge queue приносит с параллельной командой. Параллельная команда делит большую работу максимум на восемь частей; по умолчанию одновременно работают три агента, каждый в своём worktree. Части сливаются в интеграционную ветку, а интеграционный агент занимается конфликтами и проверкой.

Когда команда закончила, у вас одна интеграционная ветка. Нажмите Queue, чтобы отправить её. Другая команда или автоматизация за это время могли отправить что-то в main; очередь берёт всё по порядку, тестируя каждое на самом свежем main.

Общую картину работы с несколькими агентами смотрите в статье о параллельных кодинг-агентах.

Типичные ошибки

  • Пустой Check и нет тестовой команды. Очередь всё равно сливает, но без чего-либо для проверки не поймает семантические конфликты. Задайте тестовую команду проекта или впишите команду в Check.
  • Только юнит-тесты. Многие поломки вроде описанной выше проявляются в проверке типов или сборке. Добавьте их в проверку.
  • Автоматическое влитие с первого дня. Не включайте Land passing branches automatically, пока не понаблюдали за очередью какое-то время. Сначала несколько недель подтверждайте вручную.
  • Огромные ветки. Очередь их примет, но вероятность конфликтов и сбоев растёт с размером. Давайте агентам небольшие, чётко очерченные задачи.
  • Игнорирование отклонённых элементов. Отклонение обычно указывает на реальный конфликт в дизайне. Прочитайте лог и при необходимости верните работу агенту с пояснением.

Пример одного дня

Утро

Вы запускаете трёх агентов на три задачи: страница оформления заказа, API отчётов и обновление зависимости. Каждый работает в своём worktree. Есть ещё упавший с вечера CI; правило автоматизации уже поймало его и отправило исправление в очередь.

Ближе к полудню

Когда агенты заканчивают, вы открываете их карточки в Review inbox. Страница заказа и API отчётов выглядят хорошо, и вы нажимаете Send to the merge queue для обеих. В очереди теперь три элемента: исправление CI, страница заказа и API отчётов.

Полдень

Исправление CI проходит проверку и ждёт подтверждения. Вы нажимаете Land. Страница заказа сливается с новым main и проходит. API отчётов конфликтует с типом, изменённым страницей заказа; вмешивается агент-резолвер, обновляет места вызова, и проверка зеленеет. Всё, что сделали вы, — два раза подтвердили.

После обеда

Обновление зависимости после двух раундов исправлений всё ещё красное и отклоняется. Main остаётся чистым. Лог показывает смену мажорной версии в одной из библиотек, поэтому вы возвращаете работу агенту с более узкими указаниями.

Чек-лист

  • Есть ли у проекта тестовая команда или команда в Check?
  • Охватывает ли проверка тип-чек и сборку?
  • Правильна ли Target branch? Пусто означает ветку по умолчанию.
  • Соответствует ли стратегия слияния привычкам команды: Merge commit или Squash?
  • Включено или выключено Land passing branches automatically осознанно?
  • Для репозиториев GitHub: выполнен ли на этом компьютере вход в GitHub?
  • Небольшие и чётко очерченные ли задачи у ваших агентов?

Итоги

Параллельные агенты работают быстро, но скорость, ломающая main, долго не живёт. Merge queue сливает и тестирует каждую ветку на самом свежем main, так что ветки, проходящие по одной, не сломают main вместе. В AgentVera очередь поручает конфликты и упавшие проверки агенту, сама проверяет результат, а решающее слово по умолчанию оставляет вам.

Читайте дальше:

Чтобы попробовать AgentVera, начните с главной страницы.

Вопросы

Что такое merge queue?

Merge queue выстраивает в очередь ветки, ожидающие влития, сливает каждую с актуальной вершиной целевой ветки и тестирует получившийся результат до влития. Две ветки, которые проходят проверки по отдельности, не смогут вместе сломать main.

Почему main ломается, если каждая ветка прошла свои тесты?

Каждая ветка тестировалась на более старом main. Если main за это время ушёл вперёд, два изменения могут конфликтовать по смыслу, не конфликтуя по тексту, и увидеть это можно только тестом слитого результата.

Что делает merge queue в AgentVera при конфликте?

Она открывает агента-резолвера, который сохраняет намерения обеих сторон и делает коммит. Затем AgentVera проверяет, что маркеры конфликта не остались и ветка действительно слита. Если нет, элемент завершается ошибкой и не вливается.

Вливаются ли прошедшие ветки сами?

По умолчанию нет. Если «Land passing branches automatically» выключено, ветка, прошедшая проверки, ждёт вашего подтверждения и вливается, когда вы нажмёте Land. Эту настройку можно включить.

В каком тарифе есть merge queue?

Merge queue доступна в тарифах Pro и Team. В десктопном приложении она находится в разделе Details → Automation → Merge queue.

Соберите своих агентов за одним столом.

Скачайте AgentVera бесплатно; ваши установленные CLI уже готовы к работе.

Другие статьи