feat(skills): сверка mappa-* скилов с деплоем — репо догнал установленные 1.2.0/1.4.0 (интерактивный контракт wiki:2660) [skip-tdd: visual]
- mappa-task-work 1.1.0→1.2.0, mappa-delegation 1.1.0→1.2.0, mappa-knowledge 1.1.0→1.2.0, mappa-messaging 1.1.0→1.2.0, mappa-brainstorm-promote 1.3.0→1.4.0, mappa-closing-ritual 1.0.0→1.2.0
- репо нёс гибрид ae45a51 (1.1.0, следы 'карв-аут лиза'); установленные (деплой, результат #1040) чище: claim/лиз выпилены, owner=персистентный assignee, живность из session владельца
- dist/*.skill пересобраны (build.ps1); установленные уже были в этом состоянии — репо стал источником правды, совпадающим с деплоем
- сверка: claim_next/claim_expires/task_heartbeat/admin_release_lease — 0 вхождений в установленных mappa-* (подтверждено и на этом хосте)
This commit is contained in:
BIN
dist/mappa-brainstorm-promote.skill
vendored
BIN
dist/mappa-brainstorm-promote.skill
vendored
Binary file not shown.
BIN
dist/mappa-closing-ritual.skill
vendored
BIN
dist/mappa-closing-ritual.skill
vendored
Binary file not shown.
BIN
dist/mappa-delegation.skill
vendored
BIN
dist/mappa-delegation.skill
vendored
Binary file not shown.
BIN
dist/mappa-knowledge.skill
vendored
BIN
dist/mappa-knowledge.skill
vendored
Binary file not shown.
BIN
dist/mappa-messaging.skill
vendored
BIN
dist/mappa-messaging.skill
vendored
Binary file not shown.
BIN
dist/mappa-task-work.skill
vendored
BIN
dist/mappa-task-work.skill
vendored
Binary file not shown.
@@ -1,12 +1,13 @@
|
|||||||
---
|
---
|
||||||
name: mappa-brainstorm-promote
|
name: mappa-brainstorm-promote
|
||||||
author: ours
|
author: ours
|
||||||
version: 1.3.0
|
version: 1.4.0
|
||||||
description: >
|
description: >
|
||||||
Finalize a matured brainstorm buffer on the boss's desk
|
Finalize a matured brainstorm buffer on the boss's desk
|
||||||
(~/projects/.workshop/.brainstorm/): ask routing (workshop-meta → local
|
(~/projects/.workshop/.brainstorm/): ask routing (workshop-meta → local
|
||||||
.wiki/concepts/, domain → target project wiki via knowledge_ingest,
|
.wiki/concepts/, domain → target project wiki via knowledge_ingest,
|
||||||
mappa-service → mappa-борд (карв-аут), skill → claude-skills skeleton),
|
mappa-service → mappa-борд (create — карв-аут без лиза wiki:2660), skill →
|
||||||
|
claude-skills skeleton),
|
||||||
extract action-items into target .tasks, create pointers + review umbrella
|
extract action-items into target .tasks, create pointers + review umbrella
|
||||||
for impl tasks, archive the buffer. Старое имя — триггер-синоним:
|
for impl tasks, archive the buffer. Старое имя — триггер-синоним:
|
||||||
workshop-promote-brainstorm. Location-agnostic: fires from ANY folder; all
|
workshop-promote-brainstorm. Location-agnostic: fires from ANY folder; all
|
||||||
@@ -27,7 +28,7 @@ description: >
|
|||||||
|
|
||||||
- **workshop-meta** → локальный `.wiki/concepts/` (методология самой зоны).
|
- **workshop-meta** → локальный `.wiki/concepts/` (методология самой зоны).
|
||||||
- **domain** → глобал через `mcp__projects-meta__knowledge_ingest` в `~/projects/<proj>/.wiki/`.
|
- **domain** → глобал через `mcp__projects-meta__knowledge_ingest` в `~/projects/<proj>/.wiki/`.
|
||||||
- **mappa-service** → сервисные борды (mappa, .common, …): таски/вики-сущности через `mcp__mappa__task_create`/`wiki_create` (карв-аут, wiki:2660); review-umbrella — сервисная таска; covering-письмо в инбокс цели.
|
- **mappa-service** → сервисные борды (mappa, .common, …): таски/вики-сущности через `mcp__mappa__task_create`/`wiki_create` (**create — карв-аут без лиза**, wiki:2660; update — version+409); pointers-таска НЕ нужна, если спека уже в вики проекта (wiki:NNNN); review-umbrella — сервисная таска; covering-письмо в инбокс цели.
|
||||||
- **skill** → `~/projects/claude-skills/skills/<name>/SKILL.md` (только шапка + пустой каркас тела, локальный коммит без push/install/build-hermes).
|
- **skill** → `~/projects/claude-skills/skills/<name>/SKILL.md` (только шапка + пустой каркас тела, локальный коммит без push/install/build-hermes).
|
||||||
|
|
||||||
Буфер уезжает в `.archive/`. Action-items уходят тасками в target-проект. **Всегда, при любом маршруте, в воркшоп-вики остаётся summary-страница.**
|
Буфер уезжает в `.archive/`. Action-items уходят тасками в target-проект. **Всегда, при любом маршруте, в воркшоп-вики остаётся summary-страница.**
|
||||||
@@ -63,7 +64,7 @@ description: >
|
|||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ ▼ ▼ ▼
|
│ ▼ ▼ ▼
|
||||||
│ knowledge_ingest mcp__mappa__wiki_create dialog: description (trigger contract)
|
│ knowledge_ingest mcp__mappa__wiki_create dialog: description (trigger contract)
|
||||||
│ │ (карв-аут, wiki:2660) │
|
│ │ (карв-аут, wiki:2660) │
|
||||||
│ │ │ ▼
|
│ │ │ ▼
|
||||||
│ │ │ preview + confirm
|
│ │ │ preview + confirm
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
@@ -118,9 +119,11 @@ description: >
|
|||||||
- **Определить канал борда:** есть ли у проекта файловая доска `.tasks/STATUS.md` (file channel) или борд живёт в mappa-сущностях (service channel — сервисные проекты: mappa, .common, …). Проверка: файл `.tasks/STATUS.md` в чек-ауте (file) против `mcp__mappa__task_list(project=<proj>)` / `entity_search` (service). Если файловой доски нет, а mappa-сущности есть → **service channel**.
|
- **Определить канал борда:** есть ли у проекта файловая доска `.tasks/STATUS.md` (file channel) или борд живёт в mappa-сущностях (service channel — сервисные проекты: mappa, .common, …). Проверка: файл `.tasks/STATUS.md` в чек-ауте (file) против `mcp__mappa__task_list(project=<proj>)` / `entity_search` (service). Если файловой доски нет, а mappa-сущности есть → **service channel**.
|
||||||
|
|
||||||
4. **Если domain + service channel (mappa-борд, fold-in 1):**
|
4. **Если domain + service channel (mappa-борд, fold-in 1):**
|
||||||
- **Спека → вики-сущность:** `mcp__mappa__wiki_create(project, slug, body)` (или `wiki_update(project, id, version)`, если страница уже есть). Если спека уже в вики проекта (w:NNNN) — не дублировать, описание импл-тасок ссылается на неё.
|
- **Create — карв-аут, лиз НЕ нужен** (wiki:2660): `task_create`/`wiki_create`
|
||||||
|
без claim_token (интерактивный контракт, поллер вне mappa).
|
||||||
|
- **Спека → вики-сущность:** `mcp__mappa__wiki_create(project, slug, body)` (или `wiki_update(project, id, version, …)`, если страница уже есть). Если спека уже в вики проекта (wiki:NNNN) — не дублировать, описание импл-тасок ссылается на неё.
|
||||||
- **Pointers-таска НЕ нужна**, если спека уже в вики проекта — дыра pointers закрыта инлайн (описание импл-тасок прямо ссылается на спеку).
|
- **Pointers-таска НЕ нужна**, если спека уже в вики проекта — дыра pointers закрыта инлайн (описание импл-тасок прямо ссылается на спеку).
|
||||||
- **Импл-таски:** `mcp__mappa__task_create(project, slug, title, description, status='ready')` (карв-аут, wiki:2660) — **ПОСЛЕДОВАТЕЛЬНО, не батчем** (см. NB в шаге 7).
|
- **Импл-таски:** `mcp__mappa__task_create(project, slug, title, description, status='ready')` — **ПОСЛЕДОВАТЕЛЬНО, не батчем** (см. NB в шаге 7).
|
||||||
- **Review-umbrella:** сервисная таска `mcp__mappa__task_create(status='blocked', blocker=<номера импл-тасок>)`.
|
- **Review-umbrella:** сервисная таска `mcp__mappa__task_create(status='blocked', blocker=<номера импл-тасок>)`.
|
||||||
- **Covering-письмо:** `mcp__mappa__inbox_send(project=<target>, from=<своя>, subject='Промоушен <topic>: таски <#N>…', body=<перечень>).` — канон mappa-delegation: таска на борде не пингует живую сессию.
|
- **Covering-письмо:** `mcp__mappa__inbox_send(project=<target>, from=<своя>, subject='Промоушен <topic>: таски <#N>…', body=<перечень>).` — канон mappa-delegation: таска на борде не пингует живую сессию.
|
||||||
|
|
||||||
@@ -366,9 +369,9 @@ description: >
|
|||||||
|
|
||||||
- Если `tasks_create` review-таски упала — сообщить пользователю, **продолжить** к шагу 11 (архивация буфера). Review-таску можно создать вручную позже из `.archive/<date>-<topic>.md`.
|
- Если `tasks_create` review-таски упала — сообщить пользователю, **продолжить** к шагу 11 (архивация буфера). Review-таску можно создать вручную позже из `.archive/<date>-<topic>.md`.
|
||||||
|
|
||||||
- **domain (service channel):** review-umbrella — **сервисная таска**: `mcp__mappa__task_create(project=<target>, slug=<topic>-review, status='blocked', blocker=<номера импл-тасок через запятую>, description=<шаблон domain выше, спека = w:NNNN в вики проекта>)`. Pointers-таска отсутствует (спека в вики).
|
- **domain (service channel):** review-umbrella — **сервисная таска**: `mcp__mappa__task_create(project=<target>, slug=<topic>-review, status='blocked', blocker=<номера импл-тасок через запятую>, description=<шаблон domain выше, спека = wiki:NNNN в вики проекта>)` — create = карв-аут (без лиза). Pointers-таска отсутствует (спека в вики).
|
||||||
|
|
||||||
**Covering-письмо в инбокс цели (оба канала; канон mappa-delegation).** После создания тасок — `inbox_send` получателю-проекту: таска на борде не пингует живую сессию, письмо = пинг + контекст. File channel: `mcp__mappa__inbox_send(project=<target>, from=<своя>, subject='[event: created] <topic> — <N> тасок', body=<перечень: #N slug> )`. Service channel: то же, но `from` = своя папка (или сервисный адрес) и тело ссылается на w:NNNN-спеку.
|
**Covering-письмо в инбокс цели (оба канала; канон mappa-delegation).** После создания тасок — `inbox_send` получателю-проекту: таска на борде не пингует живую сессию, письмо = пинг + контекст. File channel: `mcp__mappa__inbox_send(project=<target>, from=<своя>, subject='[event: created] <topic> — <N> тасок', body=<перечень: #N slug> )`. Service channel: то же, но `from` = своя папка (или сервисный адрес) и тело ссылается на wiki:NNNN-спеку.
|
||||||
|
|
||||||
10. **Workshop-wiki summary (обязательно для всех маршрутов):**
|
10. **Workshop-wiki summary (обязательно для всех маршрутов):**
|
||||||
|
|
||||||
@@ -423,9 +426,8 @@ description: >
|
|||||||
- `mcp__projects-meta` недоступен → abort до записей.
|
- `mcp__projects-meta` недоступен → abort до записей.
|
||||||
- Целевой проект (для domain) не найден в `meta_status` → abort.
|
- Целевой проект (для domain) не найден в `meta_status` → abort.
|
||||||
- `knowledge_ingest` упал → abort до `tasks_create` и `git mv`. Буфер остаётся.
|
- `knowledge_ingest` упал → abort до `tasks_create` и `git mv`. Буфер остаётся.
|
||||||
- **Service channel:** create — карв-аут (wiki:2660), 422 busy больше не бывает; 409 на `wiki_update` (version) → retry со свежей версией.
|
- **Service channel:** create упал (гонка счётчика/переходный период) → **повторить последовательно**, не батчем; при стабильном отказе — abort до архивации.
|
||||||
- **Service channel:** `task_create` упал (гонка счётчика/переходный период) → **повторить последовательно**, не батчем; при стабильном отказе — abort до архивации.
|
- **Service channel:** спека уже существует в вики проекта (wiki:NNNN) → не дублировать `wiki_create`, ссылаться на неё.
|
||||||
- **Service channel:** спека уже существует в вики проекта (w:NNNN) → не дублировать `wiki_create`, ссылаться на неё.
|
|
||||||
- **domain:** `tasks_create` для `[<topic>-pointers]` упал → **abort** до content-тасок и до review-таски. Без pointers оставшиеся таски бесполезны (агент будет угадывать). Сообщить пользователю; буфер оставить на месте для retry.
|
- **domain:** `tasks_create` для `[<topic>-pointers]` упал → **abort** до content-тасок и до review-таски. Без pointers оставшиеся таски бесполезны (агент будет угадывать). Сообщить пользователю; буфер оставить на месте для retry.
|
||||||
- `tasks_create` упал на N-й content-таске → продолжить остальные. Сообщить partial. **Не делать** `git mv` без подтверждения пользователя.
|
- `tasks_create` упал на N-й content-таске → продолжить остальные. Сообщить partial. **Не делать** `git mv` без подтверждения пользователя.
|
||||||
- `tasks_create` упал на review-таске (шаг 8) → не блокировать; перейти к архивации, сообщить пользователю чтобы создал вручную из `.archive/`.
|
- `tasks_create` упал на review-таске (шаг 8) → не блокировать; перейти к архивации, сообщить пользователю чтобы создал вручную из `.archive/`.
|
||||||
@@ -439,7 +441,7 @@ description: >
|
|||||||
- **Всегда (любой маршрут):** создаёт summary-страницу `.wiki/concepts/<topic>.md` в `.workshop/` + добавляет строку в `index.md`.
|
- **Всегда (любой маршрут):** создаёт summary-страницу `.wiki/concepts/<topic>.md` в `.workshop/` + добавляет строку в `index.md`.
|
||||||
- **workshop-meta:** summary IS контент (шаг 6 записывает полное тело; шаг 9 дополняет секцию «задачи/ссылки» или пропускается если уже полный).
|
- **workshop-meta:** summary IS контент (шаг 6 записывает полное тело; шаг 9 дополняет секцию «задачи/ссылки» или пропускается если уже полный).
|
||||||
- **domain:** создаёт запись в target-wiki через MCP (`mcp__projects-meta__knowledge_ingest`).
|
- **domain:** создаёт запись в target-wiki через MCP (`mcp__projects-meta__knowledge_ingest`).
|
||||||
- **domain (service channel):** создаёт спека-сущность в вики mappa-проекта (`mcp__mappa__wiki_create` — карв-аут); импл-таски + review-umbrella — сервисные таски (`mcp__mappa__task_create` — карв-аут); covering-письмо в инбокс цели (`inbox_send`). Pointers-таска НЕ создаётся (спека уже в вики).
|
- **domain (service channel):** создаёт спека-сущность в вики mappa-проекта (`mcp__mappa__wiki_create`, карв-аут wiki:2660); импл-таски + review-umbrella — сервисные таски (`mcp__mappa__task_create`, карв-аут); covering-письмо в инбокс цели (`inbox_send`). Pointers-таска НЕ создаётся (спека уже в вики).
|
||||||
- **domain:** создаёт также **mandatory pre-impl** таску `[<topic>-pointers]` в target — pre-filled блок текста для `.wiki/CLAUDE.md` Domain conventions (ссылки на global wiki slug + workshop archive trace + local overview.md). Без неё последующий импл-агент попадает в дыру: where_stopped one-liner + пустой Domain conventions stub.
|
- **domain:** создаёт также **mandatory pre-impl** таску `[<topic>-pointers]` в target — pre-filled блок текста для `.wiki/CLAUDE.md` Domain conventions (ссылки на global wiki slug + workshop archive trace + local overview.md). Без неё последующий импл-агент попадает в дыру: where_stopped one-liner + пустой Domain conventions stub.
|
||||||
- **skill:** создаёт `~/projects/claude-skills/skills/<name>/SKILL.md` — **только шапка + пустой каркас**. Локальный коммит в `claude-skills/`. **Без** установки, push, или build-hermes — это всё в созданных baseline-тасках.
|
- **skill:** создаёт `~/projects/claude-skills/skills/<name>/SKILL.md` — **только шапка + пустой каркас**. Локальный коммит в `claude-skills/`. **Без** установки, push, или build-hermes — это всё в созданных baseline-тасках.
|
||||||
- Создаёт N тасок в target `.tasks/` через MCP.
|
- Создаёт N тасок в target `.tasks/` через MCP.
|
||||||
@@ -459,6 +461,6 @@ description: >
|
|||||||
- **Skill:** не бампить `version` после первой записи (это работа владельца `claude-skills/`).
|
- **Skill:** не бампить `version` после первой записи (это работа владельца `claude-skills/`).
|
||||||
- **Skill:** не промоутить в существующий скил (см. Failure modes — abort).
|
- **Skill:** не промоутить в существующий скил (см. Failure modes — abort).
|
||||||
- **Skill:** не пропускать обязательный preview + confirm перед `Write` — действие выходит за пределы мастерской, изменяет соседний репозиторий.
|
- **Skill:** не пропускать обязательный preview + confirm перед `Write` — действие выходит за пределы мастерской, изменяет соседний репозиторий.
|
||||||
- **Service channel:** не батчить `task_create` (гонка счётчика, инцидент 2026-08-24: 6/7 упали) — только последовательно; `wiki_update`/`task_close` со свежей version (409 → retry).
|
- **Service channel:** не батчить `task_create` (гонка sha-CAS счётчика, инцидент 2026-08-24: 6/7 упали) — только последовательно. Create — карв-аут, лиз не нужен.
|
||||||
- **Service channel:** не плодить pointers-таску, если спека уже в вики проекта (w:NNNN) — описание импл-тасок ссылается на неё инлайн.
|
- **Service channel:** не плодить pointers-таску, если спека уже в вики проекта (wiki:NNNN) — описание импл-тасок ссылается на неё инлайн.
|
||||||
- **Service channel:** не забывать covering-письмо в инбокс цели — таска на борде не пингует живую сессию.
|
- **Service channel:** не забывать covering-письмо в инбокс цели — таска на борде не пингует живую сессию.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: mappa-closing-ritual
|
name: mappa-closing-ritual
|
||||||
author: ours
|
author: ours
|
||||||
version: 1.0.0
|
version: 1.2.0
|
||||||
description: >
|
description: >
|
||||||
Финиш-фаза форкфлоу: handoff write (mcp__mappa__handoff_write, версия h:N)
|
Финиш-фаза форкфлоу: handoff write (mcp__mappa__handoff_write, версия h:N)
|
||||||
+ PROPOSE wiki-ingest + PROPOSE закрытий тасок. Мутации — только после
|
+ PROPOSE wiki-ingest + PROPOSE закрытий тасок. Мутации — только после
|
||||||
@@ -78,13 +78,13 @@ Forward-looking, не timeline: handoff = связка новых вещей к
|
|||||||
### 5. Propose wiki-ingest (не писать!)
|
### 5. Propose wiki-ingest (не писать!)
|
||||||
|
|
||||||
Если за сессию появилось durable-знание — **ПРЕДЛОЖИТЬ** ingest
|
Если за сессию появилось durable-знание — **ПРЕДЛОЖИТЬ** ingest
|
||||||
(`mappa-knowledge`: mappa wiki_create/update — version+409, wiki:2660), перечислив кандидатов.
|
(`mappa-knowledge`: mappa wiki create — карв-аут, update — version+409, wiki:2660), перечислив кандидатов.
|
||||||
Ничего не писать без подтверждения.
|
Ничего не писать без подтверждения.
|
||||||
|
|
||||||
### 6. Propose task-board closes (не закрывать!)
|
### 6. Propose task-board closes (не закрывать!)
|
||||||
|
|
||||||
Если есть задачи, выглядящие закрытыми — **ПРЕДЛОЖИТЬ** закрытия
|
Если есть задачи, выглядящие закрытыми — **ПРЕДЛОЖИТЬ** закрытия
|
||||||
(`mappa-task-work`: task_close — version+409). Уважать ralph-loop: verifier-задачи
|
(`mappa-task-work`: task_close с version+409, wiki:2660). Уважать ralph-loop: verifier-задачи
|
||||||
закрывать только через verifier (attempt/harness-record).
|
закрывать только через verifier (attempt/harness-record).
|
||||||
|
|
||||||
### 7. Формат предложения — один блок
|
### 7. Формат предложения — один блок
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: mappa-delegation
|
name: mappa-delegation
|
||||||
author: ours
|
author: ours
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
description: >
|
description: >
|
||||||
Цикл делегирования задачи другому агенту/проекту: pre-flight gate →
|
Цикл делегирования задачи другому агенту/проекту: pre-flight gate →
|
||||||
шаблон тела → dry-run preview → confirm → covering-письмо в инбокс
|
шаблон тела → dry-run preview → confirm → covering-письмо в инбокс
|
||||||
@@ -44,10 +44,10 @@ steering-loop поля (notify/weight), парную review-таску для im
|
|||||||
|
|
||||||
Номер задаче присваивает сервер (`tasks_create` из счётчика agenda/task-counter) — постановщик номер не придумывает и не резервирует. Возвращённый `#n` из preview/confirm — машинный ключ задачи: им ссылаются блокеры, письма, decision-trail.
|
Номер задаче присваивает сервер (`tasks_create` из счётчика agenda/task-counter) — постановщик номер не придумывает и не резервирует. Возвращённый `#n` из preview/confirm — машинный ключ задачи: им ссылаются блокеры, письма, decision-trail.
|
||||||
|
|
||||||
> **Интерактивный контракт (wiki:2660).** `task_create` — карв-аут, лиз НЕ
|
> **Контракт (interactive, wiki:2660).** `task_create` — **карв-аут без
|
||||||
> нужен (create = INSERT, входной контур). `task_close`/`task_update` — optimistic
|
> лиза** (create-без-лиза как принцип); update/close — version+409 (409 →
|
||||||
> version+409 (конфликт → свежая version из `task_get` → retry). File channel —
|
> re-GET → retry). file channel — sha-CAS через Gitea. Claim/TTL нет —
|
||||||
> sha-CAS через Gitea (projects-meta), там свои правила.
|
> «взять таску» = conditional update по version (поллер вне mappa).
|
||||||
|
|
||||||
## Steps (цикл)
|
## Steps (цикл)
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ steering-loop поля (notify/weight), парную review-таску для im
|
|||||||
4. **notify — кому докладывать о завершении/затыке?** (slug проекта; обычно `.workshop` или `OpeItcLoc03/workshop`)
|
4. **notify — кому докладывать о завершении/затыке?** (slug проекта; обычно `.workshop` или `OpeItcLoc03/workshop`)
|
||||||
5. **Session-break после этой задачи?** — нужен ли разрыв сессии после её закрытия (domain-switch, milestone, heavy infra)?
|
5. **Session-break после этой задачи?** — нужен ли разрыв сессии после её закрытия (domain-switch, milestone, heavy infra)?
|
||||||
- Если **да** → проставить `session_break` в теле задачи (см. шаблон): `true` или строка-hint с названием следующего трека. `mappa-task-work` остановится после close и предложит завершить сессию, не клеймя следующую задачу.
|
- Если **да** → проставить `session_break` в теле задачи (см. шаблон): `true` или строка-hint с названием следующего трека. `mappa-task-work` остановится после close и предложит завершить сессию, не клеймя следующую задачу.
|
||||||
- Если **нет** → поле не добавлять (дефолт — агент продолжает `claim-next`).
|
- Если **нет** → поле не добавлять (дефолт — агент продолжает цикл).
|
||||||
|
|
||||||
### 2. Составить тело задачи по шаблону
|
### 2. Составить тело задачи по шаблону
|
||||||
|
|
||||||
@@ -132,7 +132,8 @@ mcp__mappa__inbox_send(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
(`task_create` — карв-аут (wiki:2660), доставка письма — карв-аут.)
|
(Мутации update/close — version-based (409 → retry); доставка письма —
|
||||||
|
карв-аут, лиза не требует.)
|
||||||
|
|
||||||
Причина: таска на борде **не пингует живую сессию** получателя. Поллер
|
Причина: таска на борде **не пингует живую сессию** получателя. Поллер
|
||||||
подхватит по `Weight`/`Notify`, но живая интерактивная сессия узнаёт только
|
подхватит по `Weight`/`Notify`, но живая интерактивная сессия узнаёт только
|
||||||
@@ -175,7 +176,7 @@ task» — общий случай (шаг 7 — его частность дл
|
|||||||
|
|
||||||
## Side effects
|
## Side effects
|
||||||
|
|
||||||
- Создаёт таску в target-проекте через `tasks_create` (file channel — Gitea commit; service channel — mappa-сущность карв-аутом, wiki:2660).
|
- Создаёт таску в target-проекте через `tasks_create` (file channel — Gitea commit; service channel — mappa-сущность, create = карв-аут без лиза wiki:2660).
|
||||||
- Опционально создаёт парную review-таску (status=blocked).
|
- Опционально создаёт парную review-таску (status=blocked).
|
||||||
- Covering-письмо в инбокс получателя (кросс-проектная делегация).
|
- Covering-письмо в инбокс получателя (кросс-проектная делегация).
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: mappa-knowledge
|
name: mappa-knowledge
|
||||||
author: ours
|
author: ours
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
description: >
|
description: >
|
||||||
Цикл работы со знаниями проекта в Mappa (Karpathy LLM Wiki, канал =
|
Цикл работы со знаниями проекта в Mappa (Karpathy LLM Wiki, канал =
|
||||||
mappa-сущности): ingest → query → lint + граф-слой для
|
mappa-сущности): ingest → query → lint + граф-слой для
|
||||||
@@ -10,8 +10,8 @@ description: >
|
|||||||
«запроси вики», «проверь вики», «use project wiki», «query the wiki»,
|
«запроси вики», «проверь вики», «use project wiki», «query the wiki»,
|
||||||
«что связывает X и Y», «как связаны», «путь между X и Y», «what connects
|
«что связывает X и Y», «как связаны», «путь между X и Y», «what connects
|
||||||
X and Y», «что ссылается на X», «backlinks of X», «сироты», «битые ссылки»,
|
X and Y», «что ссылается на X», «backlinks of X», «сироты», «битые ссылки»,
|
||||||
«orphan pages». Wiki = сущности type=wiki (чтение — карв-аут лиза; запись —
|
«orphan pages». Wiki = сущности type=wiki (чтение — карв-аут; create —
|
||||||
version+409, wiki:2660). Реляционные вопросы — через graph_* (BFS на
|
карв-аут, update — version+409; контракт wiki:2660). Реляционные вопросы — через graph_* (BFS на
|
||||||
стороне сервиса), guarded failure-mode: одна страница и стоп, без
|
стороне сервиса), guarded failure-mode: одна страница и стоп, без
|
||||||
многохоповых цепочек чтением. Skip для одно-страничных контентных вопросов.
|
многохоповых цепочек чтением. Skip для одно-страничных контентных вопросов.
|
||||||
---
|
---
|
||||||
@@ -25,7 +25,8 @@ query / lint) + **граф-слой** для реляционных и стру
|
|||||||
сущностями читают через граф (graph_*).
|
сущностями читают через граф (graph_*).
|
||||||
|
|
||||||
Канал — Mappa (`mcp__mappa__*`), НЕ файлы. Страница — сущность `type=wiki`
|
Канал — Mappa (`mcp__mappa__*`), НЕ файлы. Страница — сущность `type=wiki`
|
||||||
(`wiki:N`); чтение — карв-аут, запись — version+409 (wiki:2660).
|
(`wiki:N`); чтение — карв-аут; **create — карв-аут без лиза; update —
|
||||||
|
optimistic concurrency (version+409 → retry)** (контракт wiki:2660, v0.12.0).
|
||||||
Файлового `.wiki/` больше нет; `setup-wiki` умер (нечего настраивать).
|
Файлового `.wiki/` больше нет; `setup-wiki` умер (нечего настраивать).
|
||||||
|
|
||||||
## Когда использовать
|
## Когда использовать
|
||||||
@@ -64,19 +65,19 @@ README/ADR (не персистентная база знаний), проект
|
|||||||
|
|
||||||
| Операция | Тул | Примечание |
|
| Операция | Тул | Примечание |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Чтение страницы | `mcp__mappa__wiki_get(project?, slug)` | чтение — карв-аут (решение 19) |
|
| Чтение страницы | `mcp__mappa__wiki_get(project?, slug)` | чтение — карв-аут |
|
||||||
| Поиск страниц | `mcp__mappa__entity_search(q, type='wiki', project?, scope?, limit)` | ILIKE по body/title |
|
| Поиск страниц | `mcp__mappa__entity_search(q, type='wiki', project?, scope?, limit)` | ILIKE по body/title |
|
||||||
| Создать страницу | `mcp__mappa__wiki_create(project, slug, body)` | карв-аут (wiki:2660), лиз не нужен |
|
| Создать страницу | `mcp__mappa__wiki_create(project, slug, body)` | **карв-аут без лиза** |
|
||||||
| Обновить страницу | `mcp__mappa__wiki_update(project, id, title?, body?, version)` | version+409; id — internal |
|
| Обновить страницу | `mcp__mappa__wiki_update(project, id, title?, body?, version)` | **version-based**: конфликт → 409 → retry со свежей version из wiki_get |
|
||||||
| Путь между сущностями | `mcp__mappa__graph_path({from, to})` | кратчайшая цепочка, BFS |
|
| Путь между сущностями | `mcp__mappa__graph_path({from, to})` | кратчайшая цепочка, BFS |
|
||||||
| Соседи / исходящие | `mcp__mappa__graph_neighbors({id})` | рёбра узла с резолвом целей |
|
| Соседи / исходящие | `mcp__mappa__graph_neighbors({id})` | рёбра узла с резолвом целей |
|
||||||
| Входящие ссылки | `mcp__mappa__graph_backlinks({id})` | кто ссылается на узел |
|
| Входящие ссылки | `mcp__mappa__graph_backlinks({id})` | кто ссылается на узел |
|
||||||
| Здоровье графа | `mcp__mappa__graph_stats()` | nodes/edges/components |
|
| Здоровье графа | `mcp__mappa__graph_stats()` | nodes/edges/components |
|
||||||
|
|
||||||
**Запись — version+409 (wiki:2660 interactive contract).** `wiki_create` —
|
**Запись — карв-аут (create) / version-based (update), без лиза (interactive
|
||||||
карв-аут (лиз не нужен); `wiki_update` несёт `version` из последнего чтения,
|
contract, wiki:2660).** `wiki_create` не требует claim_token; `wiki_update`
|
||||||
конфликт → 409 → `wiki_get` заново → retry. Долгих лизов/TTL/heartbeat больше
|
принимает ожидаемую `version` (свежую из `wiki_get`) — конфликт → 409 →
|
||||||
нет — живость владельца из session live-ingest.
|
re-GET → retry.
|
||||||
|
|
||||||
**Рефы и id (#1037/#1028).** Публичная поверхность несёт per-type реф полным
|
**Рефы и id (#1037/#1028).** Публичная поверхность несёт per-type реф полным
|
||||||
именем первым полем: `ref: "wiki:3"` (решение 20, конвенция #1028), `num`
|
именем первым полем: `ref: "wiki:3"` (решение 20, конвенция #1028), `num`
|
||||||
@@ -97,10 +98,11 @@ per-type рефы полными именами (`[[task:N]]`/`[[inbox:N]]`).
|
|||||||
3. Создай `sources/<slug>` — одну страницу-резюме на источник (~50–150 строк;
|
3. Создай `sources/<slug>` — одну страницу-резюме на источник (~50–150 строк;
|
||||||
ссылку на raw клади в frontmatter `raw_path` + `ingested:`).
|
ссылку на raw клади в frontmatter `raw_path` + `ingested:`).
|
||||||
4. Для каждой затронутой страницы:
|
4. Для каждой затронутой страницы:
|
||||||
- есть → обнови (`wiki_update(project, id, body, version)`). **Противоречия
|
- есть → обнови (`wiki_update(project, id, body, version)` — version свежая
|
||||||
помечай явно** блоком `> **Противоречие:** источник A говорит X, источник B — Y`.
|
из `wiki_get`; 409 → re-GET → retry). **Противоречия помечай явно** блоком
|
||||||
|
`> **Противоречие:** источник A говорит X, источник B — Y`.
|
||||||
Не затирай молча.
|
Не затирай молча.
|
||||||
- нет → создай (`wiki_create`).
|
- нет → создай (`wiki_create`, карв-аут).
|
||||||
5. Обнови `index` (каталог: одна строка на страницу) — опционально; каталог
|
5. Обнови `index` (каталог: одна строка на страницу) — опционально; каталог
|
||||||
по умолчанию — `entity_search` (решение 1).
|
по умолчанию — `entity_search` (решение 1).
|
||||||
6. Отчитайся пользователю: что создано, что обновлено, какие противоречия.
|
6. Отчитайся пользователю: что создано, что обновлено, какие противоречия.
|
||||||
@@ -113,8 +115,9 @@ per-type рефы полными именами (`[[task:N]]`/`[[inbox:N]]`).
|
|||||||
|
|
||||||
**Один ingest может затронуть 10–15 страниц. Это нормально — для того LLM и нужны.**
|
**Один ingest может затронуть 10–15 страниц. Это нормально — для того LLM и нужны.**
|
||||||
|
|
||||||
Порядок записи: все wiki-мутации одним циклом; `wiki_update` — со свежей
|
Порядок записи: все wiki-мутации одним циклом; create — карв-аут, update — с
|
||||||
`version` из чтения (409 → retry). Создание новых страниц — карв-аут.
|
version (свежей из `wiki_get`); 409 → re-GET → retry. Лиз/claim для записи НЕ
|
||||||
|
нужен (wiki:2660).
|
||||||
|
|
||||||
### Query — вопрос по вики
|
### Query — вопрос по вики
|
||||||
|
|
||||||
@@ -231,8 +234,9 @@ level/since/component/entity, retention 14d). Ручную `log`-страниц
|
|||||||
- **Не-ASCII слаги.** Ломают grep и кросс-платформенность. Транслитерируй.
|
- **Не-ASCII слаги.** Ломают grep и кросс-платформенность. Транслитерируй.
|
||||||
- **Пропущенные противоречия в lint.** Ценность вики — во вскрытых напряжениях,
|
- **Пропущенные противоречия в lint.** Ценность вики — во вскрытых напряжениях,
|
||||||
а не в ложном консенсусе.
|
а не в ложном консенсусе.
|
||||||
- **Запись — version+409 (wiki:2660).** `wiki_create` — карв-аут; `wiki_update` со свежей `version` (конфликт → 409 → retry).
|
- **Запись без version (update).** `wiki_update` без свежей version →
|
||||||
- **Держать лиз на чтение/раздумья.** Лиз — на время записи. Чтение — карв-аут.
|
last-write-wins, риск затирания чужого; бери version из `wiki_get`, 409 → retry.
|
||||||
|
- **Держать claim на чтение/раздумья.** Claim — на время работы; чтение — карв-аут.
|
||||||
- **Реляционный вопрос чтением одной страницы.** Это тот самый 0%-recall
|
- **Реляционный вопрос чтением одной страницы.** Это тот самый 0%-recall
|
||||||
провал — зови graph_*.
|
провал — зови graph_*.
|
||||||
- **Слаги/пути в graph-тулы.** Только internal id, и только свежие (удалённая
|
- **Слаги/пути в graph-тулы.** Только internal id, и только свежие (удалённая
|
||||||
@@ -244,7 +248,7 @@ level/since/component/entity, retention 14d). Ручную `log`-страниц
|
|||||||
|
|
||||||
- Реляционный вопрос → читаешь страницу вместо `graph_*`.
|
- Реляционный вопрос → читаешь страницу вместо `graph_*`.
|
||||||
- Правка `sources/` или молчаливая перезапись противоречия.
|
- Правка `sources/` или молчаливая перезапись противоречия.
|
||||||
- Wiki-мутация без лиза (422) или лиз держится на чтение.
|
- Wiki-мутация update без version (last-write-wins) или create с выдуманным claim.
|
||||||
- Нарративный оп-лог руками.
|
- Нарративный оп-лог руками.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: mappa-messaging
|
name: mappa-messaging
|
||||||
author: ours
|
author: ours
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
description: >
|
description: >
|
||||||
Цикл межсессионной почты через Mappa: SEND (inbox_send) → RECEIVE
|
Цикл межсессионной почты через Mappa: SEND (inbox_send) → RECEIVE
|
||||||
(inbox_monitor) → POLICY (peer ≠ authority). Адрес = имя папки проекта из
|
(inbox_monitor) → POLICY (peer ≠ authority). Адрес = имя папки проекта из
|
||||||
@@ -156,8 +156,8 @@ mcp__mappa__inbox_send(
|
|||||||
lifecycle-уведомления («таска создана», «закрыта», «заблокирована»). Не больше.
|
lifecycle-уведомления («таска создана», «закрыта», «заблокирована»). Не больше.
|
||||||
- **Задачи — только через `mcp__mappa__task_*`.** Доска — единственный
|
- **Задачи — только через `mcp__mappa__task_*`.** Доска — единственный
|
||||||
источник правды о задаче: существование, статус, скоуп, решения создаются и
|
источник правды о задаче: существование, статус, скоуп, решения создаются и
|
||||||
меняются через `task_create` / `task_close` (карв-аут + version+409, wiki:2660)
|
меняются через `task_create` / `task_close` — никогда не «решаются» внутри
|
||||||
— никогда не «решаются» внутри письма.
|
письма. (Create — карв-аут; update/close — version+409, wiki:2660.)
|
||||||
|
|
||||||
Следствие: **если это не на доске — это не задача и не решение, это разговор.**
|
Следствие: **если это не на доске — это не задача и не решение, это разговор.**
|
||||||
Значимый дизайн-выбор должен лечь на доску (или в вики), инбокс лишь указывает
|
Значимый дизайн-выбор должен лечь на доску (или в вики), инбокс лишь указывает
|
||||||
|
|||||||
@@ -1,36 +1,33 @@
|
|||||||
---
|
---
|
||||||
name: mappa-task-work
|
name: mappa-task-work
|
||||||
author: ours
|
author: ours
|
||||||
version: 1.1.0
|
version: 1.2.0
|
||||||
description: >
|
description: >
|
||||||
Центральный цикл работы с тасками в Mappa: ориентация → выбор работы
|
Центральный цикл работы с тасками в Mappa: ориентация → выбор работы
|
||||||
(owner, priority/due) → исполнение → сдача (close + review-umbrella) +
|
(priority/due) → исполнение → сдача (close + review-umbrella) +
|
||||||
loop-mode «поработай очередь». Борд = сущности mappa (решения 14/15/20);
|
loop-mode «поработай очередь». Борд = сущности mappa (решения 14/15/19/20);
|
||||||
мутации — version+409 (wiki:2660 interactive contract), «взять таску» =
|
create — карв-аут, update/close — optimistic concurrency (version+409),
|
||||||
status→active + owner, живность владельца из session live-ingest. Поглощает
|
owner = персистентный assignee, живость — из session владельца
|
||||||
using-tasks + task-format + task-loop (loop-mode ВНУТРИ) + priority-due-раздел
|
(interactive contract, wiki:2660). Поглощает using-tasks +
|
||||||
(старые имена — триггер-синонимы). Триггеры: «что на досках», «возьми таску»,
|
task-format + task-loop (loop-mode ВНУТРИ) + priority-due-раздел (старые
|
||||||
«какой статус», «update status», «pause», «switch to X», «где мы остановились»,
|
имена — триггер-синонимы).
|
||||||
«work the queue», «поработай очередь», «прогони доску». Приоритет = территория
|
Триггеры: «что на досках», «возьми таску», «какой статус», «update status»,
|
||||||
человека: агенты ставят P0-P2/дедлайн только при создании, дефолт P1;
|
«pause», «switch to X», «где мы остановились», «work the queue», «поработай
|
||||||
просрочка → notify, без авто-бампа. НЕ про делегирование (→ mappa-delegation),
|
очередь», «прогони доску». Приоритет = территория человека: агенты ставят
|
||||||
НЕ про доску-обзор (→ ops/using-system-snapshot).
|
P0-P2/дедлайн только при создании, дефолт P1; просрочка → notify, без
|
||||||
|
авто-бампа. НЕ про делегирование (→ mappa-delegation), НЕ про доску-обзор
|
||||||
|
(→ ops/using-system-snapshot).
|
||||||
---
|
---
|
||||||
|
|
||||||
# mappa-task-work
|
# mappa-task-work
|
||||||
|
|
||||||
Центральный цикл работы с задачами: **ориентация → выбор работы → исполнение →
|
Центральный цикл работы с задачами: **ориентация → выбор работы → исполнение →
|
||||||
сдача**. Борд — сущности mappa (`type=task`, `task:N`): чтение — карв-аут,
|
сдача**. Борд — сущности mappa (`type=task`, `task:N`): чтение — карв-аут;
|
||||||
**мутации — optimistic concurrency** (wiki:2660 interactive contract):
|
**create — карв-аут без лиза; update/close — optimistic concurrency
|
||||||
version+409, конфликт → retry со свежей version из `task_get`. Скилл = цикл,
|
(version+409 → retry)**; **owner = персистентный assignee; живость таски —
|
||||||
не тул: одна механика на выбор/исполнение/сдачу, плюс **loop-mode** («поработай
|
из session владельца** (interactive contract, wiki:2660; поллер вне mappa).
|
||||||
очередь») внутри — отдельный скил не создаётся.
|
Скилл = цикл, не тул: одна механика на выбор/исполнение/сдачу, плюс
|
||||||
|
**loop-mode** («поработай очередь») внутри — отдельный скил не создаётся.
|
||||||
> **Интерактивный контракт (wiki:2660).** claim/TTL/heartbeat выпилены:
|
|
||||||
> поллер не клиент mappa (живёт на файловых досках projects-meta), клиент —
|
|
||||||
> интерактивные сессии. «Взять таску» = `task_update(status=active, owner=<сессия>)`
|
|
||||||
> с верной version; конфликт (уже взято) → 409 → выбор другой таски. Живость
|
|
||||||
> владельца — из session live-ingest (сессия `pi` пишется сама), не таймер.
|
|
||||||
|
|
||||||
> **Переходное (file channel).** Пока поллер/кэш читают файловые борды
|
> **Переходное (file channel).** Пока поллер/кэш читают файловые борды
|
||||||
> (`.tasks/STATUS.md`), legacy-канал живёт: блоки в файле обязаны строгому
|
> (`.tasks/STATUS.md`), legacy-канал живёт: блоки в файле обязаны строгому
|
||||||
@@ -51,29 +48,32 @@ version+409, конфликт → retry со свежей version из `task_get
|
|||||||
|
|
||||||
| Операция | Тул | Примечание |
|
| Операция | Тул | Примечание |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Взять таску | `mcp__mappa__task_update(project, id, status='active', owner=<сессия>, version)` | «взять» = conditional update; 409 → уже взята |
|
| Взять следующую ready-таску | `mcp__mappa__task_update(project, id, owner=<своя>, status=active…, version)` | **conditional update**: status→active, owner=X, version+409 (кто первый с верной version — тот и взял) |
|
||||||
| Сбросить/отдать | `mcp__mappa__task_update(project, id, status='ready', owner='', version)` | release = обычный update |
|
| Создать таску | `mcp__mappa__task_create(project, slug, title?, description?, status?, priority?, due?)` | **карв-аут без лиза**; per-type номер (решение 20) |
|
||||||
| Создать таску | `mcp__mappa__task_create(project, slug, title?, description?, status?, priority?, due?)` | карв-аут, лиз не нужен (wiki:2660) |
|
| Закрыть таску | `mcp__mappa__task_close(project, id, version)` | **version-based**: конфликт → 409 → retry со свежей version из task_get |
|
||||||
| Закрыть таску | `mcp__mappa__task_close(project, id, version)` | version+409 (конфликт → retry) |
|
| Обновить таску | `mcp__mappa__task_update(project, id, parent?, owner?, status?, reason?, version)` | version-based; 409 → retry |
|
||||||
| Прочитать таску | `mcp__mappa__entity_get(id)` | id internal из search; несёт version |
|
| Прочитать таску | `mcp__mappa__entity_get(id)` | id internal из search |
|
||||||
| Список борда | `mcp__mappa__entity_search(q, type='task', project=<имя>, limit)` | все статусы |
|
| Список борда | `mcp__mappa__entity_search(q, type='task', project=<имя>, limit)` | все статусы |
|
||||||
| Дерево parent_of | `mcp__mappa__graph_tree(root, depth?, fields?, limit?)` | зонтики/иерархия |
|
| Дерево parent_of | `mcp__mappa__graph_tree(root, depth?, fields?, limit?)` | зонтики/иерархия |
|
||||||
| Связанные сущности | `mcp__mappa__graph_neighbors/backlinks(id)` | рефы к таске |
|
| Связанные сущности | `mcp__mappa__graph_neighbors/backlinks(id)` | рефы к таске |
|
||||||
| Просрочка | `mcp__mappa__admin_overdue_scan(project?)` | P2-джоба: notify в инбокс, без мутаций |
|
| Просрочка | `mcp__mappa__admin_overdue_scan(project?)` | P2-джоба: notify в инбокс, без мутаций |
|
||||||
|
| Живость владельца | `mcp__mappa__session_list(project, stale_minutes?)` | сессия владельца жива/стала stale → таска active or not |
|
||||||
| Уведомление при закрытии | `mcp__mappa__inbox_send(project=<notify>, from=<своя>, subject, body)` | письмо комиссионеру |
|
| Уведомление при закрытии | `mcp__mappa__inbox_send(project=<notify>, from=<своя>, subject, body)` | письмо комиссионеру |
|
||||||
|
|
||||||
**Взятие таски = version+409, не лиз.** Каждая таска несёт `version`; conditional
|
**Owner = персистентный assignee; живость — из session (interactive contract,
|
||||||
update (`status=active, owner=<сессия>, version=N`) проходит, только если никто
|
wiki:2660).** Нет TTL/claim/таймера на таске: «взял таску» = conditional
|
||||||
не изменил её после твоего чтения. Конфликт → **409** → `task_get` заново →
|
update (`status→active, owner=X` + version, 409 при конфликте — кто первый,
|
||||||
выбирай другую. Конкуренции «проект занят» нет: два агента берут разные таски
|
тот и взял). Живость владельца — сессия: таска с owner=X активна, пока сессия
|
||||||
свободно. Живость — из сессии: пока твоя pi-сессия активна (end-state≠clean),
|
X жива (end-state≠clean, не stale; `session_list(project)`); краш = stale →
|
||||||
твои 🔴 видны как «в работе».
|
решает человек/оркестратор (поллер вне mappa, работает на файловых досках
|
||||||
|
projects-meta). Write-пути (create/update/close) лизов/claim не требуют —
|
||||||
|
только version на update/close (409 при конфликте).
|
||||||
|
|
||||||
**Рефы и id (#1037/#1028).** Таски наружу несут `ref: "task:N"` полным именем
|
**Рефы и id (#1037/#1028).** Таски наружу несут `ref: "t:N"` полным именем
|
||||||
первым полем (конвенция #1028), `num` следом, глобальный `id` — internal
|
первым полем (`task:N`, конвенция #1028), `num` следом, глобальный `id` —
|
||||||
(последним, для addressing в тулах). Ссылайся на таску `[[task:N]]`/`task:N`
|
internal (последним, для addressing в тулах). Ссылайся на таску
|
||||||
в прозе (слаг/имя первым, реф как якорь: «таска `mappa-task-work` (task:1062)»),
|
`[[task:N]]`/`task:N` в прозе (слаг/имя первым, реф как якорь: «таска
|
||||||
никогда `#<глобальный id>`.
|
`mappa-task-work` (task:1062)»), никогда `#<глобальный id>`.
|
||||||
|
|
||||||
## Статусы (эмодзи для презентации)
|
## Статусы (эмодзи для презентации)
|
||||||
|
|
||||||
@@ -101,19 +101,19 @@ update (`status=active, owner=<сессия>, version=N`) проходит, то
|
|||||||
4. Подтверди одним предложением: «Мы в середине X, следующий шаг — Y».
|
4. Подтверди одним предложением: «Мы в середине X, следующий шаг — Y».
|
||||||
5. Спроси, верен ли план, перед действиями.
|
5. Спроси, верен ли план, перед действиями.
|
||||||
|
|
||||||
### Фаза 1 — Выбор работы (owner, priority/due)
|
### Фаза 1 — Выбор работы (priority/due)
|
||||||
|
|
||||||
1. Собери кандидатов: `entity_search(q, type='task', project=<имя>)` →
|
1. **Выбор таски — из списка борда** (`entity_search(q, type='task', project)`):
|
||||||
готовые ⚪ ready. Порядок приоритета: **P0-пул первый, внутри по дедлайну
|
порядок — **P0-пул первый, внутри по дедлайну (просроченные первыми),
|
||||||
(просроченные первыми), потом P1, потом P2**; отсутствующий priority = P1
|
потом P1, потом P2**; отсутствующий priority = P1 (task-priority-due).
|
||||||
(сортировка — клиентская, wiki:2660).
|
«Взять таску» = `task_update(project, id, owner=<своя>, status='active',
|
||||||
|
version)` — conditional update: status→active, owner=X, version+409; кто
|
||||||
|
первый с верной version — тот и взял (interactive contract, wiki:2660).
|
||||||
|
`owner` = `<machine>:<runtime>:<session>`.
|
||||||
2. **Локально-первая рекомендация** — борд cwd первым; кросс-проект — футонота
|
2. **Локально-первая рекомендация** — борд cwd первым; кросс-проект — футонота
|
||||||
(`Cross-project: N 🔴 active — см. tasks_aggregate`) только если N>0 и в cwd
|
(`Cross-project: N 🔴 active — см. tasks_aggregate`) только если N>0 и в cwd
|
||||||
нет активной 🔴. Кросс-проектные ургенты — информация, не драйвер «что делать здесь».
|
нет активной 🔴. Кросс-проектные ургенты — информация, не драйвер «что делать здесь».
|
||||||
3. **Взять таску:** `task_update(project, id, status='active', owner='<machine>:<pi>:<session>', version=<из чтения>)`.
|
3. **Priority/Due — территория человека (раздел task-priority-due):**
|
||||||
- 200 → таска твоя (🔴, owner=твоя сессия).
|
|
||||||
- **409** → кто-то уже взял (version устарела) → `entity_get` → бери следующую.
|
|
||||||
4. **Priority/Due — территория человека (раздел task-priority-due):**
|
|
||||||
- Агент ставит `priority`/`due` **только при создании** таски (явные параметры
|
- Агент ставит `priority`/`due` **только при создании** таски (явные параметры
|
||||||
или строки `**Priority:** P0|P1|P2` / `**Due:** yyyy-mm-dd` в description).
|
или строки `**Priority:** P0|P1|P2` / `**Due:** yyyy-mm-dd` в description).
|
||||||
Отсутствует → дефолт P1, без дедлайна.
|
Отсутствует → дефолт P1, без дедлайна.
|
||||||
@@ -127,10 +127,10 @@ update (`status=active, owner=<сессия>, version=N`) проходит, то
|
|||||||
|
|
||||||
- **Одна активная таска** 🔴 на проект. Не параллель.
|
- **Одна активная таска** 🔴 на проект. Не параллель.
|
||||||
- Читай description + per-task файл (`<slug>.md`, где есть) до старта.
|
- Читай description + per-task файл (`<slug>.md`, где есть) до старта.
|
||||||
- Heartbeat не нужен: живость = живая pi-сессия (session-sync пишет её в mappa;
|
- Живость — из сессии владельца (`session_list(project)`), не таймер; долгие
|
||||||
stale-детект — по сессии владельца, не таймер на таске).
|
таски heartbeat не требуют (interactive contract, wiki:2660).
|
||||||
- **`session_break` gate** (из task-loop): если в description таски есть маркер
|
- **`session_break` gate** (из task-loop): если в description таски есть маркер
|
||||||
`session_break` — после close НЕ бери следующую: печатай
|
`session_break` — после close НЕ клейми следующую: печатай
|
||||||
`🔚 SESSION BOUNDARY …` и останавливайся (домен-свитч / milestone / тяжёлая инфра).
|
`🔚 SESSION BOUNDARY …` и останавливайся (домен-свитч / milestone / тяжёлая инфра).
|
||||||
|
|
||||||
### Фаза 3 — Сдача (close + review-umbrella)
|
### Фаза 3 — Сдача (close + review-umbrella)
|
||||||
@@ -139,8 +139,8 @@ update (`status=active, owner=<сессия>, version=N`) проходит, то
|
|||||||
каждого — evidence: тест в диффе, артефакт, ссылка на дизайн. Нет evidence на
|
каждого — evidence: тест в диффе, артефакт, ссылка на дизайн. Нет evidence на
|
||||||
критерий → спроси user'а «закрывать или подождать coverage'а».
|
критерий → спроси user'а «закрывать или подождать coverage'а».
|
||||||
2. Resolve/drop открытые вопросы.
|
2. Resolve/drop открытые вопросы.
|
||||||
3. `task_close(project, id, version=<из чтения>)` → статус `done`.
|
3. `task_close(project, id, version)` → статус `done`. `version` —
|
||||||
**409 на конфликт** → `entity_get` → повтори close со свежей version.
|
свежая из `entity_get(id)`/`task_get(id)`; конфликт (409) → re-GET → retry.
|
||||||
4. **Notify-письмо (кросс-проектные таски).** Если таска пришла из другого
|
4. **Notify-письмо (кросс-проектные таски).** Если таска пришла из другого
|
||||||
проекта (в description/meta есть `from:`/`notify:`) — `inbox_send`
|
проекта (в description/meta есть `from:`/`notify:`) — `inbox_send`
|
||||||
комиссионеру: `project=<notify>`, `subject="[event: closed] <slug>"`,
|
комиссионеру: `project=<notify>`, `subject="[event: closed] <slug>"`,
|
||||||
@@ -158,7 +158,8 @@ update (`status=active, owner=<сессия>, version=N`) проходит, то
|
|||||||
1. Текущая 🔴 → `task_close` если завершена (см. Фазу 3), иначе пометь
|
1. Текущая 🔴 → `task_close` если завершена (см. Фазу 3), иначе пометь
|
||||||
`status=paused` (owner остаётся; «where stopped» — в description или handoff).
|
`status=paused` (owner остаётся; «where stopped» — в description или handoff).
|
||||||
2. **Инбокс-свип** на границе тасок (`inbox_monitor`).
|
2. **Инбокс-свип** на границе тасок (`inbox_monitor`).
|
||||||
3. Возьми следующую: `task_update(status=active, owner=<сессия>)`. Прежняя остаётся 🟡.
|
3. Возьми следующую: `task_update(owner, status='active', version)` — прежняя
|
||||||
|
остаётся 🟡.
|
||||||
4. Подтверди ориентацию перед стартом.
|
4. Подтверди ориентацию перед стартом.
|
||||||
|
|
||||||
> **Never lose Where I stopped** — критичное поле: в description (последний
|
> **Never lose Where I stopped** — критичное поле: в description (последний
|
||||||
@@ -174,19 +175,19 @@ update (`status=active, owner=<сессия>, version=N`) проходит, то
|
|||||||
пока очередь не пуста или user не сказал стоп. **Интерактивный цикл, не демон.**
|
пока очередь не пуста или user не сказал стоп. **Интерактивный цикл, не демон.**
|
||||||
|
|
||||||
```
|
```
|
||||||
search(ready) → пусто? → STOP «борд пуст» (не поллить)
|
task_update(owner, status=active, version) → 409? re-GET → retry → пусто? → STOP «борд пуст»
|
||||||
↓ кандидат
|
↓ таска
|
||||||
task_update(status=active, owner=<сессия>, version) → 409? → следующий кандидат
|
|
||||||
↓ взято
|
|
||||||
работа в этой сессии (read description + <slug>.md)
|
работа в этой сессии (read description + <slug>.md)
|
||||||
↓
|
↓
|
||||||
завершена? нет → park: blocked (внешний) | paused (возобновляемо) → дальше
|
завершена? нет → park: blocked (внешний) | paused (возобновляемо) → следующая
|
||||||
↓ да
|
↓ да
|
||||||
pre-close coverage check → task_close(version)
|
consult_policy: human-only/strict-human → STOP перед close/commit, спросить user
|
||||||
|
↓ auto
|
||||||
|
pre-close coverage check → task_close
|
||||||
↓
|
↓
|
||||||
session_break на таске? → да: печатай 🔚 SESSION BOUNDARY, STOP
|
session_break на таске? → да: печатай 🔚 SESSION BOUNDARY, STOP
|
||||||
↓ нет
|
↓ нет
|
||||||
следующий кандидат …
|
следующая …
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Пустая очередь — естественный стоп, не wait-loop.** Нет `CronCreate`, нет
|
- **Пустая очередь — естественный стоп, не wait-loop.** Нет `CronCreate`, нет
|
||||||
@@ -196,8 +197,12 @@ session_break на таске? → да: печатай 🔚 SESSION BOUNDARY, S
|
|||||||
- **Не завершаемая таска:** внешний блокер → `status=blocked` + blocker
|
- **Не завершаемая таска:** внешний блокер → `status=blocked` + blocker
|
||||||
(конкретный факт + что нужно); прервал ты (бюджет/стоп) → `status=paused` +
|
(конкретный факт + что нужно); прервал ты (бюджет/стоп) → `status=paused` +
|
||||||
where_stopped. Одна упавшая таска не останавливает цикл — паркуй и дальше.
|
where_stopped. Одна упавшая таска не останавливает цикл — паркуй и дальше.
|
||||||
- **409 на взятие** → таска только что взята другим (сессия жива) → следующий
|
- **Heartbeat не нужен** — живость владельца из session (wiki:2660); долгая
|
||||||
кандидат; 409 на close → свежая version из `entity_get`, повтор.
|
таска с живой сессией не «протухает».
|
||||||
|
- **Consult-гейт:** `auto` → автопилот до close; `human-only`/`strict-human` →
|
||||||
|
работай, затем **STOP перед close/commit** и спроси user. Push никогда не
|
||||||
|
автоматический (project-discipline Rule 4: commit freely, push по явному
|
||||||
|
гранту).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -205,8 +210,8 @@ session_break на таске? → да: печатай 🔚 SESSION BOUNDARY, S
|
|||||||
|
|
||||||
### Primary: mappa task_create
|
### Primary: mappa task_create
|
||||||
|
|
||||||
Создание задач — **через тул, не руками** (решение 20): карв-аут, лиз не нужен
|
Создание задач — **через тул, не руками** (решение 20): карв-аут, лиз/claim
|
||||||
(wiki:2660). Номер `task:N` назначает сервер — не выдумывай.
|
для create НЕ нужен (wiki:2660). Номер `task:N` назначает сервер — не выдумывай.
|
||||||
|
|
||||||
```
|
```
|
||||||
mcp__mappa__task_create(
|
mcp__mappa__task_create(
|
||||||
@@ -251,7 +256,9 @@ Slug-правила: короткий, lowercase, kebab-case, латиница.
|
|||||||
Поля, которые разбирает поллер: `**Weight:**` (cheap-ok | needs-claude |
|
Поля, которые разбирает поллер: `**Weight:**` (cheap-ok | needs-claude |
|
||||||
needs-human — **обязателен** для авто-взятия), `**Notify:**` (<owner>/<repo>),
|
needs-human — **обязателен** для авто-взятия), `**Notify:**` (<owner>/<repo>),
|
||||||
`**Requirements:**`, `**Runtime allowed:**`, `**Consult policy:**`, `**Blocker:**`
|
`**Requirements:**`, `**Runtime allowed:**`, `**Consult policy:**`, `**Blocker:**`
|
||||||
(только на 🔵), `**Priority:**`/`**Due:**` (как выше).
|
(только на 🔵), `**Priority:**`/`**Due:**` (как выше). `**Owner:**/`**Claim
|
||||||
|
token:**/`**Claim expires at:**` — claim-штамп, пишет и чистит поллер; залипший
|
||||||
|
штамп на ⚪ блокирует поллер.
|
||||||
|
|
||||||
**Weight — поле, решающее взятие:** без `**Weight:**` поллер паркует в 🔵
|
**Weight — поле, решающее взятие:** без `**Weight:**` поллер паркует в 🔵
|
||||||
(`no backend for weight_tier: unknown`). Обычный код → `needs-claude`;
|
(`no backend for weight_tier: unknown`). Обычный код → `needs-claude`;
|
||||||
@@ -261,10 +268,11 @@ needs-human — **обязателен** для авто-взятия), `**Notif
|
|||||||
|
|
||||||
## Failure modes
|
## Failure modes
|
||||||
|
|
||||||
- **409 на взятие** → таска уже взята (живая сессия владельца) → следующий
|
- **version conflict** на update/close → version устарела; re-GET свежую version,
|
||||||
кандидат; не «бейся о замок».
|
retry. Не «решай конфликт» перезаписью без version (last-write-wins).
|
||||||
- **task_close на незавершённую** → никогда. Park (blocked/paused).
|
- **task_close на незавершённую** → никогда. Park (blocked/paused).
|
||||||
- **409 на close** → конфликт version → `entity_get` → повтори со свежей version.
|
- **owner на таске без живой сессии** → таска формально active, но владелец
|
||||||
|
stale; спроси человека (адvisory, не замок).
|
||||||
- **notify не указан (legacy)** → без него boss не узнает о завершении.
|
- **notify не указан (legacy)** → без него boss не узнает о завершении.
|
||||||
- **weight не указан (legacy)** → поллер паркует (no backend for weight_tier).
|
- **weight не указан (legacy)** → поллер паркует (no backend for weight_tier).
|
||||||
- **update Priority/Due после создания** → сервер отклоняет; паркуй вопрос
|
- **update Priority/Due после создания** → сервер отклоняет; паркуй вопрос
|
||||||
@@ -273,11 +281,11 @@ needs-human — **обязателен** для авто-взятия), `**Notif
|
|||||||
## What NOT to do
|
## What NOT to do
|
||||||
|
|
||||||
- **Не выдумывай номера** — `task:N` назначает сервер (решение 20).
|
- **Не выдумывай номера** — `task:N` назначает сервер (решение 20).
|
||||||
- **Version-дисциплина:** мутации несут version из последнего чтения; 409 →
|
- **Version-дисциплина:** update/close — всегда с version (409 при конфликте →
|
||||||
перечитай, не перезаписывай вслепую.
|
re-GET → retry). Create — карв-аут без лиза (wiki:2660).
|
||||||
- **Одна активная таска** — только одна 🔴 на проект.
|
- **Одна активная таска** — только одна 🔴 на проект.
|
||||||
- **Never close без coverage check** — evidence на каждый acceptance criterion.
|
- **Never close без coverage check** — evidence на каждый acceptance criterion.
|
||||||
- **Не закрывай незавершённое** — park, не close; не оставляй взятое.
|
- **Не закрывай незавершённое** — park, не close.
|
||||||
- **Не бампай priority/due после создания** — территория человека.
|
- **Не бампай priority/due после создания** — территория человека.
|
||||||
- **Не «решай» задачи письмом/в чате** — борд — единственный источник правды
|
- **Не «решай» задачи письмом/в чате** — борд — единственный источник правды
|
||||||
(канон mappa-messaging: «если это не на доске — это не задача»).
|
(канон mappa-messaging: «если это не на доске — это не задача»).
|
||||||
|
|||||||
Reference in New Issue
Block a user