Files
orchestrator/docs/work-items/ORCH-071/02-trz.md

79 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ТЗ — ORCH-071: Верификация merge-в-main как условие done
> Документ фиксирует ТРЕБОВАНИЯ к изменениям (WHAT). Конкретный дизайн (HOW: новый
> leaf-модуль vs расширение существующего, где разместить шаг merge, формат
> sentinel'ов) — за архитектором (ADR `06-adr/`). ТЗ задаёт инварианты, точки
> врезки и контракты, которые дизайн обязан удовлетворить.
## 0. Резюме root cause (вход для дизайна)
Для self-hosting (`orchestrator`) стадия `deploy` идёт детерминированным путём
`_handle_self_deploy_phase_b → initiate_deploy → run_deploy_finalizer`, который
**не содержит шага merge PR в `main`** (merge делает только LLM-`deployer`, не
запускаемый на self-hosting). `done` достигается по `deploy_status: SUCCESS` без
верификации `main`. Требуется: (A) выполнить/докатить merge в `main` детерминированно
до перехода в `done`; (B) верифицировать факт merge ПОСЛЕ деплоя; (C) запретить
`done` без подтверждённого merge.
## 1. Задействованные модули `src/`
| Модуль | Роль в фиксе | Характер изменения |
|--------|--------------|--------------------|
| `src/stage_engine.py` | `run_deploy_finalizer` (Phase C), терминал-блок `next_stage == "done"`, `_handle_self_deploy_phase_b` | Врезка шага merge-в-main + пост-merge верификация; блокировка перехода в `done` при неподтверждённом merge. |
| `src/merge_gate.py` | Уже содержит `pr_already_merged` (ORCH-065, read-only guard) | Добавить детерминированный **merge-актор** для self-hosting (выполнить merge PR через Gitea API) + helper верификации «SHA предок `origin/main`». Опора на существующие `pid_alive`/`reclaim_stale_lease`. |
| `src/self_deploy.py` | Sentinel-state Phase A/B/C | Возможный новый sentinel-маркер `merged` (restart-safe), если дизайн выносит merge в отдельный переживающий рестарт шаг (G3). |
| `src/qg/checks.py` | Реестр `QG_CHECKS`, `check_deploy_status` | Возможный новый под-чек верификации merge (например `check_merged_to_main`) ЛИБО усиление условия перехода `deploy→done`. `check_deploy_status` НЕ менять по контракту парсинга. |
| `src/config.py` | Флаги | Новый kill-switch (напр. `merge_verify_enabled` / `merge_verify_repos`), таймауты merge/verify. Дефолт — область self-hosting (как ORCH-35/43/58). |
| `.openclaw/agents/deployer.md` | Промпт deployer'а (non-self merge) | Уточнить: для self-hosting merge выполняет детерминированный код; non-self путь без изменений. |
| `src/main.py` (`/queue`) | Наблюдаемость | Опционально: блок/счётчики верификации merge (`merge_verified_total`, `not_merged_alerts_total`). |
## 2. Функциональные требования
### FR-1 (G3) — Детерминированный merge-в-main для self-hosting
- Для self-hosting репо merge PR ветки в `main` ДОЛЖЕН выполняться **детерминированным кодом** (не LLM-агентом), т.к. `deployer`-агент на self-hosting `deploy` не запускается.
- Merge выполняется через **Gitea PR-merge API** (как сегодня делает агент), НИКОГДА не force-push / не прямой push в `main` (INV-4).
- ПЕРЕД merge консультироваться `merge_gate.pr_already_merged(repo, branch)` — уже слит → no-op (INV-5, переиспользовать ORCH-065).
- **G3 — порядок относительно рестарта:** merge ДОЛЖЕН быть завершён и подтверждён ДО рестарта прод-контейнера, ЛИБО вынесен в шаг, переживающий рестарт (паттерн `requeue_running_jobs`/finalizer-defer): если процесс умер во время Phase B, шаг merge докатывается после рестарта (re-drive finalizer'а или отдельный merge-job). Дизайн выбирает один из двух вариантов; выбранный обязан быть restart-safe (sentinel/jobs, без миграции БД — §4).
### FR-2 (G1) — Пост-деплой верификация merge
- ПОСЛЕ деплоя (в Phase C / финализации, ДО фиксации `done`) выполнить детерминированную верификацию: задеплоенный commit (validated SHA) — **предок `origin/main`** (`git merge-base --is-ancestor <sha> origin/main`) **ИЛИ** `PR.merged == true` (Gitea API).
- Верификация **never-raise** (INV-1): любая ошибка git/HTTP → трактуется как «не подтверждено» → alert, НЕ падение.
- При неподтверждённой верификации — **alert** «deploy succeeded but not merged» (Telegram + Plane-коммент) и задача **НЕ переходит в `done`** (FR-3).
### FR-3 (G2) — `done` только при подтверждённом merge
- Переход `deploy → done` для self-hosting ДОЛЖЕН быть обусловлен подтверждённым merge (verify из FR-2 зелёный). Наличие `deploy_status: SUCCESS` + post-deploy `HEALTHY`**недостаточно**.
- При `SUCCESS`-маркере деплоя, но неподтверждённом merge: задача удерживается (не `done`), Plane-статус — не терминальный (например текущий `Deploying`/`Awaiting` или `Blocked` по решению дизайна), шлётся alert. Конвейер НЕ откатывается на `development` автоматически из-за not-merged (это инфраструктурный, не код-дефект) — реакция = alert + ручное вмешательство (согласовать с дизайном; по умолчанию ALERT-only, как ORCH-021 self-hosting).
### FR-4 (G4) — Диагностический runbook
- В `docs/operations/` добавить runbook с 4 проверками из постмортема (метод однозначной локализации фантома):
1. Gitea API: список PR + флаги `merged`.
2. md5 прод-файлов vs `git show origin/main:<file>`.
3. `git merge-base` ветки vs `main`.
4. Таймлайн деплой-логов.
- Включить готовые команды (copy-paste) и критерий «фантом подтверждён».
### FR-5 — Условность раската (как ORCH-35/43/58)
- Новая логика merge+verify реальна для self-hosting (`is_self_hosting_repo` / `merge_verify_repos`); прочие репо — поведение БЕЗ изменений (non-self merge остаётся за агентом `deployer`).
- Kill-switch (env, дефолт `true`) → `false` восстанавливает строго прежнее поведение.
## 3. Изменения API
- **Внешний HTTP API сервиса (`/health`, `/status`, `/queue`, `/webhook/*`) — без новых endpoint'ов.** Допустимо обогащение ответа `GET /queue` блоком наблюдаемости merge-verify (счётчики), по образцу блоков `reaper`/`post_deploy`.
- **Gitea API (исходящие вызовы):** новый детерминированный вызов `POST /repos/{owner}/{repo}/pulls/{index}/merge` (merge-актор, FR-1) + чтение `GET /repos/{owner}/{repo}/pulls?...` (уже используется в `pr_already_merged`). Через существующий httpx-клиент и `settings.gitea_*`.
## 4. Изменения схемы БД
- **НЕТ.** Schema-changes запрещены (не-цель). Restart-safe состояние нового шага merge — через sentinel-файлы (`.deploy-state-<repo>/<wi>/`, как ORCH-036) и/или существующую очередь `jobs` (finalizer-defer). Колонка `jobs.pid` (ORCH-065) уже есть, при необходимости переиспользуется.
## 5. Требования к новым QG checks
- Допускается ввести детерминированный под-чек верификации merge (напр. `check_merged_to_main`), регистрируемый в `QG_CHECKS`, ЛИБО встроить верификацию как условие в логику перехода `deploy→done` без нового чека — на усмотрение дизайна. В любом случае:
- Контракт `check_deploy_status` / `_parse_deploy_status` (читает только `deploy_status:` frontmatter) **НЕ меняется**.
- `STAGE_TRANSITIONS` **НЕ меняется** (verify — это условие/под-гейт ребра/финализации, не новая стадия).
- Вердикт (если артефакт) — строго YAML-frontmatter (канон гейтов), never проза.
## 6. Артефакты, создаваемые/обновляемые по pipeline
- `14-deploy-log.md` — существующий; дизайн может добавить поле статуса merge (напр. `merged_to_main: true|false`) во frontmatter (машиночитаемо), не ломая `deploy_status:`.
- Новый runbook в `docs/operations/` (FR-4).
- **Обязательно (CLAUDE.md §2):** обновить `docs/architecture/README.md` (раздел Phase B / merge-gate / executable self-deploy — описать новый merge+verify шаг), `CHANGELOG.md`, при сквозном решении — ADR (`docs/work-items/ORCH-071/06-adr/ADR-001-*.md` и/или global `docs/architecture/adr/`).
## 7. Совместимость / регресс
- Happy-path не-self репо (enduro-trails): merge остаётся за агентом `deployer` → поведение без изменений.
- Happy-path self-hosting: при штатном merge задача `done` ставится как раньше (после добавления verify, который зелёный).
- Все существующие контракты неизменны: `STAGE_TRANSITIONS`, реестр `QG_CHECKS` (кроме возможного нового under-чека), `check_deploy_status`, БАГ-8, terminal-sync, merge-gate (ORCH-043), `Confirm Deploy` (ORCH-059), exit-коды хука (0/1/2), схема БД.