--- work_item: ORCH-110 stage: architecture author_agent: architect status: proposed created_at: 2026-06-15 model_used: claude-opus-4-8 --- # 07 — Инфра-требования: ORCH-110 — merge-gate re-test infra-tolerance + tree-kill Work Item: **ORCH-110** · Repo: **orchestrator** · Стадия: architecture > When-applicable. Топология/контейнеры/порты/CI **не меняются**; файл фиксирует новые env-ключи, > сквозной инвариант времени и аудит self-hosting безопасности. ## I-1. Топология / окружения **N/A.** Новых контейнеров/портов/томов/сетей нет. Изменения — только в коде приложения (`src/proc_group.py` новый leaf; правки `merge_gate`/`coverage_gate`/`qg.checks`/`stage_engine`/ `config`) и в значениях конфигурации. Прод `orchestrator` (8500) / staging (8501) — без изменений топологии. **Требование среды:** оркестратор должен исполняться под POSIX (Linux-контейнер, как сейчас) — D1 использует `os.setsid`/`os.killpg`/`os.getpgid`. На не-POSIX helper деградирует на прежний `subprocess.run` (never-break), но боевая среда — Linux. ## I-2. Переменные окружения / секреты Секретов нет. Новые ключи (`src/config.py` + `.env.example`); **дефолт каждого = желаемому прод-поведению** (ORCH-101 канон: пустой `.env` воспроизводит целевое поведение): | Ключ (config) | Env | Дефолт | Назначение | |---------------|-----|--------|------------| | `subprocess_tree_kill_enabled` | `ORCH_SUBPROCESS_TREE_KILL_ENABLED` | `True` | D1 kill-switch; off → прежний `subprocess.run(timeout=)` | | `merge_retest_infra_tolerance_enabled` | `ORCH_MERGE_RETEST_INFRA_TOLERANCE_ENABLED` | `True` | D3 kill-switch; off → таймаут = прежний rollback | | `merge_retest_infra_max_retries` | `ORCH_MERGE_RETEST_INFRA_MAX_RETRIES` | `2` | D3 бюджет повторов инфра-таймаута | | `merge_retest_infra_retry_delay_s` | `ORCH_MERGE_RETEST_INFRA_RETRY_DELAY_S` | `120` | D3 задержка перед повтором staging-deployer | | `merge_retest_skip_when_current_enabled` | `ORCH_MERGE_RETEST_SKIP_WHEN_CURRENT_ENABLED` | `True` | D4 kill-switch; off → re-test после rebase всегда | | `merge_retest_timeout_s` (изменение значения) | `ORCH_MERGE_RETEST_TIMEOUT_S` | `600 → 900` | D5 бюджет re-test (запас 74% над 516.7s) | Реюз существующего `agent_kill_grace_seconds` (грейс tree-kill каскада) — новый ключ не вводится. ## I-3. Деплой / рестарт - **Self-hosting инвариант соблюдён:** изменение НЕ рестартит прод-контейнер, НЕ пушит/force-push `main` (INV-4), НЕ трогает detached-деплой. Выкат — штатным конвейером через **обязательный staging-гейт (8501)**. - Дефолты вступают в силу при следующей сборке образа; ручных env-шагов на хосте не требуется (дефолты = целевое поведение). Откат — выставить 4 kill-switch в `False` и `ORCH_MERGE_RETEST_TIMEOUT_S=600`. ## I-4. CI/CD **Без изменений** `.gitea/workflows/`. Новые pytest-тесты (`tests/test_orch110_*.py` по `04-test-plan.yaml`) исполняются существующим шагом `pytest tests/ -q`. Новых зависимостей нет (`proc_group` — stdlib-only; `pytest-cov` уже в образе по ORCH-027). ## I-5. Сквозной инвариант времени (NFR-6 — операционно критично) Re-test/coverage исполняются в монитор-потоке staging-deployer-джоба, поэтому их суммарная работа считается против `reaper_max_running_s`. Проверенный worst-case deploy-staging-джоба: ``` deployer-агент 1800 + security ~120 + rebase 120 + re-test 900 + coverage 900 + image ~600 + grace 20 ≈ 4460 s < reaper_max_running_s = 5400 (запас ~940 s) ✓ ``` `reaper_max_running_s` **не меняется** (D5). При ручном повышении `ORCH_MERGE_RETEST_TIMEOUT_S` env'ом оператор ОБЯЗАН сохранить неравенство `reaper_max_running_s > Σ(gate-work) + grace`, иначе reaper (ORCH-065) может реапнуть легитимный мид-гейт джоб; при необходимости поднять `ORCH_REAPER_MAX_RUNNING_S` в локстеп (паттерн ORCH-109).