Files
orchestrator/docs/work-items/ORCH-053/03-acceptance-criteria.md

9.5 KiB
Raw Permalink Blame History

Acceptance Criteria — ORCH-053

Work Item ID: ORCH-053 Формат: каждый критерий имеет явное условие PASS/FAIL. Критерий считается выполненным, только если соответствующие тесты из 04-test-plan.yaml зелёные.

AC-1 — Реконсиляция застрявшей стадии (gate-side, F-1)

  • Дано: task на стадии development, без активных job'ов, updated_at старше grace, гейт check_ci_green для её branch — зелёный (CI прошёл, но webhook потерян, как ORCH-044).
  • Когда: срабатывает фоновый проход reconcile_gate_once().
  • PASS: задача продвинута development → review, заenqueuen reviewer (через advance_stage(..., finished_agent=None)), tasks.updated_at обновлён.
  • FAIL: задача осталась на development, либо продвижение пошло параллельной логикой (не через advance_stage).

AC-2 — Источник истины — гейт, не событие

  • PASS: продвижение в F-1 выполняется исключительно вызовом stage_engine.advance_stage(...); в reconciler.py НЕТ собственного update_task_stage+enqueue_job для advance стадии (только переиспользование).
  • FAIL: в reconciler продублирована логика advance/rollback.

AC-3 — Идемпотентность: sweeper не трогает задачи с активным job

  • Дано: task с queued или running job (has_active_job_for_task == True).
  • PASS: sweeper пропускает задачу — ни advance, ни enqueue, ни нотификации.
  • FAIL: sweeper дёргает гейт / создаёт второй job для такой задачи.

AC-4 — Идемпотентность: задержавшийся/дублированный webhook + sweeper не двоят

  • Дано: issue в Plane = In Progress, задержавшийся Plane-webhook ещё не обработан.
  • Когда: F-2 реконсилирует И затем (или одновременно) приходит реальный webhook.
  • PASS: создаётся ровно одна задача (один task row, один branch/worktree, один стартовый analyst-job). Повторный путь видит существующую задачу/активный job и не двоит.
  • FAIL: созданы две задачи / два стартовых job / два worktree на один plane_id.

AC-5 — Per-stage grace соблюдается

  • Дано: task на стадии, чей updated_at свежее grace этой стадии (агент легитимно работает, напр. analysis 8 мин при grace 1800с).
  • PASS: sweeper НЕ трогает задачу (не дёргает гейт).
  • PASS (граница): как только age(updated_at) >= grace_for_stage(stage) и нет активного job — задача становится кандидатом.
  • FAIL: sweeper дёргает гейт у задачи в пределах grace.

AC-6 — Plane In Progress без задачи → запуск (F-2)

  • Дано: issue в Plane = In Progress (статус сменён руками, webhook потерян), в tasks задачи нет, прошёл grace.
  • PASS: sweeper вызывает handle_status_start/start_pipeline → задача создана, заenqueuen analyst — как если бы пришёл webhook.
  • FAIL: задача не создана; либо создана дублирующей логикой, минуя handle_status_start.

AC-7 — Plane Approved без advance → advance (F-2)

  • Дано: issue = Approved, task существует и стадия НЕ сдвинута, нет активного job, прошёл grace.
  • PASS: sweeper вызывает handle_verdict(approved=True) → штатный advance.
  • FAIL: нет advance, либо advance вне handle_verdict/advance_stage.

AC-8 — Plane Rejected без rollback → rollback (F-2)

  • Дано: issue = Rejected, task существует и не откатана, нет активного job, прошёл grace.
  • PASS: sweeper вызывает handle_verdict(approved=False) → штатный rollback на предыдущую стадию.
  • FAIL: нет rollback, либо rollback вне штатного пути.

AC-9 — Нет спама нотификаций на красном гейте

  • Дано: застрявшая задача, у которой гейт стабильно красный (напр. CI failure), нет активного job, прошёл grace.
  • Когда: sweeper проходит несколько тиков подряд.
  • PASS: notify_qg_failure/Telegram НЕ вызывается на каждом тике (≤1 раз / без повторов); задача не продвигается.
  • FAIL: на каждом тике летит нотификация о провале гейта.

AC-10 — Тишина при синхронности

  • Дано: все задачи синхронны (нет застрявших; статусы Plane совпадают с локальными).
  • PASS: проход не выполняет действий, не пишет INFO-логов о разблокировке, не шлёт нотификаций.
  • FAIL: sweeper генерирует шум/действия при полностью синхронном состоянии.

AC-11 — Restart-safe фоновый поток

  • PASS: reconciler стартует в main.lifespan (daemon-поток), корректно останавливается (stop()), переживает рестарт сервиса без потери (нет состояния в памяти, критичного для корректности; всё перечитывается из БД/Plane).
  • FAIL: reconciler не стартует автоматически, висит при shutdown, или дублирует действия после рестарта.

AC-12 — Наблюдаемость разблокировки (F-4)

  • Дано: sweeper разблокировал застрявшую задачу.
  • PASS: в лог пишется явная строка вида reconciler: <work_item_id> <stage> разблокирована (потерян webhook); при reconcile_notify_unblock=True — Telegram-уведомление.
  • FAIL: разблокировка происходит молча (невозможно измерить частоту дыры).

AC-13 — Kill-switch

  • Дано: reconcile_enabled=False (env ORCH_RECONCILE_ENABLED=false).
  • PASS: фоновый поток reconciler не выполняет проходов (или не стартует); система работает как до ORCH-053. reconcile_plane_enabled=False гасит только F-2, F-1 работает.
  • FAIL: sweeper активен при выключенном флаге.

AC-14 — Усиленный sha→branch резолв (F-3)

  • Дано: Gitea CI-status webhook без branches и со sha, не разрезолвившимся через git branch -r --contains.
  • PASS: добавленный БД-fallback однозначно находит task (по repo + активной development-стадии) и продвигает; неоднозначность логируется на уровне INFO; существующая success/failure-семантика гейта не изменена.
  • FAIL: регресс существующего резолва, либо ложный матч при неоднозначности.

AC-15 — Never-raise в тике

  • Дано: обработка одной задачи/issue кидает исключение (битые данные, ошибка API).
  • PASS: исключение изолировано, проход продолжает остальные задачи; поток не падает.
  • FAIL: одно исключение роняет весь проход / поток reconciler.

AC-16 — F-1 не продвигает analysis по локальному состоянию

  • Дано: task на analysis, артефакты на диске присутствуют, но Plane НЕ в статусе Approved (BRD не одобрен человеком), нет активного job, прошёл grace.
  • PASS: F-1 (gate-side) НЕ продвигает analysis→architecture (advance стадии analysis отдан F-2, которая сверяется с реальным статусом Plane Approved).
  • FAIL: sweeper автопродвинул неодобренный BRD.

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

  • PASS: в PR обновлены docs/architecture/README.md, заведён docs/work-items/ORCH-053/06-adr/ADR-001-*.md, обновлён CHANGELOG.md, упомянут kill-switch в docs/operations/INFRA.md.
  • FAIL: код изменён, документация — нет (Reviewer обязан вернуть REQUEST_CHANGES).