Files

16 KiB
Raw Permalink Blame History

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, ~стр. 584599):

  1. set_issue_in_review(work_item_id);
  2. Plane-коммент «артефакты готовы»;
  3. notify_approve_requested(task_id);
  4. 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);
  • если лейбла нет / ошибка чтения → прежнее поведение (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). Делает:

  1. update_task_stage(task_id, "deploy") + notify_stage_change;
  2. set_issue_awaiting_deploy;
  3. write_marker(APPROVE_REQUESTED);
  4. Plane-коммент + Telegram «смените статус на Confirm Deploy»;
  5. return — ждёт ручного Confirm Deployhandle_confirm_deployadvance_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 лишь авто-инициирует существующий путь деплоя.