# Workitem Management

> Create, transition, query, and link WorkItems — tasks, stories, bugs, epics. Use when the user asks to add, update, query, or link work items — backlog items, tasks, bugs, user stories, or epics.

- Skill: `projectious-work/workitem-management-5` (Agent Skill, multi-file: 9 files)
- Install (CLI): `npx skillmds@latest add projectious-work/workitem-management-5`
- Raw SKILL.md: https://api.skillmd.com/api/skills/projectious-work/workitem-management-5/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: projectious-work (https://skillmd.com/u/projectious-work)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/projectious-work/workitem-management-5

---


# 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 — requires `uv` and Python ≥ 3.10 on
> PATH). Agent harnesses reach its tools by reading a single MCP config
> file at startup, so the contents of `mcp/mcp-config.json` must 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

1. Pick the `type`.
2. Write a short, imperative `title`.
3. Set `state` to the initial state (`backlog` by default).
4. Set `priority` if known (`critical`/`high`/`medium`/`low`).
5. Assign to an Actor (optional at creation).
6. Write the file to `context/workitems/BACK-<id>.md`.
7. Log `workitem.created`.

### Transitioning

The default state machine is:

```
backlog → in-progress → review → done
            ↓      ↑
          blocked ↑
            ↓      ↑
          backlog ←
(any state) → cancelled (terminal)
```

To transition:
1. Check the current state allows the transition (see `primitives/state-machines/workitem.yaml`).
2. Update `spec.state`.
3. Update `metadata.updated`.
4. Set `spec.started_at` on first entry to `in-progress` (if unset).
5. Set `spec.completed_at` when entering a terminal state.
6. Log `workitem.transitioned` with `from_state` and `to_state` in `details`.

### 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.yaml` will be
  rejected by the index, but a hand-edit can create an invalid state
  on disk. Always go through `transition_workitem` (the MCP tool),
  never edit `spec.state` directly. 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`, run `query_workitems` against 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: critical` on every bug.** "Critical" means
  drop-everything urgency. If everything is critical, nothing is.
  Default to `medium` and let the user upgrade.
- **Linking with `blocks` / `blocked_by` and forgetting the inverse.**
  These are bidirectional. If A blocks B, B is blocked_by A. The MCP
  server `link_workitems` enforces both sides — hand-edits often miss
  the inverse, leaving the index inconsistent.
- **Setting `assignee` on 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:

```yaml
estimate:
  unit: points
  value: 5
```

or

```yaml
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:

```toml
[context.sharding.WorkItem]
scheme = "state"
pattern = "context/workitems/{state}/"
```

This moves files as they transition. Turned off by default — most projects
prefer flat.

