work_item: ORCH-090
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
title: "STOP-статус: отмена задачи (остановка + полный сброс) и закрытие дыры релонча"
framework: pytest
scope: >
  Покрывается: распознавание/маршрутизация STOP, остановка агента, отмена job'ов без авто-requeue,
  снятие мониторов/терминал-скип, полный сброс ветки/worktree/прогресса при сохранении docs,
  закрытие дыры релонча (только To Analyse стартует пайплайн), идемпотентность, kill-switch,
  аддитивность БД/restart-safe, наблюдаемость (GET /queue, уведомления).
  Вне покрытия: реальный прод-деплой/рестарт контейнера (self-hosting safety проверяется на уровне
  «не вызывается рестарт/force-push», а не живым деплоем); кросс-проектная пакетная отмена.
notes: >
  Полный регресс `pytest tests/` должен оставаться зелёным (NFR-1). Регрессом считается: изменение
  STAGE_TRANSITIONS/QG_CHECKS/check_*, релонч агента ручной сменой рабочего статуса, авто-requeue
  отменённого job, «оживание» отменённой задачи reconciler/reaper, любой push/force-push в main,
  рестарт прод-контейнера обработчиком STOP. Тесты должны проходить и при stop_status_enabled=False
  (нейтральное поведение). Использовать существующие фикстуры из tests/test_plane_webhook.py /
  test_launcher.py / test_queue.py / test_reconciler.py.

tests:
  - id: TC-01
    type: unit
    description: "STOP-статус распознаётся и маршрутизируется в обработчик отмены (handle_issue_updated); неизвестная/прочая задача -> no-op, never-raise."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-02
    type: unit
    description: "Остановка активного агента: при STOP по running-job посылается SIGTERM по jobs.pid через каскад _watchdog (SIGTERM->grace->SIGKILL); нет активного процесса -> no-op."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-03
    type: unit
    description: "Отмена job'ов: queued+running job'ы задачи переведены в терминальный отменённый исход; claim_next_job их не выбирает (AC-2)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-04
    type: unit
    description: "Запрет авто-requeue: _finalize_permanent/job_reaper не возвращают отменённый job в queued (ретраи исчерпаны)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-05
    type: unit
    description: "Полный сброс: при STOP вызывается remove_worktree и удаление/архив рабочей ветки; main не трогается; force-push в main отсутствует (AC-4, AC-7)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-06
    type: unit
    description: "Docs-артефакты задачи (01..17) сохраняются/бэкапятся при сбросе прогресса, не удаляются (AC-4)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-07
    type: unit
    description: "Идемпотентность: повторный STOP на уже отменённой / done / несуществующей задаче -> no-op (нет повторного kill/cleanup, нет исключений, нет дубль-уведомлений) (AC-6)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-08
    type: unit
    description: "Kill-switch: при stop_status_enabled=False STOP-обработка нейтральна, поведение как сейчас; при True -> отмена выполняется (AC-8)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-09
    type: unit
    description: "Наблюдаемость: GET /queue несёт read-only блок отмены; never-raise при ошибке построения блока (AC-10)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-10
    type: integration
    description: "Закрытие дыры релонча: ручной перевод существующей задачи в Development/Architecture/Review/Testing НЕ порождает job стадийного агента (handle_status_start не релончит) (AC-5)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-11
    type: integration
    description: "Единственный вход: перевод в To Analyse запускает start_pipeline (новая ветка от свежего origin/main + analyst) — единственный путь старта пайплайна (AC-5)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-12
    type: integration
    description: "Терминал-скип/restart-safe: отменённая задача durable; reconciler F-1 и job_reaper её не реконсилируют/не оживляют (терминал-скип done/cancelled, _is_terminal_state) (AC-3, AC-9)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-13
    type: integration
    description: "End-to-end STOP: задача со срезанной веткой и активным job -> STOP -> агент остановлен, job'ы отменены, ветка/worktree убраны, статус задачи durable 'отменена', уведомления отправлены (AC-1..AC-4, AC-10)."
    module: tests/test_stop_status.py
    expected: PASS

  - id: TC-14
    type: unit
    description: "Аддитивность БД: миграция нового терминального исхода job/состояния задачи идемпотентна (повторная init_db не падает); существующие таблицы-контракты не изменены (AC-9, NFR-2)."
    module: tests/test_stop_status.py
    expected: PASS
