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