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

# 10 — Технические риски: ORCH-111 — watchdog-алерт на долго живущий тест-процесс

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

> Информационный (гейтом не парсится). Риски реализации и их митигейшн.

## Реестр рисков

| ID | Риск | Вер. | Влия. | Митигейшн |
|----|------|------|-------|-----------|
| TR-1 | **Расширение привилегии наблюдателя** (`pid: host`): sidecar видит таблицу процессов всего хоста (все контейнеры). | Сред. | Сред. | Привилегия **read-only** и **меньше**, чем уже-смонтированный `docker.sock` (полная интроспекция контейнеров); код читает **только** `/proc/<pid>/{stat,cmdline}`, **никогда** `/proc/<pid>/environ`; сигнал дефолт-off; обоснование в ADR-001 D1/D6 + adr-0041. (NFR-2/AC-3) |
| TR-2 | **Утечка секретов через cmdline** в Telegram-алерт (если тест-команда содержит чувствительный аргумент). | Низ. | Сред. | Скоуп паттерна — `pytest` (не принимает секретов в аргументах); cmdline в detail **усекать** до ограниченного фрагмента; канал — приватный бот оператора (C-1). |
| TR-3 | **Ложные срабатывания** на легитимном длинном прогоне → спам. | Низ. | Сред. | Порог возраста **обязан** > `max(merge_retest_timeout_s=600, coverage_run_timeout_s=900)`; дефолт `WATCHDOG_PROC_AGE_MIN=60` мин (4× запас); cmdline-скоуп; дедуп/cooldown через `decision.decide`/`AlertState` (BR-4/BR-5, по построению D2). |
| TR-4 | **Кросс-namespace PID не совпадают** (`pid: host` даёт хост-глобальные PID; `/metrics agents[].pid` — namespace орка) → ненадёжная атрибуция «процесс активного джоба». | Сред. | Низ. | Атрибуция **не** через PID, а через порог возраста (namespace-агностичен) + cmdline-скоуп; дубль с `agent_hung` исключён по построению (claude ≠ pytest). ADR-001 D2. |
| TR-5 | **Отсутствие RECOVERY** для исчезнувшего процесса (динамический per-entity ключ — как у `agent_hung`/`stage_stuck`, которые не recovery'ятся при пропадании сущности). | Сред. | Низ. | Синтез `Signal(active=False)` для `proc_blocking`-ключей, alerting=True но исчезнувших из наблюдаемых → один RECOVERY через `decide()` (ADR-001 D4, AC-6). Покрыть интеграционным тестом tick→recovery. |
| TR-6 | **PID-recycling**: PID переиспользован после смерти орфана → ложная пара recovery+new-alert. | Низ. | Низ. | Естественный цикл vanish→recovery→new-alert корректен; опционально усилить ключ `("proc_blocking", pid, start_ticks)`. |
| TR-7 | **never-raise регресс**: гонка «процесс умер между `listdir(/proc)` и `read`» или битый `/proc` роняет тик. | Низ. | Выс. | Per-pid guard (skip), top-level guard → `[]`; чистый разбор отделён от I/O и покрыт фикстурами; AC-8. |
| TR-8 | **Дрейф канона тиража**: ключи добавлены в код, но не синхронизированы в `.env.example`/`.env.watchdog.example`/`LITE_SETUP.md`. | Сред. | Низ. | Key-sync `tests/test_lite_setup_doc.py` (TC-02b) красит PR; норматив NFR-5 «обновить в том же PR»; reviewer-ось ORCH-079 (доки). |
| TR-9 | **Не-Linux / нет `/proc`** (тиражная инсталляция на не-Linux) → сигнал не работает. | Низ. | Низ. | Коллектор → `[]` (один сигнал тих, тик жив); сигнал дефолт-off; Linux-специфичность задокументирована (как CPU-liveness `agent_hung`). |

## Сводный вывод
Доминирующий класс — **безопасность наблюдателя** (TR-1/TR-2: привилегия `pid: host` + видимость
cmdline). Остаточный риск для прод-конвейера **низкий**: все изменения строго в наблюдателе
(`watchdog/**` + сервис watchdog), read-only, never-raise, дефолт-off; `src/**` / `/metrics` /
`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / схема БД — не тронуты; выкат не рестартит прод-`orchestrator`
(NFR-3). Эскалация: рекомендуется лейбл **`arch:major-change`** (изменение топологии/привилегий
наблюдателя + новый компонентный сигнал). Возврат в анализ **не требуется** — ТЗ удовлетворяется без
нарушения принципов архитектуры (всё в Docker на одном сервере, stdlib-only, без новых зависимостей).
</content>
