WorkItem Management
Intro
WorkItems are the fundamental tracked unit of work in processkit — tasks, stories, bugs, spikes, epics, tickets. This skill creates them, transitions them through their state machine, links them to other entities, and queries them.
MCP server. This skill ships a self-contained MCP server at
mcp/server.py(PEP 723 script — requiresuvand Python ≥ 3.10 on PATH). Agent harnesses reach its tools by reading a single MCP config file at startup, so the contents ofmcp/mcp-config.jsonmust be merged into the harness's MCP config and placed at the harness-specific path before this skill is usable. If processkit was installed by an installer, that wiring is the installer's responsibility; if processkit was installed manually, the project owner must do it by hand.
Overview
When to create a WorkItem
Whenever the user (or you) identifies a distinct unit of work that should be tracked. Don't create work items for every tiny thing — a WorkItem is worth creating when it has:
- A clear title ("Add aibox lint command")
- A distinct state lifecycle (it starts somewhere, ends somewhere)
- Someone who should own it (even if not yet assigned)
If it's just a one-liner you're about to do in the next 30 seconds, don't bother.
WorkItem types
spec.type distinguishes subtypes:
| type | When to use |
|---|---|
task |
Default — generic unit of work |
story |
User-facing feature framed as a user story |
bug |
Something that isn't working as intended |
epic |
Large body of work, parent of other WorkItems |
spike |
Time-boxed investigation with no committed deliverable |
chore |
Maintenance, cleanup, refactoring |
Creating
- Pick the
type. - Write a short, imperative
title. - Set
stateto the initial state (backlogby default). - Set
priorityif known (critical/high/medium/low). - Assign to an Actor (optional at creation).
- Write the file to
context/workitems/BACK-<id>.md. - Log
workitem.created.
Transitioning
The default state machine is:
backlog → in-progress → review → done
↓ ↑
blocked ↑
↓ ↑
backlog ←
(any state) → cancelled (terminal)
To transition:
- Check the current state allows the transition (see
primitives/state-machines/workitem.yaml). - Update
spec.state. - Update
metadata.updated. - Set
spec.started_aton first entry toin-progress(if unset). - Set
spec.completed_atwhen entering a terminal state. - Log
workitem.transitionedwithfrom_stateandto_stateindetails.
Linking
Four types of links, all expressed in frontmatter:
| Field | Meaning |
|---|---|
parent |
This WorkItem is a child of a larger one (epic) |
children |
This WorkItem has sub-items |
blocks |
This WorkItem blocks others until done |
blocked_by |
This WorkItem cannot proceed until others are done |
related_decisions |
DecisionRecord IDs that motivated or constrain this |
For scoped/temporal relationships (e.g. "Alice is assigned to this for sprint 42
only"), use a Binding instead of spec.assignee.
Querying
Common queries the index MCP server will expose in Phase 3:
- All WorkItems in a given state
- All WorkItems assigned to an actor
- All WorkItems blocked (or blocking something)
- All WorkItems in a scope
- Full-text search across title + body
Before Phase 3, query via filesystem glob + grep of context/workitems/.
This skill also provides the /workitem-management-create slash command for direct invocation — see commands/workitem-management-create.md.
Gotchas
Agent-specific failure modes — provider-neutral pause-and-self-check items:
- Creating a WorkItem when the user hasn't asked to track work yet. Sometimes the user is just thinking out loud. Don't translate every mention of "we should X" into a backlog entry. Ask: did the user explicitly say to track it, or did you decide to? If you decided, ask first. The Note primitive (when available) is the right home for half-formed ideas; WorkItem is for committed work.
- Transitioning state without checking the state machine. State
changes that aren't allowed by
state-machines/workitem.yamlwill be rejected by the index, but a hand-edit can create an invalid state on disk. Always go throughtransition_workitem(the MCP tool), never editspec.statedirectly. If the MCP server says no, the state machine is the source of truth — escalate to the user about the rule, don't bypass it. - Forgetting to log the transition event. If you transition outside
the MCP server (hand-editing for some reason), you must also write
the corresponding LogEntry via
event-log. The audit trail relies on this. Skipping it makes the index drift and breaks every later "what changed" query. - Creating duplicate workitems because you didn't query first.
Before
create_workitem, runquery_workitemsagainst title and tags. The cost of one query is much smaller than the cost of an orphaned duplicate the user has to merge later. - Setting
priority: criticalon every bug. "Critical" means drop-everything urgency. If everything is critical, nothing is. Default tomediumand let the user upgrade. - Linking with
blocks/blocked_byand forgetting the inverse. These are bidirectional. If A blocks B, B is blocked_by A. The MCP serverlink_workitemsenforces both sides — hand-edits often miss the inverse, leaving the index inconsistent. - Setting
assigneeon a WorkItem when the assignment is temporal. "Alice owns this for sprint 42 only" is a Binding, not an assignee. Use a Binding entity for any time-bounded or scope-bounded assignment. Assignee is for "this is fundamentally Alice's responsibility, indefinitely".
(See also "Anti-patterns" in Full reference and the parent state-machine documentation for the canonical transition rules.)
Full reference
Full field list
See src/primitives/schemas/workitem.yaml for the authoritative schema.
Every field there is valid in a WorkItem spec.
State machine override
To customize the state machine, put a project-specific file at
context/state-machines/workitem.yaml. The index MCP server will prefer the
project file over the processkit default. Transitions not listed in the
custom machine are rejected.
Estimates
spec.estimate is intentionally freeform:
estimate:
unit: points
value: 5
or
estimate:
unit: hours
value: 4
confidence: rough
processkit does not mandate a unit. Projects pick one and stick with it.
Epics and hierarchy
An epic is just a WorkItem with spec.type: epic and many children.
Children link back via parent. There is no hard limit on nesting, but
flat → one level of epic → tasks is the common shape.
Relationship to Discussions
When a WorkItem emerges from a discussion, link the discussion via
spec.related_decisions (if a decision was recorded) or mention it in the
body. The Discussion primitive (shipped later) captures multi-turn
conversations — a WorkItem is the action that comes out of one.
Creating via MCP
In Phase 3, the workitem-management MCP server provides:
create_workitem(title, type, priority=None, assignee=None, parent=None, scope=None)
-> {id, path, state}
transition_workitem(id, to_state, note=None)
-> {ok, from_state, to_state}
query_workitems(state=None, assignee=None, type=None, scope=None, limit=50)
-> [{id, title, state, assignee, priority}, ...]
link_workitems(from_id, to_id, relation) # relation ∈ blocks|parent|related
-> {ok}
Until then, agents perform the same operations by editing files directly following this SKILL.md.
File naming
Default: context/workitems/BACK-<id>.md. With shards:
[context.sharding.WorkItem]
scheme = "state"
pattern = "context/workitems/{state}/"
This moves files as they transition. Turned off by default — most projects prefer flat.