# Критерии приёмки: ORCH-060

Work Item ID: ORCH-060

Формат: каждый критерий — Дано / Когда / Тогда, с однозначным PASS/FAIL.

---

## AC-1 — Escalated-задача (retry == лимит) не разблокируется (главный кейс ET-013)

- **Дано:** задача на `stage='development'`, без активного job, `age >= grace`,
  `check_ci_green` зелёный; в `agent_runs` ровно `MAX_DEVELOPER_RETRIES` (=3)
  записей `agent='developer'`.
- **Когда:** выполняется `Reconciler.reconcile_gate_once()`.
- **Тогда:** стадия остаётся `development`; `advance_stage`/`advance_if_gate_passed`
  не приводит к смене стадии; `unblocked_total == 0`; новый developer/reviewer job
  не создаётся.
- **PASS:** стадия не изменилась И `unblocked_total == 0` И нет новых job.
- **FAIL:** стадия стала `review` / появился новый job / `unblocked_total > 0`.

## AC-2 — Граница: retry > лимита тоже пропускается

- **Дано:** то же, но developer-записей `> MAX_DEVELOPER_RETRIES` (например 4–5).
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** задача пропущена (как AC-1).
- **PASS / FAIL:** как AC-1.

## AC-3 — Регресс happy-path: retry < лимита по-прежнему доигрывается

- **Дано:** `development`, без активного job, `age >= grace`, `check_ci_green`
  зелёный; developer-записей `< MAX_DEVELOPER_RETRIES` (например 0, 1 или 2).
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** задача доигрывается `development → review`; `unblocked_total == 1`;
  enqueue следующего агента происходит как раньше.
- **PASS:** стадия стала `review` И `unblocked_total == 1`.
- **FAIL:** задача пропущена / стадия не изменилась.

## AC-4 — Граница ровно на лимите (==3) → skip, на (лимит−1) → advance

- **Дано:** две задачи-близнеца, идентичные кроме числа developer-записей:
  одна с `MAX_DEVELOPER_RETRIES`, другая с `MAX_DEVELOPER_RETRIES − 1`.
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** первая пропущена (skip), вторая доиграна (advance).
- **PASS:** ровно одна из двух доиграна (та, что `−1`).
- **FAIL:** обе доиграны / обе пропущены / доиграна задача на лимите.

## AC-5 — Plane-статус Blocked → пропуск

- **Дано:** задача-кандидат F-1 (stage не-терминальный, без активного job,
  `age >= grace`, гейт зелёный), у которой текущий Plane-статус issue = **Blocked**;
  retry < лимита (чтобы изолировать именно этот гард).
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** задача пропущена; стадия не меняется; `unblocked_total == 0`.
- **PASS:** стадия не изменилась И `unblocked_total == 0`.
- **FAIL:** задача доиграна.

## AC-6 — Plane-статус Needs Input → пропуск

- **Дано:** как AC-5, но Plane-статус = **Needs Input**.
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** задача пропущена (как AC-5).
- **PASS / FAIL:** как AC-5.

## AC-7 — Тишина при пропуске (no spam)

- **Дано:** escalated-задача (как AC-1).
- **Когда:** `reconcile_gate_once()` (один или несколько тиков).
- **Тогда:** НЕ вызывается `_note_unblock`; нет лог-строки `... разблокирована`;
  нет `send_telegram`; нет `notify_qg_failure` (пропуск — раньше оценки гейта).
- **PASS:** ни одна из перечисленных нотификаций не вызвана.
- **FAIL:** вызвана любая нотификация.

## AC-8 — Никакого сетевого вызова гейта на escalated-задаче

- **Дано:** escalated-задача (как AC-1) с замоканным `check_ci_green`.
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** `check_ci_green` (через `advance_if_gate_passed`/`_run_qg`) НЕ
  вызывается для этой задачи — пропуск происходит раньше.
- **PASS:** мок гейта не вызван.
- **FAIL:** мок гейта вызван.

## AC-9 — F-2 не доигрывает Blocked/Needs Input (регресс)

- **Дано:** issue в Plane-статусе Blocked или Needs Input (не входит в
  {in_progress, approved, rejected}).
- **Когда:** `reconcile_plane_once()`.
- **Тогда:** ни `handle_status_start`, ни `handle_verdict` не вызываются для
  этого issue; `unblocked_total == 0`.
- **PASS:** обработчики не вызваны.
- **FAIL:** вызван любой обработчик.

## AC-10 — Never-raise: ошибка проверки статуса не ломает тик

- **Дано:** проверка blocked/needs-input (Plane API в Варианте A) бросает
  исключение для одной задачи; в выборке есть ещё одна валидная задача.
- **Когда:** `reconcile_gate_once()`.
- **Тогда:** тик не падает; сбойная задача консервативно НЕ трогается (skip);
  остальные обрабатываются.
- **PASS:** исключение изолировано, остальные задачи обработаны.
- **FAIL:** исключение всплыло из `reconcile_gate_once`.

## AC-11 — Лимит не хардкодится

- **Дано:** код F-1-гарда.
- **Тогда:** используется `stage_engine.MAX_DEVELOPER_RETRIES`, а не литерал `3`.
- **PASS:** граница берётся из константы.
- **FAIL:** в reconciler.py появился магический `3`.

## AC-12 — Документация обновлена (golden source)

- **Дано:** PR задачи.
- **Тогда:** обновлены `docs/architecture/README.md` (описание F-1 с новым skip),
  `CHANGELOG.md`, создан `06-adr/ADR-001-*.md`.
- **PASS:** все три артефакта обновлены/созданы в этом же PR.
- **FAIL:** любой отсутствует (reviewer → REQUEST_CHANGES).

## AC-13 — Регресс существующих тестов reconciler

- **Дано:** существующий `tests/test_reconciler.py` (ORCH-053).
- **Когда:** `pytest tests/test_reconciler.py -q`.
- **Тогда:** все прежние тесты зелёные (поведение happy-path/analysis/kill-switch
  не сломано).
- **PASS:** 0 регрессий.
- **FAIL:** любой ранее зелёный тест упал.
