383 lines
24 KiB
Markdown
383 lines
24 KiB
Markdown
# 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 | Краткое «зачем», 1–3 предложения |
|
||
| `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.
|