From 101bd1c512267878316d89929f5e677fb8a65d64 Mon Sep 17 00:00:00 2001 From: Slava Date: Mon, 8 Jun 2026 08:38:30 +0300 Subject: [PATCH] =?UTF-8?q?docs(history):=20lesson=20=E2=80=94=20Confirm?= =?UTF-8?q?=20Deploy=20dead=20trigger=20(ORCH-066=20regression,=20see=20OR?= =?UTF-8?q?CH-070)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...S_2026-06-08_confirm-deploy-deadtrigger.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docs/history/LESSONS_2026-06-08_confirm-deploy-deadtrigger.md diff --git a/docs/history/LESSONS_2026-06-08_confirm-deploy-deadtrigger.md b/docs/history/LESSONS_2026-06-08_confirm-deploy-deadtrigger.md new file mode 100644 index 0000000..2936212 --- /dev/null +++ b/docs/history/LESSONS_2026-06-08_confirm-deploy-deadtrigger.md @@ -0,0 +1,33 @@ +# Lessons Learned — 2026-06-08: статус `Confirm Deploy` не триггерит Phase B (мёртвый триггер) + +## Контекст +ORCH-066 ввела новую статусную модель Plane, включая человекочитаемый статус **`Confirm Deploy`** для прод-деплойного approve-gate (self-deploy Phase B). Орк сам выставляет задачу в `Awaiting Deploy` / `Confirm Deploy` через `set_issue_awaiting_deploy()` и т.п. + +## Инцидент (2026-06-08, первый реальный прод-self-deploy — ORCH-068) +Слава нажал статус **`Confirm Deploy`** в Plane, ожидая запуск прод-деплоя. Орк ответил `no pipeline action` и НИЧЕГО не запустил. Прод-деплой стартовал только после ручного перевода в **`Approved`**. + +## Root cause +Диспетчер статусов `handle_issue_status` (`src/webhooks/plane.py` ~158-166) слушает РОВНО три состояния: +```python +if new_state == proj_states["to_analyse"]: await handle_status_start(...) +elif new_state == proj_states["approved"]: await handle_verdict(..., approved=True) +elif new_state == proj_states["rejected"]: await handle_verdict(..., approved=False) +else: logger.info("... no pipeline action") +``` +Phase B (прод-деплой) триггерится в `_try_advance_stage` (`src/stage_engine.py` ~215-224) при `current_stage == "deploy" and finished_agent is None` — то есть ТОЛЬКО когда пришёл вебхук `Approved`. Статус `Confirm Deploy` в эту тройку НЕ входит → ветка `else` → no-op. + +**ORCH-066 добавила статус как МЕТКУ (запись), но не подключила обратный путь (чтение/триггер).** Классическая дыра: протестировали, что орк правильно СТАВИТ статус, но не протестировали, что нажатие этого статуса человеком РЕАЛЬНО запускает действие. + +## Почему не поймали тестирование/ревью +1. **Не в scope ORCH-068.** ORCH-068 чинит reconciler (BRD §6 N1-N3 явно: не трогать диспетчер статусов / Phase B). Тестер прогнал TC-01..13 — все про reconciler/terminal-статусы. Ревьюер смотрел diff reconciler.py/plane_sync.py. Корректно — это дефект ORCH-066, не 068. +2. **Дыра ORCH-066.** Её тесты, видимо, проверяли запись статусов, а не обратный триггер. +3. **Staging не покрывает прод-путь.** Phase A (staging-деплой) автоматический, ручной `Confirm Deploy` живёт ТОЛЬКО на прод-пути, который на staging не гоняется. Поэтому всплыло лишь на первом реальном прод-деплое. + +## Уроки +1. **Тестировать обратный путь статусов, не только запись.** Для каждого статуса, который человек может нажать, нужен тест «нажатие → ожидаемое pipeline-действие». Запись (орк ставит статус) и чтение (орк реагирует на статус) — два разных контракта. +2. **Прод-only пути (ручной Confirm Deploy) нуждаются в явном тесте/чеклисте.** Staging их не ловит by design. Любой approve-gate, доступный человеку, обязан иметь регресс-тест на триггер. +3. **Новый статус = подключить В ОБЕ стороны.** При добавлении статуса в модель — сразу проверить, что диспетчер `handle_issue_status` его слушает (если он actionable), а не только что орк его выставляет. +4. **UX-консистентность:** статус, названный действием («Confirm Deploy»), обязан выполнять это действие. Иначе оператор жмёт интуитивную кнопку, а система молчит → потеря доверия к автономности. + +## Фикс +Заведена ORCH-070: подключить `Confirm Deploy` (или его actionable-эквивалент) к триггеру Phase B в `handle_issue_status`, + регресс-тест на обратный путь статусов прод-деплоя. Source-of-truth и существующий `Approved`-путь не ломать (обратная совместимость).