8.5 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-114 | architecture | architect | proposed | 2026-06-15 | claude-opus-4-8 |
10 — Технические риски: ORCH-114 — Durable transition-ownership lease + expected-stage CAS
Work Item: ORCH-114 · Repo: orchestrator · Стадия: architecture
Информационный (гейтом не парсится). Риски реализации и митигейшн. Сверено по коду.
Реестр рисков
| ID | Риск | Вер. | Влия. | Митигейшн |
|---|---|---|---|---|
| TR-1 | Дедлок / over-block: «жёсткое» владение заклинивает легитимный путь — reaper не добивает зависший finalizer, задача висит нетерминальной с удержанным lease (клинит serial-gate репо). | Сред. | Выс. | ADR D3/D8: liveness = pid+boot (мёртвый владелец реклеймится немедленно); Tier-3 reaper_max_running_s игнорирует lease и добивает зависшего живого; reaper при реапе force-освобождает lease. release в try/finally. Опц. POST /transition-lease/release. Обязательный тест AC-3 (release на исключении/откате) + AC-5 (bounded reclaim). |
| TR-2 | Lease «течёт» при исключении/откате в advance_stage → задача навсегда заблокирована. |
Сред. | Выс. | release строго в finally вокруг всего side-effectful региона (ADR D5); регресс-тест AC-3 (acquire→raise→release). Бэкстоп: stale-реклейм по pid/boot + Tier-3. |
| TR-3 | Buggy «smart recovery» сам становится источником двойного применения необратимого шага после рестарта. | Сред. | Выс. | ADR D7: НЕ новый recovery-мозг, а композиция requeue_running_jobs + stale-clear + существующие авторитетные факты (SHA-in-main ORCH-071/073, INITIATED ORCH-036, coverage-ratchet CAS). Обязательный restart-recovery регресс (BR-8/AC-6): процесс убит в середине финализации → ровно один исход, без второго merge_pr/ratchet/deploy. |
| TR-4 | Скрытые обходные пути (gitea handle_push/handle_ci_status/handle_pr, plane _rollback_stage:806) пишут стадию мимо advance_stage → CAS-инвариант обходится. |
Выс. | Сред. | ADR D4: 6 обходных update_task_stage переведены на update_task_stage_cas; граница зафиксирована в ADR. Структурный аудит (AC-11): ни одного безусловного update_task_stage на side-effectful/конкурентных путях при флаге on. |
| TR-5 | Гонка consult→acquire: актор A прошёл guard «lease свободен», но B захватил между проверкой и acquire A. | Сред. | Сред. | Двойной слой (ADR D1): даже если оба прошли consult, acquire атомарен (rowcount-guard, один INSERT выигрывает), а проигравший CAS на коммите не пишет стадию и не делает side-effect. Consult — лишь дешёвый front-defer, не источник истины. |
| TR-6 | Multi-process (--workers>1): pid+boot-liveness и SQLite-CAS на одной БД корректны для одного процесса; ввод воркеров потребует верификации (SQLite write-lock contention, boot-id на процесс). |
Низ. | Сред. | Вне объёма (BRD §scope: модель остаётся одно-процессной). Durable-форма (таблица + pid/boot + CAS) спроектирована совместимой; epoch-колонка — документированное форвард-расширение (ADR D2). Зафиксировано как ограничение в adr-0045 «Последствия (−)». |
| TR-7 | Бюджетный конфликт: lease, удерживаемый дольше reaper_max_running_s, нарушает сквозной инвариант ORCH-065/109/110/113. |
Низ. | Выс. | ADR D8: lease без собственного TTL, потолок = Tier-3 reaper_max_running_s (5400); reaper_finalize_grace_s/reaper_max_running_s НЕ меняются; инвариант 5400 > Σ(≈4460)+grace цел. Новых бюджетных констант нет. |
| TR-8 | Регрессия ORCH-113: обобщение finalizer_liveness ломает его контракт/тест или меняет поведение при выключенном ORCH-114. |
Сред. | Сред. | ADR D6: finalizer_liveness.py не правится, остаётся поведением kill-switch-off (reaper → in-memory, Tier-2/deploy-staging); on → durable cross-path. Зелёный существующий тест ORCH-113 + AC-9 (флаг off → байт-в-байт). Сверка маркеров ORCH-113 (TRACEABILITY/ORCH-078). |
| TR-9 | Сбой механизма заклинивает общую очередь всех проектов (enduro + orchestrator), нарушая AC-8 ORCH-088. | Низ. | Выс. | ADR D9: hot-path claim_next_job не трогается (lease консультируется на пути перехода/reaper/reconciler/webhook, не в claim). never-raise; acquire/guard-ошибка → defer (не клин), CAS-ошибка → аборт записи. Регресс AC-10. |
| TR-10 | Ложная stale-реклейм живого владельца (pid переиспользован ОС после рестарта, boot-id совпал случайно). | Низ. | Сред. | owner_boot_id — достаточно энтропийный нонс старта процесса (не предсказуемый), плюс pid-проверка; коллизия (тот же boot-id И тот же pid у нового процесса) практически невозможна. Бэкстоп: CAS на коммите не даст двойной записи даже при ложном реклейме. |
Сводный вывод
Доминирующий класс рисков — корректность владения и восстановления на необратимых рёбрах (TR-1/TR-2/TR-3) и полнота охвата путей (TR-4/TR-5). Все они снимаются архитектурой defense-in-depth (lease на входе + CAS на коммите) и принципом «не строить новый recovery-мозг, опереться на существующие авторитетные факты» (D7) — это сознательно минимизирует площадь нового кода, способного двоить необратимый шаг.
Эскалация arch:major-change: рекомендуется. Изменение вводит новый durable-компонент (leaf
transition_lease + таблица), трогает движок переходов и ≥5 фоновых акторов и помечается сводным сквозным
ADR (adr-0045). Реализующему агенту (developer) обязательны: регресс двойного эффекта (AC-1, red→green),
restart-recovery (AC-6), kill-switch-off байт-в-байт (AC-9), сохранность бюджета (AC-5/NFR-6) и аудит
обходных путей (TR-4/AC-11). Возврата в анализ не требуется — требования полны и реализуемы без нарушения
архитектурных принципов (всё в Docker/одном процессе/SQLite, без новых внешних зависимостей и без рестарта
прода). Остаточный риск для прод-конвейера (self-hosting) при дисциплине тестов — низкий; единственное
осознанное ограничение — multi-process (TR-6), явно вне объёма.