# 02 — ТЗ: устранение петли deploy-staging → development при self-deploy Work Item: **ORCH-061** · Тип: **BUG** · Приоритет: **P0** · Репо: `orchestrator` > Это ТЗ фиксирует **требования и контракты**, которые должна удовлетворить > реализация. Конкретный архитектурный механизм (направление (а), (б) или оба; > где именно разместить логику) выбирает архитектор в ADR (`06-adr/`). > ТЗ намеренно не предписывает дизайн, но задаёт инварианты и границы изменений. --- ## 1. Затронутые модули `src/` и артефакты Прямо относящиеся к дефекту (для контекста; точечный набор правок — за архитектором): | Файл | Роль в дефекте | |------|----------------| | `scripts/staging_check.py` | e2e-suite; C9a (branch) / C9b (analyst job) дают ложный FAIL в sandbox; exit-code управляет вердиктом deployer. | | `src/qg/checks.py` → `check_staging_status`, `_parse_staging_status` | гейт ребра `deploy-staging→deploy`; читает `staging_status:` из `15-staging-log.md`. | | `src/stage_engine.py` → `advance_stage`, `_handle_qg_failure_rollbacks` | откат `deploy-staging→development` при FAILED (ветка `agent=="deployer" and qg=="check_staging_status"`). | | `src/agents/launcher.py` → `_handle_completion`/`_try_advance_stage` | пост-ран git-commit; лог «no changes to commit»; обработка deployer-стадий. | | `src/self_deploy.py` | Phase A/B/C исполняемого self-deploy (контекст продвижения `deploy`). | | `src/config.py` | место для kill-switch/настроек нового поведения (если потребуется). | | `.openclaw/agents/deployer.md` | инструкция deployer о написании вердикта; обновить при смене контракта. | | `docs/operations/STAGING_CHECK.md`, `docs/architecture/README.md`, `CHANGELOG.md` | golden-source документация (обновить в том же PR). | ## 2. Функциональные требования ### FR-1 — Нет петли на корректном self-deploy Для self-hosting `orchestrator`, при корректном состоянии (реальный pipeline в порядке, staging-стенд здоров), задача проходит `deploy-staging → deploy → done` **без отката** `deploy-staging → development` и **без ручного вмешательства**. ### FR-2 — Ложный (инфраструктурный) FAIL не вызывает откат Ложное падение `staging_check` в sandbox, вызванное **исключительно** отсутствием sandbox-настроек (например, C9a/C9b при ненастроенных bot-токенах SANDBOX), не приводит к `staging_status: FAILED` → откату. Должно быть реализовано одним из способов (выбор — ADR): - **(а)** sandbox-инфраструктура приведена в состояние, при котором C9a/C9b проходят честно (10/10); и/или - **(б)** вердикт staging-гейта перестаёт зависеть от заведомо инфраструктурных (не пайплайновых) проверок — например, осознанный allowlist/threshold «известных sandbox-инфра» проверок, отделённый от реальных pipeline-проверок. > Любой механизм по FR-2 **обязан** сохранить FR-4 (реальный провал ловится). ### FR-3 — «no changes» на action-стадии не есть недовыполнение На стадиях деплоя (`deploy-staging`, `deploy`) для self-deploy отсутствие git-изменений (`no changes to commit`) **не** трактуется как недовыполнение и **не** приводит к откату/блокировке. Критерий успеха action-стадии = успешный exit агента/хука + доказанный health/staging-вердикт, а **не** наличие нового коммита. ### FR-4 — Реальный регресс по-прежнему откатывается (страховка цела) - Настоящий провал реальных pipeline-проверок staging → `staging_status: FAILED` → откат `deploy-staging → development` (как сейчас). - Настоящий провал прод-деплоя (`deploy_status: FAILED`, БАГ-8) → откат `deploy → development` (как сейчас). - Ослабления страховки быть не должно: «зелёный по умолчанию» при недоступности проверок запрещён (fail-closed для реальных проверок сохраняется). ### FR-5 — Условность self-hosting сохранена Изменения активны **только** для self-hosting пути (`is_self_hosting_repo` / `self_deploy_applies`). Для прочих репозиториев поведение `check_staging_status` (no-op N/A) и стадии деплоя — **без изменений**. ### FR-6 — Управляемость (kill-switch) Любое новое поведение (толерантность к инфра-FAIL и/или отвязка от git-changes) закрыто отдельным флагом конфигурации (по образцу `merge_gate_enabled`, `image_freshness_enabled`, `self_deploy_enabled`), с безопасным дефолтом и возможностью мгновенно вернуть прежнее поведение без передеплоя кода-логики. ### FR-7 — Наблюдаемость Срабатывание нового поведения (например, «staging_check: проигнорирован инфра-FAIL C9a/C9b» или «action-стадия: no-changes ожидаемо») логируется явной строкой и при необходимости отражается в Plane-комментарии/Telegram, чтобы оператор отличал «реальный зелёный» от «зелёного с допущением». ## 3. Изменения API API эндпоинты (`/health`, `/status`, `/queue`, `/webhook/*`) — **без изменений**. Допускается расширение снапшота `GET /queue` диагностическим полем (опционально, по решению архитектора) — без удаления/переименования существующих ключей. ## 4. Изменения схемы БД **Нет.** Схема (`events`, `tasks`, `agent_runs`, `jobs`) не меняется. Любое restart-safe состояние (если потребуется) — через существующие паттерны (sentinel-файлы / поля `jobs.task_content`), без миграций. ## 5. Контракты, которые НЕЛЬЗЯ менять - `STAGE_TRANSITIONS` (порядок и состав стадий) и `get_previous_stage`. - Состав/семантика `QG_CHECKS` как реестра; frontmatter-контракты `staging_status:` (`15-staging-log.md`) и `deploy_status:` (`14-deploy-log.md`) — читаются ТОЛЬКО из YAML-frontmatter, значения `SUCCESS|FAILED`. - Откатные контракты БАГ-8 (`deploy→development`) и ORCH-35 (`deploy-staging→development`) для **реальных** провалов. - Контракт exit-code хука деплоя (`0/1/2`) и `map_exit_code_to_status`. - Поведение для не-self-hosting репозиториев. ## 6. Требования к новым/изменённым QG checks - Если выбран механизм толерантности (FR-2 вариант б), он реализуется **внутри** существующего пути `check_staging_status` / staging-вердикта (не новая стадия), по образцу условности ORCH-35; контракт «never-raise» сохраняется. - Любая новая проверка/под-чек регистрируется в `QG_CHECKS` и покрывается снапшот-тестом реестра (`tests/test_qg_registry_snapshot.py`). ## 7. Требования к staging_check.py (если затрагивается) - Если выбран механизм классификации проверок (FR-2 вариант б через suite), e2e-проверки, заведомо зависящие от sandbox-инфраструктуры (C9a/C9b и связанные), должны быть **отличимы** (по метке/категории) от реальных pipeline-проверок, чтобы вердикт и/или exit-code мог их учитывать осознанно. Прежний дефолтный режим (`stub`/`full-real`) и существующие проверки A/B сохраняются. - Никакого «всегда 0»: реальный провал реальных проверок обязан давать ненулевой exit-code / FAIL-категорию. ## 8. Требования к pipeline-артефактам - Стадия деплоя по-прежнему производит машинный вердикт-артефакт (`15-staging-log.md` / `14-deploy-log.md`) с корректным frontmatter. - Артефакты, обновляемые по pipeline в этом PR: `docs/architecture/README.md` (раздел про staging-гейт/self-deploy — отметить ORCH-061), `docs/operations/STAGING_CHECK.md` (поведение C9a/C9b и/или sandbox-настройка), `CHANGELOG.md`, при изменении контракта — `.openclaw/agents/deployer.md`. - ADR: `docs/work-items/ORCH-061/06-adr/ADR-001-*.md` (решение по направлению/механизму). ## 9. Нефункциональные требования - **Безопасность self-hosting:** реализация НЕ перезапускает/не роняет прод 8500 в рамках задачи; сборки/recreate — только staging (8501). - **Идемпотентность / restart-safe:** новое поведение переживает рестарт инстанса. - **never-raise:** дефект-исправляющая логика не должна пробрасывать исключения в `advance_stage` (по образцу merge-gate / image-freshness). - **Обратная совместимость:** при выключенном флаге (FR-6) — прежнее поведение 1:1. - **Тестируемость:** «чистая» вердикт-логика выделяется так, чтобы покрываться unit-тестами без live staging/docker. ## 10. Зависимости и связанные задачи - ORCH-35 (условный staging-гейт, ADR-0003), ORCH-36 (исполняемый self-deploy, ADR-0007), ORCH-58 (провенанс staging-образа), ORCH-60 (skip escalated/Blocked). - Блокирует: ORCH-54 (автономное внедрение).