SubStatus State Machine
GuideMode uses a state machine to manage issue workflow progression. This document specifies the rules for subStatus transitions and timestamp management.
Overview
Section titled “Overview”GuideMode tracks issues using a dual state model:
state(3 values):open,in_progress,closed- simplified for GitHub compatibilitysubStatus(9 values): Fine-grained workflow state for detailed analytics
The subStatus is the source of truth for workflow position, and state is derived from it for providers other than GitHub.
SubStatus Values
Section titled “SubStatus Values”Workflow States (Linear Progression)
Section titled “Workflow States (Linear Progression)”| SubStatus | Position | Description |
|---|---|---|
backlog | 0 | Not started, not prioritized |
ready | 1 | Ready to start, prioritized |
discovery | 2 | Research, spike, or design work |
delivery | 3 | Active development |
review | 4 | Code review, testing, QA |
Side-Track States
Section titled “Side-Track States”| SubStatus | Description |
|---|---|
blocked | Waiting on external dependency |
parked | Intentionally paused |
Side-track states can occur at any point in the workflow and don’t affect workflow timestamps.
Terminal States
Section titled “Terminal States”| SubStatus | Description |
|---|---|
done | Completed successfully |
canceled | Closed without completion |
Terminal states end the workflow and use closedAt for timestamp tracking.
Timestamp Fields
Section titled “Timestamp Fields”Each workflow subStatus has a corresponding timestamp field:
| SubStatus | Timestamp Field | Description |
|---|---|---|
ready | readyAt | When issue became prioritized |
discovery | discoveryStartedAt | When research/spike began |
delivery | deliveryStartedAt | When active development began |
review | reviewStartedAt | When entered review/QA |
blocked | blockedAt | When became blocked |
parked | parkedAt | When intentionally paused |
Note: backlog, done, and canceled don’t have dedicated timestamps. Backlog is the initial state, and terminal states use closedAt.
Transition Rules
Section titled “Transition Rules”Forward Transitions
Section titled “Forward Transitions”When moving forward in the workflow (e.g., ready → delivery):
- Set the timestamp for the new subStatus
- Preserve all existing timestamps
Example: Moving from ready to delivery:
- Sets
deliveryStartedAtto current time - Preserves
readyAtvalue
Backward Transitions
Section titled “Backward Transitions”When moving backward in the workflow (e.g., review → delivery):
- Set the timestamp for the new subStatus (re-entering that phase)
- Clear all timestamps for phases AFTER the new subStatus
Example: Moving from review back to delivery:
- Sets
deliveryStartedAtto current time - Clears
reviewStartedAttonull - Preserves
readyAt(phase before delivery)
Example: Moving from delivery back to backlog:
- Clears
readyAt,discoveryStartedAt,deliveryStartedAt,reviewStartedAt - (backlog has no timestamp field to set)
Side-Track Transitions
Section titled “Side-Track Transitions”Entering side-track (→ blocked/parked):
- Set
blockedAtorparkedAt - Preserve all workflow timestamps
Leaving side-track (blocked/parked →):
- Clear
blockedAtorparkedAt - Set the new subStatus timestamp if not already set
Example: delivery → blocked:
- Sets
blockedAt - Preserves
deliveryStartedAt(work was in progress)
Terminal Transitions
Section titled “Terminal Transitions”Entering terminal (→ done/canceled):
- No subStatus timestamp changes (uses
closedAtseparately) - All workflow timestamps are preserved
Reopening (done/canceled →):
- Set the new subStatus timestamp only if not already set
- This allows resuming work from where it was left off
State Derivation
Section titled “State Derivation”For non-GitHub providers, state is derived from subStatus:
| SubStatus | Derived State |
|---|---|
discovery, delivery, review | in_progress |
done, canceled | closed |
backlog, ready, blocked, parked | open |
WIP Exclusion
Section titled “WIP Exclusion”Issues are excluded from Work-In-Progress (WIP) counts when their subStatus is:
backlog,ready(not yet started)blocked,parked(not actively being worked)done,canceled(completed)
Only discovery, delivery, and review count toward WIP.
Implementation Reference
Section titled “Implementation Reference”The state machine is implemented in:
apps/server/src/api/utils/sub-status-state-machine.ts- Pure function state machineapps/server/src/api/utils/status-sub-status-inference.ts- Status mapping and transition computation
Key Functions
Section titled “Key Functions”| Function | Purpose |
|---|---|
computeSubStatusTransition() | Main function - computes all timestamp changes for a transition |
getTimestampFieldsToClear() | Returns fields to clear for backward transitions |
isBackwardTransition() | Detects backward workflow movement |
deriveStateFromSubStatus() | Derives 3-state from subStatus |
computeTransitionTimestamp() | Wrapper used by sync services (backward compatible) |
Usage Example
Section titled “Usage Example”import { computeSubStatusTransition, type SubStatusTimestamps } from './sub-status-state-machine.js'
const existingTimestamps: SubStatusTimestamps = { readyAt: new Date('2024-01-01'), deliveryStartedAt: new Date('2024-01-02'), reviewStartedAt: new Date('2024-01-03'), // ... other fields null}
// Simulate moving from review back to delivery (rework)const result = computeSubStatusTransition({ oldSubStatus: 'review', newSubStatus: 'delivery', existingTimestamps, transitionTime: new Date('2024-01-05'),})
// result.timestamps = {// deliveryStartedAt: new Date('2024-01-05'), // Updated// reviewStartedAt: null, // Cleared// }// result.isBackward = true// result.clearedFields = ['reviewStartedAt']Workflow Examples
Section titled “Workflow Examples”Normal Forward Flow
Section titled “Normal Forward Flow”Issue created → backlog └─→ Prioritized → ready (sets readyAt) └─→ Development starts → delivery (sets deliveryStartedAt) └─→ PR opened → review (sets reviewStartedAt) └─→ Merged → done (sets closedAt)All timestamps are preserved at completion.
Rework Scenario
Section titled “Rework Scenario”Issue in review → review (reviewStartedAt: Jan 3) └─→ Needs more work → delivery (Jan 5) ├─→ Sets deliveryStartedAt: Jan 5 └─→ Clears reviewStartedAt └─→ Fixed → review (Jan 6) └─→ Sets reviewStartedAt: Jan 6The rework is reflected in the new reviewStartedAt timestamp.
Blocked Flow
Section titled “Blocked Flow”Issue in delivery → delivery (deliveryStartedAt: Jan 2) └─→ Waiting on API → blocked ├─→ Sets blockedAt: Jan 3 └─→ Preserves deliveryStartedAt: Jan 2
Unblocked → delivery └─→ Clears blockedAt └─→ Preserves deliveryStartedAt: Jan 2Workflow timestamps are preserved through the blocked state.