# Критерии приёмки — ORCH-071

Формат: каждый критерий имеет явное условие PASS/FAIL. Машинные вердикты — из артефактов/состояния, не из прозы.

## AC-1 (G1) — Пост-деплой верификация: not-merged ⇒ не done + alert
- **Условие:** после Phase B/финализации, если задеплоенный commit НЕ влит в `origin/main` (не предок `origin/main` И `PR.merged != true`).
- **PASS:** задача НЕ переходит в `done`; шлётся alert «deploy succeeded but not merged» (Telegram + Plane-коммент).
- **FAIL:** задача стала `done` при неслитом PR ИЛИ alert не отправлен.

## AC-2 (G2) — done только при PR.merged==true (mock-тест)
- **Условие:** SUCCESS-маркеры деплоя присутствуют (`deploy_status: SUCCESS`), но PR `open` (`merged=false`).
- **PASS:** переход в `done` НЕ выполняется (тест на mock Gitea: PR open → done не ставится).
- **FAIL:** задача переведена в `done`.

## AC-3 (G3) — Merge подтверждён до/независимо от рестарта (smoke)
- **Условие:** симулирован рестарт контейнера во время Phase B (процесс/держатель merge умер до завершения merge).
- **PASS:** после рестарта merge докатывается (re-drive finalizer / merge-job, как `requeue_running_jobs`), `main` получает commit, верификация зелёная → задача `done`.
- **FAIL:** после рестарта merge не докатился, задача `done` без merge ИЛИ навсегда зависла без alert.

## AC-4 (регресс) — Happy-path
- **Условие:** merge прошёл штатно, `PR.merged==true`, deploy `SUCCESS`, верификация зелёная.
- **PASS:** `done` ставится как раньше (терминал-sync/Plane-статус как сегодня для self-hosting), без лишних alert.
- **FAIL:** регрессия — happy-path не доходит до `done` или шлёт ложный not-merged alert.

## AC-4b (регресс) — non-self репо без изменений
- **Условие:** деплой репо enduro-trails (не self-hosting).
- **PASS:** merge выполняет агент `deployer` (прежний путь), новая детерминированная merge/verify-логика — no-op для не-self.
- **FAIL:** изменилось поведение non-self деплоя.

## AC-5 — Зелёный pytest + документация
- **PASS:** `pytest tests/ -q` зелёный; обновлены `CHANGELOG.md`, `docs/architecture/README.md` (раздел Phase B / merge-verify) и runbook (`docs/operations/`).
- **FAIL:** красные тесты ИЛИ документация/CHANGELOG/runbook не обновлены (reviewer → REQUEST_CHANGES, CLAUDE.md §6).

## AC-6 — Воспроизведение исходного сценария на staging
- **Условие:** на staging провести задачу до деплоя.
- **PASS:** проверить (методом runbook), что `main` реально получил commit задачи (PR merged / SHA предок `origin/main`).
- **FAIL:** прод/«done» достигнуты, а `main` не получил commit.

## AC-7 (INV-1) — never-raise на верификации
- **Условие:** verify сталкивается с ошибкой git/HTTP (Gitea недоступна, битый ref).
- **PASS:** функция возвращает «не подтверждено» → alert, процесс/конвейер НЕ падает (исключение не пробрасывается).
- **FAIL:** исключение из verify валит finalizer/advance_stage.

## AC-8 (INV-2) — self-hosting safety
- **Условие:** шаг верификации/merge исполняется для `orchestrator`.
- **PASS:** verify/merge НЕ рестартят и НЕ роняют прод-контейнер 8500, не трогают другие проекты; merge — только PR-merge API, без push в `main`.
- **FAIL:** verify/merge перезапускает прод ИЛИ делает прямой/force push в `main`.

## AC-9 (INV-5) — идемпотентность повторного прогона
- **Условие:** re-drive стадии `deploy` / повторный webhook / reaper-requeue при уже слитом PR.
- **PASS:** `pr_already_merged` → merge не повторяется (no-op), верификация зелёная, нет дубль-merge/ошибки Gitea, нет ложного БАГ-8 отката.
- **FAIL:** второй merge / merge-error / ложный откат.

## AC-10 (FR-5) — kill-switch
- **Условие:** kill-switch новой merge/verify-логики выключен (`false`).
- **PASS:** строго прежнее поведение (1:1 до фикса).
- **FAIL:** при выключенном флаге логика всё равно срабатывает.

## AC-11 (INV-3) — ручной approve сохранён
- **PASS:** прод-деплой по-прежнему запускается только статусом «Confirm Deploy» (ORCH-059); merge/verify не вводят авто-деплой.
- **FAIL:** деплой/merge запускается без человеческого триггера.
