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

7.3 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-093 analysis analyst ready-for-review 2026-06-09 claude-opus-4-8

03 — Критерии приёмки (Acceptance Criteria): ORCH-093 — ретрай транзиентных merge-ошибок Gitea + гард already-in-main

Work Item: ORCH-093 · Repo: orchestrator · Стадия: analysis

Формат: каждый критерий имеет PASS (что должно быть истинно для приёмки) и FAIL (что считается провалом). Reviewer/tester проверяет их буквально по файлам репозитория и тестам.


AC-1 — ретрай транзиента 405/5xx/таймаут → успешный мерж

Условие: merge_pr при транзиентной ошибке мержа повторяет POST …/merge с backoff и доводит мерж до успеха в пределах бюджета.

  • PASS: мок httpx даёт на POST …/merge 405 дважды, затем 200merge_pr возвращает (True, …), выполнено ровно 3 POST, ложного False нет. Аналогично для 5xx и таймаута/сетевой ошибки в первых попытках.
  • FAIL: merge_pr возвращает False на первом 405/5xx/таймауте (one-shot), не делая повторных POST.

AC-2 — реальный конфликт / не-mergeable НЕ ретраится (быстрый честный HOLD)

Условие: merge_pr при реальном конфликте (409/422 с mergeable==False) или 403 не зацикливается, а возвращает (False, …) быстро.

  • PASS: мок httpx даёт 409 на POST …/merge и GET /pulls/{n} с mergeable=Falsemerge_pr возвращает (False, …) без дополнительных POST (не более одной попытки мержа); reason различим как терминальный. 403 → немедленный (False, …).
  • FAIL: merge_pr ретраит реальный конфликт до исчерпания бюджета (вечный/долгий цикл), задерживая честный HOLD.

AC-3 — исчерпание ретраев → (False, …) + защита ORCH-071/081 как прежде

Условие: если транзиент не проходит за N попыток, merge_pr возвращает (False, …) с понятным reason; защита «deploy succeeded but not merged» срабатывает как раньше.

  • PASS: мок даёт 405 на всех N попытках → merge_pr возвращает (False, "merge failed after <N> attempts: HTTP 405") (или эквивалент); в _handle_merge_verify неподтверждённый SHA-in-main → HOLD + алерт (поведение ORCH-071/081 неизменно). Тест на не-merged HOLD остаётся зелёным.
  • FAIL: при исчерпании ретраев reason неинформативен; или защита HOLD не срабатывает / задача ошибочно уходит в done.

AC-4 — гард «ветка уже в main» → нет мусорного PR, задача доходит до done

Условие: если ветка уже полностью в main (нет коммитов origin/main..branch), ensure_open_pr не создаёт PR и возвращает already-in-main; финализатор доводит до done.

  • PASS: мок: открытого code-PR нет, git rev-list --count origin/main..branch == 0ensure_open_pr возвращает ("already-in-main", …) и не делает POST …/pulls; в _handle_merge_verify этот статус пропускает merge_pr и verify_merged_to_main (SHA-in-main) подтверждает мерж → задача доходит до done без создания пустого PR.
  • FAIL: ensure_open_pr создаёт новый пустой PR на уже влитой ветке, либо статус already-in-main ошибочно трактуется как failed (ложный HOLD).

AC-5 — kill-switch / конфиг ретраев; дефолты задокументированы

Условие: ретрай-поведение конфигурируемо (число попыток, backoff, kill-switch); при выключении — one-shot как сейчас; дефолты в .env.example.

  • PASS: в src/config.py есть поля merge_retry_enabled / merge_retry_max_attempts / merge_retry_backoff_base_s / merge_retry_backoff_max_s с разумными дефолтами (≈3 / 2 / 5); .env.example содержит дескрипторы ORCH_MERGE_RETRY_*; при merge_retry_enabled=False тест подтверждает ровно одну попытку POST (one-shot).
  • FAIL: ретрай захардкожен (нет флагов/kill-switch), или .env.example не обновлён, или при выключенном флаге поведение отличается от текущего one-shot.

AC-6 — never-raise сохранён; регресс зелёный; доки обновлены

Условие: контракт never-raise merge_pr/ensure_open_pr цел; полный регресс зелёный; документация и CHANGELOG обновлены.

  • PASS: при любой HTTP/parse/сетевой ошибке (в т.ч. внутри ретрай-цикла и git-проверки гарда) функции возвращают безопасный кортеж, исключение не пробрасывается; pytest tests/ -q зелёный; merge-gate-раздел доки (docs/architecture/README.md / CLAUDE.md) и CHANGELOG.md описывают ретрай и гард already-in-main.
  • FAIL: исключение пробрасывается в advance_stage; падает любой тест в tests/; доки/CHANGELOG не отражают изменение.

AC-7 — инварианты self-hosting / INV-4 не нарушены

Условие: изменение не вводит прямых push/force-push в main и не трогает STAGE_TRANSITIONS/QG_CHECKS/схему БД.

  • PASS: мерж по-прежнему идёт только через Gitea PR-merge API; git diff не содержит правок STAGE_TRANSITIONS / состава QG_CHECKS / схемы БД; никаких новых вызовов git push … main.
  • FAIL: появился прямой push в main, либо изменены STAGE_TRANSITIONS/QG_CHECKS/схема БД.

Сводная матрица AC ↔ FR/BR

AC Покрывает
AC-1 BR-1 / FR-1, FR-2
AC-2 BR-2, BR-3 / FR-2
AC-3 BR-4 / FR-1
AC-4 BR-5 / FR-3, FR-4
AC-5 BR-6, BR-7 / FR-5
AC-6 NFR-1, NFR-6 / FR-1…FR-5
AC-7 NFR-2 / §6, §7 ТЗ