# 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//...`). Вы открываете 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 | Краткое «зачем», 1–3 предложения | | `success_metric` | text | Измеримая метрика успеха | | `repo_branch` | url | Ссылка на ветку в Git | | `repo_pr` | url | Ссылка на PR (заполняется CI после открытия) | | `repo_artifacts_path` | text | `docs/work-items//` — путь к папке артефактов | | `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 в шаблон: ```markdown ## Запрос от заказчика <копия исходного description> ## Артефакты - 📋 BRD: `docs/work-items//01-brd.md` (создаётся Analyst'ом) - 📐 ТЗ: `docs/work-items//02-trz.md` - ✅ Acceptance: `docs/work-items//03-acceptance-criteria.md` - 🧪 Test Plan: `docs/work-items//04-test-plan.yaml` - 🏛 ADR: `docs/work-items//06-adr/` - 🎨 Design: `docs/work-items//11-design/` (если ui_affected) - 👀 Code Review: `docs/work-items//12-review.md` - 🧾 Test Report: `docs/work-items//13-test-report.md` - 🚀 Deploy Log: `docs/work-items//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`) ```markdown ## Цель Сформировать 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//01-brd.md docs/work-items//02-trz.md docs/work-items//03-acceptance-criteria.md docs/work-items//04-test-plan.yaml ``` ### Subtask: «Архитектура» (`stage:arch`) ```markdown ## Цель Зафиксировать архитектурные решения по ТЗ (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//06-adr/ docs/work-items//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/-` в Git; 3) Создать 7 подзадач (или 6 без UI на старте — Analyst пометит); 4) Создать `docs/work-items//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 (по `` в имени ветки). Проставить `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-сервер: ```json { "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: ```markdown - 📋 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.