docs(skills): mappa-delegation 1.2.0→1.3.0 — English translation, bilingual triggers (task:1086)

This commit is contained in:
2026-08-25 17:42:35 +03:00
parent e91eb701aa
commit 76ff6ad3fc

View File

@@ -1,209 +1,261 @@
---
name: mappa-delegation
author: ours
version: 1.2.0
version: 1.3.0
description: >
Цикл делегирования задачи другому агенту/проекту: pre-flight gate →
шаблон тела → dry-run preview → confirm → covering-письмо в инбокс
получателя → парная review-таска для impl. Каждая кросс-проектная делегация
— пара: tasks_create + письмо (event: created) — таска на борде не пингует
живую сессию. Старое имя — триггер-синоним: delegate-task. Триггеры:
«делегировать таску», «delegate task», «создать задачу на агента»,
«поставить задачу агенту», «tasks_create для». НЕ применимо: self-assigned
таски на своей доске («создать задачу себе» → mappa-task-work), работа
своими руками, workshop-внутренние таски.
The cycle of delegating a task to another agent/project: pre-flight gate →
body template → dry-run preview → confirm → covering letter to the
recipient's inbox → paired review task for impl. Every cross-project
delegation is a pair: tasks_create + letter (event: created) — a task on the
board does not ping a live session. Old name — trigger-synonym:
delegate-task. Triggers (bilingual): «делегировать таску», «создать задачу
на агента», «поставить задачу агенту», «tasks_create для», "delegate task",
"create a task for an agent", "assign a task to an agent". NOT applicable:
self-assigned tasks on your own board («создать задачу себе» →
mappa-task-work), doing work yourself, workshop-internal tasks.
---
# mappa-delegation
Унифицированный **цикл постановки задач на агентов**: от pre-flight гейта до
covering-письма получателю. Гарантирует, что каждая делегированная задача
содержит: обязательные скилы (императивный invoke), pre-flight разрешения,
steering-loop поля (notify/weight), парную review-таску для impl — и что
получатель реально узнаёт о задаче (письмо, не только борд).
Unified **cycle of assigning tasks to agents**: from the pre-flight gate to
the covering letter to the recipient. Guarantees that every delegated task
carries: mandatory skills (imperative invoke), pre-flight permissions,
steering-loop fields (notify/weight), a paired review task for impl — and that
the recipient actually learns about the task (letter, not just the board).
## When to use
Перед каждым вызовом `tasks_create` для другого проекта или агента.
Before every `tasks_create` call for another project or agent.
**Активируется:** «делегировать таску», «delegate task», «создать задачу на агента», «поставить задачу агенту», «tasks_create для».
**Activates:** «делегировать таску», «создать задачу на агента», «поставить задачу агенту», «tasks_create для», "delegate task", "create a task for an agent".
**Не применяется:**
- Работа которую выполняешь сам в текущей сессии.
- Self-assigned таски на своей доске («создать задачу себе», «task for myself», «поставить себе задачу») → `mappa-task-work`, не делегирование. Дизамбигуатор: «на агента»/«агенту»/«в проект X» = делегирование; «себе»/«myself» = своя доска.
- Workshop-internal таски (`.workshop/.tasks/` — workshop-meta, не делегирование).
- `tasks_create` с `target=agenda` (cross-project agenda — не делегирование агенту).
**Not applicable:**
- Work you do yourself in the current session.
- Self-assigned tasks on your own board («создать задачу себе», "task for myself") → `mappa-task-work`, not delegation. Disambiguator: «на агента»/«агенту»/«в проект X» = delegation; «себе»/"myself" = your own board.
- Workshop-internal tasks (`.workshop/.tasks/` — workshop-meta, not delegation).
- `tasks_create` with `target=agenda` (cross-project agenda — not delegation to an agent).
## Inputs
- `target_project` — qualified `<owner>/<repo>` (обязательно)
- `target_project` — qualified `<owner>/<repo>` (required)
- `slug` — kebab-case latin
- Краткое описание задачи (цель + acceptance criteria)
- Short task description (goal + acceptance criteria)
- `weight``cheap-ok | needs-claude | needs-human`
- `notify`slug проекта-комиссионера (кому писать inbox при close/park)
- `notify`commissioning project slug (who gets the inbox letter on close/park)
Номер задаче присваивает сервер (`tasks_create` из счётчика agenda/task-counter) — постановщик номер не придумывает и не резервирует. Возвращённый `#n` из preview/confirm — машинный ключ задачи: им ссылаются блокеры, письма, decision-trail.
The task number is assigned by the server (`tasks_create` from the
agenda/task-counter) — the assigner neither invents nor reserves it. The
returned `#n` from preview/confirm is the task's machine key: blockers,
letters, and the decision trail reference it.
> **Контракт (interactive, wiki:2660).** `task_create` — **карв-аут без
> лиза** (create-без-лиза как принцип); update/close — version+409 (409 →
> re-GET → retry). file channel — sha-CAS через Gitea. Claim/TTL нет
> «взять таску» = conditional update по version (поллер вне mappa).
> **Contract (interactive, wiki:2660).** `task_create` — **carve-out without a
> lease** (create-without-lease as a principle); update/close — version+409
> (409 → re-GET → retry). file channel — sha-CAS via Gitea. No claim/TTL —
> "take a task" = conditional update by version (poller outside mappa).
## Steps (цикл)
## Steps (the cycle)
### 1. Pre-flight gate (6 вопросов пользователю)
### 1. Pre-flight gate (6 questions to the user)
Спросить **до** составления тела задачи:
Ask **before** composing the task body:
0. **Критическая инфраструктура?** — задача меняет: поллер/агент-раннер, MCP серверы (projects-meta, interns), механизм claim/close/heartbeat, deploy-инфру (traefik, docker, systemd), CI/CD пайплайны, git hooks.
- Если **да**`weight: needs-human` принудительно, без обсуждения. Объяснить пользователю почему.
- Если **нет** → идти дальше.
1. **Интерны — разрешены?** (да/нет, per задача)
2. **Автопуш — разрешён?** (да/нет, per задача)
3. **Контекстные скилы сверх дефолтов?** — предложить по содержанию задачи (например `claude-api` для работы с Anthropic SDK, `frontend-design` для UI, `using-interns` если интерны разрешены), пользователь утверждает.
4. **notify — кому докладывать о завершении/затыке?** (slug проекта; обычно `.workshop` или `OpeItcLoc03/workshop`)
5. **Session-break после этой задачи?** — нужен ли разрыв сессии после её закрытия (domain-switch, milestone, heavy infra)?
- Если **да** → проставить `session_break` в теле задачи (см. шаблон): `true` или строка-hint с названием следующего трека. `mappa-task-work` остановится после close и предложит завершить сессию, не клеймя следующую задачу.
- Если **нет** → поле не добавлять (дефолт — агент продолжает цикл).
0. **Critical infrastructure?** — the task changes: poller/agent-runner, MCP
servers (projects-meta, interns), claim/close/heartbeat mechanics, deploy
infra (traefik, docker, systemd), CI/CD pipelines, git hooks.
- If **yes** → force `weight: needs-human`, no discussion. Explain to the
user why.
- If **no** → continue.
1. **Interns — allowed?** (yes/no, per task)
2. **Auto-push — allowed?** (yes/no, per task)
3. **Contextual skills beyond defaults?** — propose per task content (e.g.
`claude-api` for Anthropic SDK work, `frontend-design` for UI,
`using-interns` if interns are allowed); the user approves.
4. **notify — who gets the completion/block report?** (project slug; usually
`.workshop` or `OpeItcLoc03/workshop`)
5. **Session-break after this task?** — is a session break needed after it
closes (domain-switch, milestone, heavy infra)?
- If **yes** → set `session_break` in the task body (see template): `true`
or a string-hint with the next track's name. `mappa-task-work` will stop
after close and propose ending the session, without claiming the next task.
- If **no** → don't add the field (default — the agent continues the cycle).
### 2. Составить тело задачи по шаблону
### 2. Compose the task body per template
Секции строго по порядку:
Sections strictly in order:
```
<Цель — одно-два предложения. Acceptance criteria если есть.>
**Спека:** <path к design-решению или .brainstorm/…> — обязательно для задач
из дизайна/решения: импл читает дизайн, не угадывает
<Goal — one or two sentences. Acceptance criteria if any.>
**Spec:** <path to the design solution or .brainstorm/…> — mandatory for tasks
from design/decision: the impl reads the design, doesn't guess
## Обязательные скилы — вызвать до начала работы
## Mandatory skills — invoke before starting work
- invoke `tdd-criteria` — до написания кода
- invoke `mappa-task-work` — для управления статусом задачи
- invoke `project-discipline` — дисциплина коммитов/пушей
- invoke `mappa-knowledge` после закрытия — заингесть .wiki/concepts/<slug>.md
[если кросс-проектная: - invoke `using-projects-meta` — cross-project tasks/wiki]
[контекстные скилы из шага 1.3]
- invoke `tdd-criteria` — before writing code
- invoke `mappa-task-work` — for task status management
- invoke `project-discipline` — commit/push discipline
- invoke `mappa-knowledge` after closing — ingest .wiki/concepts/<slug>.md
[if cross-project: - invoke `using-projects-meta` — cross-project tasks/wiki]
[contextual skills from step 1.3]
**TDD:** да | нет — <причина>
**Разрешения:** интерны: да/нет | автопуш: да/нет
**TDD:** yes | no — <reason>
**Permissions:** interns: yes/no | auto-push: yes/no
**weight:** cheap-ok | needs-claude | needs-human
**notify:** <commissioning-project-slug>
[**allow_upgrade:** true/false]
[**session_break:** true | "<следующий трек / hint>"] # optional — mappa-task-work остановится после close, не клеймит следующую задачу
[**session_break:** true | "<next track / hint>"] # optional — mappa-task-work stops after close, doesn't claim the next task
```
**Когда ставить `session_break`** (опционально; по умолчанию НЕ ставить — это маркер реальной границы, не дефолт). Три случая:
**When to set `session_break`** (optional; by default DON'T set it — it marks
a real boundary, not a default). Three cases:
1. **Смена домена / репо** — задача завершает один трек перед переходом на несвязанный.
2. **Milestone-задача** — последняя в группе sub-tasks одной фичи.
3. **Тяжёлая инфра-задача** — shared checkout, migrations, deploy — где разумно остановиться и проверить состояние.
1. **Domain / repo switch** — the task finishes one track before moving to an
unrelated one.
2. **Milestone task** — the last in a group of sub-tasks of one feature.
3. **Heavy infra task** — shared checkout, migrations, deploy — where it's
reasonable to stop and check the state.
Значение: `true` (следующий трек = «см. STATUS.md») либо строка-hint с названием следующего трека. Потребитель — `mappa-task-work`: после close печатает `🔚 SESSION BOUNDARY …` и останавливается, не клеймя следующую задачу. Дизайн: `.wiki/concepts/delegate-task-session-break.md`.
Value: `true` (next track = "see STATUS.md") or a string-hint with the next
track's name. Consumer — `mappa-task-work`: after close it prints
`🔚 SESSION BOUNDARY …` and stops, without claiming the next task. Design:
`.wiki/concepts/delegate-task-session-break.md`.
**Этапные цепочки (staged breakdown):** если решение бьётся на этапы
(1 → 1b → 3), создавай каждый этап отдельной таской со `status: blocked` +
`blocker: <номера-предшественников> (#n1, #n2 — номера, не слаги; номер =
машинный ключ)`. Доска показывает порядок, поллер не возьмёт зависимую
работу раньше времени. Таски в один репо создавай последовательно, не
параллельно (иначе sha-lock конфликт — см. Failure modes).
**Staged breakdown:** if the solution splits into stages (1 → 1b → 3), create
each stage as a separate task with `status: blocked` + `blocker:
<predecessor numbers> (#n1, #n2 — numbers, not slugs; the number = machine
key)`. The board shows the order, the poller won't take dependent work early.
Create tasks in one repo sequentially, not in parallel (otherwise sha-lock
conflict — see Failure modes).
**Почему `invoke` а не триггер-фраза:** AGENTS.md ненадёжен (уплывает при compression, слабые модели игнорируют). Тело задачи читается активно — императив `invoke` это прямая команда, не пассивный матчинг.
**Why `invoke` and not a trigger phrase:** AGENTS.md is unreliable (drifts
under compression, weak models ignore it). The task body is read actively —
the imperative `invoke` is a direct command, not passive matching.
### 3. Dry-run preview
`tasks_create(confirm=false)`показать пользователю preview до реального коммита.
`tasks_create(confirm=false)`show the user the preview before the real commit.
### 4. Подтверждение и создание
### 4. Confirmation and creation
После OK пользователя: `tasks_create(confirm=true)`.
After the user's OK: `tasks_create(confirm=true)`.
### 5. Сопроводительное письмо — обязательно при кросс-проектной делегации
### 5. Covering letter — mandatory for cross-project delegation
После создания **каждая кросс-проектная делегация** дублируется письмом в
инбокс получателя (канон — `mappa-messaging`: канал Mappa, адрес из адресной
книги `~/projects/.wiki/concepts/projects-address-book.md`):
After creation, **every cross-project delegation** is duplicated by a letter to
the recipient's inbox (canon — `mappa-messaging`: Mappa channel, address from
the address book `~/projects/.wiki/concepts/projects-address-book.md`):
```
mcp__mappa__inbox_send(
project: <адрес-получателя>, # имя папки, из адресной книги
from: <своя-папка>,
project: <recipient address>, # folder name, from the address book
from: <your folder>,
subject: "[event: created] #n slug",
body: "1-2 строки — что за задача, почему, slug; «разбери и возьми»"
body: "1-2 lines — what the task is, why, slug; «sort it out and take it»"
)
```
(Мутации update/close — version-based (409 → retry); доставка письма
карв-аут, лиза не требует.)
(update/close mutations — version-based (409 → retry); letter delivery
carve-out, requires no lease.)
Причина: таска на борде **не пингует живую сессию** получателя. Поллер
подхватит по `Weight`/`Notify`, но живая интерактивная сессия узнаёт только
через inbox-монитор — т.е. через письмо. Правило «task + letter, не только
task» — общий случай (шаг 7 — его частность для downstream-задач).
Reason: a task on the board **does not ping the recipient's live session**.
The poller will pick it up by `Weight`/`Notify`, but a live interactive
session learns only through the inbox monitor — i.e. through the letter. The
rule "task + letter, not just task" — is the general case (step 7 is its
particular case for downstream tasks).
Пропуск: self-assigned задачи на своей доске; `target=agenda` (общая доска,
конкретного получателя нет — steering-loop через `Notify`).
Skip: self-assigned tasks on your own board; `target=agenda` (shared board,
no concrete recipient — steering-loop via `Notify`).
### 6. Парная review-таска (только для impl-задач)
### 6. Paired review task (impl tasks only)
Если задача имплементационная — создать парную `<slug>-review` (status=blocked, blocker=`#n` — номер impl-таски). Пропустить для: pointers-тасок, ops-тасок, research-тасок, любых non-impl.
If the task is implementation — create the paired `<slug>-review`
(status=blocked, blocker=`#n` — the impl task number). Skip for: pointer
tasks, ops tasks, research tasks, any non-impl.
**`weight` review-таски — наследовать от impl-таски, но не ниже `needs-claude`** (проставлять явно при `tasks_create`):
**`weight` of the review task — inherit from the impl task, but never below
`needs-claude`** (set explicitly at `tasks_create`):
- impl `needs-human` → review `needs-human` (критично-инфраструктурное изменение нельзя ревьюить слабым tier'ом — ревью наследует строгость impl).
- impl `needs-human` → review `needs-human` (a critical-infra change cannot
be reviewed by a weak tier — the review inherits the impl's strictness).
- impl `needs-claude` → review `needs-claude`.
- impl `cheap-ok` → review `needs-claude` (флор: review дисциплинарно-критична, см. What NOT to do — cheap-ok сюда не опускать).
- impl `cheap-ok` → review `needs-claude` (floor: review is
discipline-critical, see What NOT to do — don't drop to cheap-ok).
Без явного `weight` поллер не маршрутизирует review-таску (reconciler её пропускает) — поэтому проставлять всегда, даже когда impl и review совпадают по tier'у.
Without an explicit `weight` the poller won't route the review task (the
reconciler skips it) — so always set it, even when impl and review are at the
same tier.
### 7. Downstream-задача для ЖИВОЙ сессии → требовать task + inbox-письмо
### 7. Downstream task for a LIVE session → require task + inbox letter
Если тело задачи **поручает агенту самому создать downstream-задачу** для другого проекта, где работает **живая интерактивная сессия** (напр. прог сам ставит deploy-таску админу), — в ТЗ **явно потребуй И `tasks_create`, И inbox-письмо** тому проекту (`mcp__mappa__inbox_send(project=<target>, from=<своя>, subject="[event: created] #n slug", ...)`).
If the task body **instructs the agent to create a downstream task itself** for
another project where a **live interactive session** is working (e.g. the
programmer sets a deploy task for the admin) — in the spec **explicitly require
BOTH `tasks_create` AND the inbox letter** to that project
(`mcp__mappa__inbox_send(project=<target>, from=<yours>, subject="[event: created] #n slug", ...)`).
Причина: таска на борде живую сессию **НЕ пингует**. Поллер подхватит по `Weight`/`Notify`, но живая интерактивная сессия узнаёт только через inbox-монитор / Stop-хук — т.е. через письмо. ТЗ, требующее лишь `tasks_create`, оставляет downstream-таску висеть незамеченной, и кто-то доделывает пинг руками.
Reason: a task on the board does **NOT** ping the live session. The poller
will pick it up by `Weight`/`Notify`, but a live interactive session learns
only through the inbox monitor / Stop-hook — i.e. through the letter. A spec
that requires only `tasks_create` leaves the downstream task hanging unnoticed,
and someone finishes the ping by hand.
Правило: poller-driven таргет`Weight`/`Notify` обязательны; live-сессия → inbox-письмо обязательно; **не уверен, поллер или живой — требуй ОБА.** Это же правило применяй, когда пингуешь пира сам: task + letter, не только task.
Rule: poller-driven target`Weight`/`Notify` mandatory; live session → inbox
letter mandatory; **not sure poller or live — require BOTH.** Apply the same
rule when you ping a peer yourself: task + letter, not just task.
## Failure modes
- **Пользователь отказывает на pre-flight** → abort, задачу не создавать.
- **Пользователь отклоняет dry-run preview** → abort.
- **notify не указан** → переспросить, не пропускать молча. Без notify steering-loop не замыкается.
- **weight не указан** → переспросить. Без weight поллер не знает кому отдать задачу.
- **tasks_create упал** → различить: **PushRejected** (sha-lock конфликт —
репо уехало между preview и confirm; бывает при параллельном создании в один
репо) → **retry**: повторить confirm — сервер перечитает актуальный base_sha.
Другие ошибки → сообщить пользователю, не делать retry без явного запроса.
- **User refuses the pre-flight** → abort, don't create the task.
- **User rejects the dry-run preview** → abort.
- **notify not specified** → re-ask, don't skip silently. Without notify the
steering-loop doesn't close.
- **weight not specified** → re-ask. Without weight the poller doesn't know who
to give the task to.
- **tasks_create failed** → distinguish: **PushRejected** (sha-lock conflict —
the repo moved between preview and confirm; happens on parallel creation into
one repo) → **retry**: repeat the confirm — the server re-reads the actual
base_sha. Other errors → tell the user, don't retry without an explicit request.
## Side effects
- Создаёт таску в target-проекте через `tasks_create` (file channel — Gitea commit; service channel — mappa-сущность, create = карв-аут без лиза wiki:2660).
- Опционально создаёт парную review-таску (status=blocked).
- Covering-письмо в инбокс получателя (кросс-проектная делегация).
- Creates a task in the target project via `tasks_create` (file channel —
Gitea commit; service channel — mappa entity, create = carve-out without a
lease wiki:2660).
- Optionally creates the paired review task (status=blocked).
- Covering letter to the recipient's inbox (cross-project delegation).
## What NOT to do
- Не пропускать pre-flight gate — даже если кажется что всё очевидно.
- Не использовать пассивные триггер-фразы вместо `invoke` — «tdd-criteria» в тексте слабее чем «invoke `tdd-criteria`».
- Не пропускать `notify` — без него boss не узнает о завершении.
- Не пропускать `weight` — без него fleet routing слеп.
- Не создавать review-таску для pointers/ops/research задач — только для impl.
- Не создавать review-таску без `weight` — reconciler/поллер её пропустит. Наследовать от impl, флор `needs-claude` (см. Step 6).
- Не назначать `weight: cheap-ok` для задач где дисциплина критична (review, security, schema migration) — слабые модели могут игнорировать invoke-инструкции.
- Не назначать `weight: needs-claude` или `cheap-ok` задачам, меняющим критическую инфраструктуру (поллер, MCP серверы, deploy, CI/CD) — только `needs-human`.
- Не ставить `session_break` рутинно на каждую задачу — это маркер реальной границы (domain-switch / milestone / heavy infra), не дефолт; иначе `mappa-task-work` рвёт сессию после каждого close.
- **Не создавать задачи из дизайна/решения без `**Спека:**`-ссылки** —
импл-агент угадывает пороги/скоуп вместо чтения дизайна.
- **Не создавать несколько тасок в один репо параллельно** — sha-lock
конфликты (PushRejected); сериализуй confirm'ы.
- **Не делегировать кросс-проектную задачу без сопроводительного письма** в
инбокс получателя (шаг 5, Mappa `inbox_send`). `tasks_create` в чужой борд
живую сессию не пингует — task без letter остаётся незамеченной до
поллера/руки.
- **Не поручать агенту создать downstream-таску для живой сессии без парного inbox-письма** (см. Step 7). `tasks_create` в чужой борд живую сессию не пингует — ТЗ обязано требовать И таску, И письмо, иначе downstream-таска висит незамеченной.
- Don't skip the pre-flight gate — even if everything seems obvious.
- Don't use passive trigger phrases instead of `invoke` — "tdd-criteria" in
text is weaker than "invoke `tdd-criteria`".
- Don't skip `notify` — without it the boss won't learn about completion.
- Don't skip `weight` — without it fleet routing is blind.
- Don't create a review task for pointer/ops/research tasks — impl only.
- Don't create a review task without `weight` — the reconciler/poller will
skip it. Inherit from impl, floor `needs-claude` (see Step 6).
- Don't assign `weight: cheap-ok` where discipline is critical (review,
security, schema migration) — weak models may ignore invoke instructions.
- Don't assign `weight: needs-claude` or `cheap-ok` to tasks changing critical
infrastructure (poller, MCP servers, deploy, CI/CD) — only `needs-human`.
- Don't set `session_break` routinely on every task — it marks a real
boundary (domain-switch / milestone / heavy infra), not a default; otherwise
`mappa-task-work` breaks the session after every close.
- **Don't create tasks from design/decision without a `**Spec:**` reference**
— the impl agent guesses thresholds/scope instead of reading the design.
- **Don't create several tasks in one repo in parallel** — sha-lock conflicts
(PushRejected); serialize the confirms.
- **Don't delegate a cross-project task without the covering letter** to the
recipient's inbox (step 5, Mappa `inbox_send`). `tasks_create` into a foreign
board doesn't ping the live session — a task without a letter stays unnoticed
until the poller/hand.
- **Don't instruct the agent to create a downstream task for a live session
without the paired inbox letter** (see Step 7). `tasks_create` into a foreign
board doesn't ping the live session — the spec must require BOTH the task
and the letter, otherwise the downstream task hangs unnoticed.
## Reference
- Письма: `mappa-messaging` (канон inbox_send, адресная книга).
- Задачи/борд: `mappa-task-work`.
- Знание: `mappa-knowledge` (wiki после закрытия).
- Промоушен: `mappa-brainstorm-promote` (review-umbrella через него же).
- Letters: `mappa-messaging` (inbox_send canon, address book).
- Tasks/board: `mappa-task-work`.
- Knowledge: `mappa-knowledge` (wiki after closing).
- Promotion: `mappa-brainstorm-promote` (review-umbrella through it too).