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

8.6 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-063 analysis analyst ready-for-review 2026-06-09 claude-opus-4-8

03 — Критерии приёмки (Acceptance Criteria): ORCH-063 — INFRA: мониторинг диска mva154 + алерт при >85%

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

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


AC-1 — Heartbeat-демон запускается с приложением

Условие: фоновый disk-watchdog периодически измеряет заполнение диска и стартует вместе с приложением без ручного запуска.

  • PASS: есть daemon-поток (паттерн reconciler/job_reaper: threading.Thread(daemon=True) + threading.Event), стартующий в main.lifespan (после reaper.start()) и останавливающийся на shutdown; период замера = disk_monitor_interval_s; есть метод status().
  • FAIL: watchdog не стартует автоматически; блокирующий time.sleep без чистого stop; замер выполняется в обработчике вебхука/в горячем пути конвейера, а не в отдельном демоне.

AC-2 — Алерт при заполнении ≥ порога

Условие: при заполнении отслеживаемого пути ≥ disk_monitor_threshold_pct (дефолт 85%) оператор получает Telegram-алерт с действенными деталями.

  • PASS: при used_pct ≥ threshold вызывается send_telegram (notifying, не silent) с сообщением, содержащим путь/точку монтирования, занято %, свободно (ГБ или %) и порог.
  • FAIL: алерт не отправляется при превышении; отправляется silent (disable_notification=True) и не пингует; сообщение без действенных деталей (нет %/пути/свободно).

AC-3 — Анти-спам: не на каждом тике

Условие: при длительном превышении порога алерт не дублируется на каждом тике.

  • PASS: алерт отправляется при пересечении порога (переход «ниже→на/выше»); пока заполнение остаётся выше порога, повторный алерт шлётся не чаще disk_monitor_realert_s. Решение об отправке выражено чистой функцией от (current_pct, threshold, previous_state, now) и покрыто юнит-тестом.
  • FAIL: алерт шлётся на каждом тике при стабильном превышении; нет cooldown/состояния; логика отправки не тестируема (зашита в поток с реальным таймером).

AC-4 — Recovery при возврате ниже порога

Условие: при возврате заполнения ниже порога состояние сбрасывается и приходит однократное сообщение восстановления.

  • PASS: переход «выше→ниже порога» сбрасывает состояние алерта и отправляет ровно одно recovery-сообщение «диск ниже порога»; последующее новое превышение снова алертит (цикл повторяем).
  • FAIL: после спада ниже порога состояние не сбрасывается (новое превышение молчит из-за «залипшего» cooldown); recovery шлётся повторно на каждом тике ниже порога.

AC-5 — Конфигурируемость и kill-switch

Условие: порог, период, период повтора, пути и включение конфигурируемы; выключение даёт нулевую регрессию.

  • PASS: в config.py есть disk_monitor_enabled / disk_monitor_interval_s / disk_monitor_threshold_pct / disk_monitor_realert_s / disk_monitor_paths (с env-маппингом); при disk_monitor_enabled=False демон не стартует, /queue-блок отдаёт {"enabled": false}, поведение приложения идентично текущему. Новые env задокументированы в .env.example.
  • FAIL: значения захардкожены; нет kill-switch; при выключении меняется поведение конвейера; env не задокументированы.

AC-6 — never-raise (изоляция от конвейера)

Условие: любой сбой watchdog не роняет и не блокирует конвейер.

  • PASS: замер по несуществующему/недоступному пути, ошибка send_telegram, исключение в тике — логируются и не пробрасываются; демон продолжает работу; конвейер и enduro-trails не затронуты. Покрыто тестом (замер по битому пути / исключение в отправке → тик не падает).
  • FAIL: исключение в тике останавливает поток или всплывает в приложение; недоступный путь роняет замер всех путей.

AC-7 — Наблюдаемость в GET /queue

Условие: состояние watchdog видно в GET /queue.

  • PASS: ответ GET /queue содержит аддитивный блок disk_monitor с enabled, threshold_pct, interval_s, paths (последний замер: used_pct, свободно), alerting, last_alert_at; существующие ключи ответа не изменены; блок never-raise (при ошибке — минимальный словарь).
  • FAIL: блока нет; изменены/сломаны существующие ключи /queue; блок может выбросить исключение.

AC-8 — Корректный источник замера (хост-ФС)

Условие: замер отражает заполнение хост-раздела, а не overlay-ФС контейнера.

  • PASS: дефолтный набор путей — смонтированные хост-пути (/repos, /app/data); замер по ним репрезентативен для заполняющегося хост-раздела. Источником истины не является shutil.disk_usage("/") (overlay контейнера).
  • FAIL: мониторится только / контейнера → ложно-низкое заполнение при реально полном хосте (риск повтора инцидента 07.06).

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

Условие: документация обновлена в том же PR (CLAUDE.md §2; reviewer-ось).

  • PASS: обновлены docs/architecture/README.md (компонент + блок /queue), docs/operations/INFRA.md (что мониторится, порог, как отключить, реакция на алерт), .env.example (новые ORCH_DISK_*), CHANGELOG.md (feat:); создан docs/work-items/ORCH-063/06-adr/ADR-001-*.md.
  • FAIL: функционал добавлен, но обзорные/операционные доки или ADR не обновлены.

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

AC Покрывает
AC-1 BR-1 / BR-8 / FR-1
AC-2 BR-2 / FR-2 / FR-3
AC-3 BR-3 / FR-4
AC-4 BR-4 / FR-4
AC-5 BR-5 / FR-5 / NFR-4
AC-6 BR-6 / NFR-1
AC-7 BR-7 / FR-6
AC-8 NFR-3 / FR-2
AC-9 CLAUDE.md §2 (документация = golden source)