4.3 KiB
adr-0006: Merge-gate — догон main + re-test + сериализация слияний
- Статус: proposed
- Дата: 2026-06-06
- Задача: ORCH-043
- Детальный ADR:
docs/work-items/ORCH-043/06-adr/ADR-001-merge-gate.md
Контекст
Ветка валидируется относительно того main, из которого создана, а не относительно main
на момент слияния. Параллельная задача могла влиться раньше → семантический конфликт
слияния (git мержит без текстового конфликта, но main сломан). Для self-hosting это
красный main инструмента, обслуживающего все проекты. Слияние в main делает
deployer-агент в начале стадии deploy; замена механизма PR-merge — вне объёма.
Решение
Детерминированный merge-gate (check_branch_mergeable, без LLM) на ребре
deploy-staging → deploy, ДО запуска deployer'а, который мержит. STAGE_TRANSITIONS не
меняется (минимальный blast-radius); в QG_CHECKS добавлен check_branch_mergeable.
- Догон: ветка отстаёт ⇔
origin/mainне предок HEAD →rebase origin/mainв worktreepush --force-with-lease(ТОЛЬКО ветка задачи;main— никогда). Текстовый конфликт →rebase --abort→ откат наdevelopment.
- Re-test:
python -m pytest tests/в worktree догнанной ветки, тайм-аутmerge_retest_timeout_s. Красный/тайм-аут → откат наdevelopment. - Сериализация (BR-5): файловый merge-lease на репо
(
<repos_dir>/.merge-lease-<repo>.json), живёт от гейта до фактического merge. Acquire неблокирующий (anti-deadlock приmax_concurrency=1): busy → defer (re-enqueue deployer с задержкой черезavailable_at), не rollback. Release — на PR-merged вебхуке /deploy→done/ откате / по возрасту (crash-реклейм). Restart-safe. - Условность (как ORCH-35): реален для
orchestrator; прочие репо — no-op. Флагиmerge_gate_enabled/merge_gate_reposдля поэтапного раската.
Альтернативы
- Новая стадия
merge-gate(кандидат B) — «пустая» стадия без агента не имеет триггера (advance_stageсрабатывает только на завершении агента/вебхуке); потребовала бы chaining в движке (не restart-safe) или синтетический job-тип. Отклонено. - Перенос merge в детерминированный шаг оркестратора (кандидат C) — запрещён объёмом (замена механизма PR-merge вне scope). Отклонено.
- Блокирующий lock — дедлок при одном worker-слоте. Отклонено в пользу defer.
Последствия
- Сценарий «две зелёные ветки ломают
main» закрыт: re-test против актуальногоmain+ сериализация слияний. - Плата: merge-gate — «скрытый» под-гейт ребра (нет в
STAGE_TRANSITIONS); сериализация опирается на PR-merged вебхук со страховкой реклеймом по возрасту; defer перепрогоняет staging; длинный re-test держит worker-слот. - Сквозное изменение конвейера →
arch:major-change; прод-деплой ORCH-043 строго через staging-гейт (8501).
Связи
adr-0001 (is_self_hosting_repo), adr-0003 (условный staging-гейт — образец условности),
adr-0002 (очередь / available_at для defer), ORCH-2 (worktree-изоляция), ORCH-046
(дословный reason в task_desc при откате).