work_item: ORCH-086
description: >
  Терминал-скип и проброс state_uuid на пути F-1 реконсилятора.
  Тесты добавляются в tests/test_reconciler.py (рядом с существующими TC-01..TC-21),
  переиспользуя фикстуры fresh_db / silence_side_effects / _green_ci /
  plane_state_not_blocked и спай send_telegram. Все тесты — pytest, оффлайн
  (Plane/Telegram мокаются), детерминированные.
tests:
  - id: TC-86-01
    type: unit
    description: >
      AC-1 — задача enduro НЕ-done в БД, но терминальная в Plane (group=completed),
      гейт зелёный: F-1 НЕ вызывает _note_unblock и НЕ шлёт Telegram (ни при тике,
      ни на первом проходе свежего Reconciler).
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-02
    type: unit
    description: >
      AC-2 — терминал-скип инкрементирует skipped_terminal_total и НЕ вызывает
      advance_if_gate_passed для терминальной задачи (advance_stage-спай не дёрнут).
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-03
    type: unit
    description: >
      AC-2/R1 — терминал-детект по ГРУППЕ статуса Plane (completed/cancelled)
      срабатывает независимо от проекта (enduro и orchestrator): задача в группе
      cancelled тоже скипается.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-04
    type: unit
    description: >
      AC-2/R1 — fallback терминал-детекта при пустых groups: терминальность по
      логическому ключу done/cancelled проекта. Пустой groups + state_uuid ==
      states['done'] -> скип.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-05
    type: unit
    description: >
      AC-2 — терминальность по стадии БД оркестратора: задача со stage='cancelled'
      (не отсекается get_active_tasks_for_reconcile, которое фильтрует только 'done')
      скипается, не доходит до _note_unblock.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-06
    type: unit
    description: >
      AC-3 — F-1 вызывает _note_unblock С непустым state_uuid (3 аргумента) на
      легитимном unblock; проверяется, что dedup сохраняет ключ issue_id->state_uuid.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-07
    type: unit
    description: >
      AC-3 — повторный F-1-тик для того же issue+state_uuid подавляется dedup-guard:
      deduped_total += 1, второго send_telegram нет.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-08
    type: unit
    description: >
      AC-4 (анти-регресс) — НЕ-терминальная реально застрявшая задача (рабочий
      Plane-статус, прошла grace, нет active-job, гейт зелёный) ПО-ПРЕЖНЕМУ
      продвигается и шлёт РОВНО один Telegram; unblocked_total += 1.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-09
    type: unit
    description: >
      AC-5 — never-raise: исключение в терминал-детекте / fetch_issue_state не
      роняет тик (reconcile_gate_once завершается) и НЕ приводит к ложной отправке
      Telegram (консервативно: при неопределённости терминальности не уведомляем).
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-10
    type: unit
    description: >
      AC-6 — регресс F-2: существующие TC F-2 (терминал-скип/dedup/счётчики
      ORCH-068) остаются зелёными; форма status()/GET-queue не изменилась
      (skipped_terminal_total, deduped_total, unblocked_total присутствуют).
    module: tests/test_reconciler_plane.py
    expected: PASS

  - id: TC-86-11
    type: unit
    description: >
      AC-6 — reconcile_skip_blocked_enabled=False (escape hatch Guard 2) НЕ
      отключает терминал-скип TR-1: терминальная задача всё равно скипается.
    module: tests/test_reconciler.py
    expected: PASS

  - id: TC-86-12
    type: unit
    description: >
      Полный прогон регрессии пакета reconciler: pytest tests/test_reconciler.py
      tests/test_reconciler_plane.py tests/test_config.py -q зелёный.
    module: tests/test_reconciler.py
    expected: PASS
