--- work_item: ORCH-126 stage: architecture author_agent: architect status: accepted created_at: 2026-06-17 model_used: claude-opus-4-8 track: bug --- # 10 — Технические риски: ORCH-126 — гигиена run-ownership queued-job Work Item: **ORCH-126** · Repo: **orchestrator** · Стадия: architecture > Информационный (гейтом не парсится). Риски реализации сброса `run_id`/`pid` на путях возврата в > `queued` и их митигейшн. На bug-маршруте необязателен, но включён: правка — горячий путь клейма, > затрагивает 4 маркированных инварианта (ORCH-065/113/114/099) на **общей** очереди всех проектов. ## Реестр рисков | ID | Риск | Вер. | Влия. | Митигейшн | |----|------|------|-------|-----------| | TR-1 | **Сброс run-ownership не в той точке** — обнуление `run_id`/`pid` у **активного** `running`-job стёрло бы идентичность живого run'а (reaper/`/metrics` потеряли бы pid живого процесса; зомби-детекция сломалась бы). | Низ. | Выс. | Сброс **строго на переходе В `queued`** (D1) и в `claim` **до** `_spawn` (D2). Активный `running` не трогается. TC-10 (анти-регресс здорового job'а) + TC-04 (атомарный `WHERE status='running'`-guard сохранён). | | TR-2 | **Забытый будущий путь возврата в `queued`** (6-й путь мимо инварианта) воскрешает класс «stale run-ownership». | Сред. | Сред. | Named-инвариант (adr-0052) + D4 startup/reap self-heal (идемпотентно лечит пропуск) + счётчик `impossible_queued` в `GET /queue` + reviewer-норматив «нарушение = ≥P1». | | TR-3 | **Регресс reaper Tier-1** — неверная трактовка `pid IS NULL` как «dead → reap» реапнула бы легитимный старт. | Низ. | Выс. | Правка reaper НЕ требуется: `job_reaper.py:245` реапит лишь `pid is not None and not pid_alive(pid)`, `:257` сбрасывает streak при «no pid». Фикс **восстанавливает** предусловие. Покрыто TC-07. | | TR-4 | **Гонка worker↔reaper↔monitor** на возврате в `queued` (двойная обработка строки). | Низ. | Сред. | Атомарные `status`-guard'ы (`reap_running_job ... WHERE status='running'`, rowcount) сохранены байт-в-байт (FR-1). Restart-safe (TC-04 повторный вызов → rowcount 0). | | TR-5 | **Окно claim→spawn без pid** — job, чей `_spawn` упал до стампа pid и не был реквью́ен, висит `running` с `pid IS NULL` до Tier-3 backstop. | Низ. | Низ. | Штатный путь — немедленный реквью через `_drain_once`+D1 (TC-09). Worst-case ловит Tier-3 `reaper_max_running_s` (без изменений). Поведение не хуже текущего. | | TR-6 | **Ошибка в горячем пути клейма роняет/клинит очередь всех проектов** (NFR-1). | Низ. | Выс. | Сброс — часть существующего `UPDATE` (без нового SELECT/сети, offline NFR-2); D4-диагностика изолирована (never-raise) от клейма. Полный `pytest tests/ -q` зелёный (AC-7). | | TR-7 | **Невозможные строки на проде на момент апгрейда** (job 2286/2303) не санируются. | Низ. | Сред. | D4 авто-санация при первом старте `main.lifespan` (миграция не требуется); идемпотентно, выдерживает повторный рестарт (NFR-5). Покрыто TC-08. | ## Сводный вывод Доминирующий класс — **точечная гигиена данных в горячем пути** при сохранении атомарных guard'ов и 4 маркированных инвариантов. Все риски — низкой вероятности; высокое влияние (TR-1/TR-3/TR-6) полностью снимается тем, что (а) сброс ограничен переходом В `queued`/claim-до-`_spawn`, (б) reaper не правится и его предусловие лишь восстанавливается, (в) изменения — внутри существующих UPDATE без сети. **Эскалация не требуется** (`arch:major-change` — нет; возврат в анализ — нет): схема БД / `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict — байт-в-байт, решение реализуемо без нарушения принципов. Остаточный риск для прод-конвейера (self-hosting) — **низкий**; обязательный регресс-тест (TC-01, red→green) + анти-регресс здорового job'а (TC-10) фиксируют корректность.