feat(task-format): new skill v0.1.0 — poller task-block format reference
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>
This commit is contained in:
95
skills/task-format/SKILL.md
Normal file
95
skills/task-format/SKILL.md
Normal file
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: task-format
|
||||
version: 0.1.0
|
||||
description: >
|
||||
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`? Use `delegate-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), see `using-tasks`.
|
||||
|
||||
## Canonical block (copy this)
|
||||
|
||||
```markdown
|
||||
## ⚪ [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
|
||||
|
||||
1. **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**.
|
||||
|
||||
2. **Fields are `**Label:** value` lines** — 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:**`.
|
||||
Reference in New Issue
Block a user