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:
2026-08-25 01:04:12 +03:00
parent ae45a51420
commit c213997e1d
12 changed files with 134 additions and 119 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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-письмо в инбокс цели — таска на борде не пингует живую сессию.

View File

@@ -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. Формат предложения — один блок

View File

@@ -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-письмо в инбокс получателя (кросс-проектная делегация).

View File

@@ -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>` — одну страницу-резюме на источник (~50150 строк; 3. Создай `sources/<slug>` — одну страницу-резюме на источник (~50150 строк;
ссылку на 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 может затронуть 1015 страниц. Это нормально — для того LLM и нужны.** **Один ingest может затронуть 1015 страниц. Это нормально — для того 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.
- Нарративный оп-лог руками. - Нарративный оп-лог руками.
--- ---

View File

@@ -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.)
Следствие: **если это не на доске — это не задача и не решение, это разговор.** Следствие: **если это не на доске — это не задача и не решение, это разговор.**
Значимый дизайн-выбор должен лечь на доску (или в вики), инбокс лишь указывает Значимый дизайн-выбор должен лечь на доску (или в вики), инбокс лишь указывает

View File

@@ -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: «если это не на доске — это не задача»).