16 KiB
02 — ТЗ: Авто-режим по лейблам (autoApprove + autoDeploy)
Work Item: ORCH-089
Базируется на BRD: 01-brd.md
ТЗ фиксирует что должно измениться (модули, API, БД, гейты, артефакты, флаги) и предметные требования к поведению. Архитектурное как (структура leaf-модуля, стратегия кэша лейблов, точная сигнатура хелперов) — за архитектором (ADR
06-adr/). ТЗ задаёт границы, которые архитектура обязана соблюсти.
1. Обзор изменения
Ввести два независимых авто-прохода человеческих гейтов, управляемых лейблами Plane на конкретной задаче:
- autoApprove — авто-проход гейта BRD (
analysis:In Review → Approved). - autoDeploy — авто-проход гейта прод-деплоя (
deploy:Confirm Deploy→ Phase B).
Принцип врезки — аддитивно, по образцу условных под-гейтов (ORCH-035/043/058/088):
leaf-модуль чистой логики (never-raise) + точечные врезки в существующие точки
принятия решений + флаги в config.py. STAGE_TRANSITIONS и реестр QG_CHECKS
НЕ трогаются — авто-режим переиспользует уже существующие переходы и гейты, лишь
устраняя ожидание человеческого сигнала.
2. Задействованные модули src/
| Модуль | Роль изменения |
|---|---|
src/labels.py (новый, leaf) |
Чистая логика авто-режима: auto_approve_applies(repo), auto_deploy_applies(repo), has_label(work_item_id, label, project_id) -> bool/None, нормализация имён лейблов, fail-safe. never-raise. |
src/plane_sync.py |
Новая функция чтения лейблов issue из Plane API (fetch_issue_labels) + резолв карты лейблов проекта (имя↔uuid, с кэшем по образцу get_project_states). Новый сеттер статуса set_issue_approved (PATCH в Approved-UUID) для индикации авто-аппрува. |
src/stage_engine.py |
Врезка autoApprove в _handle_analysis_approved_flow (ветка files_ok, после set_issue_in_review). Врезка autoDeploy в _handle_self_deploy_phase_a (после advance на deploy, перед возвратом). |
src/config.py |
Новые флаги auto_label_enabled, auto_approve_label, auto_deploy_label, auto_label_repos (+ при необходимости TTL кэша лейблов). |
src/main.py (GET /queue) |
Аддитивный блок наблюдаемости auto_labels (опционально: счётчики авто-проходов). |
src/webhooks/plane.py |
(Опц.) если payload вебхука несёт labels — использовать как быстрый путь; иначе чтение через fetch_issue_labels. Источник истины лейблов — Plane API (надёжнее payload). |
Точные имена функций/флагов — ориентир; финальные сигнатуры закрепляет ADR. Обязательное требование: вся логика определения авто-режима — never-raise и при ошибке возвращает «нет авто» (fail-safe к ручному гейту, BR-6).
3. Точки врезки (insertion points) — предметные требования
3.1 Гейт BRD (autoApprove)
Текущее поведение (src/stage_engine.py::_handle_analysis_approved_flow, ветка
files_ok, ~стр. 584–599):
set_issue_in_review(work_item_id);- Plane-коммент «артефакты готовы»;
notify_approve_requested(task_id);return— без advance; ждёт ручного Approved через webhook (handle_verdict(approved=True)→_try_advance_stage→ advance наarchitecture).
Требуемое поведение при autoApprove:
- ПОСЛЕ установки
In Reviewи коммента (для прозрачности и клока) проверить лейблautoApproveна задаче; - если лейбл есть И
auto_approve_applies(repo)Иauto_label_enabled:- выставить Plane-статус Approved (индикация;
set_issue_approved); - залогировать авто-проход (
label autoApprove → BRD auto-approved); - отправить Telegram + Plane-коммент о факте авто-аппрува (BR-7, прозрачность);
- инициировать тот же advance, что делает ручной Approved, т.е. переход
analysis → architectureчерез штатный путь (advance_stage(..., finished_agent=None)сqg_passed/approved-via-status-семантикой), чтобы:- закрылся клок
brd_review_ended_at(mark_brd_review_ended), - выполнились все стандартные пост-переходные эффекты (карточка, plane-sync);
- закрылся клок
- выставить Plane-статус Approved (индикация;
- если лейбла нет / ошибка чтения → прежнее поведение (return, ждём человека).
Требование к реализации advance: НЕ дублировать переходную логику. Авто-аппрув обязан идти через тот же advance-путь, что и человеческий Approved (единый источник истины перехода). Защита от двойного advance/гонки с реальным webhook — идемпотентность (advance применяется один раз; повторный сигнал — no-op).
3.2 Гейт прод-деплоя (autoDeploy)
Текущее поведение (src/stage_engine.py::_handle_self_deploy_phase_a, ~стр. 1151):
вызывается на ребре deploy-staging → deploy ПОСЛЕ зелёных под-гейтов (security →
merge-gate → image-freshness → staging). Делает:
update_task_stage(task_id, "deploy")+notify_stage_change;set_issue_awaiting_deploy;write_marker(APPROVE_REQUESTED);- Plane-коммент + Telegram «смените статус на Confirm Deploy»;
return— ждёт ручногоConfirm Deploy→handle_confirm_deploy→advance_stage(confirm_deploy=True)→_handle_self_deploy_phase_b(initiate_deploy).
Требуемое поведение при autoDeploy:
- Все тех-гейты ребра
deploy-staging → deployуже зелёные к моменту Phase A (иначе сюда не дошли бы) — это структурно гарантирует BR-5 (авто не деплоит сломанное); - ПОСЛЕ advance на
deploy(шаг 1) проверить лейблautoDeploy; - если лейбл есть И
auto_deploy_applies(repo)Иauto_label_enabled:- залогировать авто-проход (
label autoDeploy → prod deploy auto-confirmed); - Telegram + Plane-коммент о факте авто-деплоя (BR-7);
- инициировать Phase B тем же путём, что ручной Confirm Deploy
(
_handle_self_deploy_phase_b(...)), сохранив идемпотентность (маркерINITIATED); - индикация статуса —
Deploying(ставит уже сам Phase B);
- залогировать авто-проход (
- если лейбла нет / ошибка → прежнее поведение (Phase A ждёт человека).
Требование: НЕ обходить и НЕ дублировать тех-гейты. autoDeploy запускается строго в точке, где Phase A уже прошёл все под-гейты. Phase C (finalizer) + merge-verify + regression-guard + post-deploy monitor остаются неизменны и продолжают верифицировать результат деплоя.
4. Изменения Plane API
Новых endpoint оркестратора (FastAPI) — нет. Изменяется только клиентское взаимодействие с Plane API v1:
| Действие | Endpoint Plane | Назначение |
|---|---|---|
| Чтение лейблов issue | GET /workspaces/{slug}/projects/{pid}/issues/{issue_id}/ → поле labels (список uuid) |
Узнать, какие лейблы навешены на задачу. |
| Карта лейблов проекта | GET /workspaces/{slug}/projects/{pid}/labels/ → [{id,name}] |
Сопоставить uuid лейбла ↔ имя (autoApprove/autoDeploy). Кэшировать (TTL, образец get_project_states/plane_states_ttl_s). |
| Установка Approved | PATCH /…/issues/{issue_id}/ {"state": <approved_uuid>} |
Индикация авто-аппрува BRD (set_issue_approved, через get_project_states(...)["approved"]). |
| (Инфра) создание лейблов | POST /…/labels/ |
Однократно создать autoApprove и autoDeploy в проекте ORCH (см. 07-infra-requirements.md). |
Требования:
- Все GET/PATCH к Plane — через существующие
PLANE_HEADERS/_resolve_project_id, таймаут как у соседей (10с), never-raise. - Сопоставление лейбла — по имени (нормализованному: регистр/пробелы), резолвенному из карты лейблов проекта; неоднозначность/нет совпадения → «нет лейбла» (fail-safe).
- Чтение лейблов НЕ должно блокировать конвейер при недоступности Plane: ошибка → «нет авто» → ручной гейт.
5. Изменения схемы БД
Не требуются. Авто-режим — stateless относительно БД:
- источник истины лейблов — Plane (читается на гейте);
- идемпотентность авто-деплоя обеспечена существующими sentinel-маркерами
(
APPROVE_REQUESTED/INITIATED, ORCH-036), а не новой колонкой; - клок
brd_review_*уже существует (ORCH-087).
Если архитектура решит кэшировать факт авто-прохода для наблюдаемости — допускается
аддитивная идемпотентная миграция (_ensure_column, образец ORCH-065 jobs.pid),
но это не требование ТЗ (предпочтительно без миграции, restart-safe через Plane/маркеры).
6. Новые QG checks
Не вводятся. Авто-режим не добавляет проверок качества — он устраняет ожидание
человеческого сигнала на существующих гейтах. Реестр QG_CHECKS и
check_analysis_approved / check_deploy_status / check_staging_status —
без изменений. (Это сознательно: добавление QG-чека усложнило бы матрицу и нарушило
инвариант «STAGE_TRANSITIONS/QG_CHECKS не трогаются», характерный для соседних под-гейтов.)
7. Конфигурация (флаги src/config.py)
По образцу ORCH-035/043/059/088 (kill-switch + CSV scope):
| Флаг | Тип / дефолт | Назначение |
|---|---|---|
auto_label_enabled |
bool = True (env ORCH_AUTO_LABEL_ENABLED) |
Глобальный kill-switch обоих авто-режимов. False → строго прежнее поведение (оба гейта ручные). |
auto_approve_label |
str = "autoApprove" |
Имя лейбла гейта BRD. |
auto_deploy_label |
str = "autoDeploy" |
Имя лейбла гейта деплоя. |
auto_label_repos |
str = "" (CSV) |
Scope. Пусто → self-hosting only (как ORCH-035/043), либо «все репо» — выбор фиксирует ADR; дефолт безопасный (self-hosting). |
auto_label_states_ttl_s |
int (опц.) |
TTL кэша карты лейблов проекта (образец plane_states_ttl_s). |
Требование: при auto_label_enabled=False — нулевая регрессия (ни одного нового
сетевого вызова на гейтах, поведение 1:1 как до ORCH-089).
8. Наблюдаемость
- Каждый авто-проход →
logger.infoс причиной (label X → действие). - Telegram-уведомление + обновление live-карточки (ORCH-042/087, never-raise).
- Plane-коммент в задаче (автор —
analystдля BRD,deployerдля деплоя — по образцу существующих комментов гейтов). - (Опц.) аддитивный блок
auto_labelsвGET /queue(enabled, label-имена, scope, счётчикиauto_approved_total/auto_deployed_total) — образец блоковreconcile/serial_gate.
9. Артефакты pipeline
Новых обязательных артефактов задачи нет. Авто-проходы отражаются в:
- Plane-комментах и Telegram/карточке (прозрачность, BR-7);
- существующих логах деплоя (
14-deploy-log.mdдля autoDeploy — пишется Phase C как сейчас).
Документация golden-source (обязательно в этом же PR):
CLAUDE.md— раздел про авто-режим по лейблам (флаги, инвариант «снимает только человеческое решение»);docs/architecture/README.md— описание врезок autoApprove/autoDeploy + флаги;06-adr/ADR-001-*.md— архитектурное решение (точки врезки, fail-safe, чтение лейблов);07-infra-requirements.md— создание лейбловautoApprove/autoDeployв Plane ORCH;CHANGELOG.md—## [Unreleased].
10. Инварианты (что НЕ должно измениться)
STAGE_TRANSITIONS, реестрQG_CHECKS,check_analysis_approved,check_deploy_status,check_staging_status— без изменений.- Все технические под-гейты (security/merge-gate/image-freshness/merge-verify/ regression-guard/post-deploy) — без изменений; авто-режим их не обходит.
- Ручной путь (без лейблов) — 1:1 как сейчас.
- Схема БД, exit-коды deploy-хука, merge-lease, sentinel-маркеры self-deploy — без изменений.
- never-raise: ни одна ошибка авто-режима не роняет конвейер и не пропускает гейт ошибочно (fail-safe к ручному).
- Self-hosting: авто-режим НЕ рестартит/не роняет прод вне штатного Phase B (который и так есть); autoDeploy лишь авто-инициирует существующий путь деплоя.