Substitute `{{LANG}}`, `{{CLOSE_MARKER_SHORT}}`. Spec-layer placeholders (gated by `{{SPEC_MODE}}`) -- LINE kind: `{{SPEC_INVARIANTS}}`, `{{SPEC_ADD_STEP}}`, `{{SPEC_MOVE_STEPS}}`, `{{SPEC_VIEW_FLOW}}`; INLINE kind: `{{SPEC_DESC_TRIGGERS}}`, `{{SPEC_ADD_ROW_COL}}`. Write the body below to `TARGET/.claude/skills/task-board/SKILL.md`. > `disable-model-invocation` MUST NOT be set on the emitted skill: plain-prose invocation is a first-class path, alongside `/task-board [view|add|move|backlog|gro...
32 stars
0 votes
0 copies
0 views
Added September 5, 2026
ai-agentsrustgobashnodeapi
Works with
api
Security analysis
B88/100
criticalAccesses sensitive system or user directories
Installs into .claude/skills of the current project.
Are you the author of References?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kochetkov-ma-references-14c5f4e4)
# 03 -- Step 3: `task-board` skill template
Substitute `{{LANG}}`, `{{CLOSE_MARKER_SHORT}}`. Spec-layer placeholders (gated by `{{SPEC_MODE}}`) -- LINE kind: `{{SPEC_INVARIANTS}}`, `{{SPEC_ADD_STEP}}`, `{{SPEC_MOVE_STEPS}}`, `{{SPEC_VIEW_FLOW}}`; INLINE kind: `{{SPEC_DESC_TRIGGERS}}`, `{{SPEC_ADD_ROW_COL}}`. Write the body below to `TARGET/.claude/skills/task-board/SKILL.md`.
> `disable-model-invocation` MUST NOT be set on the emitted skill: plain-prose invocation is a first-class path, alongside `/task-board [view|add|move|backlog|groom]`.
`{{CLOSE_MARKER_SHORT}}` map by RELEASE_STYLE:
- `vtag` → `the closing version/commit (vX.Y.Z tag or SHA)`
- `sha` → `the closing commit SHA`
- `none` → `the closing date / marker`
## Spec-layer placeholders (`SPEC_MODE` gate)
When `SPEC_MODE=on`, substitute each placeholder with its expansion below. When `SPEC_MODE=off`, omit only spec-layer expansions (5 flows); methodology/graph/anti-drift and `PROGRESS.md` remain UNGATED baseline in BOTH modes. Off-mode Invariants = 6 bullets, on-mode = 7; scheduling tools are available to this skill in either mode:
- **LINE kind** -- the placeholder owns its line: REMOVE the whole line, !=leave it blank.
- **INLINE kind** -- the placeholder sits mid-line (`{{SPEC_DESC_TRIGGERS}}` inside `description:`, `{{SPEC_ADD_ROW_COL}}` inside the ADD-flow column list): delete the token itself and nothing else, no stray space. Both carry NO space before the token; the expansion supplies its own leading space.
Authoritative rules live in `TRACKER.md` section 10. These expansions mirror it; !=invent extra rules here.
`{{SPEC_DESC_TRIGGERS}}` expands to:
```
specs view, spec status, which tasks need a spec, spec coverage, blocking questions.
```
`{{SPEC_INVARIANTS}}` expands to 1 bullet appended to the Invariants block:
```markdown
- **Scope change invalidates specs (G3).** Editing a task's `## Scope` -> spec `status: draft` + `/task-spec <ID> refresh`. Editing ONLY a `status` cell !=a scope change -- it never trips G3.
```
`{{SPEC_ADD_ROW_COL}}` expands to the board's 6th column cell:
```
| spec
```
`{{SPEC_ADD_STEP}}` expands to ADD-flow steps 5-6:
```markdown
5. Set `spec:` -- ALWAYS, never blank. `pending` if ANY holds: >1 domain | >~5 files | new integration/dependency | schema/API/contract change | ambiguous requirements or open questions | user asked for a design/spec. Else `none`. The same value goes in the board row's `spec` cell. Every `## Scope` row is born with a `status`: an `in` row `not-started`, an `out` row `--`.
6. If `spec: pending`, end the flow with exactly: `NEXT: run /task-spec <ID> (spec required: <reason>)`. !=author the spec here.
```
`{{SPEC_MOVE_STEPS}}` expands to MOVE-flow steps 5-6:
```markdown
5. On `todo -> progress`: set `spec:` by the ADD-flow heuristic if missing or stale. `spec: pending` -> report `NEXT: run /task-spec <ID> (spec required: <reason>)`; the move still happens. The same value goes in the board row's `spec` cell.
6. On `-> closed`: enforce gate G2 BEFORE moving. Read BOTH docs -- `specs/<ID>-spec.md` `## Open questions` (ids `Q1..Qn`) and `specs/<ID>-design.md` `## Open architectural questions` (ids `AQ1..AQn`); a missing doc contributes nothing, it never waives the gate. If ANY row in EITHER table is `blocking: yes`, REFUSE the move and report the blocking ids (e.g. `Q1, AQ3`) instead. Move anyway ONLY if `## Notes` carries `SPEC WAIVER: <reason>`. Non-blocking questions warn, never block. Independently of G2: flip each `in` scope id's `status` to `in-progress` / `done` as that part lands, and on `-> closed` report LOUDLY every `in` id not `done` (list the ids) -- G2 is the only thing that refuses a close, status never is, and there is no waiver marker for it. G5, on the SAME two reads G2 just did: spec FM `status:` still `draft`, or an `in` id just marked `done` that is `uncovered`/`partial` in `## Scope coverage` -> report `SPEC STALE: <ID> ...` + ONE `NEXT: run /task-spec <ID> refresh`. Report-only -- !=write either doc, !=touch `## Scope coverage`, !=block the close.
```
`{{SPEC_VIEW_FLOW}}` expands to a whole flow section placed after GROOM:
```markdown
### 6. SPECS view
1. `Glob` `.claude/features/{todo,progress,closed}/*.md` and `.claude/features/specs/*.md`.
2. One row per task: `id | spec: | spec.md | design.md | blocking Qs | uncovered scope | scope status`.
- `spec.md` / `design.md`: `yes` | `--`, by existence of `specs/<ID>-spec.md`, `specs/<ID>-design.md`.
- `blocking Qs`: count of `blocking: yes` rows across BOTH `<ID>-spec.md` `## Open questions` (`Q#`) and `<ID>-design.md` `## Open architectural questions` (`AQ#`).
- `uncovered scope`: `in` scope ids marked `partial` or `uncovered` in either `## Scope coverage` table. `out` rows never count.
- `scope status`: every `in` scope id with its `## Scope` `status`, e.g. `S1 done, S2 in-progress, S3 not-started`. `out` rows never count. Orthogonal to coverage -- `covered` !=`done`, `done` !=`covered`.
3. Report DRIFT first, ABOVE the table -- loudly, one line each:
| Drift | Call it |
|-------|---------|
| `spec: pending` + no docs | spec owed -> `NEXT: run /task-spec <ID> (spec required: <reason>)` |
| `spec: full` + a file missing | FM lies -> re-run `/task-spec <ID>` |
| `spec: design-only` + `<ID>-spec.md` exists | FM lies -> fix `spec:` |
| blocking Qs > 0 while in `progress/` | close is gated (G2) -> resolve, or record `SPEC WAIVER:` |
| any `in` scope id `partial` / `uncovered` (`out` rows never count) | G1 unmet -> spec `status:` must stay `draft` |
| an `in` scope id missing from a `## Scope coverage` table | G3: scope changed after the spec -> spec `status: draft` + `/task-spec <ID> refresh` |
| `spec:` blank or absent | !=allowed -> set it per the ADD heuristic |
| an `in` scope id not `done` while in `closed/` (`out` rows never count) | delivery gap -> say which ids; report only, !=a gate, no waiver |
4. This flow VIEWS and GATES only. Authoring or refreshing a spec routes to `/task-spec <ID>` (`design` | `refresh`). !=write spec or design content here.
```
---
```markdown
---
name: task-board
description: "Views and updates this repo's file-based task board at .claude/features/. Triggers: show the board, task board, board status, what's in progress, add a task, create task, move task to progress, close task, dump to backlog, groom backlog.{{SPEC_DESC_TRIGGERS}}"
argument-hint: "[prompt] [view | add | move | backlog | groom]"
allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, Agent, CronCreate, CronList, CronDelete]
doc_type: llm
version: "{PLUGIN_VERSION}"
content_version: "{CONTENT_VERSION}"
generated_by: "{GENERATED_BY}"
last_updated: "{LAST_UPDATED}"
---
# Task Board (dashboard)
On-demand entry point for the file-based Kanban under `.claude/features/`.
Authoritative procedure: `.claude/features/TRACKER.md`. This skill mirrors it -- do not invent rules.
## Prompt contract
Position 1 of `$ARGUMENTS` is a **free-form prompt** ({{LANG}}) -- `view`/`add`/`move`/`backlog`/
`groom` and any flags are optional and may follow in any order. Nobody types keys: resolve the flow
FROM the prompt.
| Mode | EN keywords | RU keywords | Mutates? |
|------|-------------|-------------|----------|
| `view` (default) | *(empty)*, show the board, task board, board status, what's in progress | покажи доску, статус доски, что в работе | no |
| `add` | add a task, create task, new task | добавь задачу, создай задачу, новая задача | yes |
| `move` | move task to progress, close task, pick up, ship it | перемести в работу, возьми в работу, закрой задачу | yes |
| `backlog` | dump to backlog, backlog it, look into later | закинь в бэклог, в бэклог | yes |
| `groom` | groom backlog, groom the backlog, triage backlog | разбери бэклог, приведи бэклог в порядок | yes |
1. Strip flags. An explicit mode token anywhere wins outright, no scoring.
2. Else score modes by distinct whole-word keyword hits (table above). Highest unique score wins;
a tie against `view` picks `view` (read-only); a tie of two mutating modes falls to the keyword
appearing first in the prompt.
3. Empty arguments -> `view` (the documented default); a read-only run asks nothing.
4. Prose that is not a mode is still input: extract the task id, folder or row it names before
entering the flow (VIEW/ADD/MOVE/BACKLOG/GROOM below) -- never guess the first word as a mode.
5. Outcome-changing ambiguity (which task, which folder) -> ONE `AskUserQuestion` before any write.
Then print this block once, before the first action:
\`\`\`
PLAN — task-board
INPUT: <arguments verbatim, or "(empty)">
MODE: <resolved> -- <explicit | matched keyword: X | default>
SCOPE: <task id / row / folder touched, or "read-only view">
DO: <2-5 imperative bullets>
RESULT: <board.md row, task file, or the view/report the user ends up holding>
\`\`\`
Labels are literal ASCII; values follow {{LANG}}.
## Invariants (always hold)
- **Folder == status.** A task file lives in `todo/` | `progress/` | `closed/` (or `backlog/`); its `status:` frontmatter MUST equal the folder. On a move, change both.
- **Board is canonical and never lags.** Edit `board.md` in the SAME change as any transition. A lagging board is a wrong board.
- **Ids never change.** UPPER-KEBAB, short, stable -- the filename stem and the board key.
- **Every accepted todo/progress task MUST have a real file** with filled Methodology/base work and a unique COMPLETE saved cron prompt. Only raw unaccepted backlog ideas may remain table-only. A queued prompt is prepared intent, never a live schedule.
- **{{LANG}} only.** Closing records {{CLOSE_MARKER_SHORT}} in `## Notes`.
- **`PROGRESS.md` tracks the SESSION, not the tasks.** Refresh `.claude/features/PROGRESS.md` in the SAME change as any transition -- five fields: `Updated`, `In flight`, `Moved since last update`, `Blocked`, `Next`, overwritten in place. !=a second board; rules in `.claude/rules/tasks.md`.
{{SPEC_INVARIANTS}}
Layout: `board.md` (dashboard), `PROGRESS.md` (session progress), `TRACKER.md` (procedure), `METHODOLOGY.md`, `ANTI-DRIFT.md`, `task-graph.md` (derived active work), `TASK_TEMPLATE.md`, `backlog/` (ungated inbox), `todo/`, `progress/`, `closed/`, `specs/`.
## Methodology and session timer
Read `METHODOLOGY.md` + `ANTI-DRIFT.md` before ADD/GROOM promotion/MOVE or a tick; accepting a task requires its filled Methodology (goal/acceptance, domain review/tests or explicit gaps, base work units/dependencies/owners, parent id) and complete unique Anti-drift cron prompt, with every token resolved. Hourly default; user cadence overrides it. Queued tasks store state `prepared` and no live scheduler id; only active top-level claims start timers. The MAIN SESSION running this skill owns timer calls; `task-tracker` owns file reconciliation and returns `CRON:` actions. After delegated results, execute those actions here BEFORE any mandatory final `NEXT:` redirect. On direct ADD/MOVE, refresh derived graph/PROGRESS and reconcile timers after a successful transition; never stop a timer for a refused close.
Before creating/resuming, list and match by task id + absolute project root; reuse one matching timer, reconcile only this task's duplicates, verify deletion before replacing. Create one recurring session timer per active top-level task, not child work unit; persist complete prompt/runtime state in its task file and announce effective cadence, timezone, verified id/state, known due time, session limits and stop/change controls. Completion/cancellation/parking stops this task's timers and verifies absence. Missing/denied cron tools -> save intent and report unavailable; never invent delivery or a durable fallback. Details and tick/report format: `ANTI-DRIFT.md`.
VIEW remains read-only: show missing/stale timer/methodology/graph state without scheduling. In plan mode read/report only; include methodology, saved prompt, graph and timer reconciliation as execution steps, defer writes/timers. A delivered tick runs the saved plain prompt: reread/reconcile, force goal/acceptance drift checks and advance authorized work, then at most five compact lines with local time, tick number, elapsed, achievements, remaining/next, blockers/questions and drift verdict using only 🟢🔵🔴⚪. Preserve all unfinished graph nodes + latest 10 completed; archive completion evidence before pruning rows.
## Flows
### 1. VIEW
1. Read `.claude/features/board.md` + `PROGRESS.md`.
2. Summarize: overall status (release line), counts (backlog | todo | progress | closed), current focus (1-3 lines), then the Progress (WIP) and Todo tables. Do not enumerate backlog noise. Close with `PROGRESS.md`'s `Blocked` / `Next` only -- `In flight` / `Moved` are already in the tables above; if its `Updated` predates the newest task `updated:`, report it stale and recommend reconciliation (VIEW does not write).
### 2. ADD task
1. Mint an UPPER-KEBAB id by prefix: `T-*` feature, `BUG-*` defect, `M-*` maintenance, `EPIC-*` umbrella. First kebab segment = a repo domain (see TRACKER.md id convention).
2. ALWAYS create `<ID>.md` from `TASK_TEMPLATE.md` in the accepted target folder (usually `todo/`); table-only acceptance is prohibited.
3. Fill frontmatter: `id`, `title`, `status` (== folder), `priority`, `owner`, dates, tags/links; fill Context/Acceptance, domain review/checks, bounded base units/owners/dependencies and COMPLETE unique saved prompt with actual id/root/paths/goal/base work/acceptance. No unresolved template guidance/tokens. Queued cron state `prepared`, scheduler id empty; scheduling starts only on active top-level claim.
4. Add its actual file link to `board.md` (`id | title | prio | owner | file{{SPEC_ADD_ROW_COL}}`); sync graph/PROGRESS in the same change. A missing record/method/base work/prompt means acceptance is incomplete: finish preparation before reporting it accepted.
{{SPEC_ADD_STEP}}
### 3. MOVE / TRANSITION
`todo -> progress` (pick up) | `progress -> closed` (ship) | `progress -> todo` (re-queue/park).
1. Verify the accepted record is complete before moving; repair legacy row-only or incomplete tasks through ADD preparation requirements without discarding decisions. Refresh method/prompt for current corrections, then move its file between folders.
2. Set `status:` to match the new folder; set `owner` (on pick-up); set `updated` to today.
3. On `-> closed`: add a one-line outcome + {{CLOSE_MARKER_SHORT}} in `## Notes`.
4. Update `board.md` in the SAME change: move the row between tables, refresh counts and current focus. Refresh `PROGRESS.md`'s five fields too. On `-> closed` with the `progress` count now `0` AND no `.claude/skills/task-spec/` in this repo, add ONE line: `NEXT: run /brewtools:task-board-setup upgrade <repo path>` (it retrofits the spec + design layer). Spec layer already present -> say nothing.
{{SPEC_MOVE_STEPS}}
### 4. BACKLOG dump
Drop an unclear/raw item into `.claude/features/backlog/<slug>.md` -- raw idea, pasted log, "look into X later". No format gate. It is NOT a task yet; it becomes one (or is trashed) during grooming.
### 5. GROOM backlog
1. `Glob` `.claude/features/backlog/*.md` (skip `README.md`).
2. For each item decide its fate: **promote** -> real `todo` task (run flow 2), **merge** -> fold into an existing task's `## Notes`, or **trash** -> delete the file.
3. Delete the backlog file once handled. Never leave a groomed item behind.
4. Refresh the board backlog count.
{{SPEC_VIEW_FLOW}}
## Delegation
A big task handed to one agent = an agent gone for an hour: you cannot observe it, cannot correct it, and it usually drifts off-target. One subagent = ONE bounded unit — ONE board pass (one groom run, or one status folder's transitions), ~<=5 files, ~<=10 steps. Bigger MUST be split into N tasks, all spawned in ONE message.
Every spawn prompt MUST carry:
| Field | Content |
|-------|---------|
| GOAL | the overall task and why it exists — the point beyond the file edit |
| ROLE | what this agent owns; what it must NOT touch |
| SCOPE | exact paths/commands in bounds + explicit out-of-bounds |
| CONTEXT | what is already done, by whom, what runs in parallel — trimmed to what THIS agent needs |
| CONSUMER | who or what uses the result next, and the shape it must fit |
| DONE | acceptance criteria + the exact report shape you want back |
A bare one-line task is never enough. Simple single-task view/add/move: do it directly here. For non-trivial passes (bulk transitions, large groom, migrating many rows) delegate to the `task-tracker` agent rather than hand-editing:
\`\`\`
Agent(subagent_type="task-tracker", prompt="
GOAL: keep .claude/features/ truthful — a lagging board.md is a wrong board, and every reader
(this skill's VIEW flow, any status report) trusts it over the files.
ROLE: you own this groom pass. Promote / merge / trash each backlog item, then sync board.md,
task-graph.md and PROGRESS.md from the task files and existing control contracts.
Do NOT touch source dirs, do NOT invent tasks no backlog item supports, do NOT rename existing ids.
SCOPE: in — .claude/features/backlog/*.md (skip README.md), the task files you promote into todo/,
board.md, task-graph.md and PROGRESS.md. Out — progress/, closed/, specs/, source code, CLAUDE.md.
CONTEXT: the authoritative procedure is .claude/features/TRACKER.md and the id convention is in
TASK_TEMPLATE.md — read both first, do not reinvent them. Ids are UPPER-KEBAB and never change.
Nothing else is editing the board right now; the current counts in board.md are the pre-groom ones.
CONSUMER: the VIEW flow reads board.md counts + tables next, and folder == status: a file whose
status: frontmatter disagrees with its folder, or a task missing from board.md, is invisible.
DONE: every backlog file handled (promoted / merged / trashed — none left behind); board.md tables,
counts, backlog count, task-graph.md and PROGRESS.md refreshed in the SAME change. Report a table: promoted ids | merged-into
ids | trashed slugs, plus the new counts.
")
\`\`\`
## Guards
| Condition | Response |
|-----------|----------|
| an argument that matches no mode keyword and names no task/row/folder is still read as a mode | defect -- it is prose: extract the target from it or ask, never guess |
| the `PLAN` block is missing, or is printed after the first file write | defect -- print it once, right after mode resolution, before entering the flow |
## References
- Procedure (authoritative): `.claude/features/TRACKER.md`
- Dashboard: `.claude/features/board.md`
- Template: `.claude/features/TASK_TEMPLATE.md`
- Rules: `.claude/rules/tasks.md`
- Methodology/timer controls: `.claude/features/METHODOLOGY.md`, `.claude/features/ANTI-DRIFT.md`
- Derived active work: `.claude/features/task-graph.md`
- Control-file index: `.claude/features/INDEX.md`
```