Files

7.1 KiB
Raw Permalink Blame History

BRD — ORCH-071: Фантомный merge — деплой без слияния в main

1. Контекст и тип

  • Тип: BUG CRITICAL (целостность main / надёжность деплоя, self-hosting).
  • Обнаружено: Слава + Стрим, 2026-06-08, при разборе «ORCH-067 не подхватился».
  • Постмортем: docs/history/LESSONS_2026-06-08_phantom-merge.md.
  • Подозрение на регресс: ORCH-065 (idempotent merge / lease-reclaim) — последний честный merge (PR#66).
  • Связано: восстановление текущего main ведётся ОТДЕЛЬНО (ветка integ/restore-main-2026-06-08); эта задача — ROOT-FIX, чтобы фантом не повторялся.

2. Проблема (бизнес-формулировка)

Self-deploy (Phase B) для self-hosting репо orchestrator собирает прод-образ из ВЕТКИ задачи и рапортует finalize SUCCESS + post-deploy HEALTHY, но git-merge ветки в main НЕ происходит. PR остаётся open. Следующая задача срезает свою ветку от устаревшего main → теряет код незалитых предшественников.

Накопительно потеряны в main: ORCH-022, 059, 066, 068 (PR#67/68/69/70 — open). Последний реально слитый — ORCH-065 (PR#66).

3. Подтверждённый root cause (по результатам код-аудита)

Гипотеза A постмортема подтверждена аудитом кода ветки:

  1. В src/ НЕТ кода, выполняющего merge PR в main (grep по pulls/.../merge, /merge, merge_pr — 0 совпадений). Фактический merge выполняет ТОЛЬКО LLM-агент deployer через Bash в начале стадии deploy (см. .openclaw/agents/deployer.md).
  2. Для self-hosting (orchestrator) стадия deploy оркеструется детерминированным кодом (stage_engine._handle_self_deploy_phase_bself_deploy.initiate_deploy → finalizer run_deploy_finalizer), и агент deployer НЕ запускается (так предписывает deployer.md). Detached host-процесс делает retag staging-образа на прод-тег + рестарт 8500. Ни одна фаза A/B/C не вызывает merge ветки в main.
  3. run_deploy_finalizer маппит exit-code хука 0→SUCCESS, пишет 14-deploy-log.md и вызывает advance_stage(..., finished_agent="deployer"). Гейт check_deploy_status читает только deploy_status: из артефакта → SUCCESS → done. Состояние main нигде не верифицируется.

Итог: для self-hosting путь deploy структурно НЕ содержит шага merge-в-main, а done достигается исключительно по deploy-маркеру. «Зелёный» деплой + здоровый прод (образ из рабочей ветки) маскируют отсутствие merge — сигнала о проблеме нет, пока следующая задача не потеряет код предшественника.

Вторичный фактор (усиливает риск даже если merge добавить наивно): Phase B рестартит прод-контейнер, поэтому любой держатель merge-lease / незавершённый git-шаг внутри процесса умирает до завершения merge (урок №3 постмортема).

4. Бизнес-цели

ID Цель
G1 Деплой ВЕРИФИЦИРУЕТ, что задеплоенный commit реально влит в main ПОСЛЕ деплоя (deployed SHA — предок origin/main ИЛИ PR.merged==true). Иначе — alert, задача НЕ done.
G2 Задача → done ТОЛЬКО при подтверждённом merge (PR.merged==true); маркеров finalize/post-deploy недостаточно.
G3 Merge в main завершается и подтверждается ДО рестарта прод-контейнера, ЛИБО merge вынесен в шаг, переживающий рестарт (паттерн requeue_running_jobs для merge-в-main).
G4 Диагностический runbook (4 проверки из постмортема) — в docs/operations.

5. Не-цели

  • Не менять source-of-truth (Plane), схему БД.
  • Не отменять self-hosting safety (no auto-rollback / no-restart-others) — наоборот, усилить верификацией.
  • Восстановление текущего main (долив 022/059/066/068) — ОТДЕЛЬНАЯ ветка integ/restore-main-2026-06-08, вне scope.

6. Инварианты (обязательны к соблюдению)

ID Инвариант
INV-1 never-raise на шаге верификации — при ошибке шлётся alert, не падение процесса/конвейера.
INV-2 self-hosting safety: верификация НЕ рестартит и НЕ роняет прод-контейнер orchestrator (8500), не трогает другие проекты.
INV-3 Ручной approve прод-деплоя (триггер «Confirm Deploy», ORCH-059) сохранён — новая логика не вводит авто-деплой.
INV-4 Никогда не делать force-push / прямой push в main; merge только через PR-merge API Gitea (как у deployer-агента сегодня).
INV-5 Идемпотентность: повторный прогон (re-drive/reaper/двойной webhook) не делает второй merge и не ломает контракты (опора на pr_already_merged, ORCH-065).

7. Заинтересованные стороны

  • Owner — одобряет прод-деплой («Confirm Deploy»), получает alert при «deployed but not merged».
  • Все проекты на инстансе (enduro-trails) — косвенно: целостность main орка влияет на инструмент, обслуживающий их из общей БД/очереди.

8. Критерий успеха (бизнес-уровень)

После доработки невозможно состояние «задача done + прод задеплоен, а PR open / commit не в main»: либо merge подтверждён и задача done, либо задача НЕ done и поднят alert «deploy succeeded but not merged». Воспроизведение исходного сценария на staging показывает, что main реально получает commit.