--- work_item: ORCH-113 stage: analysis author_agent: analyst status: ready-for-review created_at: 2026-06-15 model_used: claude-opus-4-8 escalate: full-cycle --- # 03 — Критерии приёмки (Acceptance Criteria): ORCH-113 — BUG: job-reaper не должен повторно запускать финализацию `deploy-staging`, пока жив исходный finalizer Work Item: **ORCH-113** · Repo: **orchestrator** · Стадия: analysis Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL** (что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам репозитория и тестам. --- ## AC-1 — Нет второго прогона edge-гейтов при живом finalizer'е **Условие:** job на `deploy-staging` с `exit_code=0`, `finished_age_s >= reaper_finalize_grace_s`, но исходный monitor/finalizer ещё **жив** (сигнал живости присутствует). - **PASS:** reaper **не** вызывает `_gate_driven_advance`/`advance_stage` для этого job; второй прогон security / merge-gate / локального re-test / coverage / image-freshness **не** запускается; reaper логирует defer. - **FAIL:** reaper запускает повторный `advance_stage` / любой edge-под-гейт, пока finalizer жив. --- ## AC-2 — Идемпотентность и строгое владение состоянием **Условие:** монитор финализирует `deploy-staging` и параллельно срабатывает reaper-тик для того же job/stage. - **PASS:** тяжёлый прогон edge-гейтов (merge-gate / локальный re-test) исполняется **ровно один раз** для пары `(job, stage)`; актор без владения состоянием не выполняет побочных шагов (мерж/re-test/ rollback). - **FAIL:** второй локальный re-test/merge-gate запускается для того же job/stage без владения состоянием (двойное исполнение edge-гейтов). --- ## AC-3 — Мёртвый finalizer по-прежнему добивается **Условие:** monitor/finalizer на `deploy-staging` реально **умер** посреди финализации (сигнал живости отсутствует/протух), job завис в `running`. - **PASS:** reaper за ограниченное время добивает job по существующему контракту (retry в пределах бюджета, иначе `failed` + Telegram; Tier-3 backstop как предохранитель); reaper для `deploy-staging` **не** превращён в no-op. - **FAIL:** мёртвый finalizer на `deploy-staging` не добивается reaper'ом (зомби-job блокирует очередь). --- ## AC-4 — Нет ложного отката и расхождения состояния после успешного deploy **Условие:** сценарий инцидента ORCH-111 — долгая (> grace) финализация `deploy-staging` при зелёном `staging_status: SUCCESS`, deploy/finalizer параллельно доходит до `deploy_status: SUCCESS` / merge PR. - **PASS:** задача **не** откатывается `deploy-staging → development` параллельной reaper-веткой; developer-retry **не** инкрементируется ложно; у задачи единственное консистентное терминальное/стадийное состояние (сходимость, не расхождение). - **FAIL:** задача откатана `deploy-staging → development` и/или начислен ложный developer-retry, в то время как deploy фактически успешен; ветки состояния расходятся. --- ## AC-5 — Инварианты и контракт reaper сохранены **Условие:** аудит диффа и поведения при выключенном kill-switch. - **PASS:** `STAGE_TRANSITIONS` / `QG_CHECKS` / каждый `check_*` / machine-verdict ключи / схема существующих таблиц — **байт-в-байт**; БД-правки только аддитивные (`_ensure_column` / `CREATE TABLE IF NOT EXISTS`); reaper остаётся never-raise per unit; выключенный флаг → прежнее поведение; правки не рестартят прод и не пушат `main`; сквозной инвариант `reaper_max_running_s > Σ gate-work + grace` (ORCH-065/109/110) сохранён. - **FAIL:** изменены `STAGE_TRANSITIONS`/`QG_CHECKS`/семантика `check_*`/machine-verdict ключи или схема существующих таблиц; reaper может бросить исключение из тика; флаг `False` меняет поведение; нарушен сквозной бюджетный инвариант. --- ## AC-6 — Обязательный регресс-тест и зелёный полный прогон **Условие:** запуск тест-сюита репозитория. - **PASS:** добавлен регресс-тест инцидента ORCH-111 (TC-05 в `04-test-plan.yaml`), **красный** на коде до фикса и **зелёный** после; полный `pytest tests/ -q` зелёный. - **FAIL:** регресс-теста нет, либо он зелёный и до фикса (не воспроизводит баг), либо полный регресс `tests/` красный. --- ## Сводная матрица AC ↔ FR/BR | AC | Покрывает | |----|-----------| | AC-1 | BR-1 / BR-3 / FR-1 | | AC-2 | BR-2 / FR-2 | | AC-3 | BR-4 / FR-4 | | AC-4 | BR-5 / FR-5 | | AC-5 | NFR-1 / NFR-2 / NFR-3 / NFR-6 / FR-3 | | AC-6 | BR-1…BR-5 (регресс-доказательство) |