8.5 KiB
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 |