Files
wiki/tasks/orchestrator/proposal_v1/06_plane_integration.md
2026-06-02 21:00:01 +03:00

24 KiB
Raw Permalink Blame History

06. Интеграция с Plane

Назначение: описать, как использовать Plane так, чтобы он стал «витриной» процесса для человека (заказчика, менеджера, наблюдателя), при этом источником правды оставался Git. Здесь — иерархия объектов, шаблоны Work Item'ов, custom fields, webhooks, MCP-инструменты, сценарии реакции на события.


Простым языком

Вы хотите видеть весь процесс в одном месте — в Plane: какие фичи, какие фазы, что на каком этапе, кто (какой агент) сейчас работает, какие у задачи документы, ссылки на код. Чтобы новые задачи можно было заводить из Plane (или попросить агента завести), а ковыряться в репозитории не приходилось.

Именно так и устроено:

  1. Workspace = ваша компания.
  2. Project = один продукт / один репозиторий (например, fr24-noisemap).
  3. Work Item типа Phase = группа фич в одном релизе (опционально, для крупных проектов).
  4. Work Item типа Feature = одна фича / задача с самостоятельной ценностью.
  5. Подзадачи Work Item'а = 7 шагов производственного процесса (Анализ → Архитектура → Дизайн → Разработка → Review → Тест → Внедрение).

В каждой подзадаче — статус (To Do / In Progress / Awaiting Approval / Done / Blocked), ссылка на коммиты/PR, прикреплены или связаны артефакты из Git (через ссылки на docs/work-items/<id>/...). Вы открываете Work Item — и видите полную картину: ТЗ, дизайн, код, отчёт о тестах, deploy log.

Согласование БТ, ТЗ, дизайна — через комментарии и reactions (:approved:). Завести новую фичу — через кнопку «New Work Item» в Plane или через комментарий «Аналитик, заведи фичу: …» агенту-Analyst (если включён MCP).


Иерархия объектов

Workspace (ваша компания)
└── Project (= один репозиторий)
    └── Work Item (Phase — опционально)
        └── Work Item (Feature)
            ├── Subtask: Анализ
            ├── Subtask: Архитектура
            ├── Subtask: Дизайн UI/UX
            ├── Subtask: Разработка
            ├── Subtask: Code Review
            ├── Subtask: Тестирование
            └── Subtask: Внедрение

Ограничение Plane: глубина вложенности — 1 уровень. То есть Phase → Feature → Subtask не работает: Subtask не может иметь свой Subtask.

Решение: этапы производственного процесса висят как Subtask на Feature (не на Phase). Phase же — просто группирующая «папка» с привязанными Feature'ами через parent_id или label.


Типы Work Item

В Plane создаются (через UI или API) следующие типы (через module или cycle или через label type:*):

Тип Когда используется Имеет подзадачи производственного процесса?
Feature Самостоятельная фича с измеримой ценностью Да (7 субтасков)
Bug Найденный дефект, требующий исправления Да (но обычно урезано: Анализ → Разработка → Review → Тест → Внедрение)
Tech-debt Технический долг Да (полный цикл, либо урезано)
Phase Группа Feature'ов в один релиз Нет (управление через привязки)
Spike Исследование / прототип / RFC Свободная форма (без QG-конвейера)
Decomposition Метка задачи, разбитой на дочерние Нет (после декомпозиции закрывается, дальше работают дочерние)
Qg-override Аварийный обход QG Нет (особый процесс)
Incident Инцидент в проме Свободная форма + обязательный postmortem

Custom fields на Work Item (Feature)

Plane поддерживает custom properties через настройки workspace. Включить:

Field Type Описание
business_value text Краткое «зачем», 13 предложения
success_metric text Измеримая метрика успеха
repo_branch url Ссылка на ветку в Git
repo_pr url Ссылка на PR (заполняется CI после открытия)
repo_artifacts_path text docs/work-items/<plane-id>/ — путь к папке артефактов
phase_id reference Ссылка на родительскую Phase (опционально)
qg_status select По текущему этапу: qg-1, qg-2, qg-3, qg-4, qg-5, qg-6, qg-7, qg-final, qg-blocked
tokens_spent_usd number Накопительная стоимость LLM-вызовов (CI обновляет)
lead_time_hours number От создания до закрытия (CI обновляет)
ui_affected boolean Затрагивает UI (определяется на этапе Анализа)
breaking_change boolean Содержит breaking change

Лейблы (labels)

