7.9 KiB
01 — BRD: ORCH-073 — CRIT: эрозия main (код ORCH-067/069 затёрт ребейзами, не доехал)
- Work Item: ORCH-073
- Тип: BUG CRITICAL — целостность
main, накопительный регресс/эрозия - Репозиторий: orchestrator (self-hosting)
- Ветка:
feature/ORCH-073-crit-main-orch-067-069 - Связь: усиливает/чинит ORCH-071 (merge-verify); НЕ покрыт ORCH-071.
1. Бизнес-проблема
Код успешно «задеплоенных» и переведённых в done задач ORCH-067 (tracker bump,
Plane-статусы, кликабельные ссылки plane_issue_link) и ORCH-069 (qg0_title_max)
физически отсутствовал в origin/main, хотя обе прошли весь конвейер, Confirm Deploy,
merge-verify CONFIRMED и стали done. В main попадали только их docs-коммиты
(staging-log / verdict через отдельные авто docs-PR), но НЕ код feature-веток.
Внешнее проявление (нашёл Слава, 08.06): «ссылок на задачу в Plane нет», карточка Telegram
показывает сырой номер задачи вместо кликабельной ссылки — потому что код ссылок есть в ветке
ORCH-067, но не в main.
Накопительный характер: каждая новая задача срезает ветку от УСТАРЕВШЕГО main и при merge
тихо (без конфликт-маркеров) затирает код предшественника. Уже потеряны ORCH-067 и ORCH-069;
без системного фикса теряется код каждой следующей задачи с правкой CHANGELOG.md.
2. Подтверждённый root cause (git-аудит 08.06, не гипотеза)
verify_merged_to_mainподтверждает merge по ложному признаку.src/merge_gate.py::verify_merged_to_mainвозвращаетTrue, если выполнено ЛИБОpr_already_merged(repo, branch), ЛИБОgit merge-base --is-ancestor <sha> origin/main. Первая ветка (pr_already_merged) и есть дыра.pr_already_mergedзасчитывает ЛЮБОЙ merged PR ветки.src/merge_gate.py::pr_already_mergedделаетGET /pulls?state=all&head=<branch>и возвращаетTrue, если хоть один PRmerged==True. У одной ветки несколько PR (code-PR + авто docs-PR со staging/deploy-логами). Сливается docs-PR → функция говорит «already-merged» →verify_merged_to_main=True→ merge-verifyCONFIRMED→done, хотя code-PR НЕ слит. Ложно-зелёный.- CHANGELOG.md-ребейзы — вторичный усилитель.
Merge-gate
auto_rebase_onto_mainпри конфликтеCHANGELOG.mdоткатываетdeploy-staging → development; повторный ребейз ветки от старогоmainнесёт устаревшие версии файлов (notifications.py/config.py/webhooks/plane.py), которые при merge тихо затирают соседний код (фантом-эффект, как в ORCH-071, без конфликт-маркеров).
Уточнение для архитектора: в ТЗ упомянута «инвертированная проверка
merge-base --is-ancestor origin/main HEAD(merge_gate.py ~76)» — этоbranch_is_behind_main(детектор «ветка свежая»), он корректен для своей цели. Фактический дефект merge-verify — это OR-веткаpr_already_mergedвverify_merged_to_main(строка ~649), которая засчитывает docs-PR.
3. Состояние на момент анализа (G1)
Аудит origin/main показал, что восстановительный PR #76 (restore(main): re-merge ORCH-067 + ORCH-069 (ORCH-073)) уже вернул код в main:
plane_issue_linkприсутствует (src/notifications.py),qg0_title_maxприсутствует (src/config.py,src/webhooks/plane.py),verify_merged_to_mainприсутствует.
Таким образом G1 (восстановление кода) фактически выполнено ручным restore-PR. Задача ORCH-073 должна подтвердить и зафиксировать это в критериях приёмки (AC-1) и сосредоточиться на системном фиксе навсегда (G2–G5 / FR-1…FR-5), иначе регресс повторится.
4. Цели (Goals)
- G1. КОД ORCH-067 и ORCH-069 присутствует в
origin/mainодновременно с ORCH-071 (подтвердить restore-PR #76, зафиксировать маркеры > 0). Pytest зелёный. Прод задеплоен. - G2 (FR-2/FR-3).
merge/pr_already_mergedразличают code-PR и docs-PR — merge засчитывается только за PR с кодом ветки (base==main,head==<feature-branch>). - G3 (FR-1, ядро).
verify_merged_to_mainподтверждает merge ТОЛЬКО по факту «deployed SHA — предокorigin/main». PR-флаги вспомогательны, не достаточны. - G4 (FR-4). Защита от CHANGELOG-затирания:
.gitattributesсCHANGELOG.md merge=union(+ опц.docs/*.md merge=unionдля append-only). - G5 (FR-5, регресс-гард навсегда). После деплоя — sanity-проверка целостности
main: deployed SHA вmainИ набор маркеров ранее-merged задач не уменьшился. Откат соседнего кода → alert «main regressed», задача НЕdone.
5. Не-цели (Out of scope)
- Не менять Plane / схему БД.
- Не отменять self-hosting safety (не ронять прод, merge только через PR-API, без force-push в
main). - Не менять ручной гейт
Confirm Deploy. - Не менять поведение merge/verify для non-self репозиториев (enduro-trails) — обратная совместимость.
6. Инварианты
- INV-1. never-raise на верификации (alert, не падение).
- INV-2. self-hosting safety: прод не падает; merge только PR-API, без force-push в
main. - INV-3. ручной
Confirm Deployсохранён. - INV-4. Идемпотентность: повторный прогон / reaper не делает второй merge; idempotency опирается на «SHA-в-main», а не на «любой merged PR».
- INV-5. Обратная совместимость non-self (enduro): поведение merge/verify без изменений.
7. Заинтересованные стороны
- Owner / Слава — потребитель (видит кликабельные ссылки в карточке; доверие к merge-verify).
- Все проекты на инстансе (enduro-trails) — общий
main/очередь/БД; регресс орка = групповой риск.
8. Срочность
КРИТИКАЛ. Без FR-1/FR-4/FR-5 каждая новая задача с правкой CHANGELOG.md продолжает терять код
предшественников (уже потеряны 067, 069). Ложно-зелёный merge-verify подрывает само ядро
автономности конвейера.