15 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-094 | analysis | analyst | ready-for-review | 2026-06-09 | claude-opus-4-8 |
01 — BRD (бизнес-требования): ORCH-094 — терминальная (done) задача флаппит deploy-статусы в Plane (Awaiting↔Monitoring), не держит Done
Work Item: ORCH-094 · Repo: orchestrator · Стадия: analysis
1. Бизнес-контекст и проблема
Тип: BUG — рассинхрон БД↔Plane / «зомби»-цикл post-deploy-статуса (self-hosting).
Симптом (верифицирован живьём 09.06 на ORCH-061):
Задача ORCH-061 в БД оркестратора = done с 07.06 (task 47; фикс задеплоен в прод; конвейер её
не трогает — 0 активных job'ов). При этом карточка задачи в Plane не держит Done: непрерывно
флаппит Monitoring after Deploy ⟷ Awaiting Deploy парами (туда-обратно за ~2 сек), каждые
несколько минут. Накоплено 273 активности. Доходило до абсурда: 09.06 14:56 встала в Done →
15:48 её выдернуло обратно Done → Awaiting Deploy. Воспроизводится детерминированно: ручной
sync 061→Done (PATCH 200, 16:47) → через ~60 сек снова Done → Awaiting Deploy → Monitoring
(16:48). Само не затихает.
Установленные факты (по логам/БД прода + чтение кода ветки):
- Сам оркестратор не инициирует переходы из своих штатных стадийных обработчиков для done-задачи.
В момент флаппа лог орка показывает только входящие webhook-и Plane
(
issue … updated to state … (Awaiting Deploy) → no pipeline action, затем(Monitoring) → no pipeline action). Обработчикwebhooks/plane.py::handle_issue_updatedдля статусов Awaiting/Monitoring логирует «no pipeline action» и сам статус не переотправляет (echo-loop обработчика исключён). - Actor всех 273 переходов =
daf4d3f4-55df-4016-9095-0cf9ddd8fd28— бот-актор оркестратора (тот же токен, под которым орк делает гигиену доски / sync). То есть PATCH-и шлёт что-то под токеном орка, не привязанное к активной task/job в БД. - В БД орка нет активного post-deploy-monitor для task 47 (pdm активен только у текущей
063/task 74).
orchestrator-staging(8501) — не источник (task 061 в его БД отсутствует). - В коде ветки единственные три писателя deploy-статусов —
src/stage_engine.py:set_issue_monitoring(строка 404, на переходеdeploy → doneдля self-hosting),set_issue_awaiting_deploy(строка 1218, Phase A),set_issue_deploying(строка 1316, Phase B). Все три — внутри стадийных обработчиков (advance_stage/_handle_self_deploy_phase_*), ни один не сидит в фоновом цикле, независимом от таблицыjobs. notifications.py::_live_plane_branch_overrideтолько читает живой Plane-статус (для рендера карточки) — писателем не является.- Реконсилятор: F-1 пропускает задачи со
stage in ('done','cancelled')(terminal-skip ORCH-086); F-2 опрашивает issue только в статусах[to_analyse, approved, rejected]— статусыMonitoring/Awaitingон не перебирает. Механизма «привести done-задачу, застрявшую на deploy-статусе, обратно к Done» (идемпотентного схождения) — нет.
Боль: карточка вводит наблюдателя в заблуждение («задача деплоится», хотя она в проде и done), шумит активностью (273 события на одной задаче), вечно жжёт API-вызовы Plane флаппом и маскирует реальное состояние доски. Конвейер технически не нарушен (задача в проде), поэтому приоритет MEDIUM, но дефект бессрочный и самовоспроизводящийся.
Родственные задачи: ORCH-091 (врущие/застывшие статусы карточки), ORCH-068/086 (терминал-скип как защита инвариантов). ORCH-094 распространяет идею терминал-скипа на deploy-статусы и закрывает источник флаппа.
2. Объём (scope)
В объёме
- G1 — устранить источник PATCH-ей deploy-статуса на задачу, у которой в БД
stage=doneи нет активного job'а. Терминальная (done) задача в Plane должна стабильно держатьDoneи не получатьAwaiting/Monitoring. - G2 — идемпотентность sync/setter'ов: если БД=
done, любой sync/монитор/реконсилятор/прямой вызов приводит Plane кDone(не к промежуточному deploy-статусу) — терминал-скип/схождение, распространённые на статусыMonitoring/Awaiting(как ORCH-068/086 для других статусов). - G3 — детерминированный конец post-deploy-monitor: монитор завершается чётко (HEALTHY / N тиков → Done) и не оставляет «зомби»-таймеров, переживающих завершение задачи/рестарт; тики монитора привязаны к активному job'у в БД (нет job → нет тиков, нет статус-PATCH).
- G4 — наблюдаемость: лог однозначно показывает, кто и почему ставит deploy-статус (caller/функция + причина), для будущей диагностики таких флаппов.
- Инструментальная локализация фактического актора флаппа на проде (воспроизведение на 061) и его документирование (что это было) — в рамках выполнения задачи (developer/architect).
Вне объёма
- Изменение конвейера стадий (
STAGE_TRANSITIONS), составаQG_CHECKS, семантики machine-verdict ключей (deploy_status:/staging_status:/…) — не трогать. - Изменение рабочего deploy-цикла для реально деплоящейся задачи (Phase A→B→C, post-deploy HEALTHY-окно) — поведение должно сохраниться 1:1 (регресс, AC-4).
- Поведение для не-self-hosting репозиториев (enduro-trails) — нулевая регрессия.
- Архитектурное решение «где именно поставить гард» (на уровне setter'а в
plane_syncvs на уровне вызывающего вstage_enginevs реконсилятор) — определяет архитектор в06-adr/.
3. Заинтересованные стороны
- Заказчик/репортёр: Слава (владелец) — обнаружил на ORCH-061 09.06.
- Затрагивает: всех наблюдателей доски Plane проекта ORCH (ложная индикация); лимиты Plane API (вечный флапп жжёт вызовы под общим бот-токеном).
- Принимает результат: Owner / CI на финальной стадии конвейера.
- Особый риск: self-hosting — правка идёт в инструмент, обслуживающий прод всех проектов из общего инстанса; рабочий deploy-цикл нельзя сломать.
4. Бизнес-требования (BR)
- BR-1 — Терминальная задача (БД
stage=done, 0 активных job'ов), выставленная в Plane=Done, остаётсяDoneи не получает авто-переходов вAwaiting Deploy/Monitoring after Deploy. - BR-2 — Любой источник синхронизации (реконсилятор, монитор, прямой вызов setter'а deploy-статуса)
для задачи с БД=
doneприводит Plane кDoneидемпотентно, а не к промежуточному deploy-статусу; повторные срабатывания не качают маятник. - BR-3 — Post-deploy-monitor имеет детерминированный конец (HEALTHY / исчерпание N тиков → Done, или DEGRADED → Blocked+freeze) и после завершения не производит ни одного последующего статус-PATCH для этой задачи; не оставляет таймера/состояния, переживающего завершение или рестарт.
- BR-4 — Тики post-deploy-monitor привязаны к активному job'у в таблице
jobs: нет активного job'а для задачи → нет тиков → нет статус-PATCH. «Зомби»-монитор (тики без соответствующего активного job'а) исключён. - BR-5 — Для реально деплоящейся задачи (063-подобной) deploy-окно
Awaiting → Deploying → Monitoring → Doneработает в точности как раньше (нет регресса). - BR-6 — Каждый вызов, выставляющий deploy-статус, оставляет в логе однозначную запись кто (функция/путь) и почему ставит статус (наблюдаемость для будущей диагностики флаппов).
- BR-7 — Фактический источник флаппа на проде локализован и задокументирован (что это было)
в
06-adr/и/илиCHANGELOG.md.
5. Нефункциональные требования (NFR)
- NFR-1 — never-raise: вся новая логика (гарды/терминал-скип/идемпотентность) не бросает исключений в горячих путях; сетевая ошибка Plane при сверке статуса → безопасная деградация (не флаппить и не падать), а не блокировка конвейера всех проектов.
- NFR-2 — self-hosting безопасность: не перезапускать/не ронять прод-контейнер; не трогать
main/force-push/прод-деплой; правка не меняет рабочий критический путь self-deploy. - NFR-3 — обратимость: поведение под kill-switch (или иным обратимым флагом) — при выключении возврат к прежнему поведению; нулевая регрессия для не-self репозиториев.
- NFR-4 — restart-safe: состояние монитора/гардов корректно после рестарта контейнера (нет «воскрешения» тиков для уже завершённой задачи).
- NFR-5 —
pytest tests/ -qзелёный;STAGE_TRANSITIONS/QG_CHECKS/ machine-verdict ключи / схема БД (если без миграции) — без изменений или строго аддитивно.
6. Допущения и ограничения
- Допущение: статусы
Monitoring after Deploy/Awaiting Deployсуществуют в Plane-проекте ORCH как реальные статусы (иначе alias-fallback маппит их на базовые UUID — это часть диагностики терминал-детекта). - Допущение: бот-токен орка (
daf4d3f4-…) — единственный актор переходов; внешняя Plane-automation под другим токеном считается отдельной гипотезой и проверяется при локализации (H-внешнее). - Ограничение: установленные факты выше не изобретать — они верифицированы на проде; точный актор флаппа требует инструментального воспроизведения (фикс — после локализации).
- Ограничение: правка строго в зоне self-hosting deploy/post-deploy/sync; конвейер и гейты неизменны.
7. Критерии успеха
Терминальная задача стабильно держит Done ≥10 мин без авто-переходов (AC-1); любой sync для done
идемпотентно сходится к Done (AC-2); post-deploy-monitor завершается детерминированно и не
оставляет тиков/таймеров (AC-3); рабочий deploy-цикл 063-подобной задачи не регрессирует (AC-4);
never-raise + зелёный pytest + источник флаппа задокументирован (AC-5). Детальные PASS/FAIL — в
03-acceptance-criteria.md.
8. Риски
- Гард терминал-скипа поставлен слишком широко → подавит легитимный
Monitoringу реально деплоящейся задачи (регресс AC-4). Митигировать тонкой привязкой к БДstage=done+ активность job. - Фактический актор флаппа окажется внешней Plane-automation (вне кода орка) → код-фикс не закроет G1 полностью; нужно зафиксировать в ADR и, при необходимости, защититься идемпотентным схождением к Done (BR-2) как буфером.
- Детали —
10-tech-risks.md(заполняет архитектор).