5.1 KiB
03-Acceptance Criteria — ORCH-086
Каждый критерий формулирует чёткое условие PASS/FAIL. Проверяется автотестами (tests/test_reconciler.py) и код-ревью.
AC-1 — ET-002 (терминальная) больше не генерирует «разблокирована»
Дано: F-1 (reconcile_gate_once) обрабатывает задачу enduro, чья стадия в БД оркестратора НЕ-done (дрейф), а текущий статус в Plane — терминальный (Done, группа completed); гейт стадии зелёный (для enduro — no-op True).
- PASS:
_note_unblockНЕ вызывается →send_telegramНЕ вызывается ни при обычном тике, ни при первом проходе после старта (свежий процесс/чистый_unblock_dedup). - FAIL: уведомление «… разблокирована (потерян webhook)» отправлено хотя бы раз.
AC-2 — терминальные задачи (done/cancelled) не доходят до _note_unblock
Дано: задача терминальна в Plane (группа completed или cancelled) ИЛИ её стадия в БД ∈ {done, cancelled}.
- PASS: F-1 делает ранний скип (нет
advance/ нет_note_unblock);skipped_terminal_totalувеличен на 1 на каждую такую задачу за тик. - FAIL: терминальная задача доходит до
advance_if_gate_passed→_note_unblock, либоskipped_terminal_totalне растёт. - Грабли (R1): условие должно срабатывать для ОБОИХ проектов — enduro (терминал по группе
completed/cancelled, либо fallback-ключdone/cancelled) и orchestrator (свой набор статусов). Тест покрывает оба пути терминал-детекта: (а) по группе, (б) fallback по логическому ключу при пустыхgroups.
AC-3 — _note_unblock на всех путях получает state_uuid → dedup покрывает все вызовы
Дано: легитимный unblock реально застрявшей НЕ-терминальной задачи на пути F-1 (гейт зелёный, стадия сменилась).
- PASS:
_note_unblockвызван с непустымstate_uuid; повторный вызов для того жеissue_id+state_uuid(например на следующем тике до фактической смены статуса) подавляется dedup-guard'ом →deduped_totalрастёт, второгоsend_telegramнет. - FAIL: F-1 зовёт
_note_unblockбезstate_uuid(2 аргумента) → dedup не работает → повторные уведомления.
AC-4 — легитимный unblock реально застрявшей задачи ПО-ПРЕЖНЕМУ уведомляет (анти-регресс)
Дано: НЕ-терминальная задача (Plane-статус рабочий, не done/cancelled/blocked/needs_input), реально застрявшая (прошла grace, нет active-job), гейт зелёный → F-1 её продвигает (result.advanced=True).
- PASS:
_note_unblockвызван ОДИН раз; приreconcile_notify_unblock=Trueотправлен ровно один Telegram;unblocked_total+= 1. - FAIL: уведомление подавлено (полезный алерт задушен) ИЛИ отправлено более одного раза за одну смену стадии.
AC-5 — pytest зелёный; never-raise в тике сохранён
- PASS:
pytest tests/ -qзелёный; при исключении внутри терминал-детекта/fetch_issue_state/_reconcile_gate_taskтик НЕ падает (изоляция per-task), и ложное уведомление при ошибке НЕ отправляется (консервативно). - FAIL: падение тика, незелёный pytest, либо исключение терминал-детекта приводит к ложной отправке.
AC-6 — без регрессий смежного поведения (контрактный)
- PASS: F-2 (plane-side) терминал-скип/dedup/счётчики работают как в ORCH-068;
STAGE_TRANSITIONS,QG_CHECKS, схема БД, сигнатурыadvance_stage/advance_if_gate_passed/_note_unblock, формаstatus()/GET /queue— не изменены; новые config-флаги не введены;reconcile_skip_blocked_enabledпо-прежнему гейтит только Guard 2 (терминал-скип ему не подчинён). Документация (README.md,CHANGELOG.md) обновлена в том же PR. - FAIL: любое из перечисленного нарушено.