Как AITM сливает завершённую работу в dev, исправляет сбои тестов после слияния вперёд, а не откатом, и проверяет, что Task затронула только то, что должна была.

Слияние, исправления после слияния и Scope Gate

Как работает слияние

Каждая Task выполняется в собственной ветке git/Worktree. Когда Pipeline завершён (реализация, ревью, тесты — всё зелёное), Task попадает в Merge queue AITM — сериализованную очередь, благодаря которой параллельные Task никогда не сливаются в dev одновременно и не затирают изменения друг друга.

  • Автоматический запуск слияния. Task с включённым autoMergeDev сливается в dev автоматически после завершения её Pipeline — без шага ручного одобрения, поэтому готовая работа попадает в ветку непрерывно, а не накапливается в ожидании, пока человек нажмёт merge.
  • Барьер сборки перед слиянием. Ветка Task сначала обновляется до текущего dev, затем собирается и проверяется по типам в том виде, какой она будет после слияния. Если проверка красная, агент-исправитель получает ограниченное число попыток; ошибки, уже существующие в dev, не вменяются Task. Если барьер остаётся красным, Task не сливается и завершается в статусе conflict с приложенным выводом сборки.
  • Обработка конфликтов. Если ветка Task конфликтует с тем, что уже попало в dev, AITM повторяет слияние с другими стратегиями, а затем передаёт конфликтующие файлы ИИ-разрешителю конфликтов, который объединяет оба изменения и заново запускает барьер сборки. Task, ожидающая в статусе conflict, перепроверяется автоматически; если за это время причина исчезла, она исцеляется сама и переходит к слиянию.
  • Контролируемое слияние в dev. Слияния происходят по одному из очереди, поэтому dev никогда не находится в наполовину слитом состоянии. Слияние не является шагом Pipeline: Task отображается как finished с маркером Finalizing… и становится archived, когда слияние выполнено. Пока Task остаётся в статусе conflict, другие Task из очереди в той же вкладке ждут за ней — поэтому её стоит разрешить поскорее.
Завершённая Task, которая финализируется и сливается
Завершённая Task, которая финализируется и сливается в dev.

Обнаружение и исправление ошибок после слияния

После слияния ветки Task в dev AITM заново запускает затронутые тесты на новом состоянии dev. Если они теперь падают, реакцией по умолчанию не является откат слияния.

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

  1. Изолирует, какие файлы/тесты на самом деле падают и изменение какой Task за это отвечает.
  2. Исправляет вперёд в ветке — создаётся корректирующая Task, направленная только на область сбоя и работающая от текущего состояния dev (а не от diff какой-либо исходной Task).
  3. Повторно тестирует исправление изолированно, прежде чем ему будет позволено снова приблизиться к dev.
  4. Сливает исправление через ту же очередь, что и любую другую Task.

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

Оценка Scope Task (Business Scope Gate)

Каждая Task заранее объявляет, какие файлы планирует затронуть. Когда Task завершается, Business Scope Gate сравнивает файлы, которые она фактически изменила, с этим объявлением.

  • Вне Scope означает, что изменённый файл не был объявлен и не имеет правдоподобной связи с заявленной целью Task — например, Task о странице оформления заказа также редактирует не связанный файл настроек администратора.
  • Поправки к Scope. Иногда изменение необъявленного файла правомерно — потребовалось изменить общий тип или константа находится в соседнем файле. В таком случае Task записывает короткое явное обоснование для дополнительного файла ("поправка к Scope") вместо того чтобы молча выходить за границы. Обоснованная поправка принимается; необъяснённый дополнительный файл — нет.
  • Блокирующие и рекомендательные нарушения. Не каждый необъявленный файл рассматривается одинаково:
    • Блокирующее — изменённый файл действительно чужд Task (другая область функциональности, нет общих зависимостей, обоснование не приведено). Это останавливает слияние до разрешения.
    • Рекомендательное — изменённый файл находится в том же каталоге/модуле, что и объявленный Scope, и правдоподобно связан с ним (например, соседний файл в той же папке функциональности). Это помечается для проверки, но само по себе не блокирует слияние.

Что становится багом, а что новой Task

Когда шаг review находит нечто, выходящее за пределы текущего diff, AITM выбирает один из двух исходов:

  • Становится багом, когда находка — блокирующее нарушение Scope либо настоящий дефект, не связанный с тем, что должна была сделать Task, — нечто, что уже сломано и требует собственного цикла исправления, независимо от исхода текущей Task.
  • Становится новой (последующей) Task, когда находка — уточнение, желательное улучшение или правомерная, но выходящая за Scope идея, возникшая при работе над чем-то другим, — она попадает в очередь на собственных условиях, а не расширяет Scope текущей Task.

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

Когда Task завершается сбоем и требует вмешательства человека

Не каждый сбой поддаётся автоматическому восстановлению. Watchdog и механизмы самовосстановления AITM самостоятельно справляются со сбоями инфраструктуры и обычными ошибками компиляции/тестов, но некоторые ошибки терминальные — им нужно решение человека, а не очередная попытка. Task завершается в терминальном состоянии failed, когда:

  • Конфигурация неверна. Недействительные API-ключи, неправильные настройки, некорректный JSON — ничто в коде не может исправить сломанное окружение.
  • У ИИ не хватает данных. Prompt Task неполон или неоднозначен, необходимый контекст не предоставлен или требования недостаточно определены.
  • Существует принципиальное препятствие, которое может устранить только пользователь. Архитектуру нужно уточнить, Scope оспаривается или сторонний сервис недоступен таким образом, что требуется явное подтверждение, прежде чем работа сможет продолжиться.

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

  1. Task помечается как failed.
  2. Вы (и Claude) обсуждаете первопричину в Chat или Brainstorm.
  3. Вы решаете: поставить в очередь заново с более чётким Scope? Сначала создать отдельную Task по проектированию архитектуры? Скорректировать подход?
  4. Затем создаёте новую Task с уточнённым пониманием или ставите в очередь заново с обновлённым prompt.

Не все сбои являются багами — многие правомерно неразрешимы без участия человека. Сбой не означает потраченную впустую работу — диагностика и журналы неудавшегося запуска всё равно точно показывают, где что-то пошло не так. А когда Task завершается сбоем, это повод для разговора между вами и AITM, а не тупик.

Модель веток

Каждый проект под управлением AITM следует одной и той же двухветочной модели релизов.

  • dev — ветка по умолчанию / интеграционная ветка. Каждая Task Pipeline сливается в dev — именно сюда непрерывно попадает завершённая, протестированная работа (см. Merge queue выше).
  • main — стабильная релизная ветка. Она обновляется только слиянием dev → main в момент релиза, а не отдельными Task.
  • Ветки master не существует. AITM никогда не создаёт и не ожидает её.
  • Импортированные проекты могут сохранять собственную интеграционную ветку. Если подключаемый проект уже использует другое имя для интеграционной ветки, задайте его через настройку Integration branch (defaultBranch) в настройках проекта и используйте проверку Verify remote там же, чтобы убедиться, что оно разрешается на фактическом удалённом репозитории git.
  • Встроенный Gitea в релизе Docker создаёт демонстрационные репозитории с dev в качестве ветки по умолчанию, что соответствует этой же модели «из коробки».

Если у проекта Task нет пригодного удалённого репозитория git, Task останавливается с понятным сообщением, направляющим в Project settings → Verify remote, вместо вывода необработанной ошибки git.