Files
orchestrator/docs/work-items/ORCH-090/03-acceptance-criteria.md

147 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
work_item: ORCH-090
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-090 — Механизм отмены задачи: статус STOP в Plane
Work Item: **ORCH-090** · Repo: **orchestrator** · Стадия: analysis
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
(что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам
репозитория.
---
## AC-1 — STOP останавливает активного агента
**Условие:** задача с running-job'ом переведена в Plane-статус STOP.
- **PASS:** активному процессу агента послан SIGTERM через существующий каскад
(`launcher._watchdog`: SIGTERM → grace → SIGKILL); по grace процесс завершён; `agent_runs`/`jobs`
отражают завершение. Тест демонстрирует вызов остановки по `jobs.pid`.
- **FAIL:** процесс агента продолжает работать после STOP, либо kill реализован новым «грязным»
механизмом мимо graceful-каскада, либо STOP падает с исключением.
---
## AC-2 — Все job'ы задачи отменены без авто-requeue
**Условие:** у задачи есть job'ы в `queued` и/или `running`; пришёл STOP.
- **PASS:** все job'ы задачи переведены в терминальный отменённый исход; `claim_next_job` их не
выбирает; `_finalize_permanent`/`job_reaper` не возвращают их в `queued` (ретраи исчерпаны).
Тест: после STOP claim не возвращает job задачи, reaper не requeue'ит.
- **FAIL:** хотя бы один job задачи остаётся claimable/возвращается в `queued` после STOP, либо
происходит авто-requeue.
---
## AC-3 — Таймеры/мониторы сняты, отменённая задача не реконсилируется
**Условие:** задача отменена через STOP.
- **PASS:** связанные таймеры/мониторы (post-deploy monitor, brd-review clock, defer'ы) не активны
для задачи; `reconciler` (`_is_terminal_state`, терминал-скип `done`/`cancelled`) и `job_reaper`
не трогают/не «оживляют» отменённую задачу. Тест: reconciler F-1 пропускает отменённую задачу.
- **FAIL:** монитор/таймер срабатывает по отменённой задаче, либо reconciler/reaper её
релончит/реанимирует.
---
## AC-4 — Полный сброс: ветка/worktree удалены/архивированы, прогресс сброшен, docs сохранены
**Условие:** задача отменена через STOP.
- **PASS:** рабочий worktree удалён (`remove_worktree`, never-raise), рабочая ветка удалена/
заархивирована; `main` не тронут (force-push в `main` отсутствует); прогресс задачи в БД приведён
к durable-состоянию «отменена» (повторный запуск возможен только с нуля); docs-артефакты
(`docs/work-items/ORCH-090/01..17`) **сохранены/забэкаплены**, не удалены.
- **FAIL:** worktree/ветка остаются как «живой» прогресс, либо тронут `main`, либо docs-артефакты
удалены, либо задача способна продолжиться «с середины».
---
## AC-5 — Единственный вход к запуску — To Analyse; дыра релонча закрыта
**Условие:** существующая задача (с веткой/прогрессом) вручную переведена в промежуточный рабочий
статус (Architecture/Development/Review/Testing/Deploying/Awaiting Deploy/Monitoring).
- **PASS:** агент соответствующей стадии **не** запускается (нет `enqueue_job` стадийного агента по
факту ручной смены рабочего статуса). Запуск пайплайна происходит ТОЛЬКО при статусе «To Analyse»
(`start_pipeline`). Тест: перевод в Development не порождает job; перевод в To Analyse порождает
старт с нуля.
- **FAIL:** ручной перевод в любой промежуточный рабочий статус релончит агента текущей стадии
(текущее дырявое поведение `handle_status_start`).
---
## AC-6 — Идемпотентность STOP
**Условие:** STOP приходит на задачу, которая уже отменена / `done` / не существует.
- **PASS:** обработчик — no-op: нет повторного kill, нет повторного удаления ветки, нет ошибок, нет
Telegram-спама дублями. Тест: повторный STOP не меняет состояние и не бросает.
- **FAIL:** повторный STOP бросает исключение, повторно убивает/чистит, либо генерирует
дубль-уведомления.
---
## AC-7 — Безопасное прерывание merge/deploy (self-hosting safety)
**Условие:** STOP приходит во время merge/deploy задачи.
- **PASS:** `main` не остаётся в half-merged состоянии; прод-контейнер не рестартится/не роняется
обработчиком STOP; force-push в `main` отсутствует. Если необратимый шаг уже запущен — он не
«разрывается» с порчей (исход зафиксирован честно, затем применена отмена). Тест/обоснование
демонстрирует fail-safe точку прерывания.
- **FAIL:** после STOP `main` в неконсистентном состоянии, прод перезапущен/упал по вине STOP, либо
выполнен force-push в `main`.
---
## AC-8 — Kill-switch и нулевая регрессия
**Условие:** флаг `stop_status_enabled=False`.
- **PASS:** STOP-обработка не активна, дыра релонча в поведении не меняется относительно текущего
кода; `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` не изменены; полный `pytest tests/` зелёный;
enduro-trails не затронут. При `True` — STOP работает по AC-1…AC-7.
- **FAIL:** при выключенном флаге поведение отличается от текущего; изменены exit-гейты/реестр QG;
регресс существующих тестов.
---
## AC-9 — Аддитивность БД и restart-safe
**Условие:** изменения схемы БД и поведение после рестарта.
- **PASS:** все миграции аддитивны и идемпотентны (`CREATE TABLE IF NOT EXISTS`/`_ensure_column`);
после рестарта контейнера отменённая задача остаётся отменённой и не релончится. Тест: повторная
инициализация БД не падает; отменённая задача durable.
- **FAIL:** деструктивная/неидемпотентная миграция, изменение существующих таблиц-контрактов, либо
«оживание» отменённой задачи после рестарта.
---
## AC-10 — Наблюдаемость STOP
**Условие:** STOP применён к задаче.
- **PASS:** факт отмены залогирован; отправлен Telegram-алерт с кликабельным номером задачи;
Plane-коммент (best-effort); live-карточка обновлена (never-raise); `GET /queue` несёт read-only
блок отмены. Тест: блок присутствует в ответе `GET /queue`.
- **FAIL:** STOP не оставляет следов в логе/уведомлениях, либо `GET /queue` падает/не отражает
отмену.
---
## Сводная матрица AC ↔ FR/BR
| AC | Покрывает |
|----|-----------|
| AC-1 | BR-1 / FR-2 |
| AC-2 | BR-1 / FR-3 |
| AC-3 | BR-1 / FR-4 / NFR-4 |
| AC-4 | BR-2 / FR-5 |
| AC-5 | BR-3, BR-4 / FR-6 |
| AC-6 | BR-5 / FR-1 |
| AC-7 | BR-6 / FR-7 / NFR-3 |
| AC-8 | NFR-1 / FR-6 |
| AC-9 | NFR-2, NFR-4 / FR-3, FR-5 |
| AC-10 | BR-8 / FR-8 |