work_item: ORCH-111
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-15
model_used: claude-opus-4-8
title: "Watchdog alert на долго живущие pytest/дочерние процессы, блокирующие конвейер"
framework: pytest
scope: >
  Покрывает новый сигнал watchdog `proc_blocking`: чистый builder, конфиг/kill-switch,
  never-raise/read-only коллектор, анти-спам/recovery, отсутствие дубля с agent_hung и
  диспетч в tick(). Вне покрытия: автоматический reap/kill процессов (ремедиация — вне
  объёма задачи) и любые изменения конвейера/Quality Gates.
notes: >
  Эталон тестируемости — чистые функции `watchdog/signals.py` + `watchdog/decision.py`
  (тесты без контейнера/сокета/таймера, см. tests/watchdog/test_decision.py,
  test_host_collector.py). TC-01 и TC-07 — ОБЯЗАТЕЛЬНЫЙ регресс-тест бага: красный до
  фикса (сигнал/диспетч отсутствуют → нет алерта на долго живущий процесс), зелёный
  после. Точная форма теста КОЛЛЕКТОРА (host-scan vs orch-/metrics enrichment) зависит
  от механизма, утверждаемого архитектором (ADR); детерминированные TC ниже якорятся на
  чистом сигнале + decision-поверхности и не зависят от выбора механизма. Полный регресс
  `pytest tests/` обязан оставаться зелёным.

tests:
  - id: TC-01
    type: unit
    description: >
      РЕГРЕСС (красный→зелёный): builder сигнала по записи о процессе с возрастом >
      порога и cmdline класса pytest, не принадлежащему активному джобу, возвращает
      активный Signal с ключом `proc_blocking`. До фикса — алерт отсутствует.
    module: tests/watchdog/test_proc_blocking_signal.py
    expected: PASS

  - id: TC-02
    type: unit
    description: >
      Анти-false-positive: процесс с возрастом НИЖЕ порога ИЛИ атрибутированный активному
      отслеживаемому джобу → сигнал НЕ активен (нет алерта). Покрывает BR-4.
    module: tests/watchdog/test_proc_blocking_signal.py
    expected: PASS

  - id: TC-03
    type: unit
    description: >
      Конфиг/kill-switch: `WATCHDOG_PROC_*` парсятся с безопасными дефолтами; дефолтный
      порог возраста превышает merge_retest_timeout_s; выключенный `WATCHDOG_PROC_ENABLED`
      делает коллектор/сигнал инертными (нулевая регрессия). Покрывает BR-6/FR-3/AC-7.
    module: tests/watchdog/test_proc_blocking_signal.py
    expected: PASS

  - id: TC-04
    type: unit
    description: >
      never-raise/read-only коллектора: битый/пустой/недоступный источник → `[]` (один
      сигнал пропущен), без исключения; на пути нет os.kill/signal/subprocess/мутаций.
      Покрывает NFR-1/NFR-2/AC-3/AC-8.
    module: tests/watchdog/test_proc_blocking_signal.py
    expected: PASS

  - id: TC-05
    type: unit
    description: >
      Анти-спам/recovery через decision.decide+AlertState: ALERT при пересечении порога,
      NONE в пределах cooldown, REALERT по истечении, однократный RECOVERY при исчезновении
      процесса. Покрывает BR-5/AC-6.
    module: tests/watchdog/test_proc_blocking_signal.py
    expected: PASS

  - id: TC-06
    type: unit
    description: >
      Без дубля с agent_hung: процесс, присутствующий в /metrics agents[], не порождает
      `proc_blocking` (исключён атрибуцией к активному джобу). Покрывает NFR-4/FR-6/AC-5.
    module: tests/watchdog/test_proc_blocking_signal.py
    expected: PASS

  - id: TC-07
    type: integration
    description: >
      РЕГРЕСС tick→dispatch: Watchdog.tick() с инъектированным коллектором, отдающим долго
      живущий блокирующий процесс, диспетчеризует `proc_blocking`-алерт через fake-Notifier;
      при выключенном флаге алерт не отправляется. Покрывает BR-1/FR-5/AC-1/AC-7.
    module: tests/watchdog/test_tick_proc_blocking_integration.py
    expected: PASS

  - id: TC-08
    type: integration
    description: >
      Конфиг-канон/тираж: key-set `.env.watchdog.example` ↔ блок WATCHDOG_* в `.env.example`
      синхронизирован после добавления `WATCHDOG_PROC_*` (key-sync/LITE_SETUP тест зелёный).
      Покрывает NFR-5/AC-10.
    module: tests/watchdog/test_config_killswitch.py
    expected: PASS

  - id: TC-09
    type: integration
    description: >
      Полный регресс: `pytest tests/` зелёный; конвейер/Quality Gates не затронуты
      (STAGE_TRANSITIONS/QG_CHECKS/схема БД без изменений); при orch-side варианте
      schema_version /metrics не бампнут. Покрывает AC-9.
    module: tests/
    expected: PASS
