work_item: ORCH-123
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-16
model_used: claude-opus-4-8
title: "Staging-runner execution strategy: docker CLI absent in container must not false-fail deploy-staging"
framework: pytest
scope: >
  Покрывается: исполнение staging-сюиты для self-hosting orchestrator на deploy-staging без
  зависимости от docker CLI внутри прод-контейнера; различение environment/tool-error vs настоящего
  код-фейла; анти-over-tolerance (реальный фейл сюиты по-прежнему откатывает); prod-like preflight;
  сохранность контракта гейта/артефакта/STAGE_TRANSITIONS/схемы БД; self-hosting safety; kill-switch/
  область; never-raise. Вне покрытия: логика самой staging_check.py (не трогается), выбор конкретного
  механизма исполнения (host-side ssh / docker.sock+SDK / CLI в образе / hook-режим — решает архитектор),
  изменения STAGE_TRANSITIONS/QG_CHECKS/схемы БД (их нет).
notes: >
  TC-01 — ОБЯЗАТЕЛЬНЫЙ регресс-тест воспроизведения инцидента ORCH-116/ORCH-115: КРАСНЫЙ до фикса,
  ЗЕЛЁНЫЙ после. Тесты механизм-агностичны: проверяют ТРЕБУЕМЫЙ ИНВАРИАНТ (сюита исполняется;
  environment-дефект не даёт код-фейл-отката; настоящий фейл откатывает), а не конкретную стратегию.
  Окружение «нет docker CLI» моделировать без сети/прода/ssh (монки-патч PATH/spawn-функции
  proc_group, либо изоляция argv staging_runner). Точные имена тест-функций уточнит разработчик после
  выбора механизма архитектором. Полный регресс `pytest tests/ -q` обязан оставаться зелёным (NFR-1).

tests:
  - id: TC-01
    type: integration
    description: "РЕГРЕСС (обязательный, red→green): исполнение staging-сюиты в окружении БЕЗ docker CLI в прод-контейнере. До фикса воспроизводит proc_group spawn-error '[Errno 2] No such file or directory: docker' → tool-error → инфра-DEFER×2 → ложный FAILED-откат на development. После фикса сюита ИСПОЛНЯЕТСЯ (или environment-дефект не даёт код-фейл-отката). Красный до фикса."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-02
    type: unit
    description: "Стратегия исполнения не зависит от docker CLI внутри прод-контейнера: argv/канал, формируемый staging-runner, не требует наличия бинаря `docker` на PATH контейнера (host-side / socket-SDK / CLI-в-образе — в зависимости от выбора ADR; ассерт проверяет инвариант, а не конкретный механизм)."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-03
    type: integration
    description: "environment/tool-error НЕ даёт код-фейл-отката (AC-3): при неработоспособной стратегии (исполняемое отсутствует) задача НЕ переходит deploy-staging → development, developer-retry НЕ инкрементируется, идёт отличимый инфра/environment-алерт ('НЕ дефект кода')."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-04
    type: unit
    description: "Анти-over-tolerance (AC-4): сюита РЕАЛЬНО исполнилась (получен exit-код) и упала (exit≠0) → staging_status: FAILED → ПРЕЖНИЙ откат deploy-staging → development + developer-retry. Настоящий фейл сюиты НЕ маскируется как 'инфра'."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-05
    type: unit
    description: "Happy-path: сюита исполнилась, exit 0 → staging_status: SUCCESS → штатная инициация advance_stage(deploy-staging, deployer) без новых рёбер/исходов (контракт ORCH-115 D7 сохранён)."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-06
    type: unit
    description: "Классификация (по образцу merge_gate.classify_retest_failure): постоянный environment-дефект (spawn-error 'исполняемое не найдено') отличается от транзиентной инфры и от настоящего код-фейла; постоянный дефект НЕ трактуется как транзиент (бессмысленный ретрай) и НЕ как код-фейл."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-07
    type: integration
    description: "Prod-like preflight (AC-5): механизм раннего детекта 'стратегия исполнения неработоспособна (нет исполняемого/канал недоступен)' сигнализирует ДО ложного отката реальной задачи (старт сервиса / smoke / applies / should_intercept — в зависимости от выбора ADR)."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-08
    type: unit
    description: "Self-hosting safety (AC-8): путь исполнения никогда не рестартит прод 8500, не делает docker compose up orchestrator/--build прода, не force-push, не пишет в main, не правит .env (статический/поведенческий ассерт; инвариант ORCH-115 BR-7 сохранён)."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-09
    type: unit
    description: "Kill-switch/область (AC-10): staging_runner_enabled=False → should_intercept False → прежний LLM-deployer через _spawn байт-в-байт; applies(repo): self-hosting orchestrator real, прочие репо — no-op; новый флаг стратегии (если есть) имеет дефолт = боевое."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-10
    type: unit
    description: "Контракт артефакта (AC-7): 15-staging-log.md сохраняет staging_status:-frontmatter (UPPERCASE значение) + 52c-схему (author_agent: staging-runner / model_used: n/a); вердикт читается только из frontmatter через src/frontmatter.py."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-11
    type: unit
    description: "Анти-регресс конвейера (AC-7): STAGE_TRANSITIONS / реестр QG_CHECKS / имена и семантика check_staging_status / _parse_staging_status / machine-verdict ключи (staging_status:/deploy_status:) — не изменены; миграции БД нет (структурная сверка)."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-12
    type: unit
    description: "never-raise / очередь не клинится (AC-11): любая ошибка исполнения/классификации изолирована, worker не падает, задача не залипает на deploy-staging навсегда; снапшот staging_runner в GET /queue различает environment/tool-error vs код-фейл."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-13
    type: unit
    description: "Документация-инвариант (AC-12): docs/operations/INFRA.md и docs/architecture/README.md содержат описание границы исполнения staging-сюиты (host-side vs in-container, доступные исполняемые/сокеты) — структурная сверка наличия раздела."
    module: tests/test_orch123_staging_runner_exec.py
    expected: PASS

  - id: TC-14
    type: unit
    description: "Анти-дрейф ORCH-115: существующие структурные тесты staging-runner (tests/test_orch115_staging_runner.py) и LLM-determinization анти-дрейф остаются ЗЕЛЁНЫМИ после фикса (фикс не ломает инварианты ORCH-115)."
    module: tests/test_orch115_staging_runner.py
    expected: PASS
