179 lines
13 KiB
Markdown
179 lines
13 KiB
Markdown
# 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` — без регресса.
|