Files
orchestrator/docs/work-items/ORCH-123/02-trz.md
claude-bot 3865b14a1c
All checks were successful
CI / test (push) Successful in 1m12s
analyst(ET): auto-commit from analyst run_id=747
2026-06-16 07:55:43 +03:00

15 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-123 analysis analyst ready-for-review 2026-06-16 claude-opus-4-8

02 — ТЗ (TRZ): ORCH-123 — staging-runner execution strategy must not depend on Docker CLI inside the app container

Work Item: ORCH-123 · Repo: orchestrator · Стадия: analysis

ТЗ описывает требования и ограничения к реализации, выведенные из BRD и фактического кода. Архитектурное решение (какую стратегию исполнения выбрать: host-side ssh / Docker SDK поверх сокета / docker CLI в образе / выделенный hook-режим, + security-review) — задача архитектора (06-adr/), т.к. задача эскалирована в full-cycle (01-brd.mdescalate: full-cycle).

1. Сводка изменения

Восстановить работоспособную стратегию исполнения staging-сюиты для self-hosting orchestrator на стадии deploy-staging, не завися от docker CLI, отсутствующего внутри прод-контейнера (Dockerfile:11 ставит openssh-client git curl ca-certificates, не docker; docker.sock смонтирован — docker-compose.yml:40 — но клиента нет). Сегодня staging_runner.build_staging_command (src/staging_runner.py:154) формирует ["docker","exec","orchestrator-staging",…] и запускает её изнутри прод-контейнера через proc_groupPopen падает FileNotFoundError → ветка tool-error → инфра-DEFER×2 → fail-closed FAILED → откат deploy-staging → development. Требуется: (а) исполнять сюиту так, чтобы она реально запускалась в проде (паттерн host-side, уже применённый прод-деплоем ORCH-036 / --build-staging); (б) различать постоянный environment/tool-error от настоящего код-фейла и не делать вводящего в заблуждение код-фейл-отката; (в) prod-like preflight + регресс; (г) документировать границу исполнения.

2. Задействованные модули / пути

Путь Действие Примечание
src/staging_runner.py изменить build_staging_command/run_staging_suite — точка, где сюита запускается «изнутри контейнера» (корень дефекта, FR-1); классификация tool-error vs environment-дефект в run_staging_gate/_handle_tool_error (FR-2)
src/self_deploy.py возможно переиспользовать build_deploy_command/initiate_deploy — рабочий host-side ssh+setsid механизм (ORCH-036); кандидат на общий ssh-хелпер исполнения host-side команды (решает архитектор)
scripts/orchestrator-deploy-hook.sh возможно изменить --build-staging уже делает host-side docker exec "$STAGING_CONTAINER" python3 staging_check.py (строки 197/261) — прецедент/возможная точка выделенного staging-режима
Dockerfile возможно изменить строка 11 — если выбран вариант «docker CLI в образе» (тогда + security-обоснование)
docker-compose.yml возможно изменить строка 40 — docker.sock уже смонтирован; если выбран socket/SDK-вариант, зафиксировать права (:ro где возможно)
src/proc_group.py возможно изменить run_in_process_group уже корректно деградирует spawn-error в ProcResult(returncode=None) — кандидат на preflight «исполняемое существует» (FR-4)
src/config.py возможно изменить существующие staging_runner_*; при необходимости — флаг выбора/режима стратегии (FR-5), дефолт = боевое
docs/operations/INFRA.md изменить граница исполнения staging-сюиты относительно прод-контейнера (FR-6 / BR-5)
docs/architecture/README.md изменить описать стратегию исполнения staging-runner (FR-6 / BR-5)
CHANGELOG.md, CLAUDE.md изменить docs = golden source (CLAUDE.md §2); раздел ORCH-115 дополнить фиксом исполнения
tests/test_orch115_staging_runner.py / tests/test_orch123_staging_runner_exec.py создать/расширить регресс «docker CLI отсутствует» + классификация + preflight (04-test-plan.yaml)

3. Функциональные требования

