8.0 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-090 | architecture | architect | proposed | 2026-06-09 | claude-opus-4-8 |
ADR-0026: Системное терминальное состояние cancelled — STOP-отмена задачи
Сквозной (cross-cutting) ADR. Детальное решение задачи —
docs/work-items/ORCH-090/06-adr/ADR-001-stop-cancel-task.md.
Статус
Proposed
Контекст
ORCH-090 вводит Plane-статус STOP — единый декларативный механизм отмены задачи (остановка
агента + полный сброс прогресса). Самое́ кросс-каттинговое следствие — появление нового
системного терминального состояния cancelled (стадия tasks.stage='cancelled' + терминальный
job-статус jobs.status='cancelled'). До ORCH-090 «терминальность задачи» в горячем планировщике
была захардкожена как stage == 'done' (единственный сток в STAGE_TRANSITIONS), и это
определение разъехалось между подсистемами:
src/reconciler.pyуже трактуетstage in ("done","cancelled")как терминал-скип (ORCH-086 D2 предвосхитилcancelled; стр. 196) и_is_terminal_stateпо группе Plane{completed, cancelled}(ORCH-068, стр. 398–415).src/serial_gate.py(ORCH-088) иsrc/task_deps.py(ORCH-026) считают задачу «незавершённой» поstage != 'done'— безcancelled. Если ввестиcancelled-стадию, не тронув их, отменённая задача навсегда будет «активной»/«незавершённой зависимостью» и заклинит очередь репо.
Этот ADR фиксирует cancelled как первоклассное терминальное состояние, равноправное done, и
перечисляет ВСЕ точки, где системный предикат терминальности должен его признавать.
Решение
Инвариант
«Задача терминальна» ⇔ stage ∈ {done, cancelled}. Это единое определение для всех
подсистем планировщика/мониторинга. cancelled — терминальный сток (не новое ребро
конвейера): exit-гейты рёбер STAGE_TRANSITIONS и реестр QG_CHECKS/check_* не меняются.
Точки, признающие cancelled терминальным (исчерпывающе)
src/stages.py::STAGE_TRANSITIONS— добавить сток"cancelled": {"next": None, "agent": None, "qg": None}(параллельноdone).src/serial_gate.py—repo_has_other_unfinishedи claim-фрагментt2.stage != 'done', snapshot:stage != 'done'→stage NOT IN ('done','cancelled'). (маркер ORCH-088)src/task_deps.py— dep-gate иis_task_ready:stage != 'done'→stage NOT IN ('done','cancelled'). (маркер ORCH-026)src/reconciler.py— уже покрыто скипомstage in ("done","cancelled")(стр. 196);get_active_tasks_for_reconcileопционально сузить доNOT IN ('done','cancelled').src/job_reaper.py/src/queue_worker.py— перед авто-requeue dead/running-job'а сверять терминал задачи:stage in ("done","cancelled")→ job помечаетсяcancelled, не реквью'ится.src/post_deploy.py/stage_engine.run_post_deploy_monitor— монитор не тикает по отменённой задаче (терминал-проверка/маркерdone).
Новые терминальные исходы
- Job:
jobs.status='cancelled'— нигде не реквью'ится;claim_next_jobвыбирает толькоstatus='queued'(изменений в claim нет).mark_jobстампитfinished_atдляcancelled. - Задача:
tasks.stage='cancelled'+ аддитивные колонкиcancelled_at,cancel_requested_at(отложенная отмена в критическом окне merge/deploy). Натуральные ключиplane_id/work_item_idтумбстонятся (#cancelled-<id>) для переиспользования «To Analyse» с нуля;plane_issue_idсохраняется (аудит). Детали — 08-data-requirements.md.
Точки врезки STOP (компоненты)
plane.py— маршрутstop(fail-closed, не в_DEFAULT_STATES) →handle_stop; гейт релонча ограничен стадиейanalysis.stage_engine.cancel_task— оркестрация отмены (graceful SIGTERM, cancel-jobs, worktree+branch, tombstone, notify); безопасное прерывание merge/deploy (D7 локального ADR).- leaf
src/cancel.py— чистая логика (applies/in_critical_window/snapshot), never-raise. src/gitea.py—delete_remote_branch(never-raise; только feature-ветка,mainнеприкосновенен).GET /queue— read-only блокstop.
Флаги / совместимость
- Kill-switch
stop_status_enabled+ scopestop_status_repos(CSV, пусто → все репо). - При
stop_status_enabled=False: STOP-обработка и гейт релонча инертны; расширение терминал-набораcancelledбезвредно при отсутствии отменённых задач → нулевая регрессия. STAGE_TRANSITIONS(exit-гейты) /QG_CHECKS/check_*/ семантика Approved/Rejected/Confirm Deploy / merge-gate (ORCH-043) / merge-verify (ORCH-071/073) / image-freshness (ORCH-058) / post-deploy (ORCH-021) / serial-gate FIFO (ORCH-088) / auto-label (ORCH-089) — без изменений.- Миграции БД — только аддитивные/идемпотентные (
_ensure_column); enduro не затронут (NFR-2).
Последствия
- + Единое, консистентное определение терминальности — устранён латентный рассинхрон
done-only между планировщиком и реконсилятором. - + STOP безопасен для self-hosting: не трогает
main/прод, отложенная отмена в критическом окне. - − Терминальность теперь читается из набора
{done, cancelled}, а не из скаляра'done'— будущие подсистемы обязаны использовать набор. Митигейшн: этот ADR + маркерORCH-090в изменённых местах + тесты. - Откат:
stop_status_enabled=False; полный revert — снять врезки и вернуть предикаты кstage != 'done'.
Эволюция маркеров cancelled-терминала
Места, признающие cancelled терминальным (см. список выше), несут маркер ORCH-090. Правка
любого из них — сверяться с этим ADR (анти-археология: 3+ маркеров → одна ссылка сюда,
TRACEABILITY.md).
Ссылки
- Детальный ADR:
docs/work-items/ORCH-090/06-adr/ADR-001-stop-cancel-task.md - Data:
docs/work-items/ORCH-090/08-data-requirements.md - Связанные: adr-0017 (serial-gate), adr-0015 (task-deps), adr-0007 (self-deploy), adr-0006 (merge-gate), adr-0018 (auto-label)