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

8.5 KiB
Raw Permalink Blame History

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

03 — Критерии приёмки (Acceptance Criteria): ORCH-099 — FND/F1a: лёгкий /metrics в орке

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

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


AC-1 — Эндпоинт /metrics отдаёт четыре раздела сырья

Условие: GET /metrics возвращает 200 и JSON с разделами stages, queue, agents, cost (плюс конверт schema_version / generated_at), с полями из TRZ §3.

  • PASS: ответ — валидный JSON-объект; присутствуют ключи schema_version, generated_at, stages (список; элемент содержит work_item, stage, age_in_stage_s, repo), queue (содержит counts, breaker, max_concurrency, сырьё ретраев), agents (список; элемент содержит agent, run_id, pid, runtime_s и поле сырья CPU-liveness), cost (содержит aggregate с суммами cost_usd/input_tokens/output_tokens/cache_read_tokens/ cache_creation_tokens).
  • FAIL: отсутствует любой из четырёх разделов; в agents нет pid/runtime_s; в stages нет «как давно в стадии»; в cost нет агрегата токенов/стоимости; ответ не JSON или статус ≠ 200.

AC-2 — Аддитивность: /health, /status, /queue не сломаны

Условие: существующие эндпоинты сохраняют прежний контракт.

  • PASS: GET /health{"status":"ok", ...}; GET /status{"active_tasks":[...]}; GET /queue отдаёт прежний набор ключей; существующие тесты эндпоинтов (tests/test_queue_endpoint.py и пр.) зелёные без модификации их ожиданий.
  • FAIL: изменён/удалён любой существующий ключ ответа /health//status//queue; пришлось править существующие тесты под новый контракт; регресс в этих эндпоинтах.

AC-3 — Лёгкость и быстрая выборка

Условие: эндпоинт лёгкий — только быстрые локальные SQL + чтение in-memory снапшотов, без тяжёлых вычислений и сетевых вызовов.

  • PASS: в коде src/metrics.py нет сетевых вызовов (HTTP/Plane/Gitea/Anthropic), нет запуска подпроцессов кроме безопасного чтения /proc/<pid>/stat, нет сканирования git/файлового дерева; данные берутся из существующих helper'ов БД и worker-снапшота; на типовом объёме ответ формируется без заметной задержки.
  • FAIL: эндпоинт делает сетевой запрос, запускает агента/тяжёлый процесс, сканирует worktree/git или выполняет дорогие агрегаты, заметно тормозящие ответ.

AC-4 — Never-raise (ошибка поля → null, эндпоинт не падает)

Условие: любая ошибка сбора отдельного поля/раздела не роняет эндпоинт.

  • PASS: при недоступном источнике (например, worker не инициализирован, pid уже мёртв, /proc/<pid> отсутствует, пустые таблицы) соответствующее поле получает null/безопасный дефолт, а GET /metrics всё равно возвращает 200 и валидный JSON; есть тест, симулирующий сбой раздела и проверяющий 200 + null в этом поле.
  • FAIL: при любом из перечисленных условий эндпоинт возвращает 500 / бросает исключение / возвращает невалидный JSON.

AC-5 — Read-only (ничего не меняет; гейты/схема не тронуты)

Условие: эндпоинт и модуль строго read-only; конвейерные инварианты целы.

  • PASS: src/metrics.py и обработчик /metrics не выполняют INSERT/UPDATE/DELETE/CREATE/ ALTER, не запускают/останавливают процессы, не рестартят, не мутируют состояние демонов; STAGE_TRANSITIONS, QG_CHECKS, check_*, machine-verdict ключи и схема БД (tasks/jobs/ agent_runs и пр.) — без изменений в диффе; повторный вызов /metrics не меняет состояние БД (тест: снимок БД до/после идентичен).
  • FAIL: дифф трогает STAGE_TRANSITIONS/QG_CHECKS/check_*/схему/machine-verdict; модуль выполняет любую запись/мутацию; вызов эндпоинта меняет состояние.

AC-6 — agent-liveness содержит сырьё для alive-детекта

Условие: по каждому running-job отдаётся идентификация процесса и сырьё для CPU-детекта sidecar'ом.

  • PASS: для running-job ответ содержит agent, run_id, pid, runtime_s и поле сырья CPU-liveness (например cpu_ticks из /proc/<pid>/stat + базис тиков clk_tck, либо эквивалент по решению ADR), позволяющее внешнему наблюдателю посчитать CPU-дельту между опросами; при pid is None/мёртвом процессе CPU-поле = null (см. AC-4), прочие поля целы.
  • FAIL: liveness-раздел не позволяет sidecar'у отличить «жив» от «завис» (нет ни CPU-сырья, ни pid+runtime); отсутствуют run_id/pid; обращение к мёртвому pid роняет эндпоинт.

AC-7 — Контракт задокументирован (для sidecar F1b) + CHANGELOG

Условие: формат /metrics зафиксирован как контракт и отражён в журнале изменений.

  • PASS: в docs/architecture/README.md описан формат ответа /metrics (разделы, поля, schema_version) как стабильный контракт для sidecar (F1b); в CHANGELOG.md есть запись ## [Unreleased] с пометкой ORCH-099.
  • FAIL: формат не задокументирован или описан только в коде; нет записи в CHANGELOG.md; документация противоречит фактическому ответу эндпоинта.

AC-8 — pytest зелёный

Условие: новый тест-набор и полный регресс проходят.

  • PASS: pytest tests/ -q зелёный; присутствует tests/test_metrics.py, покрывающий структуру ответа (AC-1), never-raise (AC-4), read-only (AC-5), liveness-сырьё (AC-6) и аддитивность (AC-2).
  • FAIL: любой тест красный; новые тесты отсутствуют или не покрывают перечисленные критерии.

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

AC Покрывает
AC-1 BR-1/BR-2/BR-3/BR-5 / FR-1…FR-5
AC-2 BR-6 / FR-4
AC-3 NFR-3 / FR-6
AC-4 NFR-2 / FR-6
AC-5 NFR-1/NFR-4/NFR-5 / FR-5
AC-6 BR-4 / FR-3
AC-7 BR-7 / FR-5
AC-8 NFR-3 (валидация) / все FR