work_item: ORCH-094
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
title: "Тест-план: терминальная (done) задача не флаппит deploy-статусы, держит Done"
framework: pytest
scope: >
  Покрывается: терминал-aware идемпотентность выставления deploy-статусов
  (Awaiting/Deploying/Monitoring) для задач с БД stage=done/cancelled; детерминированный
  конец post-deploy-monitor и отсутствие "зомби"-тиков/статус-PATCH после завершения;
  привязка тиков монитора к активному job; наблюдаемость caller/причины; обратимость
  (kill-switch) и регресс рабочего deploy-цикла реально деплоящейся задачи.
  Вне покрытия: изменение STAGE_TRANSITIONS/QG_CHECKS/machine-verdict ключей (не трогаются);
  поведение не-self репозиториев (проверяется как нулевая регрессия). Точный актор флаппа на
  проде локализуется инструментально (developer) и фиксируется в ADR — на это отдельный
  smoke/прод-чек, не unit.
notes: >
  Полный регресс tests/ должен оставаться зелёным (pytest tests/ -q). Setter'ы Plane и сетевые
  вызовы — мокать (никаких реальных PATCH в Plane из тестов). Регресс = любой авто-переход
  done-задачи в deploy-статус, либо статус-PATCH после завершения монитора, либо подавление
  легитимного Monitoring у нетерминальной задачи. Тесты опираются на фикстуры задач со стадиями
  done/deploy и на счётчики вызовов set_issue_* (через мок).

tests:
  - id: TC-01
    type: unit
    description: "deploy-статус для задачи с БД stage=done сходится к Done: попытка set_issue_monitoring/awaiting/deploying при terminal-стадии выставляет Done (или no-op, если уже Done), а не промежуточный статус."
    module: tests/test_deploy_status_terminal_guard.py
    expected: PASS

  - id: TC-02
    type: unit
    description: "Идемпотентность: повторный вызов терминал-aware setter'а на уже-Done задаче — no-op (0 дополнительных PATCH), маятник Done<->deploy-статус не возникает."
    module: tests/test_deploy_status_terminal_guard.py
    expected: PASS

  - id: TC-03
    type: unit
    description: "Нетерминальная задача (stage=deploy) не подавляется: set_issue_monitoring/awaiting/deploying проходит штатно (регресс AC-4)."
    module: tests/test_deploy_status_terminal_guard.py
    expected: PASS

  - id: TC-04
    type: unit
    description: "Kill-switch выключен -> прежнее поведение 1:1 (терминал-aware гард не вмешивается); включён -> done-задача сходится к Done."
    module: tests/test_deploy_status_terminal_guard.py
    expected: PASS

  - id: TC-05
    type: unit
    description: "never-raise: при невозможности определить БД-стадию / сетевой ошибке Plane сеттер деградирует безопасно (не флаппит, не бросает исключение)."
    module: tests/test_deploy_status_terminal_guard.py
    expected: PASS

  - id: TC-06
    type: unit
    description: "post-deploy-monitor: после завершения окна (HEALTHY, ticks==budget -> set_issue_done + маркер done) последующих статус-PATCH для задачи нет (0 set_issue_* вызовов)."
    module: tests/test_post_deploy_monitor_termination.py
    expected: PASS

  - id: TC-07
    type: unit
    description: "post-deploy-monitor тик при БД stage=done / отсутствии активного основания -> немедленный no-op без статус-PATCH и без постановки следующего тика ('зомби'-тик исключён)."
    module: tests/test_post_deploy_monitor_termination.py
    expected: PASS

  - id: TC-08
    type: unit
    description: "arm_monitor не пере-арминг для задачи, уже находящейся в done: повторный deploy->done re-drive не выставляет Monitoring заново (маркер armed/done -> no-op)."
    module: tests/test_post_deploy_monitor_termination.py
    expected: PASS

  - id: TC-09
    type: unit
    description: "Наблюдаемость: каждый вызов выставления deploy-статуса логирует work_item, caller/путь, целевой статус, причину и БД-стадию; подавление терминал-aware гардом тоже логируется."
    module: tests/test_deploy_status_observability.py
    expected: PASS

  - id: TC-10
    type: integration
    description: "Реконсилятор/sync для задачи с БД=done и Plane=Monitoring приводит к Done идемпотентно (а не к промежуточному deploy-статусу) и не качает маятник на повторных тиках."
    module: tests/test_reconciler_done_deploy_convergence.py
    expected: PASS

  - id: TC-11
    type: integration
    description: "Регресс рабочего deploy-цикла: реально деплоящаяся (нетерминальная) 063-подобная задача проходит Awaiting -> Deploying -> Monitoring -> Done без подавления (Phase A/B/C, post-deploy HEALTHY-окно как раньше)."
    module: tests/test_self_deploy_cycle_regression.py
    expected: PASS

  - id: TC-12
    type: integration
    description: "Не-self репозиторий (enduro-подобный): нулевая регрессия — терминал-aware гард deploy-статусов инертен (условность self-hosting)."
    module: tests/test_deploy_status_terminal_guard.py
    expected: PASS
