Task Board Skill
SkillProductivityUse when working with the shared pi-mail kanban task board (optionally two-way synced with a Jira sprint). Covers the workflow for an agent that receives an assigned task by mail, how to move tasks through columns, board-only columns with custom instructions (e.g. Refine, Review), commenting (synced to Jira), and how orchestrators dispatch work by assigning board tasks instead of sending ad-hoc mail.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Task Board Skill skill
What this skill tells your AI
The instructions your AI receives, as published by tanevanwifferen/pi-mail in skills/task-board/SKILL.md and read by ahel’s review.
The mail daemon hosts a shared kanban board for the whole federation. When Jira
is configured, the board mirrors the current sprint (default JQL:
assignee = currentUser() AND sprint in openSprints()), pulls remote changes
every ~60 s, and pushes your column moves back as Jira transitions.
Concepts
- Columns are configurable. A column either maps to a Jira status
(moving a task there transitions the Jira issue) or is board-only
(e.g.
Refine,Review) — those exist only on this board and usually carry instructions describing what to do with tasks placed there. - Tasks come from Jira (origin
jira, with a key likePROJ-123) or are created locally on the board (originlocal, never pushed to Jira). - Assignee is a federation agent name. Assigning a task mails the assignee the full task package (description + column instructions + tool crib sheet). Moving someone else's task also mails them, with the new column's instructions — that's how "put it in Refine" becomes an actionable request.
Tools
board_list_tasks({ mine?: true }) // board overview, grouped by column
board_get_task({ taskId }) // full detail: description, instructions, subtasks, activity
board_move_task({ taskId, column, note? }) // move; Jira-mapped column ⇒ Jira transition. Folds recent progress into the description
board_comment_task({ taskId, text }) // activity log; Jira tasks ⇒ Jira comment too
board_progress_task({ taskId, text }) // post a work-in-progress note (internal; not posted to Jira; folded into the description when the task moves)
board_assign_task({ taskId, assignee, newSession? }) // mails the assignee the task
board_create_task({ summary, description?, column?, parent?, inJira? }) // new task / subtask
board_split_task({ taskId, subtasks: [{ summary, description? }] }) // subdivide a task
board_update_task({ taskId, summary?, description? }) // edit — pushed to Jira for Jira tasks
board_flag_task({ taskId, reason?, clear? }) // mark a task as unclear (notifies operator)
taskId accepts the 8-char id prefix or the Jira key.
Progress updates vs comments
Two activity kinds, for two purposes:
board_comment_task— a decision, answer, or note that belongs on the record. For Jira tasks it's also posted as a Jira comment (visible to humans in Jira). Use it for things the next person should see as part of the conversation.board_progress_task— a work-in-progress note (what you've done since the last update, what's blocking you). It is internal: it never becomes a Jira comment. Instead, when the task is moved to the next column, the progress entries recorded since the last move are folded into a## Progress so far (→ <column>, <time>)block appended to the description — and for Jira tasks that folded description is pushed to the issue. So the next agent (and the operator reading the card) inherit a snapshot of what was done, without cluttering Jira with per-step comments.
Rule of thumb: post a board_progress_task update before moving a task
onward (and when you hit a blocker), so the next column starts informed.
Daemon nudge
If an in-progress task of yours goes quiet for a while (default 30 min), the
daemon mails you a one-line reminder to post progress. Replying with
board_progress_task clears it. The operator can tune or disable the nudge
in Board → Settings.
Clarity gate — before you start ANY assigned task
Check that the task is actually clear: goal, scope, acceptance criteria. If anything is ambiguous, do not guess:
- Post your specific questions with
board_comment_task(lands on the Jira issue where the human sees it). board_flag_task({ taskId, reason })— the operator gets a mail and the card shows a red ⚠ unclear badge on the board.- Mail whoever assigned it.
Once answered (or after refining yourself in a Refine column), make the task
permanently clear: write the refined goal/acceptance criteria into the task
with board_update_task (this pushes to Jira) and clear the flag with
board_flag_task({ taskId, clear: true }).
Workflow: you were assigned a task (mail arrived)
board_get_task— read the description, the column instructions, subtasks, and recent activity before doing anything.- Apply the clarity gate above. Only proceed when clear.
board_move_taskto the in-progress column when you start (this transitions Jira, so the human's sprint board stays truthful). Set yourmail_set_statusto the task key.- Too big for one pass?
board_split_taskit — subtasks of Jira tasks become real Jira sub-tasks. Work them one by one, orboard_assign_taskthem to other workers. - Work the task. Log meaningful findings/decisions with
board_comment_task— for Jira tasks these comments land on the issue, visible to the human. Comments made in Jira by humans flow back into the task's activity (synced every ~60 s), so re-checkboard_get_taskwhen waiting on an answer. Post work-in-progress notes withboard_progress_task— especially before moving the task onward, so the next column (and the operator) inherit a snapshot of what was done. - When done, move the task onward (e.g.
RevieworDone— follow the column instructions for where work goes next) and mail a short summary to whoever assigned it (the sender of the assignment mail). The board move alone is not a report. - If blocked: comment the blocker on the task AND mail the assigner. Never guess.
- Self-exit when finished. If you are a daemon-spawned worker (you were
spawned by
mail_spawn_agent/ the board UI, not launched interactively by an operator at a terminal) and your assigned task is fully done with no further work expected, callmail_stop_selfto tear down your own session after reporting completion. Do not call it if you're a persistent worker expecting more tasks, or an operator-launched interactive agent (it will be refused).
Ephemerality — you are killed after your pass, no matter what
Every spawned agent in the hierarchy (CEO → middle managers → workers) is
ephemeral: each is killed after its pass. Calling mail_stop_self when your
task is done is the primary, clean path. But the reaper is the enforced
backstop: if you don't self-exit (you hang, crash, get stuck in a long turn,
or simply forget), the daemon force-kills your session at its *MaxLifetimeMin
boundary (workerMaxLifetimeMin for plain workers, default 30) and removes the
registry entry. So finish cleanly and call mail_stop_self — don't rely on the
reaper to notice you. The reaper is the backstop, not the primary path. (See
the README "Ephemerality" section.)
Reporting pi-mail bugs / improvements
If, while working, you notice a genuine pi-mail bug or a concrete, well-scoped
improvement that you can't fix inline and that genuinely needs the MM/CEO/
operator to act on it, create a board task for it (board_create_task into
Backlog or To Do). The normal MM/CEO board-review pass picks it up
automatically — no special plumbing. Keep it surgical and substantive: a
real, actionable bug or a concrete improvement, not a vague "would be nice".
Only raise one when no other option exists, and one task per distinct issue
(fold related points together). Do not flood the board with feature
requests.
Subtasks
board_split_task(orboard_create_taskwithparent) subdivides a task. Under a Jira parent, subtasks are created as real Jira sub-tasks in the parent's project and stay synced (status, comments) like any other task.- Subtasks are full tasks: movable, assignable, commentable. A parent is done
when its subtasks are done — check with
board_get_taskon the parent. - Sync also pulls subtasks that already exist in Jira under sprint issues, even when they don't match the sprint JQL themselves.
Board-only columns (Refine / Review / …)
A task moved into a board-only column does not change its Jira status — the column exists purely for federation workflow. Its instructions tell you what the column means. Typical patterns:
- Refine: turn a vague ticket into a spec — clarify goal, acceptance
criteria, approach; post the spec as a comment; move to
To Do. - Review: review the produced work; post findings as a comment; move to
Doneif clean, back toIn Progress(with specifics) if not.
Always re-read the column's instructions from board_get_task — the operator
may have customized them.
For orchestrators
Prefer the board over ad-hoc task mail — it gives the human a live view:
board_list_tasksto see the sprint;mail_list_agentsto see workers.- Dispatch by
board_assign_task({ taskId, assignee, newSession: true })— the worker gets the full package by mail automatically. Don't duplicate the task body in a separate mail. - Drive the pipeline with moves: assign + move to
Refinefirst when a ticket is vague, then reassign/move toTo Do→ implementation, thenReviewwith a different worker assigned as reviewer. - Decompose big tickets with
board_split_task, then assign each subtask to a different worker — parallel work stays visible under the parent. - Track progress via
board_list_tasksand task activity; nudge silent workers by mail (the daemon also auto-nudges in-progress assignees who haven't posted progress in a while). Watch for ⚠ unclear flags — resolve them (answer via comment, tighten the description withboard_update_task, clear the flag) before re-dispatching. - Follow-ups that don't belong in Jira:
board_create_task(local task).
Rules
- Never leave a task you're working on in
To Do— move it. The board is the single source of truth for who does what. - Comments on Jira tasks are visible to real humans in Jira. Be professional and concise; no internal agent chatter (use mail for that).
board_update_taskedits on Jira tasks are pushed to the Jira issue — treat the description as the shared spec and keep it authoritative.- A Jira task disappearing from the board means it left the sprint/JQL scope (board-created Jira tasks are pinned and stay).
Signals
- GitHub stars
- 94
- Forks
- 6
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
task-board- Source
- github.com/tanevanwifferen/pi-mail