ralph_workflow/cli/reducer/
state_reduction.rs1use super::event::CliEvent;
7use super::state::{CliState, PresetType};
8
9#[must_use]
29pub fn reduce(mut state: CliState, event: CliEvent) -> CliState {
30 match event {
31 CliEvent::VerbositySet { level } => state.verbosity = Some(level),
33 CliEvent::QuietModeEnabled => state.quiet_mode = true,
34 CliEvent::FullModeEnabled => state.full_mode = true,
35 CliEvent::DebugModeEnabled => state.debug_mode = true,
36
37 CliEvent::QuickPresetApplied => state.preset_applied = Some(PresetType::Quick),
39 CliEvent::RapidPresetApplied => state.preset_applied = Some(PresetType::Rapid),
40 CliEvent::LongPresetApplied => state.preset_applied = Some(PresetType::Long),
41 CliEvent::StandardPresetApplied => state.preset_applied = Some(PresetType::Standard),
42 CliEvent::ThoroughPresetApplied => state.preset_applied = Some(PresetType::Thorough),
43
44 CliEvent::DeveloperItersSet { value } => state.developer_iters = Some(value),
46 CliEvent::ReviewerReviewsSet { value } => state.reviewer_reviews = Some(value),
47
48 CliEvent::DeveloperAgentSet { agent } => state.developer_agent = Some(agent),
50 CliEvent::ReviewerAgentSet { agent } => state.reviewer_agent = Some(agent),
51 CliEvent::DeveloperModelSet { model } => state.developer_model = Some(model),
52 CliEvent::ReviewerModelSet { model } => state.reviewer_model = Some(model),
53 CliEvent::DeveloperProviderSet { provider } => state.developer_provider = Some(provider),
54 CliEvent::ReviewerProviderSet { provider } => state.reviewer_provider = Some(provider),
55 CliEvent::ReviewerJsonParserSet { parser } => state.reviewer_json_parser = Some(parser),
56
57 CliEvent::IsolationModeDisabled => state.isolation_mode = Some(false),
59 CliEvent::ReviewDepthSet { depth } => state.review_depth = Some(depth),
60 CliEvent::GitUserNameSet { name } => state.git_user_name = Some(name),
61 CliEvent::GitUserEmailSet { email } => state.git_user_email = Some(email),
62 CliEvent::StreamingMetricsEnabled => state.streaming_metrics = true,
63
64 CliEvent::AgentPresetSet { preset } => state.agent_preset = Some(preset),
66
67 CliEvent::CliProcessingComplete => state.complete = true,
69 }
70
71 state
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_reduce_verbosity_set() {
80 let state = CliState::initial();
81 let new_state = reduce(state, CliEvent::VerbositySet { level: 3 });
82 assert_eq!(new_state.verbosity, Some(3));
83 }
84
85 #[test]
86 fn test_reduce_quiet_mode() {
87 let state = CliState::initial();
88 let new_state = reduce(state, CliEvent::QuietModeEnabled);
89 assert!(new_state.quiet_mode);
90 }
91
92 #[test]
93 fn test_reduce_preset_quick() {
94 let state = CliState::initial();
95 let new_state = reduce(state, CliEvent::QuickPresetApplied);
96 assert_eq!(new_state.preset_applied, Some(PresetType::Quick));
97 assert_eq!(new_state.resolved_developer_iters(99), 1);
98 assert_eq!(new_state.resolved_reviewer_reviews(99), 1);
99 }
100
101 #[test]
102 fn test_reduce_preset_long() {
103 let state = CliState::initial();
104 let new_state = reduce(state, CliEvent::LongPresetApplied);
105 assert_eq!(new_state.preset_applied, Some(PresetType::Long));
106 assert_eq!(new_state.resolved_developer_iters(99), 15);
107 assert_eq!(new_state.resolved_reviewer_reviews(99), 10);
108 }
109
110 #[test]
111 fn test_reduce_preset_standard() {
112 let state = CliState::initial();
113 let new_state = reduce(state, CliEvent::StandardPresetApplied);
114 assert_eq!(new_state.preset_applied, Some(PresetType::Standard));
115 assert_eq!(new_state.resolved_developer_iters(99), 5);
116 assert_eq!(new_state.resolved_reviewer_reviews(99), 2);
117 }
118
119 #[test]
120 fn test_reduce_preset_thorough() {
121 let state = CliState::initial();
122 let new_state = reduce(state, CliEvent::ThoroughPresetApplied);
123 assert_eq!(new_state.preset_applied, Some(PresetType::Thorough));
124 assert_eq!(new_state.resolved_developer_iters(99), 10);
125 assert_eq!(new_state.resolved_reviewer_reviews(99), 5);
126 }
127
128 #[test]
129 fn test_reduce_preset_last_wins() {
130 let state = CliState::initial();
131 let state = reduce(state, CliEvent::QuickPresetApplied);
133 let state = reduce(state, CliEvent::LongPresetApplied);
134
135 assert_eq!(state.preset_applied, Some(PresetType::Long));
137 assert_eq!(state.resolved_developer_iters(99), 15);
138 }
139
140 #[test]
141 fn test_reduce_explicit_iters_override_preset() {
142 let state = CliState::initial();
143 let state = reduce(state, CliEvent::QuickPresetApplied);
145 let state = reduce(state, CliEvent::DeveloperItersSet { value: 7 });
147 let state = reduce(state, CliEvent::ReviewerReviewsSet { value: 3 });
148
149 assert_eq!(state.resolved_developer_iters(99), 7);
151 assert_eq!(state.resolved_reviewer_reviews(99), 3);
152 }
153
154 #[test]
155 fn test_reduce_developer_agent() {
156 let state = CliState::initial();
157 let new_state = reduce(
158 state,
159 CliEvent::DeveloperAgentSet {
160 agent: "claude".to_string(),
161 },
162 );
163 assert_eq!(new_state.developer_agent, Some("claude".to_string()));
164 }
165
166 #[test]
167 fn test_reduce_isolation_mode_disabled() {
168 let state = CliState::initial();
169 let new_state = reduce(state, CliEvent::IsolationModeDisabled);
170 assert_eq!(new_state.isolation_mode, Some(false));
171 }
172
173 #[test]
174 fn test_reduce_streaming_metrics() {
175 let state = CliState::initial();
176 let new_state = reduce(state, CliEvent::StreamingMetricsEnabled);
177 assert!(new_state.streaming_metrics);
178 }
179
180 #[test]
181 fn test_reduce_complete() {
182 let state = CliState::initial();
183 let new_state = reduce(state, CliEvent::CliProcessingComplete);
184 assert!(new_state.complete);
185 }
186
187 #[test]
188 fn test_reduce_preserves_unrelated_fields() {
189 let mut state = CliState::initial();
190 state.developer_agent = Some("existing".to_string());
191
192 let new_state = reduce(state, CliEvent::QuietModeEnabled);
194
195 assert!(new_state.quiet_mode);
196 assert_eq!(new_state.developer_agent, Some("existing".to_string()));
197 }
198
199 #[test]
200 fn test_full_event_sequence() {
201 let events = vec![
202 CliEvent::ThoroughPresetApplied,
203 CliEvent::DeveloperAgentSet {
204 agent: "opencode".to_string(),
205 },
206 CliEvent::ReviewerAgentSet {
207 agent: "claude".to_string(),
208 },
209 CliEvent::DebugModeEnabled,
210 CliEvent::StreamingMetricsEnabled,
211 CliEvent::CliProcessingComplete,
212 ];
213
214 let mut state = CliState::initial();
215 for event in events {
216 state = reduce(state, event);
217 }
218
219 assert!(state.complete);
220 assert!(state.debug_mode);
221 assert!(state.streaming_metrics);
222 assert_eq!(state.preset_applied, Some(PresetType::Thorough));
223 assert_eq!(state.developer_agent, Some("opencode".to_string()));
224 assert_eq!(state.reviewer_agent, Some("claude".to_string()));
225 assert_eq!(state.resolved_developer_iters(5), 10);
226 assert_eq!(state.resolved_reviewer_reviews(2), 5);
227 }
228}