Skip to main content

ccboard_core/models/
plan.rs

1//! Data models for PLAN.md files
2
3use serde::{Deserialize, Serialize};
4
5/// Full PLAN.md file structure
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct PlanFile {
8    /// Metadata from YAML frontmatter
9    pub metadata: PlanMetadata,
10
11    /// Phases extracted from markdown sections
12    pub phases: Vec<Phase>,
13}
14
15/// YAML frontmatter metadata
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct PlanMetadata {
18    /// Plan creation date
19    pub date: Option<String>,
20
21    /// Last update timestamp
22    pub last_updated: Option<String>,
23
24    /// Version string (e.g., "0.7.0-dev")
25    pub version: Option<String>,
26
27    /// Plan title
28    pub title: String,
29
30    /// Current status (in-progress, complete, future) - optional, can be inferred from phases
31    pub status: Option<String>,
32
33    /// Estimated total duration string (e.g., "82-120h")
34    pub estimated_total_duration: Option<String>,
35}
36
37/// Individual phase in the plan
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct Phase {
40    /// Phase identifier (e.g., "F", "H", "11", "12")
41    pub id: String,
42
43    /// Phase title
44    pub title: String,
45
46    /// Phase status
47    pub status: PhaseStatus,
48
49    /// Tasks within this phase
50    pub tasks: Vec<Task>,
51
52    /// Estimated duration for this phase
53    pub estimated_duration: Option<String>,
54
55    /// Priority level (HIGH, MEDIUM, LOW)
56    pub priority: Option<String>,
57
58    /// Version target (e.g., "v0.7.0")
59    pub version_target: Option<String>,
60}
61
62/// Phase status
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
64pub enum PhaseStatus {
65    /// Phase completed
66    Complete,
67
68    /// Phase in progress
69    InProgress,
70
71    /// Phase not started yet
72    Future,
73}
74
75/// Individual task within a phase
76#[derive(Debug, Clone, Serialize, Deserialize, Default)]
77pub struct Task {
78    /// Task identifier (e.g., "F.1", "H.2")
79    pub id: String,
80
81    /// Task title
82    pub title: String,
83
84    /// Task description
85    pub description: Option<String>,
86
87    /// Priority level (P0, P1, P2)
88    pub priority: Option<String>,
89
90    /// Estimated duration
91    pub duration: Option<String>,
92
93    /// Difficulty level (Good First Issue, Intermediate, Advanced)
94    pub difficulty: Option<String>,
95
96    /// Crate affected
97    pub crate_name: Option<String>,
98
99    /// GitHub issue number
100    pub issue: Option<u32>,
101}
102
103impl Default for PlanMetadata {
104    fn default() -> Self {
105        Self {
106            date: None,
107            last_updated: None,
108            version: None,
109            title: String::new(),
110            status: Some("future".to_string()),
111            estimated_total_duration: None,
112        }
113    }
114}
115
116impl PhaseStatus {
117    /// Parse status from string (not implementing FromStr trait to keep simple)
118    #[allow(clippy::should_implement_trait)]
119    pub fn from_str(s: &str) -> Self {
120        match s.to_lowercase().as_str() {
121            "complete" | "completed" | "done" => Self::Complete,
122            "in-progress" | "in_progress" | "active" => Self::InProgress,
123            _ => Self::Future,
124        }
125    }
126}