7.9 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-094 | architecture | architect | proposed | 2026-06-09 | claude-opus-4-8 |
adr-0028: Terminal-window-aware гард выставления deploy-фазовых статусов Plane
Сквозной (cross-cutting) ADR. Амендмент к adr-0010
(post-deploy monitor, ORCH-021) и Plane-статусной модели (ORCH-066): вводит инвариант
«deploy-фазовые Plane-статусы — terminal-window-aware» поверх общих сеттеров plane_sync и
переупорядочивает блок next_stage == "done" в advance_stage. Детальное решение задачи —
docs/work-items/ORCH-094/06-adr/ADR-001-terminal-window-aware-deploy-status-guard.md.
Регистрируется как сквозной, т.к. правит общие сеттеры
set_issue_awaiting_deploy/set_issue_deploying/set_issue_monitoring(используются системно) и трогает маркированный блок сORCH-021/ORCH-066(docs/_standards/TRACEABILITY.md).
Статус
Proposed
Контекст
Терминальная (done) задача в Plane не держит Done: непрерывный флапп
Awaiting Deploy ⟷ Monitoring after Deploy (верифицировано живьём на ORCH-061, task 47, done с
07.06 — 273 активности, само не затихает). Установлено по коду/логам/БД прода:
- Три code-писателя deploy-фазовых статусов (
src/stage_engine.py:404/1218/1316) делегируют в тонкие сеттерыsrc/plane_sync.py, которые БД-стадию не читают ⇒ терминал-слепы: любой повторный вызов перезаписываетDoneобратно на промежуточный статус. - Ordering:
update_task_stage("done")(stage_engine.py:369) пишетtasks.stage='done'раньше легитимногоset_issue_monitoring(стр. 404) ⇒ пост-деплой-окно ORCH-021 — by-design индикация поверх уже-doneзадачи. Наивный гард «stage==done → Done» ⇒ регресс легитимного окна. - Актор всех 273 переходов — бот-токен орка (
daf4d3f4-…), не привязан к активной task/job; в БД нет активного post-deploy-monitor для task 47 (окно 15 мин закрыто). Реконсилятор F-1 пропускаетdone/cancelled, F-2 опрашивает только[to_analyse, approved, rejected]⇒ механизма привести застрявшую на deploy-статусе done-задачу кDoneнет.
Решение
Единый terminal-window-aware гард на низком чокпоинте — на входе трёх deploy-фазовых сеттеров
plane_sync. Чистую логику держит новый leaf-модуль src/deploy_status_guard.py (never-raise,
config-gated; образец serial_gate.py/labels.py/cancel.py); сеттеры исполняют вердикт.
- Инвариант легитимности: deploy-фазовый статус легитимен ⇔ задача нетерминальна ИЛИ
(
doneИ активно пост-деплой-окно). Иначе — идемпотентное схождение кDone.decide(work_item_id, target) -> ALLOW | CONVERGE_DONE | SUPPRESS: kill-switch off / чужой issue / не-self репо / нетерминал → ALLOW;cancelled→ SUPPRESS;done+target==monitoring+window_active→ ALLOW;doneиначе → CONVERGE_DONE (set_issue_done, идемпотентно); любое исключение → ALLOW + warning (never-raise). - Новый helper
post_deploy.window_active(repo, wi)=has_marker(ARMED) and not has_marker(DONE)(restart-safe). - Перенос арм-блока (
post_deploy.arm_monitor) перед terminal-sync в блокеnext_stage == "done": на стр. 404ARMEDуже записан ⇒window_active==True⇒ легитимный первыйMonitoringпроходит; re-drive после закрытия окна сходится кDone. - Харднинг монитора: идемпотентный страж
has_marker(...DONE)(ранний return без PATCH/реэнкью)- тик no-op при
cancelledмид-окно; тики привязаны к активному job'у (нет job → нет тика).
- тик no-op при
- Наблюдаемость: каждый вердикт логируется (
work_item/caller/target/db_stage/window_active/вердикт); подавление/схождение — явно. - Флаги (
config.py):deploy_status_guard_enabled=True(ORCH_DEPLOY_STATUS_GUARD_ENABLED, kill-switch → 1:1) +deploy_status_guard_repos=""(ORCH_DEPLOY_STATUS_GUARD_REPOS, пусто → self-hosting only) с локальнымapplies(repo).
Альтернативы
- Гард в caller'ах
stage_engine— отвергнуто: не ловит неизвестный/стейл путь под бот-токеном, размазывает инвариант. - Наивный «stage==done → Done» без предиката окна — отвергнуто: регресс легитимного
Monitoring. - Bypass-флаг на доверенном вызове 404 — отвергнуто в пользу переноса арм-блока (один предикат).
- Активная сходимость в реконсиляторе F-2 — отвергнуто как основной механизм (лишний polling, правка маркированного F-2); гард на сеттере гасит непрерывный флапп.
Последствия
- Терминальная задача стабильно держит
Done; маятник гаснет за один цикл независимо от актора. - Легитимный пост-деплой
Monitoringи рабочий self-deploy-цикл — 1:1 (предикат окна + перенос арм). STAGE_TRANSITIONS/QG_CHECKS/check_*/ machine-verdict ключи / схема БД — не тронуты.main/force-push/прод-контейнер/detached-деплой — не тронуты; не-self репо инертны.- Ограничение: если актор флаппа — внешняя Plane-automation (вне кода орка), гард — буфер на стороне орка; локализация (FR-1) и итог документируются (BR-7).
- Откат:
ORCH_DEPLOY_STATUS_GUARD_ENABLED=false→ поведение 1:1; полный — revert ветки.
Связи
- adr-0010 (ORCH-021 — пост-деплой-окно, sentinel
armed/done, арм-блок) — амендмент: окно становится предикатом легитимностиMonitoring. - ORCH-066 (Plane-статусная модель — слой B индикации;
deploy→doneself ⇒Monitoring) — инвариант сохранён. - adr-0026 (ORCH-090 — терминал
cancelled) — гард не штампует deploy-статус поверхcancelled. - ORCH-068/086 (терминал-скип реконсилятора) — этот ADR распространяет идею терминал-aware на выставление deploy-статусов.
- Детально:
docs/work-items/ORCH-094/06-adr/ADR-001-terminal-window-aware-deploy-status-guard.md.