ralph_workflow/cli/reducer/
parser.rs1use super::event::CliEvent;
7
8#[must_use]
36pub fn args_to_events(args: &super::super::Args) -> Vec<CliEvent> {
37 let mut events = Vec::new();
38
39 if args.verbosity_shorthand.quiet {
41 events.push(CliEvent::QuietModeEnabled);
42 }
43 if args.verbosity_shorthand.full {
44 events.push(CliEvent::FullModeEnabled);
45 }
46 if args.debug_verbosity.debug {
47 events.push(CliEvent::DebugModeEnabled);
48 }
49 if let Some(level) = args.verbosity {
50 events.push(CliEvent::VerbositySet { level });
51 }
52
53 if args.quick_presets.quick {
56 events.push(CliEvent::QuickPresetApplied);
57 }
58 if args.quick_presets.rapid {
59 events.push(CliEvent::RapidPresetApplied);
60 }
61 if args.quick_presets.long {
63 events.push(CliEvent::LongPresetApplied);
64 }
65 if args.standard_presets.standard {
66 events.push(CliEvent::StandardPresetApplied);
67 }
68 if args.standard_presets.thorough {
69 events.push(CliEvent::ThoroughPresetApplied);
70 }
71
72 if let Some(iters) = args.developer_iters {
75 events.push(CliEvent::DeveloperItersSet { value: iters });
76 }
77 if let Some(reviews) = args.reviewer_reviews {
78 events.push(CliEvent::ReviewerReviewsSet { value: reviews });
79 }
80
81 if let Some(ref agent) = args.developer_agent {
83 events.push(CliEvent::DeveloperAgentSet {
84 agent: agent.clone(),
85 });
86 }
87 if let Some(ref agent) = args.reviewer_agent {
88 events.push(CliEvent::ReviewerAgentSet {
89 agent: agent.clone(),
90 });
91 }
92 if let Some(ref model) = args.developer_model {
93 events.push(CliEvent::DeveloperModelSet {
94 model: model.clone(),
95 });
96 }
97 if let Some(ref model) = args.reviewer_model {
98 events.push(CliEvent::ReviewerModelSet {
99 model: model.clone(),
100 });
101 }
102 if let Some(ref provider) = args.developer_provider {
103 events.push(CliEvent::DeveloperProviderSet {
104 provider: provider.clone(),
105 });
106 }
107 if let Some(ref provider) = args.reviewer_provider {
108 events.push(CliEvent::ReviewerProviderSet {
109 provider: provider.clone(),
110 });
111 }
112 if let Some(ref parser) = args.reviewer_json_parser {
113 events.push(CliEvent::ReviewerJsonParserSet {
114 parser: parser.clone(),
115 });
116 }
117
118 if let Some(ref preset) = args.preset {
120 events.push(CliEvent::AgentPresetSet {
121 preset: format!("{preset:?}"),
122 });
123 }
124
125 if args.no_isolation {
127 events.push(CliEvent::IsolationModeDisabled);
128 }
129 if let Some(ref depth) = args.review_depth {
130 events.push(CliEvent::ReviewDepthSet {
131 depth: depth.clone(),
132 });
133 }
134 if let Some(ref name) = args.git_user_name {
135 events.push(CliEvent::GitUserNameSet {
136 name: name.trim().to_string(),
137 });
138 }
139 if let Some(ref email) = args.git_user_email {
140 events.push(CliEvent::GitUserEmailSet {
141 email: email.trim().to_string(),
142 });
143 }
144 if args.show_streaming_metrics {
145 events.push(CliEvent::StreamingMetricsEnabled);
146 }
147
148 events.push(CliEvent::CliProcessingComplete);
150
151 events
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use crate::cli::Args;
158 use clap::Parser;
159
160 #[test]
161 fn test_args_to_events_empty() {
162 let args = Args::parse_from(["ralph"]);
163 let events = args_to_events(&args);
164
165 assert!(
167 events.contains(&CliEvent::CliProcessingComplete),
168 "Should always have completion event"
169 );
170
171 let events_without_completion: Vec<_> = events
173 .iter()
174 .filter(|e| *e != &CliEvent::CliProcessingComplete)
175 .collect();
176 assert!(
177 events_without_completion.is_empty(),
178 "Should have no other events for empty args"
179 );
180 }
181
182 #[test]
183 fn test_args_to_events_quick_preset() {
184 let args = Args::parse_from(["ralph", "-Q"]);
185 let events = args_to_events(&args);
186
187 assert!(
188 events.contains(&CliEvent::QuickPresetApplied),
189 "Should have quick preset event"
190 );
191 assert!(events.contains(&CliEvent::CliProcessingComplete));
192 }
193
194 #[test]
195 fn test_args_to_events_rapid_preset() {
196 let args = Args::parse_from(["ralph", "-U"]);
197 let events = args_to_events(&args);
198
199 assert!(
200 events.contains(&CliEvent::RapidPresetApplied),
201 "Should have rapid preset event"
202 );
203 assert!(events.contains(&CliEvent::CliProcessingComplete));
204 }
205
206 #[test]
207 fn test_args_to_events_long_preset() {
208 let args = Args::parse_from(["ralph", "-L"]);
209 let events = args_to_events(&args);
210
211 assert!(
212 events.contains(&CliEvent::LongPresetApplied),
213 "Should have long preset event"
214 );
215 assert!(events.contains(&CliEvent::CliProcessingComplete));
216 }
217
218 #[test]
219 fn test_args_to_events_standard_preset() {
220 let args = Args::parse_from(["ralph", "-S"]);
221 let events = args_to_events(&args);
222
223 assert!(
224 events.contains(&CliEvent::StandardPresetApplied),
225 "Should have standard preset event"
226 );
227 assert!(events.contains(&CliEvent::CliProcessingComplete));
228 }
229
230 #[test]
231 fn test_args_to_events_thorough_preset() {
232 let args = Args::parse_from(["ralph", "-T"]);
233 let events = args_to_events(&args);
234
235 assert!(
236 events.contains(&CliEvent::ThoroughPresetApplied),
237 "Should have thorough preset event"
238 );
239 assert!(events.contains(&CliEvent::CliProcessingComplete));
240 }
241
242 #[test]
243 fn test_args_to_events_explicit_iters() {
244 let args = Args::parse_from(["ralph", "-D", "7", "-R", "3"]);
245 let events = args_to_events(&args);
246
247 assert!(
248 events.contains(&CliEvent::DeveloperItersSet { value: 7 }),
249 "Should have developer iters event"
250 );
251 assert!(
252 events.contains(&CliEvent::ReviewerReviewsSet { value: 3 }),
253 "Should have reviewer reviews event"
254 );
255 }
256
257 #[test]
258 fn test_args_to_events_preset_plus_explicit_override() {
259 let args = Args::parse_from(["ralph", "-Q", "-D", "10", "-R", "5"]);
260 let events = args_to_events(&args);
261
262 assert!(events.contains(&CliEvent::QuickPresetApplied));
264 assert!(events.contains(&CliEvent::DeveloperItersSet { value: 10 }));
265 assert!(events.contains(&CliEvent::ReviewerReviewsSet { value: 5 }));
266
267 let preset_idx = events
269 .iter()
270 .position(|e| e == &CliEvent::QuickPresetApplied)
271 .expect("Should have quick preset");
272 let iters_idx = events
273 .iter()
274 .position(|e| e == &CliEvent::DeveloperItersSet { value: 10 })
275 .expect("Should have developer iters");
276
277 assert!(
278 preset_idx < iters_idx,
279 "Preset should come before explicit override"
280 );
281 }
282
283 #[test]
284 fn test_args_to_events_agent_selection() {
285 let args = Args::parse_from(["ralph", "-a", "claude", "-r", "gpt"]);
286 let events = args_to_events(&args);
287
288 assert!(
289 events.contains(&CliEvent::DeveloperAgentSet {
290 agent: "claude".to_string()
291 }),
292 "Should have developer agent event"
293 );
294 assert!(
295 events.contains(&CliEvent::ReviewerAgentSet {
296 agent: "gpt".to_string()
297 }),
298 "Should have reviewer agent event"
299 );
300 }
301
302 #[test]
303 fn test_args_to_events_verbose_mode() {
304 let args = Args::parse_from(["ralph", "-v", "3"]);
305 let events = args_to_events(&args);
306
307 assert!(
308 events.contains(&CliEvent::VerbositySet { level: 3 }),
309 "Should have verbosity set event"
310 );
311 }
312
313 #[test]
314 fn test_args_to_events_debug_mode() {
315 let args = Args::parse_from(["ralph", "--debug"]);
316 let events = args_to_events(&args);
317
318 assert!(
319 events.contains(&CliEvent::DebugModeEnabled),
320 "Should have debug mode event"
321 );
322 }
323
324 #[test]
325 fn test_args_to_events_no_isolation() {
326 let args = Args::parse_from(["ralph", "--no-isolation"]);
327 let events = args_to_events(&args);
328
329 assert!(
330 events.contains(&CliEvent::IsolationModeDisabled),
331 "Should have isolation mode disabled event"
332 );
333 }
334
335 #[test]
336 fn test_args_to_events_git_identity() {
337 let args = Args::parse_from([
338 "ralph",
339 "--git-user-name",
340 "John Doe",
341 "--git-user-email",
342 "john@example.com",
343 ]);
344 let events = args_to_events(&args);
345
346 assert!(
347 events.contains(&CliEvent::GitUserNameSet {
348 name: "John Doe".to_string()
349 }),
350 "Should have git user name event"
351 );
352 assert!(
353 events.contains(&CliEvent::GitUserEmailSet {
354 email: "john@example.com".to_string()
355 }),
356 "Should have git user email event"
357 );
358 }
359
360 #[test]
361 fn test_args_to_events_streaming_metrics() {
362 let args = Args::parse_from(["ralph", "--show-streaming-metrics"]);
363 let events = args_to_events(&args);
364
365 assert!(
366 events.contains(&CliEvent::StreamingMetricsEnabled),
367 "Should have streaming metrics event"
368 );
369 }
370}