123 lines
8.0 KiB
Markdown
123 lines
8.0 KiB
Markdown
# Критерии приёмки — ORCH-065
|
||
|
||
Work Item ID: ORCH-065
|
||
Формат: каждый критерий имеет явное условие PASS/FAIL. Все критерии должны быть
|
||
PASS для прохождения review/testing.
|
||
|
||
## A. Job-reaper (Проблема A)
|
||
|
||
### AC-1 — реап мёртвого running-job без рестарта
|
||
- PASS: при наличии строки `jobs` в статусе `running`, чей процесс/исполнитель
|
||
достоверно мёртв (pid не существует ИЛИ `agent_runs.exit_code` записан, а job всё
|
||
ещё `running`) и условие устойчивости (FR-1.3) выполнено, фоновый reaper переводит
|
||
строку в корректный статус (`done`/`queued`/`failed`) **без перезапуска процесса**.
|
||
- FAIL: строка остаётся `running` после `reaper_dead_ticks` тиков / превышения
|
||
`reaper_max_running_s`.
|
||
|
||
### AC-2 — разблокировка очереди при concurrency=1
|
||
- PASS: после реапа зомби-строки `count_running_jobs()` снижается, и следующий
|
||
queued-job успешно claim'ится воркером.
|
||
- FAIL: очередь остаётся заблокированной зомби-строкой.
|
||
|
||
### AC-3 — анти-ложноположительность (живой долгий агент не реапится)
|
||
- PASS: `running`-job с ЖИВЫМ процессом в пределах его `agent_timeout` НЕ помечается
|
||
зомби (ни по одному тику, ни в пределах `reaper_max_running_s`, если потолок
|
||
больше таймаута).
|
||
- FAIL: живой агент помечен `failed`/`queued` reaper'ом.
|
||
|
||
### AC-4 — корректный исход по результату
|
||
- PASS: при `agent_runs.exit_code == 0` reaper доводит до успешного завершения без
|
||
дублирования уже выполненного stage-advance (идемпотентно); при неуспехе и
|
||
`attempts < max_attempts` → `queued`; при исчерпании → `failed` + Telegram.
|
||
- FAIL: успешный исход помечен `failed`; либо дублируется stage-переход; либо
|
||
исчерпанный бюджет молча зацикливается на `queued`.
|
||
|
||
### AC-5 — restart-safe совместимость
|
||
- PASS: одновременная работа стартового `requeue_running_jobs()` и периодического
|
||
reaper не приводит к двойной обработке одной строки (атомарный UPDATE с guard
|
||
`status='running'`).
|
||
- FAIL: одна строка обработана дважды / гонка приводит к рассинхрону статуса.
|
||
|
||
## B. Stale/dead merge-lease reclaim (Проблема B)
|
||
|
||
### AC-6 — реклейм lease мёртвого держателя
|
||
- PASS: lease `.merge-lease-<repo>.json`, чей `pid` не существует, проактивно
|
||
освобождается на старте И периодическим потоком (не дожидаясь TTL и не дожидаясь
|
||
чужого `acquire`).
|
||
- FAIL: lease мёртвого держателя остаётся до истечения `merge_lock_timeout_s` или
|
||
до следующего чужого `acquire`.
|
||
|
||
### AC-7 — реклейм по TTL сохранён
|
||
- PASS: lease старше `merge_lock_timeout_s` освобождается (существующий контракт не
|
||
сломан), с `logger.warning`.
|
||
- FAIL: просроченный lease не освобождается.
|
||
|
||
### AC-8 — не трогать живой lease
|
||
- PASS: lease с ЖИВЫМ держателем (pid жив) и возрастом `< merge_lock_timeout_s` НЕ
|
||
освобождается (защита легитимного merge).
|
||
- FAIL: освобождён lease живого держателя → возможен параллельный конфликтный merge.
|
||
|
||
### AC-9 — условность и never-raise
|
||
- PASS: реклейм реален только для `merge_gate_repos`/self-hosting; для прочих репо
|
||
— no-op; любая ошибка реклейма логируется и не валит поток (never-raise).
|
||
- FAIL: реклейм выполняется для не-self-hosting репо; либо ошибка пробрасывается
|
||
наружу/роняет поток.
|
||
|
||
## C. Идемпотентная финализация merge (Проблема C)
|
||
|
||
### AC-10 — докатывание незавершённого merge
|
||
- PASS: сценарий «rebase+re-test зелёные, merge не состоялся, процесс умер»
|
||
восстанавливается автоматически (job → `queued` reaper'ом / reconciler доигрывает),
|
||
и merge доводится без повторного ненужного прогона дорогих шагов.
|
||
- FAIL: задача остаётся в полу-выполненном состоянии, требует ручного merge.
|
||
|
||
### AC-11 — идемпотентность при уже слитом PR
|
||
- PASS: повторный вызов финализации при уже слитом PR — no-op (определяется по
|
||
состоянию PR/`main`), без ошибки и без второго merge.
|
||
- FAIL: второй merge / ошибка при уже слитом PR.
|
||
|
||
## D. Инварианты и безопасность self-hosting
|
||
|
||
### AC-12 — прод-контейнер не трогается
|
||
- PASS: ни reaper, ни lease-reclaim не рестартят/не роняют прод-контейнер и не
|
||
инициируют git-push в `main`.
|
||
- FAIL: любая из новых веток кода рестартит self / пушит main.
|
||
|
||
### AC-13 — контракты неизменны
|
||
- PASS: `STAGE_TRANSITIONS`, реестр `QG_CHECKS`, сигнатуры/поведение `check_*`,
|
||
БАГ-8 откат, exit-коды deploy-хука — без изменений; новых QG checks/стадий нет.
|
||
- FAIL: затронут любой из перечисленных контрактов.
|
||
|
||
### AC-14 — kill-switches
|
||
- PASS: `reaper_enabled=false` → reaper не работает (строго прежнее поведение);
|
||
`lease_reclaim_enabled=false` → проактивный реклейм отключён (остаётся лишь
|
||
прежний ленивый TTL-реклейм в `acquire`).
|
||
- FAIL: флаг `false` не отключает соответствующий механизм.
|
||
|
||
## E. Наблюдаемость
|
||
|
||
### AC-15 — блок reaper в /queue
|
||
- PASS: `GET /queue` содержит блок `reaper` (enabled, interval, last_run_ts,
|
||
reaped_total, last_reaped, lease_reclaimed_total).
|
||
- FAIL: блок отсутствует/не обновляется.
|
||
|
||
### AC-16 — логи и алерты
|
||
- PASS: каждый reap и lease-reclaim → `logger.warning` с идентификаторами;
|
||
reap→`failed` и lease-reclaim → Telegram.
|
||
- FAIL: реап/реклейм происходят молча.
|
||
|
||
## F. Документация (gate reviewer)
|
||
|
||
### AC-17 — golden-source обновлён в этом же PR
|
||
- PASS: обновлены `docs/architecture/README.md` (раздел про reaper + lease-reclaim),
|
||
`CHANGELOG.md`, `.env.example` (новые `ORCH_*` флаги); заведён
|
||
`06-adr/ADR-001-*.md`.
|
||
- FAIL: код изменён, документация — нет (reviewer → REQUEST_CHANGES).
|
||
|
||
## G. Тесты
|
||
|
||
### AC-18 — регресс-тесты зелёные
|
||
- PASS: новые unit/integration тесты (см. 04-test-plan.yaml) проходят; существующий
|
||
`pytest tests/ -q` зелёный (нет регресса merge_gate / queue / reconciler).
|
||
- FAIL: любой тест из плана красный или сломан существующий тест.
|