analyst(ET): auto-commit from analyst run_id=339

This commit is contained in:
2026-06-07 21:05:49 +00:00
committed by deployer
parent b6c0e11e4d
commit 4a06537afd
4 changed files with 543 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
# 01 — Business Requirements Document (BRD)
**Work Item:** ORCH-066
**Заголовок:** [высокий] Статусная модель Plane: осмысленные статусы этапов
**Стадия:** analysis
**Автор:** Analyst
**Дата:** 2026-06-07
---
## 1. Контекст и проблема
Статусная модель Plane оркестратора имеет **семантические перегрузки**: один и тот
же Plane-статус используется для несовместимых смыслов, из-за чего:
- оператор не понимает, на каком реально этапе стоит задача (доска нечитаема);
- повышается риск ошибки оператора (например, неверный ручной перевод статуса);
- `In Progress` одновременно означает «человек запускает конвейер», «идёт анализ»,
«идёт прод-деплой» и «возврат из Needs Input» — четыре разных смысла на одном статусе.
Уже частично исправлено: ORCH-059 ввёл отдельный статус для подтверждения деплоя
(`Confirm Deploy`), разгрузив перегруженный `Approved`. ORCH-066 завершает наведение
порядка по **утверждённой Owner** статусной модели.
### Два слоя (критично различать)
| Слой | Что это | Источник | Трогаем? |
|------|---------|----------|----------|
| **A** | `STAGE_TRANSITIONS` — внутренняя машина стадий (`created→analysis→…→done`) | `src/stages.py` | **НЕТ (инвариант)** |
| **B** | Plane-статусы — индикация на доске | `src/plane_sync.py` + точки в `src/stage_engine.py` / `src/webhooks/plane.py` | **ДА** |
ORCH-066 меняет **только слой B** и точки, где код вручную проставляет Plane-статусы.
---
## 2. Целевая статусная модель (решение Owner)
```
Backlog → Todo → [To Analyse] → Analysis → [In Review → Approved] → Architecture →
Development → Code-Review → Testing → Awaiting Deploy → [Confirm Deploy] → Deploying →
Monitoring after Deploy → Done
```
- `[...]` = **действие человека** (вход-триггер).
- Остальное ставит **орк** (индикация).
### Ветки (нелинейные исходы)
- **Rejected** — откат на предыдущую стадию (человек).
- **Needs Input** — ТОЛЬКО аналитик (НЕ расширять на других агентов).
- **Blocked** — затык / фейл деплоя / деградация прода.
- **Cancelled** — человек решил не делать задачу (валидный выход из In Review).
---
## 3. Бизнес-требования
| ID | Требование | Приоритет |
|----|------------|-----------|
| **BR-1** | Каждый этап конвейера показывается на доске Plane осмысленным статусом (To Analyse / Analysis / Code-Review / Awaiting Deploy / Deploying / Monitoring after Deploy). | Must |
| **BR-2** | `To Analyse` — единый человеческий вход: (а) старт нового конвейера, (б) resume/relaunch аналитика при возврате из Needs Input. Заменяет роль `In Progress` как входа-триггера. | Must |
| **BR-3** | Стадия `analysis` индицируется отдельным статусом `Analysis` (орк ставит при старте/relaunch аналитика), а не `In Progress`. | Must |
| **BR-4** | Стадия `review` индицируется Plane-статусом `Code-Review` (переименование `Review`). | Must |
| **BR-5** | Self-deploy Phase A (approval-pending) ставит `Awaiting Deploy` вместо `In Review`. | Must |
| **BR-6** | Self-deploy Phase B (старт прод-деплоя) ставит `Deploying`. | Must |
| **BR-7** | Self-deploy Phase C (health-OK финализация) ставит `Monitoring after Deploy` (НЕ `Done` сразу). | Must |
| **BR-8** | Post-deploy monitor (ORCH-021): чистое закрытие окна (HEALTHY) → `Done`; UNHEALTHY/деградация → `Blocked`. | Must |
| **BR-9** | `In Review` разгрузить: оставить ТОЛЬКО за approve-pending артефактов конвейера (BRD/ревью). Выходы: `Approved` (вперёд), `Rejected` (откат), `Cancelled` (человек отменил). | Must |
| **BR-10** | `Needs Input` — БЕЗ ИЗМЕНЕНИЙ. Остаётся только у аналитика (`01-questions.md``set_issue_needs_input`). Механизм не трогать. | Must |
| **BR-11** | Возврат аналитика из Needs Input выполняется через `To Analyse` (а НЕ через `In Progress`). Логика fork «старт vs resume» (по наличию task + active-job) сохраняется. | Must (грабли R1) |
| **BR-12** | **Fail-closed:** отсутствие нового статуса в проекте (enduro / Plane API down / fallback `_DEFAULT_STATES`) НЕ приводит к падению; поведение остаётся backward-compatible (паттерн ORCH-059 AC-7). | Must |
| **BR-13** | Reconciler не «оживляет» активные ожидания (`Awaiting Deploy` / `Deploying` / `Monitoring after Deploy`) как зависшие задачи (Guard 2 skip-list). | Must |
| **BR-14** | Документация (golden source) обновлена в том же PR: `CLAUDE.md`, `docs/architecture/README.md`, `CHANGELOG.md`, ADR per-work-item. | Must |
---
## 4. Границы (Out of Scope / НЕ трогать)
- `STAGE_TRANSITIONS` (`src/stages.py`) — машина стадий, инвариант.
- `QG_CHECKS`, `check_deploy_status`, exit-коды хука (0/1/2), merge-gate, схема БД.
- `Confirm Deploy` (уже работает, ORCH-059).
- Механизм `Needs Input` (analyst-only) — не расширять, не менять.
- Поведение прод-деплоя **не-self** репозиториев (enduro-trails): для них терминальный
переход остаётся `deploy → Done` как сейчас (Monitoring after Deploy не применяется —
post-deploy monitor армится только для self-hosting).
- Автоматический approve / авто-rollback self-hosting (ORCH-54 / ORCH-021 политика
ALERT_ONLY) — не меняется.
---
## 5. Инфра-предусловие (вне кода, делает оператор)
Новые Plane-статусы в проекте **ORCH** создаёт оператор через Plane API **ДО** эксплуатации:
`To Analyse`, `Analysis`, `Code-Review`, `Awaiting Deploy`, `Deploying`,
`Monitoring after Deploy` (`Confirm Deploy` уже есть).
Резолвер (`_PLANE_NAME_TO_KEY` + `get_project_states`) подхватывает их **по имени** с
**fail-closed fallback** на `_DEFAULT_STATES` (см. BR-12). Документируется в
`07-infra-requirements.md` (создаёт архитектор) и в `docs/operations/`.
---
## 6. Definition of Done
- Plane показывает осмысленные статусы на каждом этапе.
- Возврат аналитика из Needs Input работает через `To Analyse`.
- Phase A → `Awaiting Deploy`, Phase B → `Deploying`, Phase C → `Monitoring after Deploy`,
окно HEALTHY → `Done`, фейл → `Blocked`.
- `STAGE_TRANSITIONS` не изменён.
- `pytest tests/ -q` — зелёный. Fail-closed покрыт тестами.
- Документация обновлена.

