docs(lessons): record ORCH-111 reaper finalization race

This commit is contained in:
orchestrator-deployer
2026-06-15 09:28:36 +03:00
parent b6c9d27e9c
commit 56ee993233

View File

@@ -0,0 +1,49 @@
# Lessons Learned — 2026-06-15: reaper race during deploy-staging finalization (ORCH-111)
## Контекст
ORCH-111 добавляла мониторинг долгоживущих pytest/child-процессов в sidecar-watchdog. Задача прошла полный цикл до `deploy-staging`: review, testing, staging, security и первый merge-gate были зелёными.
## Инцидент
На ребре `deploy-staging → deploy` произошла гонка между штатной финализацией deployer job и job-reaper.
Факты:
- Work item: `ORCH-111`.
- Deployer job: `1914`, run_id `683`.
- Deployer успешно записал `15-staging-log.md` со `staging_status: SUCCESS`.
- После выхода агента `agent_runs.exit_code=0`, но job ещё оставалась `running`, потому что monitor продолжал послеагентную финализацию.
- Финализация `deploy-staging` включает тяжёлые edge-гейты: security, merge-gate, локальный full re-test, coverage/image-freshness.
- Первый merge-gate re-test был зелёным: `rebased onto main, re-test green`.
- После `reaper_finalize_grace_s=300` reaper решил, что monitor умер, и повторно вызвал gate-driven advance для той же job/stage.
- В результате `deploy-staging` edge-гейты запустились повторно: security-gate, merge-gate, rebase, full re-test.
- Повторный re-test стал красным: `3 failed, 1916 passed, 1 warning, 14 errors in 444.79s`.
- Орк откатил задачу `deploy-staging → development` и запустил developer retry.
- Параллельно prod-deploy/finalizer завершился успешно: hook exit `0`, PR #130 был смержен, merge-verify прошёл, задача дошла `deploy → done`.
## Root Cause
Reaper использовал слишком грубый сигнал: `exit_code=0` уже записан, job всё ещё `running` дольше grace-периода. Для обычных стадий это похоже на умерший monitor, но для `deploy-staging` это может быть нормальная долгая финализация.
`deploy-staging` — не короткая стадия. После выхода LLM-agent там ещё выполняются дорогие детерминированные гейты. Поэтому `running + exit_code=0 + age>300s` не доказывает смерть monitor.
## Почему это опасно
Система получила две конкурирующие ветки истины:
- reaper повторно обработал `deploy-staging` и откатил задачу в `development`;
- штатный deploy/finalizer параллельно довёл prod-deploy до `SUCCESS` и задачу до `done`.
Это ломает доверие к автономности: одна часть системы уже успешно внедряет, другая в это же время считает задачу неуспешной.
## Уроки
1. **Reaper не должен повторно запускать тяжёлые edge-гейты без строгого владения состоянием.** `deploy-staging → deploy` содержит дорогие операции: rebase, локальный re-test, coverage, merge-lease.
2. **`exit_code=0` агента ≠ финализация стадии завершена.** Для action-стадий после выхода агента есть отдельная длинная фаза: git/Plane comments/QG/merge/deploy/finalizer.
3. **Grace-период 300s недостаточен как универсальный критерий смерти monitor.** Полный re-test/coverage может занимать больше 5 минут даже в штатном режиме.
4. **Нужна явная модель состояния `finalizing` или эквивалентный lock/idempotency guard.** Reaper должен отличать «monitor умер» от «monitor жив и делает долгие deterministic gates».
5. **Deploy-gates должны быть safely re-drivable.** Повторный запуск не должен создавать второй re-test/rollback, если первый проход уже владеет stage/job или уже дошёл до deploy result.
6. **Успешный prod-deploy и rollback одной задачи не должны сосуществовать.** Это признак рассинхронизации stage ownership.
## Follow-up
- `ORCH-113``BUG: job-reaper must not re-run deploy-staging finalization while original finalizer is alive`.
## Related
- `ORCH-111` — watchdog proc-blocking alert.
- `ORCH-110` — merge-gate local re-test timeout/false rollback.
- `ORCH-112` — cleanup failed/cancelled task artifacts from shared checkout.
- ADR: `docs/architecture/adr/adr-0011-job-reaper-lease-reclaim.md`.