Files
wiki/tasks/multi-agent/proposal_v1/06_plane_integration.md
2026-05-15 00:50:01 +03:00

383 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 в шаблон:
```markdown
## Запрос от заказчика
<копия исходного 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`)
```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/<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`)
```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/<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-сервер:
```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.