From 195de4b8e60eef2f0ff18049e31865e46637e5b5 Mon Sep 17 00:00:00 2001 From: vitya Date: Tue, 25 Aug 2026 17:42:37 +0300 Subject: [PATCH] =?UTF-8?q?docs(skills):=20mappa-task-work=201.2.0?= =?UTF-8?q?=E2=86=921.3.0=20=E2=80=94=20English=20translation,=20bilingual?= =?UTF-8?q?=20triggers=20(task:1086)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skills/mappa-task-work/SKILL.md | 446 ++++++++++++++++---------------- 1 file changed, 229 insertions(+), 217 deletions(-) diff --git a/skills/mappa-task-work/SKILL.md b/skills/mappa-task-work/SKILL.md index 8766cb2..b1e5448 100644 --- a/skills/mappa-task-work/SKILL.md +++ b/skills/mappa-task-work/SKILL.md @@ -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=, from=<своя>, subject, body)` | письмо комиссионеру | +| Take the next ready task | `mcp__mappa__task_update(project, id, owner=, 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=, 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=, from=, 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 `#`. -## Статусы (эмодзи для презентации) +## 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=)`: unread + letters may change the plan. Handle each per `mappa-messaging`. +2. **Board** — `entity_search(q, type='task', project=, 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` = `::`. -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=, 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` = `::`. +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 файл (`.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 (`.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=`, `subject="[event: closed] "`, - body = итог (сделано, acceptance, ссылки). Живая сессия пишет сама. - Таска 🟢 ≠ комиссионер узнал. -5. **Review-umbrella для impl-тасок** (канон `mappa-delegation`): если таска - имплементационная и закрыта — парная `-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=`, `subject="[event: closed] "`, + 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 `-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 + .md) +task_update(owner, status=active, version) → 409? re-GET → retry → empty? → STOP "board is empty" + ↓ task +work in this session (read description + .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: , // обязателен, латиница - title: <одна строка>, // опционально - description: , // тело; [[refs]] → рёбра (решение 4) - status: ready | active | paused | blocked | done, // по умолчанию ready - priority: P0 | P1 | P2, // только при создании; отсутствует → P1 - due: yyyy-mm-dd // только при создании; отсутствует = нет + project: , // required + slug: , // required, latin + title: , // optional + description: , // 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)** шапка точно `## [# ] — ` -(h2, один emoji, `[# ]`, разделитель ` — `); **(2)** поля — строки -`**Label:** value`, буллеты игнорируются; **(3)** `**Created:**` обязателен. +Three load-bearing rules: **(1)** the header is exactly `## [# +] — ` (h2, one emoji, `[# ]`, separator ` — `); **(2)** +fields are `**Label:** value` lines, bullets are ignored; **(3)** +`**Created:**` is mandatory. -Поля, которые разбирает поллер: `**Weight:**` (cheap-ok | needs-claude | -needs-human — **обязателен** для авто-взятия), `**Notify:**` (/), -`**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:**` (/), +`**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`.