1use std::collections::HashMap;
9
10#[derive(Debug, Clone)]
12pub struct EmbeddedTemplate {
13 pub name: &'static str,
15 pub content: &'static str,
17 pub description: &'static str,
19 pub deprecated: bool,
21}
22
23#[must_use]
30pub fn get_embedded_template(name: &str) -> Option<String> {
31 EMBEDDED_TEMPLATES.get(name).map(|t| t.content.to_string())
32}
33
34#[must_use]
41pub fn get_template_metadata(name: &str) -> Option<&'static EmbeddedTemplate> {
42 EMBEDDED_TEMPLATES.get(name)
43}
44
45#[must_use]
51pub fn list_all_templates() -> Vec<&'static EmbeddedTemplate> {
52 let mut templates: Vec<&EmbeddedTemplate> = EMBEDDED_TEMPLATES.values().collect();
53 templates.sort_by_key(|t| t.name);
54 templates
55}
56
57#[must_use]
61pub fn get_templates_map() -> HashMap<String, (String, String)> {
62 let mut map = HashMap::new();
63 for template in list_all_templates() {
64 map.insert(
65 template.name.to_string(),
66 (
67 template.content.to_string(),
68 template.description.to_string(),
69 ),
70 );
71 }
72 map
73}
74
75static EMBEDDED_TEMPLATES: std::sync::LazyLock<HashMap<&str, EmbeddedTemplate>> =
84 std::sync::LazyLock::new(|| {
85 let mut m = HashMap::new();
86
87 m.insert(
92 "commit_message_xml",
93 EmbeddedTemplate {
94 name: "commit_message_xml",
95 content: include_str!("templates/commit_message_xml.txt"),
96 description: "Generate Conventional Commits messages from git diffs (XML format)",
97 deprecated: false,
98 },
99 );
100
101 m.insert(
102 "commit_xsd_retry",
103 EmbeddedTemplate {
104 name: "commit_xsd_retry",
105 content: include_str!("templates/commit_xsd_retry.txt"),
106 description: "XSD validation retry prompt for commit messages",
107 deprecated: false,
108 },
109 );
110
111 m.insert(
112 "commit_simplified",
113 EmbeddedTemplate {
114 name: "commit_simplified",
115 content: include_str!("templates/commit_simplified.txt"),
116 description: "Simplified commit prompt with direct instructions",
117 deprecated: false,
118 },
119 );
120
121 m.insert(
126 "analysis_system_prompt",
127 EmbeddedTemplate {
128 name: "analysis_system_prompt",
129 content: include_str!("templates/analysis_system_prompt.txt"),
130 description: "Independent analysis agent system prompt (verifies PLAN vs DIFF and writes development_result.xml)",
131 deprecated: false,
132 },
133 );
134
135 m.insert(
140 "developer_iteration_xml",
141 EmbeddedTemplate {
142 name: "developer_iteration_xml",
143 content: include_str!("templates/developer_iteration_xml.txt"),
144 description: "Developer agent implementation mode prompt (no structured output; analysis verifies progress)",
145 deprecated: false,
146 },
147 );
148
149 m.insert(
150 "developer_iteration_xsd_retry",
151 EmbeddedTemplate {
152 name: "developer_iteration_xsd_retry",
153 content: include_str!("templates/developer_iteration_xsd_retry.txt"),
154 description: "XSD validation retry prompt for developer iteration",
155 deprecated: false,
156 },
157 );
158
159 m.insert(
160 "planning_xml",
161 EmbeddedTemplate {
162 name: "planning_xml",
163 content: include_str!("templates/planning_xml.txt"),
164 description: "Planning phase prompt with XML output format and XSD validation",
165 deprecated: false,
166 },
167 );
168
169 m.insert(
170 "planning_xsd_retry",
171 EmbeddedTemplate {
172 name: "planning_xsd_retry",
173 content: include_str!("templates/planning_xsd_retry.txt"),
174 description: "XSD validation retry prompt for planning phase",
175 deprecated: false,
176 },
177 );
178
179 m.insert(
180 "developer_iteration_continuation_xml",
181 EmbeddedTemplate {
182 name: "developer_iteration_continuation_xml",
183 content: include_str!("templates/developer_iteration_continuation_xml.txt"),
184 description: "Continuation prompt when previous attempt returned partial/failed",
185 deprecated: false,
186 },
187 );
188
189 m.insert(
194 "review_xml",
195 EmbeddedTemplate {
196 name: "review_xml",
197 content: include_str!("templates/review_xml.txt"),
198 description: "Review mode prompt with XML output format and XSD validation",
199 deprecated: false,
200 },
201 );
202
203 m.insert(
204 "review_xsd_retry",
205 EmbeddedTemplate {
206 name: "review_xsd_retry",
207 content: include_str!("templates/review_xsd_retry.txt"),
208 description: "XSD validation retry prompt for review mode",
209 deprecated: false,
210 },
211 );
212
213 m.insert(
218 "fix_mode_xml",
219 EmbeddedTemplate {
220 name: "fix_mode_xml",
221 content: include_str!("templates/fix_mode_xml.txt"),
222 description: "Fix mode prompt with XML output format and XSD validation",
223 deprecated: false,
224 },
225 );
226
227 m.insert(
228 "fix_mode_xsd_retry",
229 EmbeddedTemplate {
230 name: "fix_mode_xsd_retry",
231 content: include_str!("templates/fix_mode_xsd_retry.txt"),
232 description: "XSD validation retry prompt for fix mode",
233 deprecated: false,
234 },
235 );
236
237 m.insert(
242 "conflict_resolution",
243 EmbeddedTemplate {
244 name: "conflict_resolution",
245 content: include_str!("templates/conflict_resolution.txt"),
246 description: "Merge conflict resolution prompt",
247 deprecated: false,
248 },
249 );
250
251 m.insert(
252 "conflict_resolution_fallback",
253 EmbeddedTemplate {
254 name: "conflict_resolution_fallback",
255 content: include_str!("templates/conflict_resolution_fallback.txt"),
256 description: "Fallback conflict resolution prompt",
257 deprecated: false,
258 },
259 );
260
261 m
274 });
275
276#[cfg(test)]
277mod tests {
278 use super::*;
279
280 #[test]
281 fn test_get_embedded_template_existing() {
282 let result = get_embedded_template("developer_iteration_xml");
283 assert!(result.is_some());
284 let content = result.unwrap();
285 assert!(!content.is_empty());
286 assert!(content.contains("IMPLEMENTATION MODE") || content.contains("Developer"));
287 }
288
289 #[test]
290 fn test_get_embedded_template_not_found() {
291 let result = get_embedded_template("nonexistent_template");
292 assert!(result.is_none());
293 }
294
295 #[test]
296 fn test_get_template_metadata() {
297 let metadata = get_template_metadata("commit_message_xml");
298 assert!(metadata.is_some());
299 let template = metadata.unwrap();
300 assert_eq!(template.name, "commit_message_xml");
301 assert!(!template.description.is_empty());
302 }
303
304 #[test]
305 fn test_list_all_templates() {
306 let templates = list_all_templates();
307 assert!(!templates.is_empty());
308 assert!(templates.len() >= 10); for window in templates.windows(2) {
312 assert!(window[0].name <= window[1].name);
313 }
314 }
315
316 #[test]
317 fn test_get_templates_map() {
318 let map = get_templates_map();
319 assert!(!map.is_empty());
320 assert!(map.contains_key("developer_iteration_xml"));
321 assert!(map.contains_key("commit_message_xml"));
322
323 let (content, description) = map.get("developer_iteration_xml").unwrap();
324 assert!(!content.is_empty());
325 assert!(!description.is_empty());
326 }
327
328 #[test]
329 fn test_all_templates_have_content() {
330 let templates = list_all_templates();
331 for template in templates {
332 assert!(
333 !template.content.is_empty(),
334 "Template '{}' has empty content",
335 template.name
336 );
337 }
338 }
339
340 #[test]
341 fn test_all_templates_have_descriptions() {
342 let templates = list_all_templates();
343 for template in templates {
344 assert!(
345 !template.description.is_empty(),
346 "Template '{}' has empty description",
347 template.name
348 );
349 }
350 }
351
352 #[test]
353 fn test_fallback_templates_removed() {
354 assert!(get_embedded_template("developer_iteration_fallback").is_none());
356 assert!(get_embedded_template("planning_fallback").is_none());
357 assert!(get_embedded_template("fix_mode_fallback").is_none());
358 }
360
361 #[test]
362 fn test_legacy_non_xml_templates_removed() {
363 assert!(get_embedded_template("developer_iteration").is_none());
365 assert!(get_embedded_template("planning").is_none());
366 assert!(get_embedded_template("fix_mode").is_none());
367 }
369
370 #[test]
371 fn test_unused_reviewer_templates_removed() {
372 assert!(get_embedded_template("standard_review").is_none());
375 assert!(get_embedded_template("comprehensive_review").is_none());
376 assert!(get_embedded_template("security_review").is_none());
377 assert!(get_embedded_template("universal_review").is_none());
378 assert!(get_embedded_template("standard_review_minimal").is_none());
379 assert!(get_embedded_template("standard_review_normal").is_none());
380 }
382
383 #[test]
384 fn test_review_xml_template_exists() {
385 assert!(get_embedded_template("review_xml").is_some());
387 let content = get_embedded_template("review_xml").unwrap();
388 assert!(
389 content.contains("REVIEW MODE"),
390 "review_xml should contain REVIEW MODE"
391 );
392 }
393
394 #[test]
395 fn test_commit_xsd_retry_is_read_only_except_for_xml_write() {
396 let content = get_embedded_template("commit_xsd_retry").expect("commit_xsd_retry exists");
397
398 assert!(
399 content.contains("XSD") && content.contains("FIX XML"),
400 "commit_xsd_retry should clearly be an XML-only retry prompt"
401 );
402
403 assert!(
404 content.contains("READ-ONLY")
405 && (content.contains("EXCEPT FOR writing")
406 || content.contains("except for writing")
407 || content.contains("Except for writing"))
408 && content.contains("{{COMMIT_MESSAGE_XML_PATH}}"),
409 "commit_xsd_retry should be read-only except for writing commit_message.xml"
410 );
411
412 assert!(
413 !content.contains("DO NOT print")
414 && !content.contains("Do NOT print")
415 && !content.contains("ONLY acceptable output")
416 && !content.contains("The ONLY acceptable output"),
417 "commit_xsd_retry should not include stdout suppression wording"
418 );
419 }
420}