View File

@@ -0,0 +1,178 @@
# 02 — Техническое задание (ТЗ)
**Work Item:** ORCH-066
**Стадия:** analysis → (вход для architecture)
**Автор:** Analyst
> ТЗ фиксирует ТРЕБУЕМОЕ ПОВЕДЕНИЕ и затронутые точки кода. Конкретную архитектуру
> резолвера (точные имена ключей/функций) финализирует архитектор в ADR. Ниже —
> опорный контракт, согласованный с бизнес-запросом Owner.
---
## 1. Задействованные модули `src/`
| Модуль | Роль в задаче |
|--------|---------------|
| `src/plane_sync.py` | **Ядро изменений (слой B):** реестр логических статусов (`_DEFAULT_STATES`), `_PLANE_NAME_TO_KEY`, маппинг стадия→статус (`_STAGE_TO_STATE_KEY`, `STAGE_VISIBILITY_STATE`), хелперы `set_issue_*`. |
| `src/webhooks/plane.py` | Маршрутизация входящего статуса (`handle_issue_updated`): `To Analyse``handle_status_start` (старт **или** resume). |
| `src/stage_engine.py` | Точки ручной простановки статуса: analyst-flow (`Analysis`/`Needs Input`/`In Review`), Phase A (`Awaiting Deploy`), Phase B (`Deploying`), Phase C → `Monitoring after Deploy`, post-deploy monitor → `Done`/`Blocked`. |
| `src/reconciler.py` | F-2 запрос статусов (`To Analyse` в список), Guard 2 skip-list (активные ожидания). |
| `src/stages.py` | **НЕ менять** (инвариант слоя A). Используется только для чтения переходов. |
| `src/config.py` | (При необходимости) kill-switch для новой статусной модели — на усмотрение архитектора (см. §6). |
---
## 2. Изменения статусной модели (слой B)
### 2.1. Реестр логических статусов (`src/plane_sync.py`)
Ввести новые **логические ключи** и их имена в `_PLANE_NAME_TO_KEY`:
| Логический ключ | Plane name | Назначение |
|-----------------|-----------|------------|
| `to_analyse` | `To Analyse` | Вход-триггер (старт + resume аналитика). |
| `analysis` | `Analysis` | Индикация стадии analysis (орк). |
| `code_review` | `Code-Review` | Индикация стадии review (орк). Заменяет `review`. |
| `awaiting_deploy` | `Awaiting Deploy` | Phase A approval-pending (орк). |
| `deploying` | `Deploying` | Phase B прод-деплой идёт (орк). |
| `monitoring` | `Monitoring after Deploy` | Phase C / post-deploy окно (орк). |
Сохранить существующие: `backlog`, `todo`, `in_progress` (backward-compat), `needs_input`,
`in_review`, `blocked`, `done`, `cancelled`, `architecture`, `development`, `testing`,
`approved`, `rejected`. `Cancelled` уже присутствует в `_PLANE_NAME_TO_KEY`.
### 2.2. Fail-closed резолюция (КРИТИЧНО — BR-12)
`get_project_states()` после резолва по API делает `setdefault(k, v)` из `_DEFAULT_STATES`.
Чтобы отсутствие нового статуса в проекте (enduro / Plane down / частичная конфигурация)
**не ломало** конвейер, новые логические ключи в `_DEFAULT_STATES` должны
**алиаситься на существующие UUID** (degrade-to-current):
| Новый ключ | Default-алиас (UUID) | Деградированное поведение |
|------------|----------------------|---------------------------|
| `to_analyse` | = `in_progress` | enduro/старый проект: `In Progress` по-прежнему триггерит старт/resume. |
| `analysis` | = `in_progress` | analysis показывается как `In Progress` (как сейчас). |
| `code_review` | = `review` | review показывается как `Review` (как сейчас). |
| `awaiting_deploy` | = `in_review` | Phase A показывается как `In Review` (как сейчас). |
| `deploying` | = `in_progress` | Phase B показывается как `In Progress` (как сейчас). |
| `monitoring` | = `done` | Phase C показывается как `Done` (как сейчас); монитор затем держит Done / флипает Blocked. |
> Эффект: если оператор НЕ создал новый статус — система работает строго как до ORCH-066
> (никаких падений, никаких 404 от Plane PATCH). Если создал — резолвится по имени и
> используется новый UUID. Это ровно паттерн ORCH-059 AC-7.
### 2.3. Маппинг стадия → статус
`src/plane_sync.py`:
- `_STAGE_TO_STATE_KEY`: `analysis``analysis` (было `in_progress`); `review``code_review`
(было `review`). `deploy` остаётся (управляется Phase A/B/C напрямую, не через
`update_issue_state`). `created`/`architecture`/`development`/`testing`/`done` — без изменений.
- `STAGE_VISIBILITY_STATE`: `review``code_review` (было `review`). Добавить
`analysis``analysis`, если индикация analysis ставится через `set_issue_stage_state`
(решает архитектор; альтернатива — отдельный хелпер `set_issue_analysis`).
- Сохранить совместимость `STAGE_TO_STATE` / `PLANE_STATES` алиасов (импортируются тестами).
### 2.4. Точки простановки статуса
| Место (файл:симв.) | Сейчас | Должно стать |
|--------------------|--------|--------------|
| `webhooks/plane.py` `handle_issue_updated` | `new_state == in_progress``handle_status_start` | `new_state == to_analyse` (с fail-closed: при алиасе совпадает с `in_progress`) → `handle_status_start` |
| `webhooks/plane.py` `start_pipeline` (старт) | статус остаётся `In Progress` | при старте/enqueue analyst орк ставит `Analysis` |
| `webhooks/plane.py` `handle_status_start` (resume из Needs Input) | relaunch на `In Progress`-триггере | relaunch на `To Analyse`-триггере; при relaunch орк ставит `Analysis`. Fork «старт vs resume» (по `get_task_by_plane_id` + `has_active_job_for_task`) — **сохранить как есть.** |
| `stage_engine.py` `_handle_analysis_approved_flow` (artifacts ready) | `set_issue_in_review` | оставить `In Review` (BR-9: In Review только за approve-pending конвейера) ✔ без изменений |
| `stage_engine.py` `_handle_analysis_approved_flow` (questions) | `set_issue_needs_input` | **без изменений** (BR-10) |
| `stage_engine.py` `_handle_self_deploy_phase_a` | `set_issue_in_review` | `Awaiting Deploy` (`set_issue_awaiting_deploy` или аналог) |
| `stage_engine.py` `_handle_self_deploy_phase_b` | (статус не меняет) | `Deploying` |
| `stage_engine.py` advance `deploy → done` (terminal-sync, строка ~338) | `set_issue_done` для всех | **self-hosting:** `Monitoring after Deploy` (перед/вместо арма монитора); **не-self:** `Done` как сейчас |
| `stage_engine.py` `run_post_deploy_monitor` (HEALTHY, окно закрыто) | пишет лог + коммент, статус Plane НЕ трогает (остаётся Done) | `Done` (явно) |
| `stage_engine.py` `run_post_deploy_monitor` (DEGRADED) | пишет лог + alert | `Blocked` |
> **Замечание по terminal-sync (важно для архитектора):** сейчас `advance_stage` на
> `next_stage == "done"` вызывает `set_issue_done` безусловно (строка ~338), затем армит
> post-deploy monitor для self-hosting (~361). Нужно развести: для репо, где
> `post_deploy.post_deploy_applies(repo)` истинно (self-hosting) — ставить `Monitoring
> after Deploy` вместо `Done`, и переложить простановку `Done`/`Blocked` на финал
> монитора (`run_post_deploy_monitor`). Для прочих репо — `Done` как сейчас.
### 2.5. Новые хелперы `src/plane_sync.py`
Добавить тонкие обёртки по образцу `set_issue_in_review` (резолв per-project UUID +
`_set_issue_state_direct`), never-raise при отсутствии issue:
- `set_issue_analysis(work_item_id, project_id=None)`
- `set_issue_code_review(...)` (или через `set_issue_stage_state("review")`)
- `set_issue_awaiting_deploy(...)`
- `set_issue_deploying(...)`
- `set_issue_monitoring(...)`
(Точный набор/именование — на усмотрение архитектора; контракт: per-project резолв +
fail-closed.)
---
## 3. Изменения reconciler (`src/reconciler.py`)
- **F-2** `_reconcile_plane_project`: добавить `to_analyse` в список запрашиваемых
статусов (`list_issues_by_state([... , to_analyse])`) и в `_reconcile_plane_issue`
маршрутизировать `new_state == to_analyse``handle_status_start` (старт при `task is
None`, resume при существующем task без active-job — логика уже в `handle_status_start`).
Сохранить обработку `approved`/`rejected`. При fail-closed алиасе `to_analyse==in_progress`
поведение не дублируется (один и тот же UUID).
- **Guard 2** `_is_blocked_or_needs_input` (F-1 skip): расширить skip-множество активными
ожиданиями — `awaiting_deploy`, `deploying`, `monitoring` — чтобы реконсилер НЕ
«оживлял» их как зависшие (BR-13). Имя метода/семантику можно обобщить
(«human-or-active-wait»), флаг `reconcile_skip_blocked_enabled` продолжает управлять
этим networked-чеком.
> Примечание: F-1 и так не тронет Phase A (`check_deploy_status` red → silent),
> Deploying (active finalizer job), Monitoring (стадия `done`). Guard 2 — явная
> defense-in-depth по требованию Owner.
---
## 4. Изменения API / эндпоинтов
**Нет** новых HTTP-эндпоинтов. `GET /queue` / `GET /status` — без изменений контракта
(статусы Plane там не отражаются). Изменения только во внешней индикации Plane (PATCH
issue state — существующий механизм).
---
## 5. Изменения схемы БД
**Нет.** `tasks` не хранит Plane-статус (источник истины — стадия в БД + Plane API).
Миграции не требуются.
---
## 6. Требования к новым QG checks
**Нет.** `QG_CHECKS` не расширяется. Статусы — индикация, не управление (канон:
машинные вердикты читаются из YAML-frontmatter артефактов, не из Plane-статуса).
Опционально (на усмотрение архитектора): единый kill-switch новой статусной модели
(env-флаг) для безопасного раската, по образцу `staging_infra_tolerance_enabled` /
`reconcile_skip_blocked_enabled`. Не обязателен, т.к. fail-closed алиасинг (§2.2) уже даёт
backward-compatible деградацию.
---
## 7. Артефакты pipeline, создаваемые/обновляемые
- `06-adr/ADR-001-plane-status-model.md` — архитектор (решение по резолверу,
алиасингу, разводке terminal-sync).
- `07-infra-requirements.md` — архитектор (список Plane-статусов для ручного создания
оператором + Plane API инструкция).
- Документация (golden source, тот же PR): `CLAUDE.md` (секция статусной модели),
`docs/architecture/README.md` (секция статусов рядом с ORCH-036/ORCH-021),
`CHANGELOG.md`.
---
## 8. Инварианты (проверяемые)
- `src/stages.py` `STAGE_TRANSITIONS` — байт-в-байт без изменений.
- `QG_CHECKS`, `check_deploy_status`/`_parse_deploy_status`, exit-коды хука, merge-gate,
схема БД, `Confirm Deploy`, механизм `Needs Input` — без изменений.
- Все новые `set_issue_*` / резолв — never-raise (Plane down ⇒ degrade, не crash).
- Поведение enduro (не-self) и его терминальный `Done` — без регресса.

