---
type: review
work_item_id: ORCH-065
verdict: APPROVED
version: 3
---

# Review ORCH-065

## Summary

Задача закрывает три связанных класса отказов «процесс/поток умер, а ресурс остался
захваченным навсегда»: zombie jobs (A), залипший merge-lease (B), неидемпотентная
финализация merge (C). Реализация качественная: новый daemon-поток `src/job_reaper.py`
по образцу `reconciler` (never-raise, kill-switch, снимок в `/queue`), трёхуровневая
liveness, атомарный `reap_running_job(... WHERE status='running')`, проактивный реклейм
lease (`pid_alive` + `reclaim_stale_lease`), идемпотентный guard `pr_already_merged`,
колонка `jobs.pid` через идемпотентный `_ensure_column`.

**Все блокеры предыдущих ревью устранены:**
- v1 P0 (guard `pr_already_merged` не подключён к merge-пути) — устранён `aa46e5d`:
  промпт `.openclaw/agents/deployer.md` консультирует `pr_already_merged` ПЕРЕД любым
  (повторным) merge (AC-11 wiring на месте, подтверждено строками 94–105/152).
- v2 P1 (Tier-2 реапит живой финализирующий monitor; side-effects ДО атомарного claim,
  нарушение ADR-001 Р-1) — устранён `3e2eb27` двумя мерами:
  1. **Tier-2 finalization grace** — новая колонка `finished_age_s` в `get_running_jobs`
     (`src/db.py:609`) + настройка `reaper_finalize_grace_s` (дефолт 300с); Tier-2
     реапит только при `finished_age >= grace`, иначе строка не трогается
     (`src/job_reaper.py:197-209`). Живой финализирующий monitor больше не реапится
     (FR-1.3/AC-3).
  2. **claim-before-act** — `_reap_exit0` (`src/job_reaper.py:242-286`) сначала оценивает
     канонический QG read-only (`_gate_is_green` → `_run_qg`, без побочных эффектов),
     затем атомарно claim `done` ПЕРВЫМ, и только победитель claim выполняет
     `_gate_driven_advance`. Проигравший гонку (поздний monitor / стартовый requeue) не
     делает НИКАКИХ побочных эффектов → нет дубль-advance/дубль-enqueue (FR-1.2/AC-4).
- v2 P3 (битая ссылка на adr-0011 в CHANGELOG) — исправлена в `3e2eb27`
  (`adr-0011-job-reaper-lease-reclaim.md`).

Инварианты сохранены (AC-13): ORCH-065-коммиты (`1a2e881`/`aa46e5d`/`3e2eb27`) НЕ касаются
`src/stages.py` и `src/qg/checks.py` — `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/БАГ-8/
exit-коды хука не тронуты; реклейм lease — только удаление файла, без git-операций
(AC-12). Документация (README, internals, ADR-001, глобальный adr-0011, CHANGELOG,
.env.example) обновлена в этом же PR (AC-17). Новые тесты покрывают grace-окно,
lost-claim-no-side-effects, already-advanced-идемпотентность. `pytest tests/ -q` —
**747 passed**.

## Findings

### P0 — Blocker
- нет

### P1 — Must fix
- нет

### P2 — Should fix
- нет

### P3 — Nice to have
- нет

## Документация

Обновлена корректно и в этом же PR (AC-17 PASS): `docs/architecture/README.md`
(раздел про job-reaper + lease-reclaim, таблицы БД и `/queue`),
`docs/architecture/internals.md`, `docs/architecture/adr/adr-0011-job-reaper-lease-reclaim.md`
(+ запись в `adr/README.md`),
`docs/work-items/ORCH-065/06-adr/ADR-001-job-reaper-and-lease-reclaim.md`, `CHANGELOG.md`
(ссылка на adr-0011 исправлена), `.env.example` (флаги `ORCH_REAPER_*` /
`ORCH_REAPER_FINALIZE_GRACE_S` / `ORCH_LEASE_RECLAIM_ENABLED`). ADR-001 Р-1 и реализация
exit0-пути теперь согласованы (claim-before-act).
