130 lines
7.3 KiB
Markdown
130 lines
7.3 KiB
Markdown
---
|
||
work_item: ORCH-111
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-15
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-111 — alert на долго живущие pytest/дочерние процессы
|
||
|
||
Work Item: **ORCH-111** · Repo: **orchestrator** · Стадия: analysis
|
||
|
||
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL** (что считается
|
||
провалом). Reviewer/tester проверяет их буквально по файлам репозитория и тестам.
|
||
|
||
---
|
||
|
||
## AC-1 — Алерт на долго живущий блокирующий процесс
|
||
|
||
**Условие:** на хосте есть процесс тест-класса (pytest/субпроцесс гейта), чей возраст превысил
|
||
настроенный порог и который не атрибутирован активному отслеживаемому джобу.
|
||
- **PASS:** watchdog поднимает **отдельный** сигнал (рабочий ключ `proc_blocking`) → ALERT в свой
|
||
Telegram-канал; алерт срабатывает **даже если** ни одна стадия задачи формально не `stuck`.
|
||
- **FAIL:** такой процесс присутствует, но ни одного нового алерта не поднято (поведение до ORCH-111).
|
||
|
||
---
|
||
|
||
## AC-2 — Действенный текст алерта
|
||
|
||
**Условие:** алерт `proc_blocking` сформирован.
|
||
- **PASS:** `detail` содержит фрагмент cmdline (видно, что это pytest/тест-процесс), PID, возраст
|
||
процесса в секундах и (при наличии) долю/время CPU.
|
||
- **FAIL:** алерт без идентификации процесса (нельзя понять, какой PID/команду проверять).
|
||
|
||
---
|
||
|
||
## AC-3 — Только наблюдение, без ремедиации
|
||
|
||
**Условие:** обнаружен блокирующий процесс.
|
||
- **PASS:** на всём новом пути нет `os.kill`/отправки сигналов/`subprocess.Popen|run`/иных мутаций;
|
||
watchdog **только** алертит, процесс остаётся жив (его судьба — на операторе).
|
||
- **FAIL:** код пытается убить/остановить/просигналить процесс или иначе ремедиировать.
|
||
|
||
---
|
||
|
||
## AC-4 — Без ложных срабатываний на легитимном прогоне
|
||
|
||
**Условие:** на хосте идёт нормальный тест-прогон (merge-gate re-test / coverage) под активным
|
||
отслеживаемым джобом, в пределах своего бюджета.
|
||
- **PASS:** `proc_blocking` **не** активен для такого процесса (возраст ниже порога **или** процесс
|
||
атрибутирован активному джобу) → алерта нет.
|
||
- **FAIL:** легитимный прогон под активным джобом триггерит ложный `proc_blocking`-alert.
|
||
|
||
---
|
||
|
||
## AC-5 — Без дубля с `agent_hung`
|
||
|
||
**Условие:** процесс уже представлен в `/metrics agents[]` (отслеживаемый running-агент).
|
||
- **PASS:** для него работает только существующий `agent_hung`; `proc_blocking` его **не** дублирует
|
||
(ровно один класс алерта на один процесс).
|
||
- **FAIL:** один и тот же процесс порождает и `agent_hung`, и `proc_blocking` (двойной алерт).
|
||
|
||
---
|
||
|
||
## AC-6 — Анти-спам и recovery
|
||
|
||
**Условие:** блокирующий процесс держится несколько тиков, затем исчезает.
|
||
- **PASS:** один ALERT при пересечении порога; в пределах cooldown — `NONE` (не спамит); REALERT
|
||
по истечении cooldown; **однократный** RECOVERY при исчезновении процесса (через
|
||
`decision.decide`/`AlertState`).
|
||
- **FAIL:** алерт на каждом тике (спам) либо отсутствует recovery.
|
||
|
||
---
|
||
|
||
## AC-7 — Kill-switch и нулевая регрессия
|
||
|
||
**Условие:** `WATCHDOG_PROC_ENABLED` выключен (или дефолт-off).
|
||
- **PASS:** коллектор/сигнал инертны; набор и поведение тика **байт-в-байт** как до ORCH-111; полный
|
||
`pytest tests/` зелёный; watchdog-тесты зелёные.
|
||
- **FAIL:** при выключенном флаге появляется новый алерт/сетевой оверхед, либо падают существующие
|
||
тесты/тик.
|
||
|
||
---
|
||
|
||
## AC-8 — never-raise / read-only
|
||
|
||
**Условие:** коллектор процессов получает битый/пустой/недоступный источник.
|
||
- **PASS:** коллектор деградирует в `[]` (один сигнал пропущен), тик завершается штатно; ни одной
|
||
записи/мутации/управляющего действия над процессами/ФС/БД; sidecar остаётся stdlib-only.
|
||
- **FAIL:** исключение роняет тик, либо появляется новая сторонняя зависимость, либо мутирующая
|
||
операция.
|
||
|
||
---
|
||
|
||
## AC-9 — Конвейер и контракты не тронуты
|
||
|
||
**Условие:** изменение влито.
|
||
- **PASS:** `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict ключи / схема БД —
|
||
без изменений; правка `/metrics` (если выбрана) — **аддитивна**, `schema_version` не бампнут;
|
||
выкат не требует рестарта прод-контейнера `orchestrator`.
|
||
- **FAIL:** затронут любой из перечисленных контрактов или бампнут `schema_version` без ломающего
|
||
изменения, либо выкат требует рестарта прод-орка.
|
||
|
||
---
|
||
|
||
## AC-10 — Канон конфига/тиража синхронизирован
|
||
|
||
**Условие:** добавлены ключи `WATCHDOG_PROC_*` / изменён compose.
|
||
- **PASS:** ключи присутствуют и согласованы в `.env.watchdog.example` ↔ блоке `WATCHDOG_*`
|
||
`.env.example`; описаны в `LITE_SETUP.md` и `docs/architecture/README.md` в том же PR; key-set-sync
|
||
тест зелёный.
|
||
- **FAIL:** ключи добавлены только в код, канон/доки тиража не обновлены (дрейф).
|
||
|
||
---
|
||
|
||
## Сводная матрица AC ↔ FR/BR
|
||
| AC | Покрывает |
|
||
|----|-----------|
|
||
| AC-1 | BR-1 / FR-1, FR-2, FR-5 |
|
||
| AC-2 | BR-2 / FR-1 |
|
||
| AC-3 | BR-3 / FR-4 / NFR-2 |
|
||
| AC-4 | BR-4 / FR-1, FR-6 |
|
||
| AC-5 | NFR-4 / FR-6 |
|
||
| AC-6 | BR-5 / FR-5 |
|
||
| AC-7 | BR-6 / FR-3 / §7 |
|
||
| AC-8 | NFR-1, NFR-2, NFR-6 / FR-2 |
|
||
| AC-9 | §6 / NFR-3 / §4 |
|
||
| AC-10 | NFR-5 / §7 |
|