# ADR-0007: Исполняемый самодеплой стадии `deploy` (Вариант B, ORCH-36) ## Статус Accepted (design) — реализация в ветке `feature/ORCH-036`. ## Контекст Стадия `deploy` была «бумажной»: deployer-агент писал `deploy_status:` в `14-deploy-log.md`, гейт `check_deploy_status` парсил вердикт и двигал `deploy → done`. Реального деплоя не было. ORCH-36 делает стадию исполняемой для self-hosting (`orchestrator`), сохраняя прежний ssh-путь для остальных репо. Три ограничения формируют дизайн (детально — `docs/work-items/ORCH-036/06-adr/ADR-001`): 1. **Self-restart**: рестарт прод-контейнера 8500 убивает in-container процесс → рестарт делает ВНЕШНИЙ host-процесс. 2. **Status-only verdict model**: approve = смена статуса Plane на `Approved` (комментарии не управляют конвейером). 3. **Гонка гейта**: вердикт нельзя читать до завершения асинхронного хука. ## Решение Для self-hosting стадия `deploy` исполняется в три фазы детерминированным кодом (без LLM в критическом пути self-restart): - **Фаза A (вход в `deploy`)** — для self + `deploy_require_manual_approve=true` вместо запуска прод-deployer выставляется approval-pending статус Plane + запрос approve (Plane-коммент + Telegram). Перехват в `advance_stage` на ребре `deploy-staging → deploy` (после `check_staging_status` и merge-gate). - **Фаза B (Plane → Approved)** — `advance_stage(deploy, finished_agent=None)` запускает **detached host-процесс** (ssh + setsid → `orchestrator-deploy-hook.sh` с прод-параметрами и build-once retag) и ставит **детерминированный finalizer-job** с задержкой; маркер `initiated` — идемпотентность. Возврат БЕЗ advance. - **Фаза C (finalizer)** — после рестарта новый контейнер дочитывает sentinel `result` (exit-code хука), маппит `0→SUCCESS / иначе→FAILED`, пишет `14-deploy-log.md`, вызывает `advance_stage(deploy, finished_agent="deployer")` → существующие контракты: `SUCCESS → done`, `FAILED → откат БАГ-8 на development`. ### Ключевые инварианты (НЕ меняются) `STAGE_TRANSITIONS`, реестр QG, `check_deploy_status` / `_parse_deploy_status` (frontmatter only), откат БАГ-8, terminal-sync `deploy → done`, merge-gate (ORCH-43), exit-code-контракт хука (0/1/2). ### Новое (сквозное) - **Детерминированный job-kind** `deploy-finalizer` в очереди (reserved-agent, не LLM): read-result | defer | map+write+advance. Зеркалит детерминизм merge-gate. - **Approve-флаг** `deploy_require_manual_approve` (дефолт `true`; полный авто — отдельная задача после набора метрик доверия, ORCH-54). - **Build-once**: опциональный `SOURCE_IMAGE` retag в хуке (обратно совместимо). - **Restart-safe состояние** деплоя — sentinel-файлы под `/.deploy-state-//` (как merge-lease), БЕЗ миграции БД. ### Условность Вся логика — только для `is_self_hosting_repo(repo)` (как ORCH-35). Прочие репо деплоятся прежним синхронным ssh-путём агентом. ## Последствия - `deploy_status: SUCCESS` доказан реальным health-ok; критический путь self-restart детерминирован. - Вводится новая под-компонента (finalizer job-handler) → изменение помечено `arch:major-change`. - Approve вписан в status-only модель: restart-safe, аудируемо, идемпотентно. - На старте — обязательный ручной approve; молчаливых деплоев нет (Plane+Telegram). ## Связанные ADR `adr-0003` (staging-gate), `adr-0006` (merge-gate), `adr-0005` (run-as-host-uid). Детальный per-work-item: `docs/work-items/ORCH-036/06-adr/ADR-001-executable-self-deploy.md`.