ralph_workflow/reducer/event/review.rs
1// NOTE: split from reducer/event.rs to keep the main file under line limits.
2use serde::{Deserialize, Serialize};
3
4/// Review phase events.
5///
6/// Events related to code review passes and fix attempts. The review phase
7/// runs reviewer agents to identify issues and (by default) the same reviewer
8/// agent chain to apply any required fixes.
9///
10/// # State Transitions
11///
12/// - `PhaseStarted`: Sets phase to Review, resets pass counter
13/// - `PassStarted`: Resets agent chain for the pass
14/// - `Completed(issues_found=false)`: Advances to next pass or `CommitMessage`
15/// - `Completed(issues_found=true)`: Triggers fix attempt
16/// - `FixAttemptCompleted`: Transitions to `CommitMessage`
17/// - `PhaseCompleted`: Transitions to `CommitMessage`
18#[derive(Clone, Serialize, Deserialize, Debug)]
19pub enum ReviewEvent {
20 /// Review phase has started.
21 PhaseStarted,
22 /// A review pass has started.
23 PassStarted {
24 /// The pass number starting.
25 pass: u32,
26 },
27
28 /// Review context prepared for a pass.
29 ///
30 /// Emitted after `Effect::PrepareReviewContext` completes.
31 ContextPrepared {
32 /// The pass number the context was prepared for.
33 pass: u32,
34 },
35
36 /// Review prompt prepared for a pass.
37 ///
38 /// Emitted after `Effect::PrepareReviewPrompt` completes.
39 PromptPrepared {
40 pass: u32,
41 },
42
43 /// Reviewer agent was invoked for a pass.
44 ///
45 /// Emitted after `Effect::InvokeReviewAgent` completes.
46 AgentInvoked {
47 pass: u32,
48 },
49
50 /// Review issues XML exists and was read successfully for the pass.
51 ///
52 /// Emitted after `Effect::ExtractReviewIssuesXml` completes.
53 IssuesXmlExtracted {
54 pass: u32,
55 },
56 /// Review issues XML missing for the pass.
57 ///
58 /// Emitted after `Effect::ExtractReviewIssuesXml` when the XML was absent.
59 IssuesXmlMissing {
60 pass: u32,
61 /// The invalid output attempt count.
62 attempt: u32,
63 /// Error detail if file read failed for a reason other than `NotFound`.
64 error_detail: Option<String>,
65 },
66
67 /// Review issues XML validated for a pass.
68 ///
69 /// This event is an observation: the XML was valid and the handler determined
70 /// whether issues were found and whether this was an explicit clean-no-issues output.
71 IssuesXmlValidated {
72 pass: u32,
73 issues_found: bool,
74 clean_no_issues: bool,
75 issues: Vec<String>,
76 no_issues_found: Option<String>,
77 },
78
79 /// ISSUES.md was written for a pass.
80 IssuesMarkdownWritten {
81 pass: u32,
82 },
83
84 /// Review issue snippets were extracted for a pass.
85 IssueSnippetsExtracted {
86 pass: u32,
87 },
88
89 /// Review issues XML archived for a pass.
90 IssuesXmlArchived {
91 pass: u32,
92 },
93
94 /// Review issues XML cleaned before invoking the reviewer agent.
95 IssuesXmlCleaned {
96 pass: u32,
97 },
98
99 /// Fix prompt prepared for a review pass.
100 FixPromptPrepared {
101 pass: u32,
102 },
103
104 /// Fix agent was invoked for a review pass.
105 FixAgentInvoked {
106 pass: u32,
107 },
108
109 /// Fix analysis agent was invoked for a review pass.
110 ///
111 /// Emitted after `Effect::InvokeFixAnalysisAgent` completes.
112 /// This mirrors `DevelopmentEvent::AnalysisAgentInvoked` for the fix phase.
113 FixAnalysisAgentInvoked {
114 pass: u32,
115 },
116
117 /// Fix result XML exists and was read successfully for the pass.
118 FixResultXmlExtracted {
119 pass: u32,
120 },
121 /// Fix result XML missing for the pass.
122 FixResultXmlMissing {
123 pass: u32,
124 /// The invalid output attempt count.
125 attempt: u32,
126 /// Detailed error message from file read failure (if not `NotFound`).
127 ///
128 /// This field is populated when the file exists but cannot be read
129 /// (e.g., permission denied, I/O error). It's None for simple `NotFound`.
130 error_detail: Option<String>,
131 },
132
133 /// Fix result XML validated for a pass.
134 FixResultXmlValidated {
135 pass: u32,
136 status: crate::reducer::state::FixStatus,
137 summary: Option<String>,
138 },
139
140 /// Fix result XML cleaned before invoking the fix agent.
141 FixResultXmlCleaned {
142 pass: u32,
143 },
144
145 /// Fix outcome applied for a pass.
146 FixOutcomeApplied {
147 pass: u32,
148 },
149
150 FixResultXmlArchived {
151 pass: u32,
152 },
153 /// A review pass completed with results.
154 Completed {
155 /// The pass number that completed.
156 pass: u32,
157 /// Whether issues were found requiring fixes.
158 issues_found: bool,
159 },
160 /// A fix attempt for issues has started.
161 FixAttemptStarted {
162 /// The pass number this fix is for.
163 pass: u32,
164 },
165 /// A fix attempt completed.
166 FixAttemptCompleted {
167 /// The pass number this fix was for.
168 pass: u32,
169 /// Whether changes were made.
170 changes_made: bool,
171 },
172 /// Review phase completed, all passes done.
173 PhaseCompleted {
174 /// Whether the phase exited early (before all passes).
175 early_exit: bool,
176 },
177 /// Review pass found no issues - clean exit.
178 ///
179 /// Emitted when a review pass completes with no issues found.
180 /// This is distinct from `Completed { issues_found: false }` in that
181 /// it explicitly signals a clean pass for UI/logging purposes.
182 PassCompletedClean {
183 /// The pass number that completed.
184 pass: u32,
185 },
186 /// Review output validation failed (XSD/XML parsing error).
187 ///
188 /// Emitted when review output cannot be parsed. Reducer decides
189 /// whether to retry or switch agents.
190 ///
191 /// The `error_detail` field contains the formatted validation error that will
192 /// be shown to the agent in the XSD retry prompt. This error should be
193 /// actionable and guide the agent toward producing valid XML.
194 OutputValidationFailed {
195 /// The pass number.
196 pass: u32,
197 /// Current invalid output attempt number.
198 attempt: u32,
199 /// Detailed error message from XSD validation, formatted for AI retry.
200 ///
201 /// This is the output of `XsdValidationError::format_for_ai_retry()` and
202 /// includes:
203 /// - Error type and location
204 /// - What was expected vs. what was found
205 /// - Actionable suggestions for fixing
206 /// - Examples of correct format
207 error_detail: Option<String>,
208 },
209
210 /// Fix attempt completed with incomplete status, needs continuation.
211 ///
212 /// Emitted when fix output is valid XML but indicates work is not complete
213 /// (status is "`issues_remain`"). Triggers a continuation with new session.
214 FixContinuationTriggered {
215 /// The pass number this fix was for.
216 pass: u32,
217 /// Status from the agent (typically `IssuesRemain`).
218 status: crate::reducer::state::FixStatus,
219 /// Summary of what was accomplished.
220 summary: Option<String>,
221 },
222
223 /// Fix continuation succeeded after multiple attempts.
224 ///
225 /// Emitted when a fix continuation finally reaches a complete state
226 /// (`all_issues_addressed` or `no_issues_found`).
227 FixContinuationSucceeded {
228 /// The pass number this fix was for.
229 pass: u32,
230 /// Total number of continuation attempts it took.
231 ///
232 /// Note: This field is not used by the reducer for state transitions, but
233 /// is kept for observability (event logs, checkpoint serialization, debugging).
234 total_attempts: u32,
235 },
236
237 /// Fix continuation budget exhausted.
238 ///
239 /// Emitted when fix continuations have been exhausted without reaching
240 /// a complete state. Policy decides whether to proceed to commit or abort.
241 FixContinuationBudgetExhausted {
242 /// The pass number this fix was for.
243 pass: u32,
244 /// Total number of continuation attempts made.
245 total_attempts: u32,
246 /// The last status received (typically `IssuesRemain`).
247 last_status: crate::reducer::state::FixStatus,
248 },
249
250 /// Fix output validation failed (XSD/XML parsing error).
251 ///
252 /// Emitted when fix output cannot be parsed. Reducer decides
253 /// whether to retry or switch agents.
254 FixOutputValidationFailed {
255 /// The pass number this fix was for.
256 pass: u32,
257 /// Current invalid output attempt number.
258 attempt: u32,
259 /// Detailed error message from XSD validation, formatted for AI retry.
260 ///
261 /// This is the output of `XsdValidationError::format_for_ai_retry()` and includes:
262 /// - Error type and location
263 /// - What was expected vs. what was found
264 /// - Actionable suggestions for fixing
265 /// - Examples of correct format
266 error_detail: Option<String>,
267 },
268}