FR-1 — Работоспособная стратегия исполнения staging-сюиты в проде (BR-1)

  • На стадии deploy-staging для self-hosting orchestrator staging-сюита (staging_check.py внутри orchestrator-staging) должна реально исполняться в боевом окружении, не завися от наличия бинаря docker внутри прод-контейнера orchestrator.
  • Стратегия исполнения — выбор архитектора (ADR), из перечня BRD §2: host-side через существующий ssh+setsid механизм (ORCH-036, deploy_ssh_host=127.0.0.1, ssh-ключ смонтирован, openssh-client в образе) либо Docker SDK/docker.sock (уже смонтирован, + security-review) либо docker CLI в образе либо выделенный режим хука. ТЗ не прескриптивно — фиксирует лишь требуемый инвариант «сюита исполняется».
  • Команда/контракт сюиты (python3 staging_check.py --base-url http://localhost:<staging_port> --mode stub, host-specifics из config — ORCH-101) сохраняются; меняется инициатор/канал запуска, не сама сюита.

FR-2 — Environment/tool-error ≠ код-фейл (BR-2, BR-3)

  • Невозможность исполнить сюиту по причине окружения (нет исполняемого docker/SDK недоступен/ стратегия неработоспособна) не должна завершаться откатом deploy-staging → development как кодовой ошибкой и не должна инкрементировать developer-retry. Текущий терминальный путь _handle_tool_errorwrite_staging_log("FAILED") + _advance (= откат) для постоянного environment-дефекта вводит в заблуждение (см. BRD §1) и должен быть заменён на отличимый инфра/environment-исход (хольд на deploy-staging + алерт оператору, по образцу merge_gate infra-tolerance ORCH-110: задача остаётся на стадии, без developer-retry).
  • Анти-over-tolerance (BR-3): если сюита реально исполнилась (получен exit-код) и упала (exit≠0), исход — прежний откат deploy-staging → development + developer-retry (контракт staging_runner D5 для «сюита исполнилась» сохраняется байт-в-байт).
  • Различение «сюита исполнилась / постоянный environment-дефект / транзиентная инфра» — детерминированная классификация (по образцу merge_gate.classify_retest_failure, ORCH-110 D2); никаких догадок — постоянный environment-дефект (spawn-error «исполняемое не найдено») трактуется как НЕ-транзиентный и НЕ как код-фейл.

FR-3 — Анти-бессмысленный-ретрай (BR-2)

  • При постоянном environment-дефекте бессмысленно крутить инфра-DEFER ×N (каждая попытка падает идентично, жжёт время/слот) и затем ложно откатывать. Допустимо: немедленный отличимый инфра-хольд+алерт (без отката, без developer-retry) или preflight, не дающий задаче войти в ложный путь. Конкретику решает архитектор; инвариант — не оканчиваться код-фейл-откатом.

FR-4 — Prod-like preflight (BR-4)

  • Должен существовать механизм, ловящий «стратегия исполнения неработоспособна (нет исполняемого/ канал недоступен)» до раската — preflight на старте сервиса и/или в scripts/staging_check.py/ smoke (scripts/staging_check.py Block …) / в should_intercept/applies. Условие, проявившееся в инциденте (нет бинаря docker там, где runner его зовёт), должно детектироваться до того, как реальная задача ложно откатится.
  • Реализационно preflight никак не должен трогать гейты/стадии; never-raise; область — self-hosting.

FR-5 — Условность / kill-switch (BR-1, NFR-4, NFR-6)

  • Поведение под существующим staging_runner_enabled (выключен → прежний LLM-деплойер через _spawn байт-в-байт) + staging_runner_repos (область). При необходимости нового флага выбора/режима стратегии — env ORCH_*, дефолт = боевое (паттерн ORCH-101); откат = выставить флаг(и) → поведение до ORCH-123. applies(repo) (локально, без сети) проверяется первым.

FR-6 — Документирование границы исполнения (BR-5)

  • docs/operations/INFRA.md + docs/architecture/README.md: явно зафиксировать, что docker-операции для self-hosting исполняются host-side (а не из app-контейнера, где нет docker CLI), какие исполняемые/сокеты доступны прод-контейнеру (openssh-client/git/curl; docker.sock смонтирован, CLI — нет), и как именно staging-runner запускает сюиту после фикса.

4. Изменения API

Нет обязательных. Существующий read-only блок staging_runner в GET /queue (ORCH-115) дополняется различием environment/tool-error vs код-фейл и (опц.) статусом preflight; новых управляющих эндпоинтов не требуется (на усмотрение архитектора — опц. read-only preflight-поле).

5. Изменения схемы БД

Нет. Restart-safe состояние (счётчик инфра-ретраев) уже ведётся маркером в task_content (_INFRA_RETRY_MARKER, ORCH-115) — без миграции. Новой таблицы/колонки не требуется.

6. Требования к новым/изменённым QG checks

Нет. Это не Quality Gate и не стадия — это стратегия исполнения продюсера артефакта 15-staging-log.md. STAGE_TRANSITIONS / реестр QG_CHECKS / имена и семантика check_* (check_staging_status/_parse_staging_status) / machine-verdict ключи (staging_status:/ deploy_status:/…) / схема БД — байт-в-байт не тронуты (NFR-1; зеркало инварианта ORCH-115 NFR-1).

7. Совместимость / регресс

  • Обратная совместимость: staging_runner_enabled=False → стадию deploy-staging снова ведёт LLM-deployer через _spawn байт-в-байт; для прочих репо applies==False → no-op (нулевая регрессия enduro).
  • Контракт артефакта: 15-staging-log.md (staging_status: + 52c-схема, author_agent: staging-runner/model_used: n/a) сохраняется; вердикт по-прежнему читается ТОЛЬКО из frontmatter.
  • Self-hosting инварианты (NFR-2): не рестартить прод 8500, не docker compose up orchestrator/ --build прода, не force-push, не писать в main, не править .env — сохраняются (ORCH-115 BR-7).
  • Security (NFR-3): любой socket/CLI-в-контейнере вариант проходит security-review в ADR; host-side ssh-вариант переиспользует доверенный ORCH-036 механизм без расширения привилегий.
  • Бюджеты/инварианты: тайм-аут сюиты не растёт сверх staging_runner_timeout_s (держит сквозной reaper-инвариант ORCH-065/109/110); proc_group tree-kill (ORCH-110) сохраняется.
  • Артефакты pipeline: обычные docs work item (01..04 этой задачи; 06-adr/ на стадии architecture после эскалации; 15-staging-log.md при прогоне). Новых pipeline-артефактов задача не вводит.
  • Трассировка (CLAUDE.md §9 / ORCH-078): правки маркированных блоков — ORCH-115 (staging-runner, прямой объект), ORCH-036 (self_deploy ssh), ORCH-110 (proc_group/infra-tolerance), ORCH-058 (--build-staging) — сверять с их 06-adr/ перед изменением; инварианты не ломать.