Public reference for the on-disk .tasks/STATUS.md block format the autonomous poller parses: header regex, status emoji, and the **Weight:** / **Notify:** / **Requirements:** fields. Ships with factory where the internal wiki and MCP source can't reach. Distinct from delegate-task (MCP-tool delegation) and using-tasks (board mechanics). Authored via superpowers:writing-skills TDD: - RED: 3 baseline subagents w/o skill — 2/3 used ###/bullet headers the parser cannot recognize as a task, 2/3 omitted **Weight:** (invented risk/tier/ claimable-by), 2/3 put notify in prose, 1/3 used 🟢 for a ready task. - GREEN: 2 fresh subagents w/ skill — both parser-valid, incl. correct **Weight:** needs-human for the critical-infra scenario. - REFACTOR: no new format loopholes. Ground truth verified vs live source (status-md.ts parser, claim.ts gate, fleet-router.js routing): missing Weight finds no backend tier -> poller parks to blocked, so Weight is operatively required for pickup. Closes [create-task-format-for-poller-skill]. Install to ~/.claude/skills + hermes mapping deferred as follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.6 KiB
name, version, description
| name | version | description |
|---|---|---|
| task-format | 0.1.0 | Use when writing or editing a task block in a `.tasks/STATUS.md` board that an autonomous task-runner ("poller") will read — so the task is actually claimed, routed, and reported instead of silently skipped. Covers the exact block header, the status emoji, and the `**Weight:**` / `**Notify:**` / `**Requirements:**` fields the poller parses. Triggers: «оформить таску для поллера», «формат таски», «task block format», «make a task the poller will pick up», «add Weight/Notify», poller / agent-runner not claiming a task you wrote by hand. |
task-format
The autonomous poller parses .tasks/STATUS.md line-by-line with strict regexes. A block runs only if its header and fields match exactly. Get the format wrong and the poller does not error — it silently skips the block, or claims it and then parks it. This is the canonical field reference.
Authoring a task for another project/agent via
mcp__projects-meta__tasks_create? Usedelegate-task— it drives the tool, which emits this format for you. This skill is the format itself: for hand-edited STATUS.md blocks and for understanding what the poller reads. For board working policy (claim/close/status), seeusing-tasks.
Canonical block (copy this)
## ⚪ [my-task-slug] — One-line description of the work.
**Status:** ready
**Where I stopped:** (not started)
**Next action:** First concrete step the claiming agent runs.
**Branch:** master
**Weight:** needs-claude
**Notify:** OpeItcLoc03/workshop
<!-- created-by: you@machine / from: OpeItcLoc03/workshop / 2026-06-11 -->
---
The two load-bearing rules
-
Header must match exactly:
## <emoji> [<slug>] — <description>##(h2, two hashes) — not###, not a bullet.- One status emoji, then
[slug]in square brackets, then—(space, em-dash—, space), then the description. A-hyphen or:will not match. - Slug: short, lowercase, kebab-case, Latin.
- A header that doesn't match is not seen as a task at all.
-
Fields are
**Label:** valuelines — bold label, colon, space, value. Bullet-list fields (- **weight:** …) and prose ("notify workshop when done") are ignored — the poller never reads them.
Status emoji ↔ state
| Emoji | State | |
|---|---|---|
| ⚪ | ready | the only state the poller claims |
| 🔴 | active | claimed / in flight |
| 🟡 | paused | resumable |
| 🔵 | blocked | waiting on a **Blocker:** |
| 🟢 | done | kept until merged |
**Status:** mirrors the emoji in words. ⚪ → ready. Do not use 🟢 for "ready" — 🟢 is done.
Fields the poller parses
| Field | Format | Meaning |
|---|---|---|
**Weight:** |
cheap-ok | needs-claude | needs-human |
Routing tier. Required for autonomous pickup — see below. |
**Notify:** |
<owner>/<repo> |
Inbox target. Poller writes to that project's .claude-inbox/ on close / park / delivery-failure. Omit → no report; the steering loop never closes. |
**Requirements:** |
CSV, e.g. needs-db, needs-secrets |
Hard capability gate. The agent must hold all listed capabilities or the task is skipped. |
**Runtime allowed:** |
CSV, e.g. claude-opus |
Runtime whitelist. If set, only a listed runtime may claim. |
**Consult policy:** |
auto | human-only | strict-human |
How a mid-run consult escalates. Default when absent: human-only. |
**Blocker:** |
CSV of blocker slugs | Only on 🔵 blocked. Auto-unblock flips the task to ⚪ when every blocker is 🟢. |
**Next action:** / **Where I stopped:** / **Branch:** |
free text | Core resumability fields. |
**Owner:** / **Claim token:** / **Claim expires at:** are the claim stamp — the poller writes and clears them. Never author them by hand; a stale stamp on a ⚪ task blocks the poller.
Weight — the field that decides pickup
The poller routes each claimed task to a backend by its weight tier:
cheap-ok— routine work, a cheap/weak model is fine.needs-claude— needs a capable model (refactors, anything where discipline matters, review).needs-human— never runs autonomously. The claim gate excludes it and the runner refuses to spawn. Use for anything touching critical infra: the poller/agent-runner itself, MCP servers, claim/close/heartbeat, deploy, CI/CD, git hooks.
No **Weight:** line → no backend tier matches → the poller claims the task, finds no route, and parks it to 🔵 blocked (no backend for weight_tier: unknown). So a task you want run must carry a Weight. If in doubt and the work is ordinary code, use needs-claude.
Common mistakes (from baseline failures)
| Mistake | Fix |
|---|---|
### Title or a - **id:** … bullet list |
Use the exact ## <emoji> [slug] — desc h2 header + **Field:** lines. |
| 🟢 for a ready task | 🟢 is done. Ready is ⚪. |
Inventing risk: low, tier: L, priority, claimable-by |
The poller routes on **Weight:** with three fixed values only. |
| Notification written as prose / "Done-signal" | Use a real **Notify:** <owner>/<repo> field line. |
| Omitting Weight on a task you want auto-run | Always set Weight, or the task parks. |
Hyphen or colon instead of — in the header |
The separator is space + em-dash + space. |
Verify
After editing, the block is correct when: header is ## <emoji> [slug] — …, the emoji matches **Status:**, every machine-read field is a **Label:** line (not a bullet), and a task meant for the poller has both **Weight:** (not needs-human unless intended) and **Notify:**.