Используются для маршрутизации и фильтрации. Зарезервированы префиксы:

  • area:* — область кодовой базы: area:frontend, area:backend, area:infra, area:data, area:design-system.
  • type:* — тип работы: type:feature, type:bug, type:tech-debt, type:spike, type:phase.
  • priority:* — приоритет: priority:p0 (urgent) … priority:p3 (low).
  • stage:* — текущий этап производственного процесса: stage:analysis, stage:arch, stage:design, stage:dev, stage:review, stage:test, stage:deploy, stage:done. Меняется автоматически при прохождении QG.
  • back-to:* — задача возвращена на более ранний этап: back-to:analysis, back-to:arch, back-to:dev. Метка ставится агентом-Reviewer/Tester при request-changes.
  • skip:* — этап пропущен с обоснованием: skip:not-applicable, skip:overridden.
  • block-merge — стоп-кран для деплоя.
  • escalation:* — нужна человеческая помощь: escalation:meeting-needed, escalation:human-needed, escalation:owner-approval.
  • incident:* — инциденты: incident:prom-deploy, incident:rollback-failed.
  • bug:found-by-qa, bug:found-on-prom — источник бага.
  • arch:major-change — крупное архитектурное изменение, требующее согласования.

Шаблон описания Work Item (Feature)

При создании Feature заказчиком — никаких обязательных секций (намеренно: чтобы порог входа был низким). Достаточно description ≥150 символов.

После QG-0 webhook автоматически перезаписывает Feature.description в шаблон:

## Запрос от заказчика
<копия исходного description>

## Артефакты
- 📋 BRD: `docs/work-items/<id>/01-brd.md` (создаётся Analyst'ом)
- 📐 ТЗ: `docs/work-items/<id>/02-trz.md`
- ✅ Acceptance: `docs/work-items/<id>/03-acceptance-criteria.md`
- 🧪 Test Plan: `docs/work-items/<id>/04-test-plan.yaml`
- 🏛 ADR: `docs/work-items/<id>/06-adr/`
- 🎨 Design: `docs/work-items/<id>/11-design/` (если ui_affected)
- 👀 Code Review: `docs/work-items/<id>/12-review.md`
- 🧾 Test Report: `docs/work-items/<id>/13-test-report.md`
- 🚀 Deploy Log: `docs/work-items/<id>/14-deploy-log.md`

## Связи
- Branch: <ссылка на ветку>
- PR: <добавится после открытия Developer'ом>

## Прогресс
- [ ] QG-1: Анализ approved
- [ ] QG-2: Архитектура утверждена
- [ ] QG-3: Дизайн approved (если применимо)
- [ ] QG-4: CI зелёный
- [ ] QG-5: Code Review approved
- [ ] QG-6: Тесты зелёные на preview
- [ ] QG-7: Test smoke + approve для prom
- [ ] QG-final: Prom стабилен + final approve

Чек-боксы автоматически обновляются CI через Plane API.


Шаблон каждой подзадачи

При создании Feature webhook автоматически создаёт 7 подзадач (или 6, если без UI):

Subtask: «Анализ» (stage:analysis)

## Цель
Сформировать BRD, ТЗ, Acceptance Criteria, Test Plan по запросу заказчика.

## Owner
Agent: analyst (Sonnet 4.6)

## DoD
- [ ] `01-brd.md` создан и проходит spec-linter
- [ ] `02-trz.md` создан и проходит spec-linter
- [ ] `03-acceptance-criteria.md` создан
- [ ] `04-test-plan.yaml` валиден по JSON-Schema
- [ ] Все REQ покрыты AC и TC (req-coverage check зелёный)
- [ ] `:approved:` от стейкхолдера

## SLA
24 часа на одну итерацию.

## Артефакты
docs/work-items/<id>/01-brd.md
docs/work-items/<id>/02-trz.md
docs/work-items/<id>/03-acceptance-criteria.md
docs/work-items/<id>/04-test-plan.yaml

Subtask: «Архитектура» (stage:arch)

## Цель
Зафиксировать архитектурные решения по ТЗ (ADR), обновить C4-диаграммы, требования к инфраструктуре, данным, UI.

## Owner
Agent: architect (Opus 4.7)

## DoD
- [ ] Хотя бы один ADR создан и проходит adr-linter
- [ ] Все REQ из ТЗ покрыты ADR (req-coverage check)
- [ ] C4-диаграммы рендерятся
- [ ] `07-infra-requirements.md`, `08-data-requirements.md` созданы
- [ ] `09-ui-requirements.md` создан, если ui_affected: true
- [ ] `10-tech-risks.md` создан

## SLA
24 часа.

## Артефакты
docs/work-items/<id>/06-adr/
docs/work-items/<id>/07..10-*.md

(И аналогично для остальных 5 подзадач — см. 01_production_process.md.)


Webhooks

Plane → Orchestrator (HTTP endpoint, ~300 строк Python). События:

Событие Plane Реакция Orchestrator
work_item.created (type=Feature) 1) Проверить QG-0; 2) Создать ветку feature/<id>-<slug> в Git; 3) Создать 7 подзадач (или 6 без UI на старте — Analyst пометит); 4) Создать docs/work-items/<id>/00-business-request.md с копией description; 5) Запустить агента analyst.
work_item.updated (status → To Do, Subtask «Анализ») Если ещё не запущен — запустить analyst.
comment.created на Work Item с :approved: Проверить роль автора. Если Stakeholder — перевести соответствующую подзадачу в done, запустить QG, перейти к следующей.
work_item.updated (status → Done, Subtask «Анализ») Запустить QG-1. При зелёном — запустить architect.
work_item.updated (status → Done, Subtask «Архитектура») QG-2. При зелёном — если ui_affected:true — запустить designer, иначе — закрыть подзадачу «Дизайн» как skip:not-applicable и запустить developer.
comment.created на Work Item с :break-glass: Override-процедура. Только от Owner. Логировать в qg-overrides.log.
work_item.updated (priority → urgent) Поднять приоритет в очереди агентов.

