# Kanban

> Manage tldw_server Kanban boards via MCP with explicit workflow-status control, safe transitions, lease/approval gates, and recovery primitives for orchestrators.

- Skill: `rmusser01/kanban` (Agent Skill)
- Install (CLI): `npx skillmds@latest add rmusser01/kanban`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rmusser01/kanban/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: rmusser01 (https://skillmd.com/u/rmusser01)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/rmusser01/kanban

---


Manages Kanban boards in **tldw_server** using MCP tools from the `kanban` module.

## Core Rule: Workflow State Is Canonical

For orchestration, treat `card.workflow_status` as source of truth.

- Canonical state: `kanban_card_workflow_state.workflow_status_key`
- List placement is projection side effect only (`auto_move_list_id`)
- Never infer workflow state from list column placement

## MCP Tooling

### Board/List/Card primitives

- `kanban.boards.list`
- `kanban.boards.get`
- `kanban.boards.create`
- `kanban.lists.list`
- `kanban.lists.create`
- `kanban.cards.list`
- `kanban.cards.create`
- `kanban.cards.move`
- `kanban.cards.search`
- `kanban.comments.list`
- `kanban.comments.create`

### Workflow control primitives

- `kanban.workflow.policy.get`
- `kanban.workflow.policy.upsert`
- `kanban.workflow.statuses.list`
- `kanban.workflow.transitions.list`
- `kanban.workflow.task.state.get`
- `kanban.workflow.task.state.patch`
- `kanban.workflow.task.claim`
- `kanban.workflow.task.release`
- `kanban.workflow.task.transition`
- `kanban.workflow.task.approval.decide`
- `kanban.workflow.task.events.list`
- `kanban.workflow.control.pause` (admin)
- `kanban.workflow.control.resume` (admin)
- `kanban.workflow.control.drain` (admin)
- `kanban.workflow.recovery.list_stale_claims`
- `kanban.workflow.recovery.force_reassign` (admin)

## Safety Contract (Always Enforce)

For workflow write operations:

- Always pass `expected_version` (CAS)
- Always pass unique `idempotency_key`
- Always pass `correlation_id` on transitions/approval/recovery writes
- Re-read state before retries (`kanban.workflow.task.state.get`)

Stable conflict codes to handle:

- `version_conflict`
- `lease_required`
- `lease_mismatch`
- `policy_paused`
- `transition_not_allowed`
- `approval_required`
- `projection_failed`
- `idempotency_conflict`

## Suggested Status Pipeline (Optional Policy)

Use if the project wants a 7-stage flow:

`req -> plan -> review_plan -> impl -> review_impl -> test -> done`

Suggested transitions:

- `req -> plan`
- `plan -> review_plan`
- `review_plan -> impl`
- `review_plan -> plan` (reject)
- `impl -> review_impl`
- `review_impl -> test`
- `review_impl -> impl` (reject)
- `test -> done`
- `test -> impl` (fail)

Implement this using `kanban.workflow.policy.upsert` with explicit statuses/transitions.

## Default Execution Pattern

No autonomous 7-stage loop is assumed by default.
Use explicit step-wise orchestration:

1. Load policy and task state (`policy.get`, `task.state.get`)
2. Claim lease (`task.claim`) when required by transition policy
3. Transition (`task.transition`) with CAS + idempotency + correlation
4. If approval is pending, resolve with `task.approval.decide`
5. Append card comments/checklists as execution notes
6. Release lease (`task.release`) when complete
7. Audit/replay via `task.events.list`

## Pause/Drain/Recovery Runbook

- Pause writes during incidents: `kanban.workflow.control.pause`
- Resume when safe: `kanban.workflow.control.resume`
- Drain board for controlled shutdown: `kanban.workflow.control.drain`
- Find orphaned claims: `kanban.workflow.recovery.list_stale_claims`
- Reassign ownership when needed: `kanban.workflow.recovery.force_reassign`

## Minimal MCP Call Shapes

Transition:

```json
{
  "name": "kanban.workflow.task.transition",
  "arguments": {
    "card_id": 123,
    "to_status_key": "impl",
    "actor": "builder",
    "expected_version": 4,
    "idempotency_key": "wf-123-transition-0001",
    "correlation_id": "run-2026-03-05-001",
    "reason": "begin implementation"
  }
}
```

Approval decision:

```json
{
  "name": "kanban.workflow.task.approval.decide",
  "arguments": {
    "card_id": 123,
    "reviewer": "inspector",
    "decision": "approved",
    "expected_version": 5,
    "idempotency_key": "wf-123-approval-0001",
    "correlation_id": "run-2026-03-05-001",
    "reason": "checks passed"
  }
}
```

## Notes

- Prefer explicit transitions over direct state patching for normal lifecycle flow.
- Use `task.state.patch` only for controlled admin repair operations.
- Keep admin-only tools out of general-purpose agent catalogs.

