Skip to main content

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}