feat(skills): mappa-brainstorm-promote 1.6.0 — brainstorm-сущность, общий механизм mappa (без workshop-специфики и storm-сокращений) (#1066)

This commit is contained in:
2026-08-25 10:17:08 +03:00
parent aabf8da806
commit a1f12fcdd4
2 changed files with 115 additions and 152 deletions

Binary file not shown.

View File

@@ -3,45 +3,33 @@ name: mappa-brainstorm-promote
author: ours author: ours
version: 1.6.0 version: 1.6.0
description: > description: >
Finalize a matured brainstorm storm-entity in mappa (type=storm, in ANY Finalize a matured brainstorm buffer (mappa entity type=brainstorm, status=buffer):
project): read buffer → route (workshop-meta → .workshop wiki; domain → read buffer → choose target project → promote via mcp__mappa__brainstorm_promote
target project wiki; skill → ~/projects/skills skeleton) → promote via (atomic buffer → wiki-страница в target + archive, решение 7) → extract
mcp__mappa__storm_promote (atomic buffer → wiki-страница + archive, решение 7) action-items into target tasks (mcp__mappa__task_create, карв-аут) → review
→ extract action-items into target tasks (mcp__mappa__task_create, карв-аут) umbrella → covering letter. Общий механизм mappa, как task.create/wiki.create —
→ review umbrella → covering letter. Старое имя — триггер-синоним: никакой workshop-специфики. Старое имя — триггер-синоним:
workshop-promote-brainstorm. Project-agnostic: storm lives where it is led, workshop-promote-brainstorm. Triggers (user): «промоутни брейнсторм»,
not only in .workshop; file channels (.brainstorm/.archive) are read-only
legacy (импортированы в mappa). Triggers (user): «промоутни брейнсторм»,
«finalize <topic>», «выкати в вики», «promote <topic>». «finalize <topic>», «выкати в вики», «promote <topic>».
--- ---
# mappa-brainstorm-promote # mappa-brainstorm-promote
Финализация созревшего шторм-буфера, который живёт **как mappa storm-сущность** Финализация созревшего брейнсторм-буфера, который живёт **как mappa-сущность
(type=storm, status=buffer) в любом проекте — **процедура** (линейная: от чтения типа `brainstorm`** (status=buffer). Это общий механизм mappa — ровно как
буфера до промоута и тасок), не цикл: запускается явно на финальном буфере и `task.create` или `wiki.create`: буфер существует в mappa, скил доводит его до
доводит его до конца. В форкфлоу встаёт между работой (`mappa-task-work`) и конца (промоут контента в вики + action-items тасками). Никакой
финишем (`mappa-closing-ritual`). workshop-специфики: скил триггерится из любой папки, работает с brainstorm-
сущностями любого проекта.
> **Project-agnostic.** Шторм ведётся там, где его ведут, — не только в Процедура линейная (от чтения буфера до промоута и тасок), не цикл: запускается
> `.workshop/`. Скил триггерится из любой папки; буфер ищется в mappa явно на финальном буфере и доводит его до конца. В форкфлоу встаёт между
> (`entity_search` type=storm), а не на диске. Файловые `.brainstorm/`/ работой (`mappa-task-work`) и финишем (`mappa-closing-ritual`).
> `.archive/` — read-only легаси: их содержимое уже импортировано в mappa
> storm-сущности (решение 15, флип), новые записи в файлы не делаются.
Три ветки маршрутизации (спросить пользователя): **Промоут контента — всегда через `mcp__mappa__brainstorm_promote`:**
атомарно создаёт wiki-страницу (slug из буфера, body сохраняется) в проекте из
- **workshop-meta** → промоут в `.workshop`: wiki-страница в вики зоны вызова и переводит буфер в `archive` (номер/slug стабильны, решение 20; рёбра
(методология самой зоны). parent_of, событие `brainstorm.promoted`). Никаких файловых каналов. Action-items
- **domain** → промоут в целевой проект: wiki-страница (спека) в его вики +
импл-таски + review-umbrella.
- **skill** → каркас скила в `~/projects/skills/skills/<name>/SKILL.md`
(только шапка + пустой каркас тела, локальный коммит без push/install).
Промоут контента — **всегда через `mcp__mappa__storm_promote`**: атомарно
создаёт wiki-страницу (slug из шторма, body сохраняется) в проекте из вызова и
переводит шторм в `archive` (номер/slug стабильны, решение 20; рёбра parent_of,
событие `storm.promoted`). **Никаких git mv и файловых архивов.** Action-items
уходят тасками в target-проект через `mcp__mappa__task_create` (карв-аут без уходят тасками в target-проект через `mcp__mappa__task_create` (карв-аут без
лиза, #1054; последовательно, не батчем). лиза, #1054; последовательно, не батчем).
@@ -49,49 +37,37 @@ description: >
- «промоутни брейнсторм», «finalize <topic>», «выкати в вики», «promote - «промоутни брейнсторм», «finalize <topic>», «выкати в вики», «promote
<topic>». <topic>».
- Пользователь ссылается на storm-сущность (storm:N) или на тему шторма, - Пользователь ссылается на brainstorm-сущность (brainstorm:N) или на тему
которая созрела и готова к промоушену. буфера, который созрел и готов к промоушену.
## Inputs ## Inputs
- Storm-реф `storm:N` или `<topic>` (slug/тема шторма) + project (если шторм - Brainstorm-реф `brainstorm:N` или `<topic>` (slug/тема буфера) + project (если
не в текущем проекте — спросить). буфер не в текущем проекте — спросить).
- Для skill-ветки дополнительно: `<name>` нового скила (если не указан — - Для skill-ветки дополнительно: `<name>` нового скила (если не указан —
спросить, предложить производное от topic). спросить, предложить производное от topic).
## Decision flow ## Decision flow
``` ```
storm-сущность в mappa (type=storm, status=buffer) brainstorm-сущность в mappa (type=brainstorm, status=buffer)
find + read (entity_search type=storm → entity_get полный body) find + read (entity_search type=brainstorm → entity_get полный body)
ask: workshop-meta or domain or skill? ask: target project (куда промоутить)
│ │
▼ ▼ ├── обычный проект → brainstorm_promote(project=<target>)
│ ask: target proj ask: <name> + check │ → wiki-страница (спека) в вики target
│ ~/projects/skills/
┌─────┴─────┐ skills/<name>/ NOT exists └── skill → dialog: description (trigger contract)
▼ │ → preview + confirm
│ storm_promote storm_promote dialog: description (trigger contract) → mkdir + Write SKILL.md (каркас) в ~/projects/skills/
│ (project=.workshop) (project=<target>) │ → git add + commit (local, no push/install)
│ │ │ ▼
│ │ │ preview + confirm
│ │ │ │
│ │ │ ▼
│ │ │ mkdir + Write SKILL.md
│ │ │ (header + empty 6-section skeleton)
│ │ │ │
│ │ │ ▼
│ │ │ git add + commit in ~/projects/skills/
│ │ │ (local, no push, no install.sh)
│ │ │ │
└────────┴───────────┴────────────┘
parse action-items from storm body parse action-items from buffer body
for each: mcp__mappa__task_create (ПОСЛЕДОВАТЕЛЬНО, не батчем) for each: mcp__mappa__task_create (ПОСЛЕДОВАТЕЛЬНО, не батчем)
@@ -103,41 +79,28 @@ storm-сущность в mappa (type=storm, status=buffer)
covering-письмо: mcp__mappa__inbox_send (канон mappa-delegation) covering-письмо: mcp__mappa__inbox_send (канон mappa-delegation)
финальный отчёт (wiki:NNNN — спека, storm:N — архив, таски) финальный отчёт (wiki:NNNN — спека, brainstorm:N — архив, таски)
``` ```
## Steps ## Steps
1. **Найти шторм в mappa.** `mcp__mappa__entity_search(type='storm', 1. **Найти буфер в mappa.** `mcp__mappa__entity_search(type='brainstorm',
project=<проект>, q=<topic>)` → в результатах storm:N + **internal id**. project=<проект>, q=<topic>)` → в результатах brainstorm:N + **internal id**.
Прочитать полный буфер: `mcp__mappa__entity_get(id=<internal id>)` — тело = Прочитать полный буфер: `mcp__mappa__entity_get(id=<internal id>)` — тело =
running record шторма (frontmatter + раунды). running record (frontmatter + раунды).
- Если шторм не найден, но пользователь показывает файловый Если буфера нет в mappa — создать brainstorm-сущность через
`.workshop/.brainstorm/<topic>.md` — это легаси: он уже импортирован или `mcp__mappa__brainstorm_create` (или HTTP `POST /entities` type=brainstorm,
доимпортируется в mappa storm-сущность (оператор, 2026-08-25). Скил контракт решения 7/#1054). Не изобретать файловые буферы.
работает с storm-сущностью; файлы не трогает.
- Если шторма нет ни в mappa, ни в файлах — создать storm-сущность:
HTTP `POST <MAPPA_CORE_URL>/entities` с `x-api-token: $MAPPA_API_TOKEN`,
body `{project, type:'storm', slug, status:'buffer', body}` (MCP-тула
`storm.create` пока нет — follow-up на mappa; контракт POST /entities,
решение 7/#1054).
2. **Показать summary буфера (≤2 абзаца).** 2. **Показать summary буфера (≤2 абзаца).**
3. **Спросить тип:** 3. **Спросить target-проект** — куда промоутить контент. По умолчанию — проект,
- **workshop-meta** — методология самой workshop-зоны: ретро дистилляции, где буфер живёт (шторм ведут там, где тема релевантна). Проверить, что проект
паттерны, апгрейды скилов зоны. существует в mappa: `mcp__mappa__entity_search` type=project или
- **domain** — доменное содержимое для какого-то целевого проекта. `admin_status` (список проектов). Если нет — abort с сообщением.
- **skill** — методология общего назначения, оформляется как скил в
`~/projects/skills/`.
4. **Если domain:** спросить целевой проект (имя папки в `~/projects/`). 4. **Если target = skill (пользователь хочет оформить как скил):**
Проверить, что проект существует в mappa: `mcp__mappa__entity_search`
type=project или `admin_status` (список проектов). Если нет — abort с
сообщением.
5. **Если skill:**
- Спросить `<name>` нового скила (если не указан) — валидный slug - Спросить `<name>` нового скила (если не указан) — валидный slug
(`[a-z0-9-]+`). (`[a-z0-9-]+`).
- Валидация: `~/projects/skills/skills/<name>/` НЕ должна существовать. - Валидация: `~/projects/skills/skills/<name>/` НЕ должна существовать.
@@ -146,42 +109,43 @@ storm-сущность в mappa (type=storm, status=buffer)
апдейтов». апдейтов».
- Валидация: `~/projects/skills/` сам репозиторий существует. Если нет — - Валидация: `~/projects/skills/` сам репозиторий существует. Если нет —
abort с сообщением «клонируй skills через update-skills или вручную». abort с сообщением «клонируй skills через update-skills или вручную».
- Двухпроходной каркас: диалог по `description` (триггер-контракт активации:
минимум 2-3 фразы, пары русский/английский; что делает; антипаттерны) →
preview + confirm → `Write` каркаса (шапка + 6 пустых секций) → локальный
`git commit` в `~/projects/skills/`. **Без** install.sh, push,
build-hermes — это в baseline-тасках шага 7. Тело каркаса дописывается
вторым проходом глазами (вне scope этого скила).
6. **Промоут контента (всегда через `storm_promote`, решение 7):** 5. **Промоут контента (всегда через `brainstorm_promote`, решение 7):**
`mcp__mappa__storm_promote(project=<target>, storm_id=<internal id>)` `mcp__mappa__brainstorm_promote(project=<target>, brainstorm_id=<internal id>)`
- Атомарно: buffer → wiki-страница (slug из шторма, body сохраняется, - Атомарно: buffer → wiki-страница (slug из буфера, body сохраняется, рёбра
рёбра parent_of wiki→storm и refs→storm) + шторм → `archive` + parent_of buffer→wiki и refs→buffer) + буфер → `archive` + значимое событие
значимое событие `storm.promoted`. `brainstorm.promoted`.
- **workshop-meta:** `project='.workshop'` → спека/концепт в вики зоны. - **Frontmatter-summary (wiki:2661):** убедиться, что в теле буфера есть
- **domain:** `project=<target>` → спека в вики целевого проекта. **Frontmatter-summary `summary:` одной строкой в frontmatter — карточки `wiki.search` читают его.
(wiki:2661):** убедиться, что в теле шторма есть `summary:` одной строкой Если нет — дописать перед промоутом.
в frontmatter — карточки `wiki.search` читают его. Если нет — дописать - Повторный промоут архивированного буфера → ошибка (one-shot, идемпотентно
перед промоутом (через HTTP PATCH body шторма, entities.update). через статус). Сверить `brainstorm_id` (internal) из шага 1.
- **skill:** контент шторма НЕ промоутится в вики (каркас пустой, тело - Если `brainstorm_promote` упал (конфликт версии, 409) → retry со свежим
дописывается вторым проходом глазами) — но шторм всё равно архивируется
`storm_promote(project=<где шторм>)`, чтобы буфер не висел.
- Повторный промоут архивированного шторма → ошибка (one-shot, идемпотентно
через статус). Сверить `storm_id` (internal) из шага 1.
- Если `storm_promote` упал (конфликт версии, 409) → retry со свежим
internal id; при стабильном отказе — abort до создания тасок. internal id; при стабильном отказе — abort до создания тасок.
7. **Парсинг action-items:** regex по строкам вида `- [ ] ...` в теле шторма, 6. **Парсинг action-items:** regex по строкам вида `- [ ] ...` в теле буфера,
секции после `## Следующие шаги`/`## TODO`/`## Next steps`/ секции после `## Следующие шаги`/`## TODO`/`## Next steps`/
`## Action items`. Показать список, дать редактировать/удалять/добавлять. `## Action items`. Показать список, дать редактировать/удалять/добавлять.
Если 0 action-items — продолжить, не блокировать. Если 0 action-items — продолжить, не блокировать.
8. **Создание тасок:** 7. **Создание тасок:**
> **NB:** таски создавать **ПОСЛЕДОВАТЕЛЬНО**, не батчем. Один > **NB:** таски создавать **ПОСЛЕДОВАТЕЛЬНО**, не батчем. Один
> `task_create` → дождаться ответа → следующий. > `task_create` → дождаться ответа → следующий.
- **workshop-meta / domain:** для каждого action-item — - **Обычный target:** для каждого action-item —
`mcp__mappa__task_create(project=<target>, slug=<kebab>, title, description, `mcp__mappa__task_create(project=<target>, slug=<kebab>, title, description,
status='ready')`. Create — карв-аут, лиз не нужен (wiki:2660/#1054). status='ready')`. Create — карв-аут, лиз не нужен (wiki:2660/#1054).
Описание импл-таски ссылается на спеку (wiki:NNNN из шага 6). Описание импл-таски ссылается на спеку (wiki:NNNN из шага 5).
- **skill:** три baseline-таски в `project='skills'`: - **Skill:** три baseline-таски в `project='skills'`:
- `[<name>-install]` — запустить `install.sh` в `~/projects/skills/`, - `[<name>-install]` — запустить `install.sh` в `~/projects/skills/`,
проверить активацию в новой сессии. проверить активацию в новой сессии.
- `[<name>-hermes-mapping]` — запись в `~/projects/skills/hermes/mapping.yaml` - `[<name>-hermes-mapping]` — запись в `~/projects/skills/hermes/mapping.yaml`
@@ -193,7 +157,7 @@ storm-сущность в mappa (type=storm, status=buffer)
- Если N-я таска упала — продолжить остальные, в конце сообщить какие - Если N-я таска упала — продолжить остальные, в конце сообщить какие
созданы / какие нет. Запомнить slug'и для review-umbrella. созданы / какие нет. Запомнить slug'и для review-umbrella.
9. **Review-umbrella (для domain с импл-тасками и для skill — всегда):** 8. **Review-umbrella (для target с импл-тасками и для skill — всегда):**
`mcp__mappa__task_create(project=<target>, slug=<topic>-review, `mcp__mappa__task_create(project=<target>, slug=<topic>-review,
status='blocked', blocker=<номера импл-тасок через запятую>, description=<чек-лист>)` status='blocked', blocker=<номера импл-тасок через запятую>, description=<чек-лист>)`
@@ -201,56 +165,54 @@ storm-сущность в mappa (type=storm, status=buffer)
- **Кто делает:** не имплементер. Следующая сессия в этом проекте (другая - **Кто делает:** не имплементер. Следующая сессия в этом проекте (другая
модель / другой день / другой агент) с чистым контекстом. «Я только что модель / другой день / другой агент) с чистым контекстом. «Я только что
это написал» bias = главный риск. это написал» bias = главный риск.
- Чек-лист: прочитать спеку (wiki:NNNN из шага 6), `git log` shipped-коммитов, - Чек-лист: прочитать спеку (wiki:NNNN из шага 5), `git log` shipped-коммитов,
для каждой импл-таски прогнать тесты и сверить с acceptance criteria, для каждой импл-таски прогнать тесты и сверить с acceptance criteria,
findings → follow-up tasks через `task_create`. findings → follow-up tasks через `task_create`.
- Закрытие: все findings зафайлены ИЛИ ревьюер подтвердил «нет findings» - Закрытие: все findings зафайлены ИЛИ ревьюер подтвердил «нет findings»
в close-note. в close-note.
- Если review-таска упала — сообщить, **продолжить** к шагу 10 (промоут уже - Если review-таска упала — сообщить, **продолжить** к шагу 9 (промоут уже
сделан, шторм в archive). сделан, буфер в archive).
10. **Covering-письмо в инбокс цели (канон mappa-delegation).** Таска на борде 9. **Covering-письмо в инбокс цели (канон mappa-delegation).** Таска на борде
не пингует живую сессию, письмо = пинг + контекст: не пингует живую сессию, письмо = пинг + контекст:
`mcp__mappa__inbox_send(project=<target>, from=<своя папка>, subject='Промоушен `mcp__mappa__inbox_send(project=<target>, from=<своя папка>, subject='Промоушен
<topic>: таски <#N…>', body=<перечень + wiki:NNNN спека>)` <topic>: таски <#N…>', body=<перечень + wiki:NNNN спека>)`
11. **Финальный отчёт пользователю:** 10. **Финальный отчёт пользователю:**
- Куда промочено: `wiki:NNNN` (спека в вики target). - Куда промочено: `wiki:NNNN` (спека в вики target).
- Архив: `storm:N` (status=archive, номер стабилен). - Архив: `brainstorm:N` (status=archive, номер стабилен).
- Какие таски созданы (ref, title, проект). - Какие таски созданы (ref, title, проект).
- **Для skill:** напомнить про второй проход «доведём `<name>`». - **Для skill:** напомнить про второй проход «доведём `<name>`».
## Failure modes ## Failure modes
- Шторм не найден в mappa (нет storm-сущности и нет файлового легаси) → abort, - Буфер не найден в mappa (нет brainstorm-сущности) → abort, сообщить: создать
сообщить: создать шторм через HTTP POST /entities (шаг 1) или дождаться через `brainstorm_create` (шаг 1) или HTTP POST /entities.
импорта. - Target-проект не существует в mappa → abort до промоута.
- Целевой проект (domain) не существует в mappa → abort до промоута. - `brainstorm_promote` упал (409 версия / стабильный отказ) → retry со свежим
- `storm_promote` упал (409 версия / стабильный отказ) → retry со свежим internal id; при повторном отказе — abort до создания тасок. Буфер остаётся
internal id; при повторном отказе — abort до создания тасок. Шторм остаётся
в buffer — ретраится позже. в buffer — ретраится позже.
- Шторм уже `archive` (повторный вызов) → abort: промоут one-shot, идемпотентность - Буфер уже `archive` (повторный вызов) → abort: промоут one-shot,
через статус (решение 7). идемпотентность через статус (решение 7).
- `task_create` упал на N-й content-таске → продолжить остальные, сообщить - `task_create` упал на N-й content-таске → продолжить остальные, сообщить
partial. Промоут уже сделан — шторм не откатывается. partial. Промоут уже сделан — буфер не откатывается.
- `task_create` review-umbrella упал → не блокировать, сообщить пользователю - `task_create` review-umbrella упал → не блокировать, сообщить пользователю
(создать вручную из шага 9). (создать вручную из шага 8).
- **Skill:** `~/projects/skills/` не существует → abort. - **Skill:** `~/projects/skills/` не существует → abort.
- **Skill:** `~/projects/skills/skills/<name>/` уже существует → abort. - **Skill:** `~/projects/skills/skills/<name>/` уже существует → abort.
- **Skill:** пользователь не подтвердил preview → abort, состояние не меняется. - **Skill:** пользователь не подтвердил preview → abort, состояние не меняется.
- **Skill:** локальный `git commit` в `~/projects/skills/` упал → файл остаётся, - **Skill:** локальный `git commit` в `~/projects/skills/` упал → файл остаётся,
сообщить что коммит нужно сделать руками; промоут шторма не блокируется. сообщить что коммит нужно сделать руками; промоут буфера не блокируется.
## Side effects ## Side effects
- **Всегда:** `storm_promote` — атомарно wiki-страница в target + шторм - **Всегда:** `brainstorm_promote` — атомарно wiki-страница в target + буфер
`archive` + рёбра parent_of (wiki→storm, refs→storm) + событие `storm.promoted`. `archive` + рёбра parent_of (wiki→buffer, refs→buffer) + событие
Файловый `.archive/` НЕ трогается (легаси read-only). `brainstorm.promoted`.
- **workshop-meta:** wiki-страница (концепт) в вики `.workshop`. - **Обычный target:** спека-страница в вики целевого проекта (с
- **domain:** спека-страница в вики целевого проекта (с frontmatter-summary, frontmatter-summary, wiki:2661) + импл-таски + review-umbrella + covering-письмо.
wiki:2661) + импл-таски + review-umbrella + covering-письмо. - **Skill:** каркас `~/projects/skills/skills/<name>/SKILL.md` (только шапка +
- **skill:** каркас `~/projects/skills/skills/<name>/SKILL.md` (только шапка +
пустой 6-секционный каркас) + локальный коммит в `~/projects/skills/`. пустой 6-секционный каркас) + локальный коммит в `~/projects/skills/`.
**Без** install.sh, push, build-hermes — это в baseline-тасках. **Без** install.sh, push, build-hermes — это в baseline-тасках.
- Создаёт N тасок в target через `mcp__mappa__task_create` (карв-аут). - Создаёт N тасок в target через `mcp__mappa__task_create` (карв-аут).
@@ -259,13 +221,14 @@ storm-сущность в mappa (type=storm, status=buffer)
## What NOT to do ## What NOT to do
- **Не писать в файловые `.brainstorm/`/`.archive/`** — read-only легаси после - **Не использовать файловые каналы** — буфер живёт в mappa brainstorm-сущности,
флипа (решение 15). Буфер живёт в mappa storm-сущности. никаких `.brainstorm/`/`.archive/` записей.
- **Не использовать `mcp__projects-meta__tasks_create` / `knowledge_ingest` / - **Не использовать `mcp__projects-meta__tasks_create` / `knowledge_ingest` /
`knowledge_promote`** — файловые каналы выпилены. Таски — `mcp__mappa__task_create`, `knowledge_promote`** — файловые каналы выпилены. Таски —
вики — `storm_promote` (контент) + `wiki_create`/`wiki_update` (доп. страницы). `mcp__mappa__task_create`, вики — `brainstorm_promote` (контент) +
`wiki_create`/`wiki_update` (доп. страницы).
- Не делать `git mv` буфера в архив — промоут архивирует сам. - Не делать `git mv` буфера в архив — промоут архивирует сам.
- Не удалять шторм вместо промоута — теряется граф-история (parent_of, refs). - Не удалять буфер вместо промоута — теряется граф-история (parent_of, refs).
- Не батчить `task_create` (гонка; инцидент 2026-08-24: 6/7 упали) — только - Не батчить `task_create` (гонка; инцидент 2026-08-24: 6/7 упали) — только
последовательно. последовательно.
- Не забывать covering-письмо — таска на борде не пингует живую сессию. - Не забывать covering-письмо — таска на борде не пингует живую сессию.