Skip to content
This page was generated and translated with the assistance of AI. If you spot any inaccuracies, feel free to help improve it. Edit on GitHub

Workflow States

Every issue in OpenPR has a state that represents its position in the workflow. The kanban board columns map directly to these states.

OpenPR ships with four default states, but supports fully custom workflow states through a 3-tier resolution system. You can define different workflows per project, per workspace, or rely on the system defaults.

Default States

mermaid
graph LR
    BL["Backlog"] --> TD["To Do"]
    TD --> IP["In Progress"]
    IP --> DN["Done"]

    IP -.->|"blocked"| TD
    DN -.->|"reopened"| IP
    BL -.->|"prioritized"| IP
StateValueDescription
BacklogbacklogIdeas, future work, and unplanned items. Not yet scheduled.
To DotodoPlanned and prioritized. Ready to be picked up.
In Progressin_progressActively being worked on by an assignee.
DonedoneCompleted and verified.

These are the built-in states that every new workspace starts with. You can customize them or add additional states as described in Custom Workflows below.

State Transitions

OpenPR allows flexible state transitions. There are no enforced constraints -- any state can transition to any other state. Common patterns include:

TransitionTriggerExample
Backlog -> To DoSprint planning, prioritizationIssue pulled into upcoming sprint
To Do -> In ProgressDeveloper picks up workAssignee starts implementation
In Progress -> DoneWork completedPull request merged
In Progress -> To DoWork blocked or pausedWaiting on external dependency
Done -> In ProgressIssue reopenedBug regression discovered
Backlog -> In ProgressUrgent hotfixCritical production issue

Custom Workflows

OpenPR supports custom workflow states through a 3-tier resolution system. When the API validates a state for a work item, it resolves the effective workflow by checking three levels in order:

Project workflow  >  Workspace workflow  >  System defaults

If a project defines its own workflow, that takes precedence. Otherwise the workspace-level workflow is used. If neither exists, the four system default states apply.

Database Schema

Custom workflows are stored in two tables (introduced in migration 0024_workflow_config.sql):

  • workflows -- Defines a named workflow attached to a project or workspace.
  • workflow_states -- The individual states within a workflow.

Each state has the following properties:

FieldTypeDescription
keystringMachine-readable identifier (e.g. in_review)
display_namestringHuman-readable name (e.g. "In Review")
categorystringGrouping category for the state
positionintegerDisplay order on the kanban board
colorstringHex color code for the state badge
is_initialbooleanWhether this is the default state for new issues
is_terminalbooleanWhether this state represents completion

Creating a Custom Workflow via API

Step 1 -- Create a workflow for a project:

bash
curl -X POST http://localhost:8080/api/workflows \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "Engineering Flow",
    "project_id": "<project_uuid>"
  }'

Step 2 -- Add states to the workflow:

bash
curl -X POST http://localhost:8080/api/workflows/<workflow_id>/states \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "key": "in_review",
    "display_name": "In Review",
    "category": "active",
    "position": 3,
    "color": "#f59e0b",
    "is_initial": false,
    "is_terminal": false
  }'

Example: 6-State Engineering Workflow

mermaid
graph LR
    BL["Backlog"] --> TD["To Do"]
    TD --> IP["In Progress"]
    IP --> IR["In Review"]
    IR --> QA["QA"]
    QA --> DN["Done"]

    IR -.->|"changes requested"| IP
    QA -.->|"failed"| IP
StateKeyCategoryInitialTerminal
Backlogbacklogbacklogyesno
To Dotodoplannednono
In Progressin_progressactivenono
In Reviewin_reviewactivenono
QAqaactivenono
Donedonecompletednoyes

Dynamic Validation

When a work item's state is updated, the API validates the new state against the effective workflow for that project. If you set a state key that does not exist in the resolved workflow, the API returns a 422 Unprocessable Entity error. States are not hardcoded -- they are looked up dynamically at request time.

Kanban Board

The board view displays issues as cards in columns corresponding to the workflow states. Drag and drop a card between columns to change its state. When custom workflows are active, the board automatically reflects the custom states and their configured order.

Each card shows:

  • Issue identifier (e.g., API-42)
  • Title
  • Priority indicator
  • Assignee avatar
  • Label badges

Updating State via API

bash
# Move issue to "in_progress"
curl -X PATCH http://localhost:8080/api/issues/<issue_id> \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"state": "in_progress"}'

Updating State via MCP

json
{
  "method": "tools/call",
  "params": {
    "name": "work_items.update",
    "arguments": {
      "work_item_id": "<issue_uuid>",
      "state": "in_progress"
    }
  }
}

Priority Levels

In addition to states, each issue can have a priority level:

PriorityValueDescription
LowlowNice to have, no time pressure
MediummediumStandard priority, planned work
HighhighImportant, should be addressed soon
UrgenturgentCritical, needs immediate attention

Activity Tracking

Every state change is recorded in the issue's activity feed with the actor, timestamp, and old/new values. This provides a complete audit trail.

Next Steps

Released under the Apache-2.0 License.