Phase System Specification
Status: ACTIVE Version: v2.2.2 Last Updated: 2025-12-30 Schema Version: 2.2.01. Overview
The Phase System provides project-level phase lifecycle management for cleo, enabling tracking of which workflow stage a project is in while maintaining task-level phase categorization.1.1 Design Philosophy
The system follows these core principles:| Principle | Implementation |
|---|---|
| Permissive by Default | Cross-phase work allowed without blocking |
| Explicit Intent | Rollbacks require --rollback flag |
| Data Integrity | Atomic operations with validation |
| Audit Trail | Complete history of all phase transitions |
| Graceful Degradation | Commands work without project phase set |
1.2 Dual-Level Phase Model
2. Schema Specification
2.1 Project Object
Location:todo.json → project
2.2 Phase Definition Object
Location:project.phases.<slug>
| Field | Type | Required | Description |
|---|---|---|---|
order | integer | Yes | Display/transition order (min: 1) |
name | string | Yes | Human-readable name (max 50 chars) |
description | string | No | Phase description (max 200 chars) |
status | enum | Yes | pending | active | completed |
startedAt | ISO 8601 | No | When phase became active |
completedAt | ISO 8601 | No | When phase was completed |
- Slug pattern:
^[a-z][a-z0-9-]*$(lowercase, alphanumeric, hyphens) - Only ONE phase may have
status: "active"at any time startedAtrequired whenstatus: "active"orstatus: "completed"completedAtrequired whenstatus: "completed"
2.3 Phase History Entry Object
Location:project.phaseHistory[]
| Field | Type | Required | Description |
|---|---|---|---|
phase | string | Yes | Phase slug |
transitionType | enum | Yes | started | completed | rollback |
timestamp | ISO 8601 | Yes | When transition occurred |
taskCount | integer | Yes | Tasks in phase at transition time (min: 0) |
fromPhase | string | Conditional | Previous phase (required for rollback) |
reason | string | No | Context for transition (max 500 chars) |
2.4 Focus Integration
The focus object syncs with project phase:3. Phase Lifecycle States
3.1 State Diagram
3.2 Valid Transitions
| From | To | Command | Constraints |
|---|---|---|---|
pending | active | phase start | Only one active phase |
active | completed | phase complete | All tasks must be done (configurable) |
completed | active | phase set --rollback | Explicit rollback flag required |
| Any | (current) | phase set | Sets project.currentPhase pointer |
3.3 Invariants
- Single Active Phase: At most ONE phase can have
status: "active" - Timestamp Ordering:
startedAt < completedAtwhen both present - Current Phase Consistency:
project.currentPhasemust match a phase withstatus: "active"(when set) - History Immutability: Phase history entries are append-only
4. Command Specification
4.1 Phase Commands
| Command | Description | Flags |
|---|---|---|
phase show | Display current project phase | --format, --json |
phase set <slug> | Set current phase pointer | --rollback, --force, --format |
phase start <slug> | Transition pending → active | --format |
phase complete <slug> | Transition active → completed | --format |
phase advance | Complete current + start next | --force, --format |
phase list | List all phases with status | --format |
phase rename <old> <new> | Rename phase atomically | --format |
phase delete <slug> | Delete phase with protection | --reassign-to, --force, --format |
4.2 Rollback Behavior
Detection: Rollback detected whennew_phase.order < current_phase.order
Workflow:
log_phase_rollback()in todo-log.jsonladd_phase_history_entry()withtransitionType: "rollback"andfromPhase
4.3 Phase Advance Behavior
Configurable Thresholds:- Critical Task Blocking: If
blockOnCriticalTasks: trueand critical priority tasks are incomplete, advancement is BLOCKED (even with--force) - Threshold Check: If completion <
phaseAdvanceThreshold%, advancement requires--force - Interactive Prompt: Shows incomplete task breakdown by priority
- Logging: Records both completion and start transitions in phase history
4.4 Rename Operation
Atomic Multi-Step:- Create new phase definition with new name
- Update all
task.phasereferences - Update
project.currentPhaseif matches - Update
focus.currentPhaseif matches - Delete old phase definition
- Backup created before operation
- Rollback on any failure
4.5 Delete Operation
Protection Levels:- Current Phase: Cannot delete active project phase
- Tasks Exist: Blocked unless
--reassign-to <phase>provided - Force Required: Always requires
--forceflag
5. Behavioral Specifications
5.1 No Project Phase Set (Graceful Degradation)
Whenproject.currentPhase is null:
- All commands function normally
phase showreports “No current phase set”- Dashboard shows phase distribution without highlighting
- New tasks use
defaults.phasefrom config (if set) - No phase-based filtering applied
5.2 Task Phase vs Project Phase Mismatch
Default Behavior: Permissive mode- Working on tasks outside current project phase is ALLOWED
- No warnings by default
- Optional: Set
validation.warnPhaseContext: truefor warnings
5.3 Phaseless Tasks
Tasks withphase: null are treated as phase-agnostic:
- Visible in all phase views
- Never block phase advancement
- Listed with
[no-phase]indicator - Not affected by project.currentPhase
5.4 Multiple Active Phases Detection
Validation:ct validate checks for multiple phases with status: "active"
Recovery with —fix:
- Interactive prompt asks which phase to keep
- Non-interactive mode selects first by order
- Backup created before fix
- Other phases set to
status: "completed" - Action logged to todo-log.jsonl
6. Integration Specifications
6.1 TodoWrite Sync
Injection (sync --inject):
- Saves
project.currentPhasein session state file - Uses current phase for tier-based task filtering
- Phase metadata preserved in session
sync --extract):
- Detects if project phase changed during session
- Warns if phase mismatch detected
- New tasks inherit phase from focused task or
defaults.phase - Override with
--default-phase <phase>flag
6.2 Archive Integration
Statistics Updated on Archive:6.3 Dashboard Display
Phase Section:- Current phase marked with ★
- Progress bars show completion
- Completed phases show ✓
6.4 Task Creation
Phase Assignment Priority:- Explicit
--phase <slug>flag (highest) project.currentPhase(if set)defaults.phasefrom config- No phase (if none of above)
7. Validation Rules
7.1 Schema Validation
| Rule | Check | Error Code |
|---|---|---|
| Single active phase | count(status=active) <= 1 | E_MULTIPLE_ACTIVE_PHASES |
| Current phase exists | currentPhase in phases.keys() | E_INVALID_CURRENT_PHASE |
| Timestamp ordering | startedAt < completedAt | E_INVALID_PHASE_TIMESTAMPS |
| Required timestamps | Active requires startedAt | E_MISSING_STARTED_AT |
| Slug pattern | ^[a-z][a-z0-9-]*$ | E_INVALID_PHASE_SLUG |
7.2 Phase History Validation
| Rule | Check | Error Code |
|---|---|---|
| Phase exists | history.phase in phases.keys() | E_INVALID_HISTORY_PHASE |
| Valid transition | transitionType in [started,completed,rollback] | E_INVALID_TRANSITION_TYPE |
| No future timestamps | timestamp <= now | E_FUTURE_TIMESTAMP |
| Rollback has fromPhase | rollback → fromPhase required | E_MISSING_FROM_PHASE |
7.3 Validation Command
8. Logging Specification
8.1 Phase-Related Log Actions
| Action | Trigger | Details Captured |
|---|---|---|
phase_changed | phase set (forward) | fromPhase, toPhase |
phase_started | phase start | phase, timestamp |
phase_completed | phase complete | phase, duration, startedAt |
phase_rollback | phase set --rollback | fromPhase, toPhase, reason |
phase_deleted | phase delete | phase, reassignedTo, taskCount |
8.2 Log Entry Format
9. Error Codes
| Code | Description | Resolution |
|---|---|---|
E_PHASE_NOT_FOUND | Phase slug doesn’t exist | Check phase name with phase list |
E_PHASE_NOT_SET | No current phase set | Use phase set <slug> or phase start <slug> |
E_PHASE_NOT_ACTIVE | Cannot complete non-active phase | Start phase first |
E_PHASE_INCOMPLETE_TASKS | Tasks remain incomplete | Complete tasks or use --force |
E_PHASE_ROLLBACK_FORBIDDEN | Rollback without flag | Add --rollback flag |
E_PHASE_IS_CURRENT | Cannot delete current phase | Change phase first |
E_PHASE_HAS_TASKS | Tasks assigned to phase | Use --reassign-to |
E_PHASE_ALREADY_EXISTS | Rename target exists | Choose different name |
E_MULTIPLE_ACTIVE_PHASES | Data integrity violation | Run validate --fix |
E_FORCE_REQUIRED | Destructive operation | Add --force flag |
10. Configuration Options
10.1 Phase Validation Config
Location:config.json → validation.phaseValidation
| Option | Type | Default | Description |
|---|---|---|---|
enforcePhaseOrder | boolean | false | Warn on cross-phase work |
phaseAdvanceThreshold | integer | 90 | % completion required to advance |
blockOnCriticalTasks | boolean | true | Critical tasks always block advance |
warnPhaseContext | boolean | false | Warn when task phase != project phase |
10.2 Default Phase Config
Location:config.json → defaults.phase
11. Concurrency & Safety
11.1 Locking
- All phase operations use file locking (
flock) - Lock scope:
.cleo/todo.json - Lock timeout: 5 seconds
11.2 Atomic Operations
Phase-modifying commands follow this pattern:- Acquire file lock
- Read current state
- Validate operation
- Create backup
- Generate new state to temp file
- Validate temp file
- Atomic rename (temp → actual)
- Release lock
11.3 Checksum Verification
- Task checksum verified before write
- Phase operations don’t invalidate task checksum
- Project-level changes tracked in
_meta
12. Migration
12.1 Schema v2.1 → v2.2 Migration
Changes:projectstring →projectobject withname,phases,currentPhase,phaseHistory- Added
phaseHistoryarray
12.2 Backward Compatibility
- Old tasks without
phasefield continue to work project.currentPhase: nullis valid- Empty
phaseHistory: []is valid
13. Library Functions
13.1 Phase Tracking Library
Location:lib/phase-tracking.sh
| Function | Description |
|---|---|
get_current_phase <file> | Get project.currentPhase |
get_all_phases <file> | Get all phase definitions |
get_phase <slug> <file> | Get specific phase |
get_phase_status <slug> <file> | Get phase status |
count_phases_by_status <status> <file> | Count by status |
set_current_phase <slug> <file> | Update currentPhase |
start_phase <slug> <file> | pending → active |
complete_phase <slug> <file> | active → completed |
advance_phase <file> | Complete current, start next |
validate_single_active_phase <file> | Check constraint |
get_phase_history <file> | Get history array |
add_phase_history_entry <...> | Append to history |
count_tasks_in_phase <slug> <file> | Count tasks |
13.2 Logging Library
Location:lib/logging.sh
| Function | Description |
|---|---|
log_phase_changed <from> <to> | Log phase change |
log_phase_started <slug> | Log phase start |
log_phase_completed <slug> <startedAt> | Log completion |
log_phase_rollback <from> <to> <reason> | Log rollback |
log_phase_deleted <slug> <reassign> <count> | Log deletion |
14. Test Coverage
14.1 Required Test Scenarios
| Scenario | Test File | Description |
|---|---|---|
| No phase set | phase-commands.bats | Commands work without phase |
| Phase mismatch | phase-sync.bats | Cross-phase work allowed |
| Phaseless tasks | phase-sync.bats | Tasks without phase visible |
| Advance incomplete | phase-commands.bats | Warning and threshold check |
| Multi-active detection | phase-edge-cases.bats | Validation catches error |
| Rollback | phase-commands.bats | Flag required, history logged |
| Rename atomic | phase-commands.bats | All refs updated |
| Delete protected | phase-commands.bats | Force + reassign required |
| Sync preservation | todowrite-sync.bats | Phase state preserved |
| Archive stats | archive.bats | phaseSummary populated |
14.2 Test Count
- Phase Commands: 54 tests
- Phase Sync: 26 tests
- Phase Edge Cases: 16 tests
- Phase Workflow E2E: 7 tests
- Phase Tracking Library: 66 tests
- Total: 169+ phase-related tests
15. Revision History
| Version | Date | Changes |
|---|---|---|
| v2.2.0 | 2025-12-15 | Initial phase system implementation |
| v2.2.1 | 2025-12-17 | Added phaseHistory, rollback logging, archive stats |
| v2.2.2 | 2025-12-30 | Added Appendix C (wave computation cross-reference), updated Related Specifications with TASK-HIERARCHY-SPEC Parts 5-6 and CHAIN-VISUALIZATION-SPEC |
Appendix A: Quick Reference
Phase Commands Cheatsheet
Status Transitions
Appendix B: JSON Schema Reference
The complete JSON Schema for phase-related fields is defined inschemas/todo.schema.json version 2.2.0.
Key definitions:
#/properties/project/properties/phases#/properties/project/properties/currentPhase#/properties/project/properties/phaseHistory#/definitions/phaseDefinition
Related Specifications
| Document | Relationship |
|---|---|
| SPEC-BIBLE-GUIDELINES.md | AUTHORITATIVE for specification standards |
| LLM-AGENT-FIRST-SPEC.md | Related: LLM-first command design principles |
| TASK-HIERARCHY-SPEC.md | Related: Wave computation algorithm (Part 6); task hierarchy complements phase lifecycle |
| CHAIN-VISUALIZATION-SPEC.md | Related: Chain visualization across phases (computed at render time) |
| CONFIG-SYSTEM-SPEC.md | Related: Configuration system authority |
| RCSD-PIPELINE-SPEC.md | Related: Defines phase context for RCSD pipeline stages (Research→setup, Decompose→core) |
| PHASE-SYSTEM-IMPLEMENTATION-REPORT.md | Tracks implementation status (pending creation) |
Appendix C: Wave Computation Cross-Reference
C.1 Phases vs Waves
| Concept | Storage | Purpose |
|---|---|---|
| Phase | task.phase (stored) | Workflow lifecycle stage (setup → core → testing → polish) |
| Wave | COMPUTED | Execution order within scope based on dependency depth |
C.2 Wave Computation Algorithm
See: TASK-HIERARCHY-SPEC.md Part 6 for the complete wave computation specification.Summary:
- Wave 0: Tasks with no in-scope, non-done dependencies (can start immediately)
- Wave N: Tasks whose deepest dependency is at Wave N-1
- Scope filtering: Only dependencies within the analysis scope are considered
C.3 Cross-Phase Dependencies
Tasks MAY depend on tasks in different phases. The wave computation handles cross-phase dependencies by:- Including all scoped dependencies regardless of phase
- Computing wave depth across the entire dependency graph
- Allowing parallel execution within the same wave, even across phases
testing phase task depending on a core phase task will have wave = core_task_wave + 1.
End of Specification
