4.9 KiB
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) слушает РОВНО три состояния:
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 добавила статус как МЕТКУ (запись), но не подключила обратный путь (чтение/триггер). Классическая дыра: протестировали, что орк правильно СТАВИТ статус, но не протестировали, что нажатие этого статуса человеком РЕАЛЬНО запускает действие.
Почему не поймали тестирование/ревью
- Не в 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.
- Дыра ORCH-066. Её тесты, видимо, проверяли запись статусов, а не обратный триггер.
- Staging не покрывает прод-путь. Phase A (staging-деплой) автоматический, ручной
Confirm Deployживёт ТОЛЬКО на прод-пути, который на staging не гоняется. Поэтому всплыло лишь на первом реальном прод-деплое.
Уроки
- Тестировать обратный путь статусов, не только запись. Для каждого статуса, который человек может нажать, нужен тест «нажатие → ожидаемое pipeline-действие». Запись (орк ставит статус) и чтение (орк реагирует на статус) — два разных контракта.
- Прод-only пути (ручной Confirm Deploy) нуждаются в явном тесте/чеклисте. Staging их не ловит by design. Любой approve-gate, доступный человеку, обязан иметь регресс-тест на триггер.
- Новый статус = подключить В ОБЕ стороны. При добавлении статуса в модель — сразу проверить, что диспетчер
handle_issue_statusего слушает (если он actionable), а не только что орк его выставляет. - UX-консистентность: статус, названный действием («Confirm Deploy»), обязан выполнять это действие. Иначе оператор жмёт интуитивную кнопку, а система молчит → потеря доверия к автономности.
Фикс
Заведена ORCH-070: подключить Confirm Deploy (или его actionable-эквивалент) к триггеру Phase B в handle_issue_status, + регресс-тест на обратный путь статусов прод-деплоя. Source-of-truth и существующий Approved-путь не ломать (обратная совместимость).