---
work_item: ORCH-111
stage: architecture
author_agent: architect
status: proposed
created_at: 2026-06-15
model_used: claude-opus-4-8
---

# 07 — Инфра-требования: ORCH-111 — watchdog-алерт на долго живущий тест-процесс

Work Item: **ORCH-111** · Repo: **orchestrator** · Стадия: architecture

> Применимо: меняется топология контейнера-наблюдателя (`pid: host`) и добавляются env-ключи
> watchdog. Решение — `06-adr/ADR-001` + сквозной `adr-0041`.

## I-1. Топология / окружения
- **Изменение:** сервису `orchestrator-watchdog` в `docker-compose.yml` добавляется **`pid: host`**
  (ADR-001 D6). Под `pid: host` контейнерный `/proc` отражает корневой PID-namespace хоста →
  watchdog видит таблицу процессов хоста (включая осиротевшие pytest, репарентированные на tini
  orchestrator-контейнера). **Отдельный mount `/proc` не требуется** (procfs зависит от namespace
  читателя).
- `pid: host` — **НЕ volume** → существующий тест `tests/watchdog/test_compose_service.py::
  test_host_paths_mounted_read_only` (требует `:ro` на каждом volume) остаётся зелёным; разработчик
  добавляет позитивный тест на наличие `pid: host`.
- Привилегия — **только у наблюдателя** (`orchestrator-watchdog`). Прод `orchestrator` и
  `orchestrator-staging` **не** меняются. Прочие тома/порты/сеть watchdog — без изменений
  (`network_mode: host`, `docker.sock:ro`, `/repos:ro`, `./data:ro`, `mem_limit: 128m`).
- **Тираж (Lite/Bundled, ORCH-102/103):** `pid: host` входит в канонический compose sidecar; сигнал
  дефолт-off → нулевое изменение поведения у тиражных инсталляций.

## I-2. Переменные окружения / секреты
- **Новые ключи** (ADR-001 D5), парсеры never-raise:
  | Ключ | Дефолт | Смысл |
  |------|--------|-------|
  | `WATCHDOG_PROC_ENABLED` | `false` | kill-switch / осознанный opt-in |
  | `WATCHDOG_PROC_AGE_MIN` | `60` | порог возраста (мин); **обязан** > `max(merge_retest_timeout_s=600, coverage_run_timeout_s=900)/60` |
  | `WATCHDOG_PROC_PATTERNS` | `pytest` | CSV паттернов cmdline (substring-матч) |
  | `WATCHDOG_PROC_COOLDOWN_S` | `1800` | per-signal cooldown |
- **Канон тиража (NFR-5 / AC-10):** ключи добавить в **том же PR** в `.env.watchdog.example` **И** в
  блок `WATCHDOG_*` `.env.example` (равенство множеств держит `tests/test_lite_setup_doc.py`
  TC-02b) + описать в `docs/deployment/LITE_SETUP.md` и `docs/architecture/README.md`.
- **Секреты:** новых нет. Канал алертов — существующий `WATCHDOG_TG_*` (свой бот sidecar, C-1).
- **На прод-хосте (разово, человек):** в `.env.watchdog` выставить `WATCHDOG_PROC_ENABLED=true`
  (включение сигнала; без этого — дремлет).

## I-3. Деплой / рестарт
- **Self-hosting инвариант (NFR-3):** выкат пересобирает/рестартит **только** контейнер
  `orchestrator-watchdog` (`docker compose up -d --build orchestrator-watchdog`). Прод-контейнер
  `orchestrator` **НЕ** перезапускается (иначе встанет конвейер всех проектов, включая enduro).
- Прод-выкат sidecar — через staging-эквивалент (smoke на staging-хосте перед прод): проверить, что
  под `pid: host` коллектор видит процессы, сигнал поднимается на синтетическом старом pytest и молчит
  при дефолт-off.
- **Откат:** `WATCHDOG_PROC_ENABLED=false` (мгновенный; привилегия дремлет) либо снятие `pid: host` +
  рестарт только sidecar.

## I-4. CI/CD
- Без изменений `.gitea/workflows/`. Новые тесты — `tests/watchdog/test_proc_blocking_signal.py`,
  `tests/watchdog/test_tick_proc_blocking_integration.py` (TRZ §2) — исполняются существующим
  `pytest tests/`. Key-sync (`test_lite_setup_doc.py`) и compose-тесты watchdog должны остаться
  зелёными.
</content>
