feat(deploy): dedicated "Confirm Deploy" status triggers prod deploy

Split the overloaded `Approved` Plane status: it served BOTH as the human BRD
gate on `analysis` AND as the silent Phase B prod-deploy trigger on `deploy`
(ORCH-036), so a routine approve could launch a self-hosting prod restart.

ORCH-059 introduces a dedicated logical status `confirm_deploy` ("Confirm
Deploy") that triggers ONLY Phase B on `deploy`; `Approved` stays purely a
pipeline gate.

- plane_sync: map "Confirm Deploy" -> "confirm_deploy" in _PLANE_NAME_TO_KEY;
  intentionally absent from _DEFAULT_STATES => fail-closed (no UUID -> .get
  yields None, no KeyError, no blind deploy).
- webhooks/plane: handle_issue_updated routes "Confirm Deploy" (fail-closed
  .get) to new handle_confirm_deploy (guarded to stage=="deploy") ->
  _try_advance_stage(confirm_deploy=True).
- stage_engine: advance_stage gains keyword-only confirm_deploy=False; Phase B
  block returns early for deploy+finished_agent is None but only initiates the
  deploy when confirm_deploy=True; a plain Approved is a deterministic no-op
  (returns before check_deploy_status -> no false БАГ-8 rollback).
- Phase A CTA now asks the operator for "Confirm Deploy", not "Approved".

Contracts unchanged: STAGE_TRANSITIONS, QG_CHECKS, check_deploy_status, hook
exit codes, Phases A/C, merge-gate, DB schema. Conditional like ORCH-35/36
(self-hosting only). Docs updated (CLAUDE.md, architecture/README.md, CHANGELOG).

Refs: ORCH-059

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 19:12:41 +00:00
committed by deployer
parent dd07b58165
commit 86fe8dd509
12 changed files with 813 additions and 35 deletions

View File

@@ -128,6 +128,12 @@ _PLANE_NAME_TO_KEY: dict[str, str] = {
"Needs Input": "needs_input",
"In Review": "in_review",
"Blocked": "blocked",
# ORCH-059: dedicated prod-deploy trigger status, distinct from the
# human-gate "Approved". Resolved from the live Plane API for the ORCH
# project; intentionally ABSENT from _DEFAULT_STATES so environments without
# this board status (enduro / API fallback) fail-closed — no UUID, no
# confirm-deploy branch, no KeyError (accessed via .get).
"Confirm Deploy": "confirm_deploy",
}
# Per-project state cache: {project_id: {logical_key: state_uuid}}