Forge (GitHub/Gitea) → Orchestrator. События:

Событие Forge Реакция
pull_request.opened (label stage:dev) Связать PR с Plane Work Item (по <plane-id> в имени ветки). Проставить repo_pr поле.
check_suite.completed (CI на PR) Если зелёный + лейбл stage:dev → запустить QG-4. При успехе — запустить reviewer.
pull_request_review.submitted (status APPROVED) QG-5. При успехе — лейбл stage:test, запустить tester.
pull_request_review.submitted (status REQUEST_CHANGES) Лейбл back-to:dev, статус подзадачи «Разработка» → in_progress.
pull_request.merged Запустить deployer (deploy-test).
release.published (tag v*) Запустить deploy-prom workflow при наличии approve.

MCP для Plane

В каждом проекте .openclaw/mcp.json подключает Plane MCP-сервер:

{
  "mcpServers": {
    "plane": {
      "command": "npx",
      "args": ["-y", "@plane/mcp-server"],
      "env": {
        "PLANE_API_TOKEN": "${PLANE_API_TOKEN}",
        "PLANE_WORKSPACE_SLUG": "${PLANE_WORKSPACE}",
        "PLANE_BASE_URL": "${PLANE_BASE_URL}"
      }
    },
    "forge": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GH_TOKEN}"
      }
    },
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp"]
    }
  }
}

Если официального Plane MCP-сервера ещё нет на момент запуска — собрать тонкую обёртку (~150 строк Python) над Plane REST API, экспонирующую нужные действия как MCP-tools: plane_get_work_item, plane_update_status, plane_add_comment, plane_search_items, plane_create_issue, plane_set_label. Контракт MCP даёт стабильное имя; реализация — наша.

Доступные MCP-tools (минимальный контракт)

Tool Назначение Доступен агентам
plane_get_work_item(id) Получить Work Item с описанием, статусом, лейблами, подзадачами, комментариями All
plane_search_items(query, project) Найти Work Item по тексту/лейблу Analyst, Architect, Reviewer
plane_update_status(id, status) Сменить статус Work Item / подзадачи All
plane_set_label(id, label) Поставить/снять лейбл All
plane_add_comment(id, body) Оставить комментарий All
plane_get_comments(id, since?) Прочитать комментарии (с фильтром по дате) All
plane_check_reaction(id, emoji, role) Проверить, есть ли reaction указанного типа от пользователя с указанной ролью Orchestrator, agents
plane_create_issue(parent_id, type, title, body) Создать дочерний Work Item (для багов, декомпозиции) Analyst, Tester
plane_link_pr(work_item_id, pr_url) Прикрепить ссылку на PR в custom field Developer, Orchestrator
plane_set_custom_field(id, field, value) Обновить custom field Orchestrator (через CI)

Reactions как «штамп»

В Plane через UI или MCP можно ставить reactions на комментарии. Договорные реакции:

Reaction Семантика Кто ставит
:approved: Одобряю переход на следующий этап Stakeholder / Owner
:rejected: Возврат на доработку (с комментарием почему) Stakeholder / Reviewer
:break-glass: Аварийный override QG Owner
:final-approved: Финальный approve после деплоя в prom Stakeholder
:duplicate: Дубль другой задачи Analyst
:wont-fix: Не будет реализовано (с комментарием почему) Stakeholder

