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 assert!(
173 !events.iter().any(|e| e != &CliEvent::CliProcessingComplete),
174 "Should have no other events for empty args"
175 );
176 }
177
178 #[test]
179 fn test_args_to_events_quick_preset() {
180 let args = Args::parse_from(["ralph", "-Q"]);
181 let events = args_to_events(&args);
182
183 assert!(
184 events.contains(&CliEvent::QuickPresetApplied),
185 "Should have quick preset event"
186 );
187 assert!(events.contains(&CliEvent::CliProcessingComplete));
188 }
189
190 #[test]
191 fn test_args_to_events_rapid_preset() {
192 let args = Args::parse_from(["ralph", "-U"]);
193 let events = args_to_events(&args);
194
195 assert!(
196 events.contains(&CliEvent::RapidPresetApplied),
197 "Should have rapid preset event"
198 );
199 assert!(events.contains(&CliEvent::CliProcessingComplete));
200 }
201
202 #[test]
203 fn test_args_to_events_long_preset() {
204 let args = Args::parse_from(["ralph", "-L"]);
205 let events = args_to_events(&args);
206
207 assert!(
208 events.contains(&CliEvent::LongPresetApplied),
209 "Should have long preset event"
210 );
211 assert!(events.contains(&CliEvent::CliProcessingComplete));
212 }
213
214 #[test]
215 fn test_args_to_events_standard_preset() {
216 let args = Args::parse_from(["ralph", "-S"]);
217 let events = args_to_events(&args);
218
219 assert!(
220 events.contains(&CliEvent::StandardPresetApplied),
221 "Should have standard preset event"
222 );
223 assert!(events.contains(&CliEvent::CliProcessingComplete));
224 }
225
226 #[test]
227 fn test_args_to_events_thorough_preset() {
228 let args = Args::parse_from(["ralph", "-T"]);
229 let events = args_to_events(&args);
230
231 assert!(
232 events.contains(&CliEvent::ThoroughPresetApplied),
233 "Should have thorough preset event"
234 );
235 assert!(events.contains(&CliEvent::CliProcessingComplete));
236 }
237
238 #[test]
239 fn test_args_to_events_explicit_iters() {
240 let args = Args::parse_from(["ralph", "-D", "7", "-R", "3"]);
241 let events = args_to_events(&args);
242
243 assert!(
244 events.contains(&CliEvent::DeveloperItersSet { value: 7 }),
245 "Should have developer iters event"
246 );
247 assert!(
248 events.contains(&CliEvent::ReviewerReviewsSet { value: 3 }),
249 "Should have reviewer reviews event"
250 );
251 }
252
253 #[test]
254 fn test_args_to_events_preset_plus_explicit_override() {
255 let args = Args::parse_from(["ralph", "-Q", "-D", "10", "-R", "5"]);
256 let events = args_to_events(&args);
257
258 assert!(events.contains(&CliEvent::QuickPresetApplied));
260 assert!(events.contains(&CliEvent::DeveloperItersSet { value: 10 }));
261 assert!(events.contains(&CliEvent::ReviewerReviewsSet { value: 5 }));
262
263 let preset_idx = events
265 .iter()
266 .position(|e| e == &CliEvent::QuickPresetApplied)
267 .expect("Should have quick preset");
268 let iters_idx = events
269 .iter()
270 .position(|e| e == &CliEvent::DeveloperItersSet { value: 10 })
271 .expect("Should have developer iters");
272
273 assert!(
274 preset_idx < iters_idx,
275 "Preset should come before explicit override"
276 );
277 }
278
279 #[test]
280 fn test_args_to_events_agent_selection() {
281 let args = Args::parse_from(["ralph", "-a", "claude", "-r", "gpt"]);
282 let events = args_to_events(&args);
283
284 assert!(
285 events.contains(&CliEvent::DeveloperAgentSet {
286 agent: "claude".to_string()
287 }),
288 "Should have developer agent event"
289 );
290 assert!(
291 events.contains(&CliEvent::ReviewerAgentSet {
292 agent: "gpt".to_string()
293 }),
294 "Should have reviewer agent event"
295 );
296 }
297
298 #[test]
299 fn test_args_to_events_verbose_mode() {
300 let args = Args::parse_from(["ralph", "-v", "3"]);
301 let events = args_to_events(&args);
302
303 assert!(
304 events.contains(&CliEvent::VerbositySet { level: 3 }),
305 "Should have verbosity set event"
306 );
307 }
308
309 #[test]
310 fn test_args_to_events_debug_mode() {
311 let args = Args::parse_from(["ralph", "--debug"]);
312 let events = args_to_events(&args);
313
314 assert!(
315 events.contains(&CliEvent::DebugModeEnabled),
316 "Should have debug mode event"
317 );
318 }
319
320 #[test]
321 fn test_args_to_events_no_isolation() {
322 let args = Args::parse_from(["ralph", "--no-isolation"]);
323 let events = args_to_events(&args);
324
325 assert!(
326 events.contains(&CliEvent::IsolationModeDisabled),
327 "Should have isolation mode disabled event"
328 );
329 }
330
331 #[test]
332 fn test_args_to_events_git_identity() {
333 let args = Args::parse_from([
334 "ralph",
335 "--git-user-name",
336 "John Doe",
337 "--git-user-email",
338 "john@example.com",
339 ]);
340 let events = args_to_events(&args);
341
342 assert!(
343 events.contains(&CliEvent::GitUserNameSet {
344 name: "John Doe".to_string()
345 }),
346 "Should have git user name event"
347 );
348 assert!(
349 events.contains(&CliEvent::GitUserEmailSet {
350 email: "john@example.com".to_string()
351 }),
352 "Should have git user email event"
353 );
354 }
355
356 #[test]
357 fn test_args_to_events_streaming_metrics() {
358 let args = Args::parse_from(["ralph", "--show-streaming-metrics"]);
359 let events = args_to_events(&args);
360
361 assert!(
362 events.contains(&CliEvent::StreamingMetricsEnabled),
363 "Should have streaming metrics event"
364 );
365 }
366
367 #[test]
368 fn test_args_parses_pause_on_exit_mode() {
369 let args = Args::try_parse_from(["ralph", "--pause-on-exit", "always"])
370 .expect("pause-on-exit should parse");
371
372 assert_eq!(args.pause_on_exit, crate::cli::PauseOnExitMode::Always);
373 }
374}