1use std::fmt;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum PromptTemplate {
16 FeatureSpec,
18 BugFix,
20 Refactor,
22 Test,
24 Docs,
26 Quick,
28 PerformanceOptimization,
30 SecurityAudit,
32 ApiIntegration,
34 DatabaseMigration,
36 DependencyUpdate,
38 CliTool,
40 WebApi,
42 DataPipeline,
44 UiComponent,
46 CodeReview,
48 DebugTriage,
50 Release,
52 TechDebt,
54 Onboarding,
56}
57
58impl PromptTemplate {
59 pub const fn name(self) -> &'static str {
61 match self {
62 Self::FeatureSpec => "feature-spec",
63 Self::BugFix => "bug-fix",
64 Self::Refactor => "refactor",
65 Self::Test => "test",
66 Self::Docs => "docs",
67 Self::Quick => "quick",
68 Self::PerformanceOptimization => "performance-optimization",
69 Self::SecurityAudit => "security-audit",
70 Self::ApiIntegration => "api-integration",
71 Self::DatabaseMigration => "database-migration",
72 Self::DependencyUpdate => "dependency-update",
73 Self::CliTool => "cli-tool",
74 Self::WebApi => "web-api",
75 Self::DataPipeline => "data-pipeline",
76 Self::UiComponent => "ui-component",
77 Self::CodeReview => "code-review",
78 Self::DebugTriage => "debug-triage",
79 Self::Release => "release",
80 Self::TechDebt => "tech-debt",
81 Self::Onboarding => "onboarding",
82 }
83 }
84
85 pub const fn description(self) -> &'static str {
87 match self {
88 Self::FeatureSpec => "Comprehensive product specification with questions to consider and code quality standards",
89 Self::BugFix => "Bug fix template with investigation guidance and testing requirements",
90 Self::Refactor => "Code refactoring template with behavior preservation emphasis",
91 Self::Test => "Test writing template with edge case considerations",
92 Self::Docs => "Documentation update template with completeness checklist",
93 Self::Quick => "Quick/small change template (minimal)",
94 Self::PerformanceOptimization => "Performance optimization template with benchmarking and profiling guidance",
95 Self::SecurityAudit => "Security audit template covering OWASP Top 10 and vulnerability remediation",
96 Self::ApiIntegration => "API integration template with error handling, retry logic, and resilience patterns",
97 Self::DatabaseMigration => "Database migration template with zero-downtime strategies and rollback plans",
98 Self::DependencyUpdate => "Dependency update template with migration guides and breaking change handling",
99 Self::CliTool => "CLI tool development template with argument parsing, completion, and error handling",
100 Self::WebApi => "Web API development template with REST design, error handling, and security considerations",
101 Self::DataPipeline => "Data pipeline template with ETL processing, reliability, and monitoring guidance",
102 Self::UiComponent => "UI component template with accessibility, responsive design, and user experience",
103 Self::CodeReview => "Code review template for structured pull request feedback",
104 Self::DebugTriage => "Debug triage template for systematic issue investigation and diagnosis",
105 Self::Release => "Release preparation template with versioning, changelog, and deployment checklist",
106 Self::TechDebt => "Technical debt refactoring template with prioritization and planning guidance",
107 Self::Onboarding => "Onboarding template for learning new codebases efficiently",
108 }
109 }
110
111 pub const fn content(self) -> &'static str {
113 match self {
114 Self::FeatureSpec => {
115 include_str!("../../templates/prompts/feature-spec.md")
116 }
117 Self::BugFix => {
118 include_str!("../../templates/prompts/bug-fix.md")
119 }
120 Self::Refactor => {
121 include_str!("../../templates/prompts/refactor.md")
122 }
123 Self::Test => {
124 include_str!("../../templates/prompts/test.md")
125 }
126 Self::Docs => {
127 include_str!("../../templates/prompts/docs.md")
128 }
129 Self::Quick => {
130 include_str!("../../templates/prompts/quick.md")
131 }
132 Self::PerformanceOptimization => {
133 include_str!("../../templates/prompts/performance-optimization.md")
134 }
135 Self::SecurityAudit => {
136 include_str!("../../templates/prompts/security-audit.md")
137 }
138 Self::ApiIntegration => {
139 include_str!("../../templates/prompts/api-integration.md")
140 }
141 Self::DatabaseMigration => {
142 include_str!("../../templates/prompts/database-migration.md")
143 }
144 Self::DependencyUpdate => {
145 include_str!("../../templates/prompts/dependency-update.md")
146 }
147 Self::CliTool => {
148 include_str!("../../templates/prompts/cli-tool.md")
149 }
150 Self::WebApi => {
151 include_str!("../../templates/prompts/web-api.md")
152 }
153 Self::DataPipeline => {
154 include_str!("../../templates/prompts/data-pipeline.md")
155 }
156 Self::UiComponent => {
157 include_str!("../../templates/prompts/ui-component.md")
158 }
159 Self::CodeReview => {
160 include_str!("../../templates/prompts/code-review.md")
161 }
162 Self::DebugTriage => {
163 include_str!("../../templates/prompts/debug-triage.md")
164 }
165 Self::Release => {
166 include_str!("../../templates/prompts/release.md")
167 }
168 Self::TechDebt => {
169 include_str!("../../templates/prompts/tech-debt.md")
170 }
171 Self::Onboarding => {
172 include_str!("../../templates/prompts/onboarding.md")
173 }
174 }
175 }
176}
177
178impl fmt::Display for PromptTemplate {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 write!(f, "{}", self.name())
181 }
182}
183
184pub const ALL_TEMPLATES: [PromptTemplate; 20] = [
186 PromptTemplate::FeatureSpec,
187 PromptTemplate::BugFix,
188 PromptTemplate::Refactor,
189 PromptTemplate::Test,
190 PromptTemplate::Docs,
191 PromptTemplate::Quick,
192 PromptTemplate::PerformanceOptimization,
193 PromptTemplate::SecurityAudit,
194 PromptTemplate::ApiIntegration,
195 PromptTemplate::DatabaseMigration,
196 PromptTemplate::DependencyUpdate,
197 PromptTemplate::CliTool,
198 PromptTemplate::WebApi,
199 PromptTemplate::DataPipeline,
200 PromptTemplate::UiComponent,
201 PromptTemplate::CodeReview,
202 PromptTemplate::DebugTriage,
203 PromptTemplate::Release,
204 PromptTemplate::TechDebt,
205 PromptTemplate::Onboarding,
206];
207
208pub fn get_template(name: &str) -> Option<PromptTemplate> {
219 ALL_TEMPLATES.iter().find(|t| t.name() == name).copied()
220}
221
222pub fn list_templates() -> Vec<(&'static str, &'static str)> {
226 ALL_TEMPLATES
227 .iter()
228 .map(|t| (t.name(), t.description()))
229 .collect()
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn test_template_names() {
238 assert_eq!(PromptTemplate::FeatureSpec.name(), "feature-spec");
239 assert_eq!(PromptTemplate::BugFix.name(), "bug-fix");
240 assert_eq!(PromptTemplate::Refactor.name(), "refactor");
241 assert_eq!(PromptTemplate::Test.name(), "test");
242 assert_eq!(PromptTemplate::Docs.name(), "docs");
243 assert_eq!(PromptTemplate::Quick.name(), "quick");
244 assert_eq!(
245 PromptTemplate::PerformanceOptimization.name(),
246 "performance-optimization"
247 );
248 assert_eq!(PromptTemplate::SecurityAudit.name(), "security-audit");
249 assert_eq!(PromptTemplate::ApiIntegration.name(), "api-integration");
250 assert_eq!(
251 PromptTemplate::DatabaseMigration.name(),
252 "database-migration"
253 );
254 assert_eq!(PromptTemplate::DependencyUpdate.name(), "dependency-update");
255 assert_eq!(PromptTemplate::CliTool.name(), "cli-tool");
256 assert_eq!(PromptTemplate::WebApi.name(), "web-api");
257 assert_eq!(PromptTemplate::DataPipeline.name(), "data-pipeline");
258 assert_eq!(PromptTemplate::UiComponent.name(), "ui-component");
259 assert_eq!(PromptTemplate::CodeReview.name(), "code-review");
260 assert_eq!(PromptTemplate::DebugTriage.name(), "debug-triage");
261 assert_eq!(PromptTemplate::Release.name(), "release");
262 assert_eq!(PromptTemplate::TechDebt.name(), "tech-debt");
263 assert_eq!(PromptTemplate::Onboarding.name(), "onboarding");
264 }
265
266 #[test]
267 fn test_template_descriptions() {
268 assert!(!PromptTemplate::FeatureSpec.description().is_empty());
269 assert!(!PromptTemplate::BugFix.description().is_empty());
270 assert!(!PromptTemplate::Refactor.description().is_empty());
271 assert!(!PromptTemplate::Test.description().is_empty());
272 assert!(!PromptTemplate::Docs.description().is_empty());
273 assert!(!PromptTemplate::Quick.description().is_empty());
274 assert!(!PromptTemplate::PerformanceOptimization
275 .description()
276 .is_empty());
277 assert!(!PromptTemplate::SecurityAudit.description().is_empty());
278 assert!(!PromptTemplate::ApiIntegration.description().is_empty());
279 assert!(!PromptTemplate::DatabaseMigration.description().is_empty());
280 assert!(!PromptTemplate::DependencyUpdate.description().is_empty());
281 assert!(!PromptTemplate::CliTool.description().is_empty());
282 assert!(!PromptTemplate::WebApi.description().is_empty());
283 assert!(!PromptTemplate::DataPipeline.description().is_empty());
284 assert!(!PromptTemplate::UiComponent.description().is_empty());
285 assert!(!PromptTemplate::CodeReview.description().is_empty());
286 assert!(!PromptTemplate::DebugTriage.description().is_empty());
287 assert!(!PromptTemplate::Release.description().is_empty());
288 assert!(!PromptTemplate::TechDebt.description().is_empty());
289 assert!(!PromptTemplate::Onboarding.description().is_empty());
290 }
291
292 #[test]
293 fn test_get_template() {
294 assert_eq!(
295 get_template("feature-spec"),
296 Some(PromptTemplate::FeatureSpec)
297 );
298 assert_eq!(get_template("bug-fix"), Some(PromptTemplate::BugFix));
299 assert_eq!(
300 get_template("performance-optimization"),
301 Some(PromptTemplate::PerformanceOptimization)
302 );
303 assert_eq!(
304 get_template("security-audit"),
305 Some(PromptTemplate::SecurityAudit)
306 );
307 assert_eq!(
308 get_template("api-integration"),
309 Some(PromptTemplate::ApiIntegration)
310 );
311 assert_eq!(
312 get_template("database-migration"),
313 Some(PromptTemplate::DatabaseMigration)
314 );
315 assert_eq!(
316 get_template("dependency-update"),
317 Some(PromptTemplate::DependencyUpdate)
318 );
319 assert_eq!(get_template("cli-tool"), Some(PromptTemplate::CliTool));
320 assert_eq!(get_template("web-api"), Some(PromptTemplate::WebApi));
321 assert_eq!(
322 get_template("data-pipeline"),
323 Some(PromptTemplate::DataPipeline)
324 );
325 assert_eq!(
326 get_template("ui-component"),
327 Some(PromptTemplate::UiComponent)
328 );
329 assert_eq!(
330 get_template("code-review"),
331 Some(PromptTemplate::CodeReview)
332 );
333 assert_eq!(
334 get_template("debug-triage"),
335 Some(PromptTemplate::DebugTriage)
336 );
337 assert_eq!(get_template("release"), Some(PromptTemplate::Release));
338 assert_eq!(get_template("tech-debt"), Some(PromptTemplate::TechDebt));
339 assert_eq!(get_template("onboarding"), Some(PromptTemplate::Onboarding));
340 assert_eq!(get_template("nonexistent"), None);
341 }
342
343 #[test]
344 fn test_list_templates() {
345 let templates = list_templates();
346 assert_eq!(templates.len(), 20);
347 assert!(templates.iter().any(|(name, _)| name == &"feature-spec"));
348 assert!(templates.iter().any(|(name, _)| name == &"bug-fix"));
349 assert!(templates
350 .iter()
351 .any(|(name, _)| name == &"performance-optimization"));
352 assert!(templates.iter().any(|(name, _)| name == &"security-audit"));
353 assert!(templates.iter().any(|(name, _)| name == &"api-integration"));
354 assert!(templates
355 .iter()
356 .any(|(name, _)| name == &"database-migration"));
357 assert!(templates
358 .iter()
359 .any(|(name, _)| name == &"dependency-update"));
360 assert!(templates.iter().any(|(name, _)| name == &"cli-tool"));
361 assert!(templates.iter().any(|(name, _)| name == &"web-api"));
362 assert!(templates.iter().any(|(name, _)| name == &"data-pipeline"));
363 assert!(templates.iter().any(|(name, _)| name == &"ui-component"));
364 assert!(templates.iter().any(|(name, _)| name == &"code-review"));
365 assert!(templates.iter().any(|(name, _)| name == &"debug-triage"));
366 assert!(templates.iter().any(|(name, _)| name == &"release"));
367 assert!(templates.iter().any(|(name, _)| name == &"tech-debt"));
368 assert!(templates.iter().any(|(name, _)| name == &"onboarding"));
369 }
370
371 #[test]
372 fn test_template_content_has_goal() {
373 for template in ALL_TEMPLATES {
374 let content = template.content();
375 assert!(
376 content.contains("## Goal"),
377 "Template {} missing Goal section",
378 template.name()
379 );
380 }
381 }
382
383 #[test]
384 fn test_template_content_has_acceptance() {
385 for template in ALL_TEMPLATES {
386 let content = template.content();
387 assert!(
388 content.contains("## Acceptance") || content.contains("## Acceptance Checks"),
389 "Template {} missing Acceptance section",
390 template.name()
391 );
392 }
393 }
394}