View File

@@ -0,0 +1,71 @@
# 03 — Критерии приёмки (Acceptance Criteria)
**Work Item:** ORCH-066
Каждый критерий — чёткое условие PASS/FAIL. Покрытие тестами — см. `04-test-plan.yaml`.
---
## Группа A — Вход и стадия анализа
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-1** | `To Analyse` запускает конвейер | Перевод issue без task в `To Analyse``handle_status_start``start_pipeline` (создаётся task, ветка, enqueue analyst). | Не запускается / запускается на другом статусе. |
| **AC-2** | `To Analyse` делает resume аналитика из Needs Input | Существующий task без active-job + перевод в `To Analyse` → relaunch агента текущей стадии (analyst читает свежие комменты). Fork «старт vs resume» определяется по `get_task_by_plane_id` + `has_active_job_for_task` (как раньше). | Создаётся второй task / двойной запуск / resume не происходит. |
| **AC-3** | Стадия `analysis` индицируется статусом `Analysis` | При старте/relaunch аналитика орк ставит `Analysis`. | Остаётся `In Progress` (при наличии статуса `Analysis` в проекте). |
| **AC-4** | Busy-guard сохранён | `To Analyse` при существующем active-job для task → НЕ relaunch (no double launch). | Двойной запуск агента. |
## Группа B — Code-Review
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-5** | Стадия `review` индицируется `Code-Review` | Вход в стадию `review` → Plane-статус `Code-Review`. | Остаётся `Review` (при наличии нового статуса). |
## Группа C — Self-deploy фазы
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-6** | Phase A → `Awaiting Deploy` | `_handle_self_deploy_phase_a` ставит `Awaiting Deploy` (не `In Review`). | Ставит `In Review` (при наличии нового статуса). |
| **AC-7** | Phase B → `Deploying` | `_handle_self_deploy_phase_b` при успешном `initiate_deploy` ставит `Deploying`. | Статус не меняется / иной. |
| **AC-8** | Phase C → `Monitoring after Deploy` (self) | Финализатор SUCCESS для self-hosting → статус `Monitoring after Deploy`, НЕ `Done` сразу. | Ставит `Done` немедленно (для self-hosting). |
| **AC-9** | Не-self deploy → `Done` без регресса | Для не-self репо (`post_deploy_applies==False`) терминальный `deploy → done` ставит `Done` как сейчас. | Не-self репо получает `Monitoring after Deploy` / иной регресс. |
## Группа D — Post-deploy monitor
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-10** | Чистое окно → `Done` | `run_post_deploy_monitor` HEALTHY + окно исчерпано → статус `Done`. | Остаётся `Monitoring after Deploy` / иной. |
| **AC-11** | Деградация → `Blocked` | `run_post_deploy_monitor` DEGRADED → статус `Blocked` (+ существующий ALERT_ONLY для self). | Остаётся в Monitoring / ставит Done. |
| **AC-12** | Self-hosting монитор не рестартит прод | Тик НИКОГДА не рестартит/откатывает прод-контейнер (ORCH-021 BR-5 сохранён). | Тик трогает прод-контейнер. |
## Группа E — In Review / Needs Input / ветки
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-13** | `In Review` только за approve-pending конвейера | `In Review` ставится лишь для approve артефактов (analyst BRD/ревью), не для Phase A. | Phase A / иные стадии ставят `In Review`. |
| **AC-14** | `Needs Input` без изменений | Поведение `set_issue_needs_input` (analyst `01-questions.md`) идентично прежнему; не расширено на других агентов. | Механизм изменён / расширен. |
| **AC-15** | `Cancelled` — валидный выход из In Review без действий конвейера | Перевод в `Cancelled` → орк не выполняет advance/rollback (индикация, не управление). | Орк совершает действие конвейера на `Cancelled`. |
## Группа F — Fail-closed (КРИТИЧНО)
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-16** | Отсутствие нового статуса не ломает конвейер | Проект без новых статусов (enduro/частичный/Plane down) → `get_project_states` отдаёт default-алиасы; все `set_issue_*`/триггеры работают backward-compatible, без исключений и без 404 PATCH. | Падение / необработанное исключение / зависание задачи. |
| **AC-17** | enduro `In Progress` по-прежнему стартует конвейер | Через `to_analyse`-алиас (= `in_progress` UUID) перевод enduro-issue в `In Progress` запускает старт/resume. | enduro-старт сломан. |
| **AC-18** | Резолв по имени | При наличии статуса в проекте по `name` (`_PLANE_NAME_TO_KEY`) используется его UUID, а не default-алиас. | Используется неверный UUID. |
## Группа G — Reconciler
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-19** | F-2 реконсилирует `To Analyse` | `_reconcile_plane_project` запрашивает `to_analyse` и маршрутизирует к `handle_status_start` (старт/resume при потерянном webhook). | `To Analyse`-старты не реконсилируются. |
| **AC-20** | Guard 2 skip активных ожиданий | Задачи в `Awaiting Deploy` / `Deploying` / `Monitoring after Deploy` НЕ «оживляются» F-1 как зависшие. | Реконсилер advance'ит активное ожидание. |
## Группа H — Инварианты и документация
| ID | Критерий | PASS | FAIL |
|----|----------|------|------|
| **AC-21** | `STAGE_TRANSITIONS` не изменён | `src/stages.py` `STAGE_TRANSITIONS` идентичен (diff пуст). | Любое изменение слоя A. |
| **AC-22** | Реестры/контракты не изменены | `QG_CHECKS`, `check_deploy_status`, exit-коды хука, merge-gate, схема БД, `Confirm Deploy` — без изменений. | Любое изменение перечисленного. |
| **AC-23** | Тесты зелёные | `pytest tests/ -q` проходит полностью; новые fail-closed тесты присутствуют и зелёные. | Любой красный тест. |
| **AC-24** | Документация обновлена (golden source) | `CLAUDE.md`, `docs/architecture/README.md`, `CHANGELOG.md` обновлены; заведён `06-adr/ADR-001-*`. | Любой из артефактов не обновлён. |

