Files
orchestrator/docs/work-items/ORCH-124/03-acceptance-criteria.md
claude-bot fef5ba15d5
All checks were successful
CI / test (push) Successful in 1m9s
analyst(ET): auto-commit from analyst run_id=763
2026-06-16 17:56:23 +03:00

8.6 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used, escalate
work_item stage author_agent status created_at model_used escalate
ORCH-124 analysis analyst ready-for-review 2026-06-16 claude-opus-4-8 full-cycle

03 — Критерии приёмки (Acceptance Criteria): ORCH-124 — wait/terminal-семантика serial-gate

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

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


AC-1 — Приостановленный предшественник не блокирует срочного успешника (регресс инцидента)

Условие: репо имеет более раннюю задачу A (A.id < B.id) в состоянии паузы (Blocked/Backlog/ Needs-Input по явному намерению оператора) и более позднюю срочную задачу B с queued analyst-job.

  • PASS: build_claim_clause() НЕ блокирует analyst-job задачи B; claim_next_job() выбирает его; B входит в analysis. Тест воспроизводит инцидент ORCH-116/ORCH-123 (красный до фикса, зелёный после).
  • FAIL: analyst-job B остаётся queued, потому что приостановленная A всё ещё считается активной.

AC-2 — Нормально исполняемая задача по-прежнему держит гейт (анти-stale-base, без регресса ORCH-088)

Условие: репо имеет более раннюю задачу A, реально исполняемую (не на паузе, стадия вне {done,cancelled}) и более позднюю задачу B с queued analyst-job.

  • PASS: analyst-job B остаётся заблокированным (FIFO ORCH-088 цел); B стартует только когда A становится done/cancelled (или явно поставлена на паузу оператором).
  • FAIL: B стартует поверх ещё не завершённой активной A → возврат stale-base дефекта, который закрывал ORCH-088.

AC-3 — Пауза снимает гейт только по явному durable намерению

Условие: способ перевода задачи в «паузу» для serial-gate.

  • PASS: освобождение гейта происходит только при явном операторском сигнале (эндпоинт pause / выбранный механизм ADR), сигнал durable (переживает рестарт процесса/контейнера) и DB-резолвимый. Никакого эвристического само-распаузивания.
  • FAIL: гейт снимается без явного намерения (например, по умолчанию для любой не-done задачи) ИЛИ намерение теряется после рестарта.

AC-4 — Анти-stale-base при возобновлении (R-1 разрешён архитектором)

Условие: приостановленная A возобновлена после того, как успешник B уже прошёл вперёд.

  • PASS: ни A, ни B не остаются незаметно на устаревшей базе — выбранный механизм (демотирование A в FIFO + обязательный rebase / явный yield с rebase / иное по ADR) гарантирует, что возобновлённая задача строится/мержится на актуальном origin/main. Поведение зафиксировано тестом по контракту ADR.
  • FAIL: возобновлённая A или прошедший B приводит к stale-ветке/затиранию кода без сигнала.

AC-5 — Явные блоки (freeze + dependency) сохранены

Условие: активный repo_freeze для репо ИЛИ объявленная незавершённая зависимость в job_deps.

  • PASS: claim успешника по-прежнему заблокирован freeze'ем (до ручного POST /serial-gate/unfreeze) и/или незавершённой зависимостью (task_deps) — пауза их не обходит.
  • FAIL: «пауза» позволяет обойти freeze или объявленную зависимость.

AC-6 — Корректная причина ожидания в GET /queue

Условие: блок serial_gate в снапшоте GET /queue.

  • PASS: для ожидающего успешника видна корректная причина ожидания (active-task / paused-predecessor / freeze / dependency); приостановленный предшественник НЕ показывается как active_task. Существующие ключи снапшота не сломаны (BC).
  • FAIL: снапшот показывает приостановленную задачу как active_task ИЛИ причина ожидания неверна/ отсутствует.

AC-7 — Hot-path остаётся offline (без сети)

Условие: путь db.claim_next_jobserial_gate.build_claim_clause.

  • PASS: определение «активна/пауза» резолвится только локальной БД (SQL); ни одного сетевого вызова (Plane API и т.п.) на горячем пути claim. Проверяемо тестом (claim работает без сети / без Plane).
  • FAIL: claim делает сетевой вызов для определения паузы.

AC-8 — Машинные инварианты байт-в-байт; kill-switch off → прежнее поведение

Условие: реестры и выключатель.

  • PASS: STAGE_TRANSITIONS / состав QG_CHECKS / имена и семантика check_* / machine-verdict ключи / схемы существующих таблиц — без изменений (структурный тест). При выключенном под-флаге паузы serial-gate ведёт себя байт-в-байт как ORCH-088/090.
  • FAIL: изменён любой machine-verdict ключ / состав QG_CHECKS / STAGE_TRANSITIONS, либо выключенный флаг меняет поведение.

AC-9 — never-raise и сохранённые fail-directions

Условие: ошибки внутри новой логики паузы.

  • PASS: все публичные функции serial_gate never-raise; hot-claim build по-прежнему fail-OPEN (""-фрагмент при ошибке), freeze-решение по-прежнему fail-CLOSED; новая ветка паузы не инвертирует эти направления. Проверяемо тестом (инъекция ошибки → claim не падает, очередь не заклинивает).
  • FAIL: ошибка в ветке паузы роняет claim/worker ИЛИ инвертирует fail-direction.

AC-10 — Возобновление восстанавливает участие в гейте (BR-5)

Условие: распауза ранее приостановленной задачи.

  • PASS: после resume задача снова участвует в serial-gate согласно выбранной семантике (держит гейт как активная либо ре-входит в FIFO); нет «вечного обхода».
  • FAIL: возобновлённая задача навсегда остаётся вне гейта / её намерение паузы «залипает».

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

AC Покрывает
AC-1 BR-1 / FR-1, FR-2
AC-2 BR-3 / FR-4
AC-3 BR-2 / FR-3
AC-4 BR-3, BR-5 / FR-4
AC-5 BR-6 / FR-6
AC-6 BR-4 / FR-5
AC-7 NFR-2 / FR-1
AC-8 NFR-3, NFR-4 / FR-7
AC-9 NFR-1 / FR-7
AC-10 BR-5 / FR-3