1pub const STANDARD: &str = include_str!("../prompts/standard.md");
9
10pub const SPLIT: &str = include_str!("../prompts/split.md");
12
13pub const VERIFY: &str = include_str!("../prompts/verify.md");
15
16pub const MERGE_CONFLICT: &str = include_str!("../prompts/merge-conflict.md");
18
19pub const OLLAMA: &str = include_str!("../prompts/ollama.md");
21
22#[cfg(debug_assertions)]
24mod dev {
25 pub const BOOTSTRAP: &str = include_str!("../prompts-dev/bootstrap.md");
27
28 pub const DOCUMENTATION: &str = include_str!("../prompts-dev/documentation.md");
30
31 pub const DOC_AUDIT: &str = include_str!("../prompts-dev/doc-audit.md");
33
34 pub const RESEARCH_ANALYSIS: &str = include_str!("../prompts-dev/research-analysis.md");
36
37 pub const RESEARCH_SYNTHESIS: &str = include_str!("../prompts-dev/research-synthesis.md");
39}
40
41#[derive(Debug, Clone)]
43pub struct PromptMetadata {
44 pub name: &'static str,
46 pub purpose: &'static str,
48 pub content: &'static str,
50}
51
52pub fn all_bundled_prompts() -> Vec<PromptMetadata> {
54 let prompts = vec![
55 PromptMetadata {
56 name: "standard",
57 purpose: "Default execution prompt",
58 content: STANDARD,
59 },
60 PromptMetadata {
61 name: "split",
62 purpose: "Split a driver spec into members with detailed acceptance criteria",
63 content: SPLIT,
64 },
65 PromptMetadata {
66 name: "verify",
67 purpose: "Verify that acceptance criteria are met",
68 content: VERIFY,
69 },
70 PromptMetadata {
71 name: "merge-conflict",
72 purpose: "Resolve git merge conflicts during rebase operations",
73 content: MERGE_CONFLICT,
74 },
75 PromptMetadata {
76 name: "ollama",
77 purpose: "Optimized prompt for local LLM execution",
78 content: OLLAMA,
79 },
80 ];
81
82 #[cfg(debug_assertions)]
84 let prompts = {
85 let mut prompts = prompts;
86 prompts.extend(vec![
87 PromptMetadata {
88 name: "bootstrap",
89 purpose: "Minimal bootstrap prompt that defers to prep command",
90 content: dev::BOOTSTRAP,
91 },
92 PromptMetadata {
93 name: "documentation",
94 purpose: "Generate documentation from tracked source files",
95 content: dev::DOCUMENTATION,
96 },
97 PromptMetadata {
98 name: "doc-audit",
99 purpose: "Audit Rust code against mdbook documentation",
100 content: dev::DOC_AUDIT,
101 },
102 PromptMetadata {
103 name: "research-analysis",
104 purpose: "Chant-specific research analysis",
105 content: dev::RESEARCH_ANALYSIS,
106 },
107 PromptMetadata {
108 name: "research-synthesis",
109 purpose: "Chant-specific research synthesis",
110 content: dev::RESEARCH_SYNTHESIS,
111 },
112 ]);
113 prompts
114 };
115
116 prompts
117}
118
119pub fn get_prompt(name: &str) -> Option<PromptMetadata> {
121 all_bundled_prompts().into_iter().find(|p| p.name == name)
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn test_all_bundled_prompts_not_empty() {
130 let prompts = all_bundled_prompts();
131 assert!(!prompts.is_empty());
132 }
133
134 #[test]
135 fn test_all_prompts_have_content() {
136 let prompts = all_bundled_prompts();
137 for prompt in prompts {
138 assert!(
139 !prompt.content.is_empty(),
140 "Prompt {} has no content",
141 prompt.name
142 );
143 }
144 }
145
146 #[test]
147 #[cfg(debug_assertions)]
148 fn test_get_prompt_bootstrap() {
149 let prompt = get_prompt("bootstrap");
150 assert!(prompt.is_some());
151 let p = prompt.unwrap();
152 assert_eq!(p.name, "bootstrap");
153 assert!(p.content.contains("chant prep"));
154 }
155
156 #[test]
157 fn test_get_prompt_nonexistent() {
158 let prompt = get_prompt("nonexistent");
159 assert!(prompt.is_none());
160 }
161}