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

This commit is contained in:
2026-08-25 17:42:37 +03:00
parent 0177d46101
commit 195de4b8e6

View File

@@ -1,238 +1,247 @@
---
name: mappa-task-work
author: ours
version: 1.2.0
version: 1.3.0
description: >
Центральный цикл работы с тасками в Mappa: ориентация → выбор работы
(priority/due) → исполнение → сдача (close + review-umbrella) +
loop-mode «поработай очередь». Борд = сущности mappa (решения 14/15/19/20);
create — карв-аут, update/close — optimistic concurrency (version+409),
owner = персистентный assignee, живость — из session владельца
(interactive contract, wiki:2660). Поглощает using-tasks +
task-format + task-loop (loop-mode ВНУТРИ) + priority-due-раздел (старые
имена — триггер-синонимы).
Триггеры: «что на досках», «возьми таску», «какой статус», «update status»,
«pause», «switch to X», «где мы остановились», «work the queue», «поработай
очередь», «прогони доску». Приоритет = территория человека: агенты ставят
P0-P2/дедлайн только при создании, дефолт P1; просрочка → notify, без
авто-бампа. НЕ про делегирование (→ mappa-delegation), НЕ про доску-обзор
(→ ops/using-system-snapshot).
The central cycle of working with tasks in Mappa: orientation → work
selection (priority/due) → execution → handover (close + review-umbrella) +
loop-mode "work the queue". Board = mappa entities (decisions 14/15/19/20);
create — carve-out, update/close — optimistic concurrency (version+409),
owner = persistent assignee, liveness — from the owner's session (interactive
contract, wiki:2660). Absorbs using-tasks + task-format + task-loop (loop-mode
INSIDE) + priority-due section (old names — trigger-synonyms).
Triggers (bilingual): «что на досках», «возьми таску», «какой статус»,
«update status», «pause», «switch to X», «где мы остановились», "work the
queue", «поработай очередь», «прогони доску», "what's on the boards", "take
a task". Priority = the human's territory: agents set P0-P2/deadline only at
creation, default P1; overdue → notify, no auto-bump. NOT about delegation
(→ mappa-delegation), NOT about board overview (→ ops/using-system-snapshot).
---
# mappa-task-work
Центральный цикл работы с задачами: **ориентация → выбор работы → исполнение
сдача**. Борд — сущности mappa (`type=task`, `task:N`): чтение — карв-аут;
**create — карв-аут без лиза; update/close — optimistic concurrency
(version+409 → retry)**; **owner = персистентный assignee; живость таски —
из session владельца** (interactive contract, wiki:2660; поллер вне mappa).
Скилл = цикл, не тул: одна механика на выбор/исполнение/сдачу, плюс
**loop-mode** («поработай очередь») внутри — отдельный скил не создаётся.
The central cycle of working with tasks: **orientation → work selection
execution → handover**. Board — mappa entities (`type=task`, `task:N`): read —
carve-out; **create — carve-out without a lease; update/close — optimistic
concurrency (version+409 → retry)**; **owner = persistent assignee; task
liveness — from the owner's session** (interactive contract, wiki:2660; poller
outside mappa). The skill is a cycle, not a tool: one mechanics for
selection/execution/handover, plus **loop-mode** («поработай очередь») inside —
no separate skill is created.
> **Переходное (file channel).** Пока поллер/кэш читают файловые борды
> (`.tasks/STATUS.md`), legacy-канал живёт: блоки в файле обязаны строгому
> формату (см. «Формат таски» ниже), мутации — через `mcp__projects-meta__tasks_*`
> (Gitea-коммиты). Новые таски — через `mcp__mappa__task_create`. Не смешивай.
> **Transitional (file channel).** While the poller/cache reads file boards
> (`.tasks/STATUS.md`), the legacy channel lives: file blocks must obey a
> strict format (see "Task format" below), mutations — via
> `mcp__projects-meta__tasks_*` (Gitea commits). New tasks — via
> `mcp__mappa__task_create`. Don't mix.
## Когда использовать
## When to use
- «что на досках», «возьми таску», «какой статус», «update status», «pause», «switch to X», «где мы остановились».
- «work the queue», «поработай очередь», «прогони доску» → **loop-mode**.
- Смена задачи / пауза / конец сессии — держать борд консистентным.
- «что на досках», «возьми таску», «какой статус», «update status», «pause», «switch to X», «где мы остановились», "what's on the boards", "take a task".
- "work the queue", «поработай очередь», «прогони доску» → **loop-mode**.
- Task switch / pause / session end — keep the board consistent.
**НЕ для:** делегирования другому агенту/проекту (→ `mappa-delegation`),
промоушена (→ `mappa-brainstorm-promote`), инфра-диагностики (→ `using-vds-ops`),
кросс-проектного обзора (→ `using-system-snapshot`).
**NOT for:** delegating to another agent/project (→ `mappa-delegation`),
promotion (→ `mappa-brainstorm-promote`), infra diagnosis (→ `using-vds-ops`),
cross-project overview (→ `using-system-snapshot`).
## MCP-поверхность
## MCP surface
| Операция | Тул | Примечание |
| Operation | Tool | Note |
|---|---|---|
| Взять следующую ready-таску | `mcp__mappa__task_update(project, id, owner=<своя>, status=active…, version)` | **conditional update**: status→active, owner=X, version+409 (кто первый с верной version — тот и взял) |
| Создать таску | `mcp__mappa__task_create(project, slug, title?, description?, status?, priority?, due?)` | **карв-аут без лиза**; per-type номер (решение 20) |
| Закрыть таску | `mcp__mappa__task_close(project, id, version)` | **version-based**: конфликт → 409 → retry со свежей version из task_get |
| Обновить таску | `mcp__mappa__task_update(project, id, parent?, owner?, status?, reason?, version)` | version-based; 409 → retry |
| Прочитать таску | `mcp__mappa__entity_get(id)` | id internal из search |
| Список борда | `mcp__mappa__entity_search(q, type='task', project=<имя>, limit)` | все статусы |
| Дерево parent_of | `mcp__mappa__graph_tree(root, depth?, fields?, limit?)` | зонтики/иерархия |
| Связанные сущности | `mcp__mappa__graph_neighbors/backlinks(id)` | рефы к таске |
| Просрочка | `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)` | письмо комиссионеру |
| Take the next ready task | `mcp__mappa__task_update(project, id, owner=<yours>, status=active…, version)` | **conditional update**: status→active, owner=X, version+409 (whoever is first with the right version — takes it) |
| Create a task | `mcp__mappa__task_create(project, slug, title?, description?, status?, priority?, due?)` | **carve-out without a lease**; per-type number (decision 20) |
| Close a task | `mcp__mappa__task_close(project, id, version)` | **version-based**: conflict → 409 → retry with the fresh version from task_get |
| Update a task | `mcp__mappa__task_update(project, id, parent?, owner?, status?, reason?, version)` | version-based; 409 → retry |
| Read a task | `mcp__mappa__entity_get(id)` | internal id from search |
| Board list | `mcp__mappa__entity_search(q, type='task', project=<name>, limit)` | all statuses |
| parent_of tree | `mcp__mappa__graph_tree(root, depth?, fields?, limit?)` | umbrellas/hierarchy |
| Related entities | `mcp__mappa__graph_neighbors/backlinks(id)` | refs to the task |
| Overdue | `mcp__mappa__admin_overdue_scan(project?)` | P2 job: notify to inbox, no mutations |
| Owner liveness | `mcp__mappa__session_list(project, stale_minutes?)` | owner's session alive/stale → task active or not |
| Close notification | `mcp__mappa__inbox_send(project=<notify>, from=<yours>, subject, body)` | letter to the commissioner |
**Owner = персистентный assignee; живость — из session (interactive contract,
wiki:2660).** Нет TTL/claim/таймера на таске: «взял таску» = conditional
update (`status→active, owner=X` + version, 409 при конфликте — кто первый,
тот и взял). Живость владельца — сессия: таска с owner=X активна, пока сессия
X жива (end-state≠clean, не stale; `session_list(project)`); краш = stale
решает человек/оркестратор (поллер вне mappa, работает на файловых досках
projects-meta). Write-пути (create/update/close) лизов/claim не требуют —
только version на update/close (409 при конфликте).
**Owner = persistent assignee; liveness — from the session (interactive
contract, wiki:2660).** No TTL/claim/timer on the task: "took a task" =
conditional update (`status→active, owner=X` + version, 409 on conflict —
whoever is first takes it). Owner liveness — the session: a task with owner=X
is active while session X is alive (end-state≠clean, not stale;
`session_list(project)`); crash = stale → the human/orchestrator decides
(poller outside mappa, works on projects-meta file boards). Write paths
(create/update/close) require no leases/claims — only version on update/close
(409 on conflict).
**Рефы и id (#1037/#1028).** Таски наружу несут `ref: "t:N"` полным именем
первым полем (`task:N`, конвенция #1028), `num` следом, глобальный `id`
internal (последним, для addressing в тулах). Ссылайся на таску
`[[task:N]]`/`task:N` в прозе (слаг/имя первым, реф как якорь: «таска
`mappa-task-work` (task:1062)»), никогда `#<глобальный id>`.
**Refs and ids (#1037/#1028).** Tasks carry `ref: "t:N"` by full name as the
first field (`task:N`, convention #1028), `num` next, the global `id`
internal (last, for addressing in tools). Reference a task as
`[[task:N]]`/`task:N` in prose (slug/name first, ref as anchor: "the task
`mappa-task-work` (task:1062)"), never `#<global id>`.
## Статусы (эмодзи для презентации)
## Statuses (emojis for presentation)
| Эмодзи | Статус | Значение |
| Emoji | Status | Meaning |
|---|---|---|
| ⚪ | `ready` | не начата, полностью определена |
| 🔴 | `active` | в работе (обычно одна) |
| 🟡 | `paused` | в процессе, возобновляема |
| 🔵 | `blocked` | ждёт внешнего входа |
| 🟢 | `done` | закрыта |
| ⚪ | `ready` | not started, fully defined |
| 🔴 | `active` | in progress (usually one) |
| 🟡 | `paused` | in progress, resumable |
| 🔵 | `blocked` | waiting on external input |
| 🟢 | `done` | closed |
Не путай: 🟢 — *done*, не «готово». Ready ⚪.
Don't confuse: 🟢 — *done*, not "ready". Ready is ⚪.
---
## Цикл
## The cycle
### Фаза 0 — Ориентация
### Phase 0 — Orientation
1. **Инбокс-свип**`mcp__mappa__inbox_monitor(project=<имя>)`: непрочитанные
письма могут менять план. Обработай каждое по `mappa-messaging`.
2. **Борд**`entity_search(q, type='task', project=<имя>, limit=50)`: отсортируй
по статусу (🔴 → 🟡 → ⚪), по одной строке на таску, цитируй slug.
3. Если user назвал таску`entity_get(id)` по её рефу/номеру.
4. Подтверди одним предложением: «Мы в середине X, следующий шаг — Y».
5. Спроси, верен ли план, перед действиями.
1. **Inbox sweep**`mcp__mappa__inbox_monitor(project=<name>)`: unread
letters may change the plan. Handle each per `mappa-messaging`.
2. **Board**`entity_search(q, type='task', project=<name>, limit=50)`: sort
by status (🔴 → 🟡 → ⚪), one line per task, quote the slug.
3. If the user named a task`entity_get(id)` by its ref/number.
4. Confirm in one sentence: "We're in the middle of X, next step — Y".
5. Ask whether the plan is right before acting.
### Фаза 1 — Выбор работы (priority/due)
### Phase 1 — Work selection (priority/due)
1. **Выбор таски — из списка борда** (`entity_search(q, type='task', project)`):
порядок — **P0-пул первый, внутри по дедлайну (просроченные первыми),
потом P1, потом P2**; отсутствующий priority = P1 (task-priority-due).
«Взять таску» = `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 первым; кросс-проект — футонота
(`Cross-project: N 🔴 active — см. tasks_aggregate`) только если N>0 и в cwd
нет активной 🔴. Кросс-проектные ургенты — информация, не драйвер «что делать здесь».
3. **Priority/Due — территория человека (раздел task-priority-due):**
- Агент ставит `priority`/`due` **только при создании** таски (явные параметры
или строки `**Priority:** P0|P1|P2` / `**Due:** yyyy-mm-dd` в description).
Отсутствует → дефолт P1, без дедлайна.
- **После создания агент не меняет** приоритет/дедлайн — прецедент человека
структурный (update агентами отклоняется сервером). Обнаружил, что таска
на самом деле P0 → паркуй вопрос человеку, не бампай сам.
- **Просрочка:** due < today при ready/active → `admin_overdue_scan` уведомляет
в инбокс **однократно, без мутаций** — никакого авто-бампа/авто-смены приоритета.
1. **Task selection — from the board list** (`entity_search(q, type='task', project)`):
order — **P0 pool first, within it by deadline (overdue first),
then P1, then P2**; missing priority = P1 (task-priority-due).
"Take a task" = `task_update(project, id, owner=<yours>, status='active',
version)` — conditional update: status→active, owner=X, version+409;
whoever is first with the right version takes it (interactive contract,
wiki:2660). `owner` = `<machine>:<runtime>:<session>`.
2. **Local-first recommendation** — cwd board first; cross-project — a footnote
(`Cross-project: N 🔴 active — see tasks_aggregate`) only if N>0 and there's
no active 🔴 in cwd. Cross-project urgencies are information, not a driver
for "what to do here".
3. **Priority/Due — the human's territory (task-priority-due section):**
- An agent sets `priority`/`due` **only at task creation** (explicit
parameters or `**Priority:** P0|P1|P2` / `**Due:** yyyy-mm-dd` lines in
the description). Absent → default P1, no deadline.
- **After creation an agent doesn't change** priority/deadline — the
human's precedent is structural (agent updates are rejected by the
server). If you discover the task is actually P0 → park the question to
the human, don't bump it yourself.
- **Overdue:** due < today with ready/active → `admin_overdue_scan`
notifies the inbox **once, without mutations** — no auto-bump/auto-priority
change.
### Фаза 2 — Исполнение
### Phase 2 — Execution
- **Одна активная таска** 🔴 на проект. Не параллель.
- Читай description + per-task файл (`<slug>.md`, где есть) до старта.
- Живость — из сессии владельца (`session_list(project)`), не таймер; долгие
таски heartbeat не требуют (interactive contract, wiki:2660).
- **`session_break` gate** (из task-loop): если в description таски есть маркер
`session_break` — после close НЕ клейми следующую: печатай
`🔚 SESSION BOUNDARY …` и останавливайся (домен-свитч / milestone / тяжёлая инфра).
- **One active task** 🔴 per project. No parallelism.
- Read description + per-task file (`<slug>.md`, where present) before starting.
- Liveness — from the owner's session (`session_list(project)`), not a timer;
long tasks need no heartbeat (interactive contract, wiki:2660).
- **`session_break` gate** (from task-loop): if the task description has the
`session_break` marker — after close DON'T claim the next one: print
`🔚 SESSION BOUNDARY …` and stop (domain-switch / milestone / heavy infra).
### Фаза 3 — Сдача (close + review-umbrella)
### Phase 3 — Handover (close + review-umbrella)
1. **Pre-close coverage check.** Собери acceptance criteria из description. Для
каждого — evidence: тест в диффе, артефакт, ссылка на дизайн. Нет evidence на
критерий → спроси user'а «закрывать или подождать coverage'а».
2. Resolve/drop открытые вопросы.
3. `task_close(project, id, version)` → статус `done`. `version`
свежая из `entity_get(id)`/`task_get(id)`; конфликт (409) → re-GET → retry.
4. **Notify-письмо (кросс-проектные таски).** Если таска пришла из другого
проекта (в description/meta есть `from:`/`notify:`) — `inbox_send`
комиссионеру: `project=<notify>`, `subject="[event: closed] <slug>"`,
body = итог (сделано, acceptance, ссылки). Живая сессия пишет сама.
Таска 🟢 ≠ комиссионер узнал.
5. **Review-umbrella для impl-тасок** (канон `mappa-delegation`): если таска
имплементационная и закрыта — парная `<slug>-review` уже должна быть
создана при постановке (status=blocked, blocker=impl#); закрытие impl
разблокирует ревью. Не создавай review сам, если её не было — это работа
постановщика; упомяни в close-note.
6. Дополни summary-строку в handoff/вики при наличии.
1. **Pre-close coverage check.** Collect acceptance criteria from the
description. For each — evidence: a test in the diff, an artifact, a design
reference. No evidence for a criterion → ask the user "close or wait for
coverage".
2. Resolve/drop open questions.
3. `task_close(project, id, version)` → status `done`. `version` — fresh from
`entity_get(id)`/`task_get(id)`; conflict (409) → re-GET → retry.
4. **Notify letter (cross-project tasks).** If the task came from another
project (there's `from:`/`notify:` in description/meta) — `inbox_send` to
the commissioner: `project=<notify>`, `subject="[event: closed] <slug>"`,
body = the outcome (done, acceptance, references). A live session writes it
itself. Task 🟢 ≠ commissioner learned.
5. **Review-umbrella for impl tasks** (canon `mappa-delegation`): if the task
is implementation and closed — the paired `<slug>-review` should already
have been created at assignment (status=blocked, blocker=impl#); closing the
impl unblocks the review. Don't create a review yourself if it didn't exist
— that's the assigner's job; mention it in the close-note.
6. Add a summary line to the handoff/wiki if present.
### Пауза / переключение / конец сессии
### Pause / switch / session end
1. Текущая 🔴 → `task_close` если завершена (см. Фазу 3), иначе пометь
`status=paused` (owner остаётся; «where stopped»в description или handoff).
2. **Инбокс-свип** на границе тасок (`inbox_monitor`).
3. Возьми следующую: `task_update(owner, status='active', version)`прежняя
остаётся 🟡.
4. Подтверди ориентацию перед стартом.
1. Current 🔴 → `task_close` if finished (see Phase 3), otherwise mark
`status=paused` (owner stays; "where stopped"in the description or handoff).
2. **Inbox sweep** at the task boundary (`inbox_monitor`).
3. Take the next one: `task_update(owner, status='active', version)`the
previous stays 🟡.
4. Confirm the orientation before starting.
> **Never lose Where I stopped** — критичное поле: в description (последний
> абзац) или в handoff-сущности (`mappa-closing-ritual`). Перед концом сессии
> обязательно запиши handoff.
> **Never lose Where I stopped** — critical field: in the description (last
> paragraph) or in the handoff entity (`mappa-closing-ritual`). Before the end
> of the session, definitely write the handoff.
---
## Loop-mode — «поработай очередь»
Один триггер-сёрфейс: «поработай очередь» / «work the queue» / «прогони доску»
этот режим. Work the board **в этой сессии**: взять → работа → close → взять,
пока очередь не пуста или user не сказал стоп. **Интерактивный цикл, не демон.**
One trigger surface: «поработай очередь» / "work the queue" / «прогони доску»
this mode. Work the board **in this session**: take → work → close → take,
until the queue is empty or the user said stop. **Interactive cycle, not a daemon.**
```
task_update(owner, status=active, version) → 409? re-GET → retry → пусто? → STOP «борд пуст»
таска
работа в этой сессии (read description + <slug>.md)
task_update(owner, status=active, version) → 409? re-GET → retry → empty? → STOP "board is empty"
task
work in this session (read description + <slug>.md)
завершена? нет → park: blocked (внешний) | paused (возобновляемо) → следующая
да
consult_policy: human-only/strict-human → STOP перед close/commit, спросить user
finished? no → park: blocked (external) | paused (resumable) → next
yes
consult_policy: human-only/strict-human → STOP before close/commit, ask the user
↓ auto
pre-close coverage check → task_close
session_break на таске? → да: печатай 🔚 SESSION BOUNDARY, STOP
нет
следующая
session_break on the task? → yes: print 🔚 SESSION BOUNDARY, STOP
no
next
```
- **Пустая очередь — естественный стоп, не wait-loop.** Нет `CronCreate`, нет
спавна субагента, нет коротких поллеров — это работа отдельного поллера.
Длинный watch («работай пока не скажу стоп» + явно «продолжай проверять») —
только один `ScheduleWakeup` с интервалом ≥1200s, никогда `CronCreate`.
- **Не завершаемая таска:** внешний блокер`status=blocked` + blocker
(конкретный факт + что нужно); прервал ты (бюджет/стоп) → `status=paused` +
where_stopped. Одна упавшая таска не останавливает цикл — паркуй и дальше.
- **Heartbeat не нужен** — живость владельца из session (wiki:2660); долгая
таска с живой сессией не «протухает».
- **Consult-гейт:** `auto` → автопилот до close; `human-only`/`strict-human`
работай, затем **STOP перед close/commit** и спроси user. Push никогда не
автоматический (project-discipline Rule 4: commit freely, push по явному
гранту).
- **An empty queue is a natural stop, not a wait-loop.** No `CronCreate`, no
subagent spawn, no short pollers — that's the work of a separate poller.
Long watch ("keep working until I say stop" + explicit "keep checking") —
only one `ScheduleWakeup` with an interval ≥1200s, never `CronCreate`.
- **Non-finishable task:** external blocker`status=blocked` + blocker
(concrete fact + what's needed); you interrupted (budget/stop) →
`status=paused` + where_stopped. One fallen task doesn't stop the cycle —
park and continue.
- **No heartbeat needed** — owner liveness from the session (wiki:2660); a
long task with a live session doesn't "expire".
- **Consult gate:** `auto` → autopilot up to close; `human-only`/`strict-human`
→ work, then **STOP before close/commit** and ask the user. Push is never
automatic (project-discipline Rule 4: commit freely, push on explicit grant).
---
## Формат таски (из task-format)
## Task format (from task-format)
### Primary: mappa task_create
Создание задач — **через тул, не руками** (решение 20): карв-аут, лиз/claim
для create НЕ нужен (wiki:2660). Номер `task:N` назначает сервер — не выдумывай.
Task creation — **via the tool, not by hand** (decision 20): carve-out, no
lease/claim needed for create (wiki:2660). The number `task:N` is assigned by
the server — don't invent it.
```
mcp__mappa__task_create(
project: <имя проекта>, // обязателен
slug: <kebab-case>, // обязателен, латиница
title: <одна строка>, // опционально
description: <markdown>, // тело; [[refs]] → рёбра (решение 4)
status: ready | active | paused | blocked | done, // по умолчанию ready
priority: P0 | P1 | P2, // только при создании; отсутствует → P1
due: yyyy-mm-dd // только при создании; отсутствует = нет
project: <project name>, // required
slug: <kebab-case>, // required, latin
title: <one line>, // optional
description: <markdown>, // body; [[refs]] → edges (decision 4)
status: ready | active | paused | blocked | done, // default ready
priority: P0 | P1 | P2, // only at creation; absent → P1
due: yyyy-mm-dd // only at creation; absent = none
)
```
Slug-правила: короткий, lowercase, kebab-case, латиница. Description — markdown,
`[[refs]]` на связанное. Priority/Due — при создании ИЛИ строками в description
(`**Priority:** P0|P1|P2`, `**Due:** yyyy-mm-dd`; явные параметры переопределяют).
Slug rules: short, lowercase, kebab-case, latin. Description — markdown,
`[[refs]]` to related. Priority/Due — at creation OR as lines in the
description (`**Priority:** P0|P1|P2`, `**Due:** yyyy-mm-dd`; explicit
parameters override).
### Legacy: блок .tasks/STATUS.md (интерм до флипа поллера)
### Legacy: .tasks/STATUS.md block (interim until the poller flips)
Пока файловый поллер не переключён на mappa (#984), блоки в `.tasks/STATUS.md`
обязаны строгому формату — иначе поллер молча пропускает:
While the file poller is not switched to mappa (#984), blocks in
`.tasks/STATUS.md` must obey a strict format — otherwise the poller silently
skips:
```markdown
## ⚪ [#1234 my-task-slug] — One-line description.
@@ -249,65 +258,68 @@ Slug-правила: короткий, lowercase, kebab-case, латиница.
---
```
Три load-bearing правила: **(1)** шапка точно `## <emoji> [#<n> <slug>] — <desc>`
(h2, один emoji, `[#<n> <slug>]`, разделитель ` — `); **(2)** поля — строки
`**Label:** value`, буллеты игнорируются; **(3)** `**Created:**` обязателен.
Three load-bearing rules: **(1)** the header is exactly `## <emoji> [#<n>
<slug>] — <desc>` (h2, one emoji, `[#<n> <slug>]`, separator ` — `); **(2)**
fields are `**Label:** value` lines, bullets are ignored; **(3)**
`**Created:**` is mandatory.
Поля, которые разбирает поллер: `**Weight:**` (cheap-ok | needs-claude |
needs-human — **обязателен** для авто-взятия), `**Notify:**` (<owner>/<repo>),
`**Requirements:**`, `**Runtime allowed:**`, `**Consult policy:**`, `**Blocker:**`
(только на 🔵), `**Priority:**`/`**Due:**` (как выше). `**Owner:**/`**Claim
token:**/`**Claim expires at:**` — claim-штамп, пишет и чистит поллер; залипший
штамп на ⚪ блокирует поллер.
Fields the poller parses: `**Weight:**` (cheap-ok | needs-claude |
needs-human — **mandatory** for auto-claim), `**Notify:**` (<owner>/<repo>),
`**Requirements:**`, `**Runtime allowed:**`, `**Consult policy:**`,
`**Blocker:**` (only on 🔵), `**Priority:**`/`**Due:**` (as above).
`**Owner:**/`**Claim token:**/`**Claim expires at:**` — claim stamp, written
and cleared by the poller; a stuck stamp on ⚪ blocks the poller.
**Weight — поле, решающее взятие:** без `**Weight:**` поллер паркует в 🔵
(`no backend for weight_tier: unknown`). Обычный код → `needs-claude`;
критикал-инфра (поллер, MCP-серверы, деплой, CI, git-хуки) → `needs-human`.
**Weight — the field that decides the take:** without `**Weight:**` the poller
parks to 🔵 (`no backend for weight_tier: unknown`). Ordinary code →
`needs-claude`; critical infra (poller, MCP servers, deploy, CI, git hooks) →
`needs-human`.
---
## Failure modes
- **version conflict** на update/close → version устарела; re-GET свежую version,
retry. Не «решай конфликт» перезаписью без version (last-write-wins).
- **task_close на незавершённую** → никогда. Park (blocked/paused).
- **owner на таске без живой сессии** → таска формально active, но владелец
stale; спроси человека (адvisory, не замок).
- **notify не указан (legacy)** → без него boss не узнает о завершении.
- **weight не указан (legacy)** → поллер паркует (no backend for weight_tier).
- **update Priority/Due после создания** → сервер отклоняет; паркуй вопрос
человеку, не бампай сам.
- **version conflict** on update/close → version is stale; re-GET the fresh
version, retry. Don't "resolve the conflict" by overwriting without version
(last-write-wins).
- **task_close on an unfinished task** → never. Park (blocked/paused).
- **owner on a task without a live session** → the task is formally active but
the owner is stale; ask the human (advisory, not a lock).
- **notify not specified (legacy)** → without it the boss won't learn about completion.
- **weight not specified (legacy)** → the poller parks (no backend for weight_tier).
- **update Priority/Due after creation** → the server rejects; park the
question to the human, don't bump yourself.
## What NOT to do
- **Не выдумывай номера** — `task:N` назначает сервер (решение 20).
- **Version-дисциплина:** update/close — всегда с version (409 при конфликте
re-GET → retry). Create — карв-аут без лиза (wiki:2660).
- **Одна активная таска** — только одна 🔴 на проект.
- **Never close без coverage check** — evidence на каждый acceptance criterion.
- **Не закрывай незавершённое** — park, не close.
- **Не бампай priority/due после создания** — территория человека.
- **Не «решай» задачи письмом/в чате** — борд — единственный источник правды
(канон mappa-messaging: «если это не на доске — это не задача»).
- **Не полли пустую очередь** — пусто = стоп и отчёт; без демона/CronCreate.
- **Не автопилоть human-only/strict-human** через close/commit; push — только по гранту.
- **Не батчи tasks_create в один репо** — sha-lock конфликты; сериализуй.
- **Don't invent numbers** — `task:N` is assigned by the server (decision 20).
- **Version discipline:** update/close — always with version (409 on conflict
re-GET → retry). Create — carve-out without a lease (wiki:2660).
- **One active task** — only one 🔴 per project.
- **Never close without a coverage check** — evidence for every acceptance criterion.
- **Don't close unfinished work** — park, not close.
- **Don't bump priority/due after creation** — the human's territory.
- **Don't "settle" tasks by letter/in chat** — the board is the only source of
truth (mappa-messaging canon: "if it's not on the board — it's not a task").
- **Don't poll an empty queue** — empty = stop and report; no daemon/CronCreate.
- **Don't autopilot human-only/strict-human** through close/commit; push — only on grant.
- **Don't batch tasks_create into one repo** — sha-lock conflicts; serialize.
## Red flags — STOP
- «Поставлю таймер проверять новые таски» → нет. Стоп на пустой очереди.
- «Спавну фонового воркера гнать доску» → нет. Один цикл, эта сессия.
- «Таска не готова, но закрою и отмечу» → никогда. Park.
- «Приоритет у таски явно P0, сам бампну» → нет. Вопрос человеку.
- "I'll set a timer to check for new tasks" → no. Stop on an empty queue.
- "I'll spawn a background worker to run the board" → no. One cycle, this session.
- "The task isn't ready, but I'll close and mark it" → never. Park.
- "The task is clearly P0, I'll bump it myself" → no. Ask the human.
---
## Reference
- Делегирование (постановка на агентов): `mappa-delegation`.
- Почта (covering-письма, notify): `mappa-messaging`.
- Знание (wiki-ингест после закрытия): `mappa-knowledge`.
- Финиш сессии (handoff write): `mappa-closing-ritual`.
- Старт сессии (pull/handoff/inbox/snapshot): `mappa-session-orient`.
- Промоушен: `mappa-brainstorm-promote` (review-umbrella для промоушенов).
- Кросс-проектный обзор: `using-system-snapshot` (liveness) / `mcp__projects-meta__tasks_aggregate`.
- Delegation (assigning to agents): `mappa-delegation`.
- Mail (covering letters, notify): `mappa-messaging`.
- Knowledge (wiki-ingest after closing): `mappa-knowledge`.
- Session finish (handoff write): `mappa-closing-ritual`.
- Session start (pull/handoff/inbox/snapshot): `mappa-session-orient`.
- Promotion: `mappa-brainstorm-promote` (review-umbrella for promotions).
- Cross-project overview: `using-system-snapshot` (liveness) / `mcp__projects-meta__tasks_aggregate`.