Orchestrator через plane_check_reaction собирает reactions и принимает решения о переходе.


Создание новой задачи: 3 пути

Путь 1: через UI Plane (для человека). Заказчик нажимает «New Work Item», заполняет title и description, выбирает project и priority. Webhook на event work_item.created запускает QG-0 → создание ветки и подзадач.

Путь 2: через комментарий «Analyst»-агенту в Plane (тоже для человека, но более «разговорно»). В любом проекте есть Work Item с лейблом bot:analyst-inbox. Заказчик оставляет туда комментарий: «Хочу новую фичу: чтобы на карте отображалась частота полётов». Plane MCP запускает Analyst в режиме intake, который через plane_create_issue создаёт новый Feature, перепосылает description, и стартует QG-0.

Путь 3: через CLI / API (для автоматизаций). plane create-work-item --project fr24-noisemap --title "..." --description "...". Используется для bulk-импорта или интеграций.

Все три пути приходят в одну точку: создание Feature → webhook → QG-0 → ветка + 7 подзадач.


Прикрепление артефактов к Work Item

Plane умеет прикреплять файлы, но это не наш путь: артефакты живут в Git. Вместо вложений — ссылки в description Work Item на файлы в Git (через permalink на коммит).

Webhook каждый раз при коммите в ветку обновляет description Feature, чтобы ссылки указывали на актуальный SHA:

- 📋 BRD: [docs/.../01-brd.md@a1b2c3d](https://gitea.example.com/.../docs/.../01-brd.md?at=a1b2c3d)

Так в Plane всегда виден актуальный артефакт, без ручных загрузок.

Дополнительно: Plane умеет рендерить markdown в comments — поэтому ссылка прямая на raw-файл рендерит preview прямо в Plane.


Просмотр документации в Plane

Агент analyst при изменении ТЗ автоматически:

  1. Делает коммит с новой версией 02-trz.md.
  2. Постит в комментарии Work Item: «Обновил ТЗ. Diff: <ссылка на forge-compare>».
  3. (опц.) Прикладывает inline-diff в комментарий через plane_add_comment.

Так заказчик видит изменения прямо в Plane, не открывая Git.


Согласование, изменение, заведение через Plane

Согласование:

  • Reaction :approved: или :rejected: (с обязательным следующим комментарием объясняющим причину) на соответствующей подзадаче.

Изменение:

  • Комментарий на Work Item: «Хочу изменить REQ-F-3 — теперь ...» . Analyst видит, делает коммит с новой версией ТЗ, пингует стейкхолдера на новый approve.
  • Если изменение крупное (меняется scope) — Analyst может предложить декомпозировать: «Это уже не правка текущей задачи, а новая. Разрешите завести Feature Y?»

Заведение новой:

  • См. «Путь 1/2/3» выше.

Дашборды для человека

Plane умеет строить Views и Dashboards. Рекомендуемые:

  1. Текущая работа (для каждого юзера): мои Work Item'ы, в которых я Stakeholder, и в которых статус = awaiting-approval (нужен мой apprve).
  2. Витрина проекта (на проект): список всех активных Feature, разбитый по stage:*, цветной по priority:*, с показом tokens_spent_usd и lead_time_hours.
  3. Phase board (если используются фазы): все Feature внутри Phase, разбитые по статусу.
  4. Backlog: все Feature в статусе backlog/To Do, отсортированные по приоритету и business_value.
  5. Health: алёрты — задачи в Blocked дольше 24ч, задачи с tokens_spent_usd > порога, задачи с количеством back-to:* > 2.

Audit и compliance

Каждое изменение Work Item Plane логирует автоматически. Дополнительно Orchestrator пишет в свой Postgres-журнал:

  • запуски агентов (when, agent, model, tokens, cost)
  • QG-проверки (when, gate, verdict, reason)
  • Override-события
  • Reaction-events

Это даёт полный аудит-трейл: «кто (агент) что сделал, когда и почему».


Антипаттерны интеграции с Plane

  • Хранить ТЗ как вложение к Work Item. Только в Git.
  • Менять статусы вручную, обходя webhook'и. Орекстратор — единственный, кто двигает по конвейеру.
  • Делать «несколько подзадач Анализа». Подзадач ровно 6/7 типовых; декомпозиция — через дочерние Feature.
  • Использовать Plane как чат. Длинные обсуждения — голосом, итог — в комментарии-резюме.
  • Хранить секреты Plane API в репо. Только в .env и в секретах CI.
  • Запускать агентов напрямую из Plane UI. Это всегда через Orchestrator.