ralph_workflow/templates/
mod.rs1use 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}
29
30impl PromptTemplate {
31 pub const fn name(self) -> &'static str {
33 match self {
34 Self::FeatureSpec => "feature-spec",
35 Self::BugFix => "bug-fix",
36 Self::Refactor => "refactor",
37 Self::Test => "test",
38 Self::Docs => "docs",
39 Self::Quick => "quick",
40 }
41 }
42
43 pub const fn description(self) -> &'static str {
45 match self {
46 Self::FeatureSpec => "Comprehensive product specification with questions to consider and code quality standards",
47 Self::BugFix => "Bug fix template with investigation guidance and testing requirements",
48 Self::Refactor => "Code refactoring template with behavior preservation emphasis",
49 Self::Test => "Test writing template with edge case considerations",
50 Self::Docs => "Documentation update template with completeness checklist",
51 Self::Quick => "Quick/small change template (minimal)",
52 }
53 }
54
55 pub const fn content(self) -> &'static str {
57 match self {
58 Self::FeatureSpec => {
59 include_str!("../../templates/prompts/feature-spec.md")
60 }
61 Self::BugFix => {
62 include_str!("../../templates/prompts/bug-fix.md")
63 }
64 Self::Refactor => {
65 include_str!("../../templates/prompts/refactor.md")
66 }
67 Self::Test => {
68 include_str!("../../templates/prompts/test.md")
69 }
70 Self::Docs => {
71 include_str!("../../templates/prompts/docs.md")
72 }
73 Self::Quick => {
74 include_str!("../../templates/prompts/quick.md")
75 }
76 }
77 }
78}
79
80impl fmt::Display for PromptTemplate {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(f, "{}", self.name())
83 }
84}
85
86pub const ALL_TEMPLATES: [PromptTemplate; 6] = [
88 PromptTemplate::FeatureSpec,
89 PromptTemplate::BugFix,
90 PromptTemplate::Refactor,
91 PromptTemplate::Test,
92 PromptTemplate::Docs,
93 PromptTemplate::Quick,
94];
95
96pub fn get_template(name: &str) -> Option<PromptTemplate> {
107 ALL_TEMPLATES.iter().find(|t| t.name() == name).copied()
108}
109
110pub fn list_templates() -> Vec<(&'static str, &'static str)> {
114 ALL_TEMPLATES
115 .iter()
116 .map(|t| (t.name(), t.description()))
117 .collect()
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_template_names() {
126 assert_eq!(PromptTemplate::FeatureSpec.name(), "feature-spec");
127 assert_eq!(PromptTemplate::BugFix.name(), "bug-fix");
128 assert_eq!(PromptTemplate::Refactor.name(), "refactor");
129 assert_eq!(PromptTemplate::Test.name(), "test");
130 assert_eq!(PromptTemplate::Docs.name(), "docs");
131 assert_eq!(PromptTemplate::Quick.name(), "quick");
132 }
133
134 #[test]
135 fn test_template_descriptions() {
136 assert!(!PromptTemplate::FeatureSpec.description().is_empty());
137 assert!(!PromptTemplate::BugFix.description().is_empty());
138 assert!(!PromptTemplate::Refactor.description().is_empty());
139 assert!(!PromptTemplate::Test.description().is_empty());
140 assert!(!PromptTemplate::Docs.description().is_empty());
141 assert!(!PromptTemplate::Quick.description().is_empty());
142 }
143
144 #[test]
145 fn test_get_template() {
146 assert_eq!(
147 get_template("feature-spec"),
148 Some(PromptTemplate::FeatureSpec)
149 );
150 assert_eq!(get_template("bug-fix"), Some(PromptTemplate::BugFix));
151 assert_eq!(get_template("nonexistent"), None);
152 }
153
154 #[test]
155 fn test_list_templates() {
156 let templates = list_templates();
157 assert_eq!(templates.len(), 6);
158 assert!(templates.iter().any(|(name, _)| name == &"feature-spec"));
159 assert!(templates.iter().any(|(name, _)| name == &"bug-fix"));
160 }
161
162 #[test]
163 fn test_template_content_has_goal() {
164 for template in ALL_TEMPLATES {
165 let content = template.content();
166 assert!(
167 content.contains("## Goal"),
168 "Template {} missing Goal section",
169 template.name()
170 );
171 }
172 }
173
174 #[test]
175 fn test_template_content_has_acceptance() {
176 for template in ALL_TEMPLATES {
177 let content = template.content();
178 assert!(
179 content.contains("## Acceptance") || content.contains("## Acceptance Checks"),
180 "Template {} missing Acceptance section",
181 template.name()
182 );
183 }
184 }
185}