1use super::{Template, TemplateCategory};
4use crate::{
5 Result,
6 parser::{UnifiedRule, WorkflowStepData},
7};
8
9#[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 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 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 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 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 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}