View File

@@ -0,0 +1,184 @@
work_item: ORCH-066
description: >
Тест-план статусной модели Plane (слой B). Покрывает осмысленные статусы этапов,
возврат аналитика через To Analyse, фазы self-deploy, post-deploy monitor,
fail-closed деградацию и reconciler. Слой A (STAGE_TRANSITIONS) проверяется на
неизменность. Все тесты — pytest; Plane API мокается (httpx), как в существующих
tests/test_plane_*.py / tests/test_orch10_states.py.
tests:
# --- Группа A: вход и стадия анализа ---
- id: TC-01
type: unit
description: "To Analyse без существующего task -> handle_status_start -> start_pipeline (старт конвейера)."
module: tests/test_status_trigger.py
covers: [AC-1]
expected: PASS
- id: TC-02
type: integration
description: "To Analyse при существующем task без active-job -> relaunch агента стадии (resume из Needs Input), новый task НЕ создаётся."
module: tests/test_plane_to_analyse_resume.py
covers: [AC-2, BR-11]
expected: PASS
- id: TC-03
type: unit
description: "Старт/relaunch аналитика ставит Plane-статус Analysis (а не In Progress) при наличии статуса в проекте."
module: tests/test_plane_status_model.py
covers: [AC-3]
expected: PASS
- id: TC-04
type: unit
description: "To Analyse при существующем task с active-job -> НЕ relaunch (busy-guard)."
module: tests/test_plane_to_analyse_resume.py
covers: [AC-4]
expected: PASS
# --- Группа B: Code-Review ---
- id: TC-05
type: unit
description: "Вход в стадию review -> Plane-статус Code-Review (маппинг _STAGE_TO_STATE_KEY / STAGE_VISIBILITY_STATE)."
module: tests/test_plane_status_model.py
covers: [AC-5]
expected: PASS
# --- Группа C: self-deploy фазы ---
- id: TC-06
type: unit
description: "_handle_self_deploy_phase_a ставит Awaiting Deploy (не In Review)."
module: tests/test_deploy_approve.py
covers: [AC-6, AC-13]
expected: PASS
- id: TC-07
type: unit
description: "_handle_self_deploy_phase_b при успешном initiate_deploy ставит Deploying."
module: tests/test_deploy_approve.py
covers: [AC-7]
expected: PASS
- id: TC-08
type: integration
description: "Phase C (finalizer SUCCESS) для self-hosting ставит Monitoring after Deploy, НЕ Done; армит post-deploy monitor."
module: tests/test_deploy_terminal_sync.py
covers: [AC-8]
expected: PASS
- id: TC-09
type: integration
description: "Не-self репо: deploy->done ставит Done (без регресса, Monitoring не применяется)."
module: tests/test_deploy_terminal_sync.py
covers: [AC-9]
expected: PASS
# --- Группа D: post-deploy monitor ---
- id: TC-10
type: unit
description: "run_post_deploy_monitor HEALTHY + окно исчерпано -> Plane-статус Done."
module: tests/test_post_deploy.py
covers: [AC-10]
expected: PASS
- id: TC-11
type: unit
description: "run_post_deploy_monitor DEGRADED -> Plane-статус Blocked (+ ALERT_ONLY для self)."
module: tests/test_post_deploy.py
covers: [AC-11]
expected: PASS
- id: TC-12
type: unit
description: "Self-hosting тик НЕ рестартит/не откатывает прод-контейнер (ORCH-021 BR-5 сохранён)."
module: tests/test_post_deploy.py
covers: [AC-12]
expected: PASS
# --- Группа E: In Review / Needs Input / Cancelled ---
- id: TC-13
type: unit
description: "In Review ставится только за approve-pending конвейера (analyst BRD ready), не Phase A."
module: tests/test_analyst_status_only_regression.py
covers: [AC-13]
expected: PASS
- id: TC-14
type: unit
description: "set_issue_needs_input (analyst 01-questions.md) поведение идентично прежнему; не расширено на других агентов."
module: tests/test_plane_status_model.py
covers: [AC-14, BR-10]
expected: PASS
- id: TC-15
type: unit
description: "Перевод в Cancelled -> handle_issue_updated не выполняет advance/rollback (индикация, не управление)."
module: tests/test_plane_webhook.py
covers: [AC-15]
expected: PASS
# --- Группа F: fail-closed (критично) ---
- id: TC-16
type: unit
description: "Проект без новых статусов: get_project_states отдаёт default-алиасы (to_analyse=in_progress, code_review=review, awaiting_deploy=in_review, monitoring=done); исключений нет."
module: tests/test_plane_status_failclosed.py
covers: [AC-16, BR-12]
expected: PASS
- id: TC-17
type: unit
description: "Plane API down -> get_project_states fallback на _DEFAULT_STATES; set_issue_* never-raise."
module: tests/test_plane_status_failclosed.py
covers: [AC-16]
expected: PASS
- id: TC-18
type: integration
description: "enduro In Progress по-прежнему стартует конвейер через to_analyse-алиас."
module: tests/test_plane_status_failclosed.py
covers: [AC-17]
expected: PASS
- id: TC-19
type: unit
description: "Резолв по имени: при наличии статуса в проекте используется его UUID, а не default-алиас."
module: tests/test_orch10_states.py
covers: [AC-18]
expected: PASS
# --- Группа G: reconciler ---
- id: TC-20
type: integration
description: "F-2 _reconcile_plane_project запрашивает to_analyse и маршрутизирует к handle_status_start (потерянный webhook старта/resume)."
module: tests/test_reconciler_plane.py
covers: [AC-19]
expected: PASS
- id: TC-21
type: unit
description: "Guard 2: задачи в Awaiting Deploy / Deploying / Monitoring after Deploy НЕ оживляются F-1 как зависшие."
module: tests/test_reconciler.py
covers: [AC-20, BR-13]
expected: PASS
# --- Группа H: инварианты ---
- id: TC-22
type: unit
description: "STAGE_TRANSITIONS не изменён (явная проверка ключей/значений слоя A)."
module: tests/test_plane_status_model.py
covers: [AC-21]
expected: PASS
- id: TC-23
type: unit
description: "QG_CHECKS реестр и check_deploy_status контракты не изменены."
module: tests/test_plane_status_model.py
covers: [AC-22]
expected: PASS
- id: TC-24
type: integration
description: "Полный прогон pytest tests/ -q зелёный (регрессия)."
module: tests/
covers: [AC-23]
expected: PASS