architect(ET): auto-commit from architect run_id=519
This commit is contained in:
@@ -585,6 +585,39 @@ sentinel-state, `write_post_deploy_log`.
|
||||
Подробнее: [adr-0010](adr/adr-0010-post-deploy-monitor.md), детально —
|
||||
`docs/work-items/ORCH-021/06-adr/ADR-001-post-deploy-monitor.md`.
|
||||
|
||||
### Terminal-window-aware гард deploy-статусов: done-задача держит Done (ORCH-094 — design)
|
||||
Терминальная (`done`) задача в Plane **не держала `Done`**: непрерывный флапп
|
||||
`Awaiting Deploy ⟷ Monitoring after Deploy` (верифицировано на **ORCH-061**, task 47, done с 07.06 —
|
||||
273 активности, само не затихает). Причина: три code-писателя deploy-фазовых статусов
|
||||
(`stage_engine.py:404/1218/1316`) делегируют в тонкие сеттеры `plane_sync`, которые **БД-стадию не
|
||||
читают** ⇒ терминал-слепы; любой повторный/стейл вызов под бот-токеном орка перезаписывает `Done`
|
||||
обратно. Тонкость: `update_task_stage("done")` (стр. 369) пишет стадию **раньше** легитимного
|
||||
`set_issue_monitoring` (стр. 404) ⇒ пост-деплой-окно ORCH-021 by-design индицируется поверх уже-`done`
|
||||
задачи; наивный гард «stage==done → Done» затёр бы легитимный `Monitoring` (регресс).
|
||||
|
||||
Решение — **единый terminal-window-aware гард на входе трёх deploy-фазовых сеттеров** (новый leaf
|
||||
`src/deploy_status_guard.py`, never-raise, config-gated; образец `serial_gate`/`labels`/`cancel`).
|
||||
- **Инвариант:** deploy-фазовый статус легитимен ⇔ задача **нетерминальна** ИЛИ (`done` И активно
|
||||
пост-деплой-окно). `decide(work_item_id, target) → ALLOW | CONVERGE_DONE | SUPPRESS`: off / чужой
|
||||
issue / не-self репо / нетерминал → ALLOW; `cancelled` → SUPPRESS; `done`+`monitoring`+`window_active`
|
||||
→ ALLOW; `done` иначе → CONVERGE_DONE (`set_issue_done`, идемпотентно); исключение → ALLOW+warning.
|
||||
- **Окно** — новый `post_deploy.window_active(repo,wi)` = `has_marker(ARMED) and not has_marker(DONE)`
|
||||
(restart-safe). **Перенос арм-блока перед terminal-sync** в `advance_stage` блок `next_stage=="done"`
|
||||
⇒ на стр. 404 `ARMED` уже есть ⇒ легитимный первый `Monitoring` проходит; re-drive после закрытия
|
||||
окна сходится к `Done`.
|
||||
- **Харднинг монитора:** страж `has_marker(...DONE)` (ранний return) + тик no-op при `cancelled`
|
||||
мид-окно; тики привязаны к активному job'у (нет job → нет тика, нет статус-PATCH).
|
||||
- **Наблюдаемость:** каждый вердикт логируется (`work_item`/`caller`/`target`/`db_stage`/
|
||||
`window_active`/вердикт); подавление — явно.
|
||||
- **Инварианты:** `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict ключи/схема БД — НЕ тронуты;
|
||||
`main`/force-push/прод-контейнер/detached-деплой — НЕ тронуты; рабочий self-deploy-цикл 1:1; не-self
|
||||
репо инертны. Kill-switch `ORCH_DEPLOY_STATUS_GUARD_ENABLED` (→ 1:1), область
|
||||
`ORCH_DEPLOY_STATUS_GUARD_REPOS` (пусто → self-hosting). Ограничение: внешняя Plane-automation (если
|
||||
таков актор) закрывается буфером сходимости, а не code-фиксом — локализация актора в задаче (BR-7).
|
||||
|
||||
Подробнее: [adr-0028](adr/adr-0028-terminal-window-aware-deploy-status-guard.md), детально —
|
||||
`docs/work-items/ORCH-094/06-adr/ADR-001-terminal-window-aware-deploy-status-guard.md`.
|
||||
|
||||
### Свежесть артефакта BUILD-ONCE: провенанс staging-образа (ORCH-058 — реализовано)
|
||||
BUILD-ONCE retag (ORCH-36) промоутит `SOURCE_IMAGE=orchestrator-orchestrator-staging` в прод
|
||||
**без rebuild**, полагаясь на «staging-образ свеж и провалидирован». Этой гарантии нет:
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
work_item: ORCH-094
|
||||
stage: architecture
|
||||
author_agent: architect
|
||||
status: proposed
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# adr-0028: Terminal-window-aware гард выставления deploy-фазовых статусов Plane
|
||||
|
||||
Сквозной (cross-cutting) ADR. **Амендмент** к [adr-0010](adr-0010-post-deploy-monitor.md)
|
||||
(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"`: на стр. 404 `ARMED` уже записан ⇒ `window_active==True` ⇒ легитимный первый
|
||||
`Monitoring` проходит; re-drive после закрытия окна сходится к `Done`.
|
||||
- **Харднинг монитора:** идемпотентный страж `has_marker(...DONE)` (ранний return без PATCH/реэнкью)
|
||||
+ тик no-op при `cancelled` мид-окно; тики привязаны к активному job'у (нет job → нет тика).
|
||||
- **Наблюдаемость:** каждый вердикт логируется (`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](adr-0010-post-deploy-monitor.md) (ORCH-021 — пост-деплой-окно, sentinel `armed`/`done`,
|
||||
арм-блок) — амендмент: окно становится предикатом легитимности `Monitoring`.
|
||||
- ORCH-066 (Plane-статусная модель — слой B индикации; `deploy→done` self ⇒ `Monitoring`) — инвариант
|
||||
сохранён.
|
||||
- [adr-0026](adr-0026-stop-cancel-task.md) (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`.
|
||||
</content>
|
||||
Reference in New Issue
Block a user