ORCH-053: sweeper потерянных webhook (реконсиляция застрявших стадий) #56

Merged
admin merged 7 commits from feature/ORCH-053-sweeper-webhook-stuck-task into main 2026-06-07 00:20:54 +03:00
Owner

Summary

Фоновый daemon-поток src/reconciler.py устраняет тихое застревание задач, когда конвейер не двигается из-за потерянного webhook (502 на ребилде, нет ретраев у Plane/Gitea, неразрезолвленный sha→branch — класс инцидента ORCH-044). Реконсилятор доигрывает пропущенный переход через те же штатные гейты/обработчики, что и webhook, не дублируя логику.

  • F-1 gate-side: для stage≠done, без активного job, age(updated_at) ≥ grace — read-only пред-оценка QG; зелёный → advance_stage(..., finished_agent=None); красный → тишина. analysis F-1 не трогает (человеческий гейт).
  • F-2 plane-side: опрос Plane API per-project (list_issues_by_state) → реплей In Progress/Approved/Rejected через handle_status_start/handle_verdict.
  • F-3: БД-fallback sha→branch в handle_ci_status (единственная development-задача repo; неоднозначность → не резолвим).
  • Анти-дубль (AC-4): create_task_atomic под process-wide Lock.
  • F-4: лог разблокировки + Telegram + блок reconcile в GET /queue.

Старт/стоп в main.lifespan (после worker.start() / перед worker.stop()), restart-safe, never-raise. Kill-switches ORCH_RECONCILE_ENABLED / ORCH_RECONCILE_PLANE_ENABLED. Схема БД и реестры STAGE_TRANSITIONS/QG_CHECKS не менялись.

Документация (golden source)

docs/architecture/README.md, docs/operations/INFRA.md (kill-switch), README.md / .env.example, CHANGELOG.md, adr-0007 → accepted.

Test plan

  • test_reconciler.py (F-1, observability, restart)
  • test_reconciler_plane.py (F-2, анти-дубль)
  • test_gitea_sha_resolve.py (F-3)
  • test_config.py (reconcile_* defaults + env)
  • Полный прогон: 563 passed

Refs: ORCH-053

## Summary Фоновый daemon-поток `src/reconciler.py` устраняет тихое застревание задач, когда конвейер не двигается из-за потерянного webhook (502 на ребилде, нет ретраев у Plane/Gitea, неразрезолвленный `sha→branch` — класс инцидента ORCH-044). Реконсилятор доигрывает пропущенный переход **через те же штатные гейты/обработчики**, что и webhook, не дублируя логику. - **F-1 gate-side:** для `stage≠done`, без активного job, `age(updated_at) ≥ grace` — read-only пред-оценка QG; зелёный → `advance_stage(..., finished_agent=None)`; красный → тишина. `analysis` F-1 не трогает (человеческий гейт). - **F-2 plane-side:** опрос Plane API per-project (`list_issues_by_state`) → реплей In Progress/Approved/Rejected через `handle_status_start`/`handle_verdict`. - **F-3:** БД-fallback `sha→branch` в `handle_ci_status` (единственная development-задача repo; неоднозначность → не резолвим). - **Анти-дубль (AC-4):** `create_task_atomic` под process-wide `Lock`. - **F-4:** лог разблокировки + Telegram + блок `reconcile` в `GET /queue`. Старт/стоп в `main.lifespan` (после `worker.start()` / перед `worker.stop()`), restart-safe, never-raise. Kill-switches `ORCH_RECONCILE_ENABLED` / `ORCH_RECONCILE_PLANE_ENABLED`. Схема БД и реестры `STAGE_TRANSITIONS`/`QG_CHECKS` не менялись. ## Документация (golden source) `docs/architecture/README.md`, `docs/operations/INFRA.md` (kill-switch), `README.md` / `.env.example`, `CHANGELOG.md`, adr-0007 → accepted. ## Test plan - [x] test_reconciler.py (F-1, observability, restart) - [x] test_reconciler_plane.py (F-2, анти-дубль) - [x] test_gitea_sha_resolve.py (F-3) - [x] test_config.py (reconcile_* defaults + env) - [x] Полный прогон: 563 passed Refs: ORCH-053
admin added 6 commits 2026-06-06 23:55:26 +03:00
Конвейер продвигается только входящими webhook; потерянное событие (502 на
ребилде, отсутствие ретраев у Plane/Gitea, неразрезолвленный sha→branch)
оставляет задачу молча застрявшей (класс инцидента ORCH-044). Новый фоновый
daemon-поток src/reconciler.py (паттерн queue_worker) доигрывает пропущенный
переход через те же штатные гейты/обработчики, что и webhook:

- F-1 gate-side: для задач stage≠done, без активного job и age(updated_at) ≥
  grace_for_stage(stage) — read-only пред-оценка канонического QG; зелёный →
  stage_engine.advance_stage(..., finished_agent=None); красный → тишина (спам
  нотификаций структурно невозможен). analysis F-1 не трогает (человеческий гейт).
- F-2 plane-side: опрос Plane API per-project (plane_sync.list_issues_by_state,
  курсорная пагинация, never-raise) → реплей In Progress/Approved/Rejected через
  существующие handle_status_start/handle_verdict (async из sync-потока, asyncio.run).
- F-3: усиление sha→branch в handle_ci_status — БД-fallback по единственной
  development-задаче repo (неоднозначность → не резолвим), debug→info.
- Анти-дубль на создании (db.create_task_atomic под process-wide Lock): гонка
  reconcile↔webhook не плодит второй task/branch/worktree/analyst-job (AC-4).
- F-4 observability: лог-строка разблокировки + Telegram + блок reconcile в /queue.

Старт/стоп в main.lifespan (после worker.start() / перед worker.stop()),
restart-safe, never-raise на единицу работы. Kill-switches ORCH_RECONCILE_ENABLED
/ ORCH_RECONCILE_PLANE_ENABLED + grace-настройки. Схема БД и реестры
STAGE_TRANSITIONS/QG_CHECKS не менялись.

Тесты: test_reconciler.py, test_reconciler_plane.py, test_gitea_sha_resolve.py,
test_config.py (33 новых, 563 всего зелёные). Документация обновлена (golden source):
architecture/README.md, INFRA.md, README.md, CHANGELOG.md, adr-0007 → accepted.

Refs: ORCH-053

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tester(ET): auto-commit from tester run_id=200
All checks were successful
CI / test (push) Successful in 15s
CI / test (pull_request) Successful in 16s
5089f99bb1
admin force-pushed feature/ORCH-053-sweeper-webhook-stuck-task from f08fcc4bc1 to 5089f99bb1 2026-06-06 23:55:26 +03:00 Compare
admin added 1 commit 2026-06-07 00:04:41 +03:00
deployer(ET): auto-commit from deployer run_id=204
All checks were successful
CI / test (push) Successful in 16s
CI / test (pull_request) Successful in 15s
c1196e34e8
admin merged commit e2dc9d6df6 into main 2026-06-07 00:20:54 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/orchestrator#56