# 01 — Business Requirements Document (BRD) **Work Item:** ORCH-043 **Тема:** Безопасная параллель в одном репо: merge-gate + auto-rebase + re-test **Проект:** orchestrator (self-hosting) **Автор:** Analyst **Дата:** 2026-06-06 --- ## 1. Контекст и проблема Оркестратор ведёт несколько work item **параллельно**, каждый в своём изолированном git worktree / ветке (`feature/ORCH-NNN-slug`, ORCH-2/S-4). Все ветки одного проекта исходят из общего `origin/main` и в конце конвейера **вливаются обратно в `main`**. Текущий конвейер валидирует ветку **относительно того состояния `main`, из которого она была создана**, а не относительно `main` на момент слияния: - `check_ci_green` (стадия `development`) — CI зелёный **на ветке** (Gitea commit status ветки). - `check_tests_passed` (стадия `testing`) — вердикт тестировщика по коду **ветки**. - На стадии `deploy` ветка вливается в `main` (слияние выполняет deployer-агент, см. `src/webhooks/gitea.py` — комментарий про «deployer merges the PR at the START of its run»). **Между «ветка проверена» и «ветка влита» `main` мог уйти вперёд** из-за слияния другой параллельной задачи. Возникает **семантический (логический) конфликт слияния**: git сливает ветки без текстового конфликта, но объединённый код `main` сломан — тесты, которые были зелёными на ветке, на обновлённом `main` падают. ### Почему это критично именно здесь (self-hosting) Проект ORCH правит инструмент, который СЕЙЧАС работает в проде и обслуживает другие проекты (enduro-trails) из одного инстанса с общей БД и общей очередью (см. `CLAUDE.md`, `docs/operations/INFRA.md`). Сломанный `main` оркестратора = встал конвейер ВСЕХ проектов. Две параллельные ORCH-задачи, каждая «зелёная» по отдельности, при последовательном слиянии способны положить прод. ### Сценарий-иллюстрация 1. Задачи A и B ответвлены от `main@C0`. 2. A проходит конвейер, вливается → `main@C1`. 3. B тестировалась против `C0`; её CI зелёный относительно `C0`. Git-слияние B в `C1` проходит без текстового конфликта, но `C1` содержит изменения A, ломающие B. 4. `main` становится красным. Конвейер всех проектов деградирует. --- ## 2. Цель Гарантировать, что ветка вливается в `main` **только если она проверена против актуального `origin/main`**. Перед слиянием ветка автоматически догоняет `main` (auto-rebase) и **повторно тестируется** (re-test); зелёный результат на актуальном `main` — обязательное условие слияния (merge-gate). Слияния в `main` одного репозитория **сериализуются**, чтобы окно гонки не воспроизводилось между двумя гейтами. ## 3. Заинтересованные стороны - **Owner / разработчики** — не хотят красный `main` и ручные разборы конфликтов. - **Все проекты на инстансе** — зависят от живого прод-оркестратора. - **Агенты конвейера** — получают детерминированный гейт вместо ручной координации. ## 4. Объём (Scope) ### В объёме 1. **Merge-gate** — детерминированный гейт перед слиянием в `main`: пропускает слияние только если ветка не отстаёт от `origin/main` И повторная проверка зелёная. 2. **Auto-rebase** — если ветка отстаёт от `origin/main`, автоматически догнать `main` (rebase/merge ветки на актуальный `origin/main`) в worktree и запушить результат. 3. **Re-test** — после auto-rebase повторно прогнать тест-набор на догнанной ветке; зелёный результат — условие прохода гейта. 4. **Сериализация слияний** — в пределах одного репозитория одновременно «догон+слияние» выполняет только одна задача (merge-lock), иначе гонка воспроизводится. 5. **Откаты при неуспехе** — текстовый конфликт rebase ИЛИ красный re-test → возврат задачи на `development` (по образцу существующих откатов) с понятным комментарием. 6. **Конфигурируемость** — пороги/тайм-ауты re-test и поведение гейта вынесены в `settings`. ### Вне объёма - Изменение логики стадий `analysis` / `architecture` / `review`. - Замена самого механизма слияния PR в Gitea (UI/настройки репозитория). - Реальные прод-деплои (остаются за `scripts/orchestrator-deploy-hook.sh`). - Кросс-репозиторная сериализация (гейт защищает `main` каждого репо отдельно). ## 5. Бизнес-требования (BR) | ID | Требование | |----|------------| | BR-1 | Перед слиянием ветки в `main` оркестратор обязан проверить, что ветка содержит последний `origin/main` (не отстаёт). | | BR-2 | Если ветка отстаёт — оркестратор автоматически догоняет её до `origin/main` без участия человека (auto-rebase). | | BR-3 | После догона тест-набор повторно прогоняется; слияние разрешено только при зелёном результате (re-test). | | BR-4 | Текстовый конфликт при auto-rebase или красный re-test НЕ приводит к слиянию: задача откатывается на `development` для ручного фикса. | | BR-5 | В пределах одного репозитория «догон+проверка+слияние» сериализуются: две задачи не могут одновременно пройти merge-gate и влиться. | | BR-6 | Гейт детерминированный (Python/гит-команды + код тестов), а не доверие LLM-агенту. | | BR-7 | Гейт обязателен минимум для self-hosting репозитория `orchestrator`; применим к любому репо с параллельными задачами. | | BR-8 | Все события гейта (догон, re-test, проход/откат) логируются и отражаются комментарием в Plane, без рассинхрона стадий. | ## 6. Критерии успеха - Воспроизводимый ранее сценарий «две зелёные ветки ломают `main`» более не приводит к красному `main`: вторая ветка либо догоняется и проходит re-test, либо откатывается. - Прод-контейнер `orchestrator` не перезапускается и не падает в рамках задачи. - Реестр гейтов и стадий остаётся консистентным (snapshot-тесты обновлены осознанно). ## 7. Риски и ограничения - **Гонка между двумя гейтами** — снимается merge-lock (BR-5); без него фикс неполон. - **Долгий re-test** — нужен тайм-аут и понятный откат, а не вис задачи. - **Force-push догнанной ветки** — допустим только `--force-with-lease` и только по own-ветке задачи; никогда по `main`. - **Self-hosting** — любые изменения не должны ронять/рестартить прод-оркестратор; обязательная страховка стадией `deploy-staging` (порт 8501) сохраняется. - Окончательное место встройки в конвейер (новая стадия / гейт существующего перехода / шаг перед слиянием) — **решение архитектора** (ADR), BRD фиксирует требуемое поведение. ## 8. Связанные артефакты - `02-trz.md` — техническое задание (модули, гейт, конфиг, точки встройки). - `03-acceptance-criteria.md` — критерии приёмки PASS/FAIL. - `04-test-plan.yaml` — план тестов. - Контекст кода: `src/qg/checks.py`, `src/stage_engine.py`, `src/git_worktree.py`, `src/agents/launcher.py`, `src/webhooks/gitea.py`, `src/stages.py`, `src/config.py`.