Skip to main content

driven/templates/
workflow.rs

1//! Development workflow templates
2
3use super::{Template, TemplateCategory};
4use crate::{
5    Result,
6    parser::{UnifiedRule, WorkflowStepData},
7};
8
9/// Workflow template definition
10#[derive(Debug, Clone)]
11pub struct WorkflowTemplate {
12    name: String,
13    description: String,
14    steps: Vec<WorkflowStepData>,
15    tags: Vec<String>,
16}
17
18impl WorkflowTemplate {
19    /// Test-Driven Development workflow
20    pub fn tdd() -> Self {
21        Self {
22            name: "tdd".to_string(),
23            description: "Test-Driven Development workflow".to_string(),
24            steps: vec![
25                WorkflowStepData {
26                    name: "Write Failing Test".to_string(),
27                    description: "Write a test that describes the expected behavior. The test should fail initially.".to_string(),
28                    condition: None,
29                    actions: vec![
30                        "Identify the behavior to implement".to_string(),
31                        "Write a test case for that behavior".to_string(),
32                        "Run tests to confirm failure".to_string(),
33                    ],
34                },
35                WorkflowStepData {
36                    name: "Write Minimal Code".to_string(),
37                    description: "Write just enough code to make the test pass.".to_string(),
38                    condition: Some("Test is failing".to_string()),
39                    actions: vec![
40                        "Implement the minimum code needed".to_string(),
41                        "Run tests to confirm pass".to_string(),
42                    ],
43                },
44                WorkflowStepData {
45                    name: "Refactor".to_string(),
46                    description: "Improve the code while keeping tests green.".to_string(),
47                    condition: Some("Tests are passing".to_string()),
48                    actions: vec![
49                        "Look for code smells".to_string(),
50                        "Apply refactoring patterns".to_string(),
51                        "Run tests after each change".to_string(),
52                    ],
53                },
54            ],
55            tags: vec!["tdd".to_string(), "testing".to_string(), "development".to_string()],
56        }
57    }
58
59    /// Feature development workflow
60    pub fn feature_development() -> Self {
61        Self {
62            name: "feature-development".to_string(),
63            description: "Standard feature development workflow".to_string(),
64            steps: vec![
65                WorkflowStepData {
66                    name: "Understand Requirements".to_string(),
67                    description: "Clarify what needs to be built and why.".to_string(),
68                    condition: None,
69                    actions: vec![
70                        "Read the feature specification".to_string(),
71                        "Ask clarifying questions".to_string(),
72                        "Identify acceptance criteria".to_string(),
73                    ],
74                },
75                WorkflowStepData {
76                    name: "Design Solution".to_string(),
77                    description: "Plan the technical approach.".to_string(),
78                    condition: Some("Requirements are clear".to_string()),
79                    actions: vec![
80                        "Identify affected components".to_string(),
81                        "Consider edge cases".to_string(),
82                        "Document design decisions".to_string(),
83                    ],
84                },
85                WorkflowStepData {
86                    name: "Implement".to_string(),
87                    description: "Write the code.".to_string(),
88                    condition: Some("Design is approved".to_string()),
89                    actions: vec![
90                        "Create feature branch".to_string(),
91                        "Write code following standards".to_string(),
92                        "Write tests".to_string(),
93                        "Update documentation".to_string(),
94                    ],
95                },
96                WorkflowStepData {
97                    name: "Review & Merge".to_string(),
98                    description: "Get code reviewed and merged.".to_string(),
99                    condition: Some("Implementation is complete".to_string()),
100                    actions: vec![
101                        "Create pull request".to_string(),
102                        "Address review feedback".to_string(),
103                        "Merge to main branch".to_string(),
104                    ],
105                },
106            ],
107            tags: vec![
108                "feature".to_string(),
109                "development".to_string(),
110                "process".to_string(),
111            ],
112        }
113    }
114
115    /// Bug fixing workflow
116    pub fn bug_fixing() -> Self {
117        Self {
118            name: "bug-fixing".to_string(),
119            description: "Systematic bug fixing workflow".to_string(),
120            steps: vec![
121                WorkflowStepData {
122                    name: "Reproduce".to_string(),
123                    description: "Confirm and reproduce the bug.".to_string(),
124                    condition: None,
125                    actions: vec![
126                        "Read the bug report".to_string(),
127                        "Reproduce the issue".to_string(),
128                        "Identify exact steps to reproduce".to_string(),
129                    ],
130                },
131                WorkflowStepData {
132                    name: "Diagnose".to_string(),
133                    description: "Find the root cause.".to_string(),
134                    condition: Some("Bug is reproducible".to_string()),
135                    actions: vec![
136                        "Add logging if needed".to_string(),
137                        "Use debugger".to_string(),
138                        "Trace through the code".to_string(),
139                        "Identify root cause".to_string(),
140                    ],
141                },
142                WorkflowStepData {
143                    name: "Fix".to_string(),
144                    description: "Implement the fix.".to_string(),
145                    condition: Some("Root cause is identified".to_string()),
146                    actions: vec![
147                        "Write a test that fails".to_string(),
148                        "Implement the fix".to_string(),
149                        "Verify test passes".to_string(),
150                        "Check for similar issues".to_string(),
151                    ],
152                },
153                WorkflowStepData {
154                    name: "Verify".to_string(),
155                    description: "Confirm the fix works.".to_string(),
156                    condition: Some("Fix is implemented".to_string()),
157                    actions: vec![
158                        "Run all tests".to_string(),
159                        "Manually verify fix".to_string(),
160                        "Check for regressions".to_string(),
161                    ],
162                },
163            ],
164            tags: vec![
165                "bug".to_string(),
166                "fix".to_string(),
167                "debugging".to_string(),
168            ],
169        }
170    }
171
172    /// Refactoring workflow
173    pub fn refactoring() -> Self {
174        Self {
175            name: "refactoring".to_string(),
176            description: "Safe refactoring workflow".to_string(),
177            steps: vec![
178                WorkflowStepData {
179                    name: "Ensure Tests".to_string(),
180                    description: "Make sure adequate test coverage exists.".to_string(),
181                    condition: None,
182                    actions: vec![
183                        "Check existing test coverage".to_string(),
184                        "Add tests for uncovered code".to_string(),
185                        "Run tests to establish baseline".to_string(),
186                    ],
187                },
188                WorkflowStepData {
189                    name: "Small Steps".to_string(),
190                    description: "Make small, incremental changes.".to_string(),
191                    condition: Some("Tests are green".to_string()),
192                    actions: vec![
193                        "Make one small change".to_string(),
194                        "Run tests".to_string(),
195                        "Commit if green".to_string(),
196                        "Repeat".to_string(),
197                    ],
198                },
199                WorkflowStepData {
200                    name: "Review".to_string(),
201                    description: "Review the refactored code.".to_string(),
202                    condition: Some("Refactoring is complete".to_string()),
203                    actions: vec![
204                        "Compare before/after".to_string(),
205                        "Check for improvements".to_string(),
206                        "Verify behavior is unchanged".to_string(),
207                    ],
208                },
209            ],
210            tags: vec![
211                "refactoring".to_string(),
212                "cleanup".to_string(),
213                "improvement".to_string(),
214            ],
215        }
216    }
217
218    /// Code review workflow
219    pub fn code_review() -> Self {
220        Self {
221            name: "code-review".to_string(),
222            description: "Thorough code review workflow".to_string(),
223            steps: vec![
224                WorkflowStepData {
225                    name: "Understand Context".to_string(),
226                    description: "Read the PR description and linked issues.".to_string(),
227                    condition: None,
228                    actions: vec![
229                        "Read PR description".to_string(),
230                        "Check linked issues".to_string(),
231                        "Understand the goal".to_string(),
232                    ],
233                },
234                WorkflowStepData {
235                    name: "Review Code".to_string(),
236                    description: "Examine the code changes.".to_string(),
237                    condition: Some("Context is understood".to_string()),
238                    actions: vec![
239                        "Check for correctness".to_string(),
240                        "Check for security issues".to_string(),
241                        "Check for performance issues".to_string(),
242                        "Check for readability".to_string(),
243                        "Check test coverage".to_string(),
244                    ],
245                },
246                WorkflowStepData {
247                    name: "Provide Feedback".to_string(),
248                    description: "Give constructive feedback.".to_string(),
249                    condition: Some("Review is complete".to_string()),
250                    actions: vec![
251                        "Praise good patterns".to_string(),
252                        "Suggest improvements".to_string(),
253                        "Distinguish critical from minor".to_string(),
254                        "Approve or request changes".to_string(),
255                    ],
256                },
257            ],
258            tags: vec![
259                "review".to_string(),
260                "code-review".to_string(),
261                "pr".to_string(),
262            ],
263        }
264    }
265}
266
267impl Template for WorkflowTemplate {
268    fn name(&self) -> &str {
269        &self.name
270    }
271
272    fn description(&self) -> &str {
273        &self.description
274    }
275
276    fn category(&self) -> TemplateCategory {
277        TemplateCategory::Workflow
278    }
279
280    fn expand(&self) -> Result<Vec<UnifiedRule>> {
281        Ok(vec![UnifiedRule::Workflow {
282            name: self.name.clone(),
283            steps: self.steps.clone(),
284        }])
285    }
286
287    fn tags(&self) -> Vec<&str> {
288        self.tags.iter().map(|s| s.as_str()).collect()
289    }
290}
291
292#[cfg(test)]
293mod tests {
294    use super::*;
295
296    #[test]
297    fn test_tdd_workflow() {
298        let template = WorkflowTemplate::tdd();
299        assert_eq!(template.name(), "tdd");
300        assert_eq!(template.category(), TemplateCategory::Workflow);
301
302        let rules = template.expand().unwrap();
303        assert_eq!(rules.len(), 1);
304
305        if let UnifiedRule::Workflow { steps, .. } = &rules[0] {
306            assert_eq!(steps.len(), 3);
307        } else {
308            panic!("Expected Workflow rule");
309        }
310    }
311}