ralph_workflow/reducer/event/commit.rs
1//! Commit generation events.
2//!
3//! Events related to commit message generation, validation, and creation.
4
5use serde::{Deserialize, Serialize};
6
7/// Commit generation events.
8///
9/// Events related to commit message generation, validation, and creation.
10/// Commit generation occurs after development iterations and review fixes.
11///
12/// # State Machine
13///
14/// ```text
15/// NotStarted -> Generating -> Generated -> Committed
16/// | |
17/// +--> (retry) --+
18/// |
19/// +--> Skipped
20/// ```
21///
22/// # Emitted By
23///
24/// - Commit generation handlers in `handler/commit/`
25/// - Commit message validation handlers
26/// - Git commit handlers
27#[derive(Clone, Serialize, Deserialize, Debug)]
28pub enum CommitEvent {
29 /// Commit message generation started.
30 GenerationStarted,
31 /// Commit diff computed for commit generation.
32 ///
33 /// Emitted after preparing the diff that will be committed. The reducer
34 /// uses the `empty` flag to decide whether to skip commit creation.
35 DiffPrepared {
36 /// True when the diff is empty.
37 empty: bool,
38 /// Content identifier (sha256 hex) of the prepared diff content.
39 ///
40 /// This is used to guard against reusing stale materialized inputs when the
41 /// diff content changes across checkpoints or retries.
42 content_id_sha256: String,
43 },
44 /// Commit diff computation failed.
45 DiffFailed {
46 /// The error message for the diff failure.
47 error: String,
48 },
49 /// Commit diff is no longer available and must be recomputed.
50 ///
51 /// This is used for recoverability when `.agent/tmp` artifacts are cleaned between
52 /// checkpoints or when required diff files go missing during resume.
53 DiffInvalidated {
54 /// Reason for invalidation.
55 reason: String,
56 },
57 /// Commit prompt prepared for a commit attempt.
58 PromptPrepared {
59 /// The attempt number.
60 attempt: u32,
61 },
62 /// Commit agent invoked for a commit attempt.
63 AgentInvoked {
64 /// The attempt number.
65 attempt: u32,
66 },
67 /// Commit message XML extracted for a commit attempt.
68 CommitXmlExtracted {
69 /// The attempt number.
70 attempt: u32,
71 },
72 /// Commit message XML missing for a commit attempt.
73 CommitXmlMissing {
74 /// The attempt number.
75 attempt: u32,
76 },
77 /// Commit message XML validated successfully.
78 CommitXmlValidated {
79 /// The generated commit message.
80 message: String,
81 /// The attempt number.
82 attempt: u32,
83 /// Optional list of files to selectively commit.
84 ///
85 /// Empty means commit all changed files.
86 /// Defaults to empty for backward compatibility with old checkpoints.
87 #[serde(default)]
88 files: Vec<String>,
89 /// Files excluded from this commit with documented reasons.
90 ///
91 /// Audit/observability metadata only — does not affect commit execution.
92 /// Defaults to empty for backward compatibility with old checkpoints.
93 #[serde(default)]
94 excluded_files: Vec<crate::reducer::state::pipeline::ExcludedFile>,
95 },
96 /// Commit message XML validation failed.
97 CommitXmlValidationFailed {
98 /// The reason for validation failure.
99 reason: String,
100 /// The attempt number.
101 attempt: u32,
102 },
103 /// Commit message XML archived.
104 CommitXmlArchived {
105 /// The attempt number.
106 attempt: u32,
107 },
108 /// Commit message XML cleaned before invoking the commit agent.
109 CommitXmlCleaned {
110 /// The attempt number.
111 attempt: u32,
112 },
113 /// Commit message was generated.
114 MessageGenerated {
115 /// The generated commit message.
116 message: String,
117 /// The attempt number.
118 attempt: u32,
119 },
120 /// Commit message validation failed.
121 MessageValidationFailed {
122 /// The reason for validation failure.
123 reason: String,
124 /// The attempt number that failed.
125 attempt: u32,
126 },
127 /// Commit was created successfully.
128 Created {
129 /// The commit hash.
130 hash: String,
131 /// The commit message used.
132 message: String,
133 },
134
135 // === Cloud mode git remote operations (emitted only when cloud mode is enabled) ===
136 /// Git authentication configured successfully for remote operations.
137 GitAuthConfigured,
138
139 /// Push to remote completed successfully.
140 PushCompleted {
141 remote: String,
142 branch: String,
143 commit_sha: String,
144 },
145
146 /// Push to remote failed.
147 PushFailed {
148 remote: String,
149 branch: String,
150 error: String,
151 },
152
153 /// Pull request created successfully.
154 PullRequestCreated { url: String, number: u32 },
155
156 /// Pull request creation failed.
157 PullRequestFailed { error: String },
158 /// Commit generation failed completely.
159 GenerationFailed {
160 /// The reason for failure.
161 reason: String,
162 },
163 /// Commit was skipped (e.g., no changes to commit).
164 Skipped {
165 /// The reason for skipping.
166 reason: String,
167 },
168
169 /// Pre-termination commit safety check completed successfully.
170 ///
171 /// Emitted after `Effect::CheckUncommittedChangesBeforeTermination` when the
172 /// working directory is clean, allowing termination to proceed.
173 PreTerminationSafetyCheckPassed,
174
175 /// Pre-termination commit safety check detected uncommitted changes.
176 ///
177 /// This is not a terminal error: the reducer must route back through the
178 /// commit phase so the changes are committed (or explicitly skipped).
179 PreTerminationUncommittedChangesDetected {
180 /// Number of lines in `git status --porcelain` output.
181 file_count: usize,
182 },
183
184 /// Residual uncommitted files detected after a selective commit pass.
185 ///
186 /// When `pass == 1`, triggers an automatic second commit pass.
187 /// When `pass == 2`, the files are carried forward to the next cycle.
188 ResidualFilesFound {
189 /// Repo-relative paths of remaining dirty files.
190 files: Vec<String>,
191 /// Which pass just completed (1 = first pass, 2 = second pass).
192 pass: u8,
193 },
194
195 /// No residual uncommitted files detected after a commit pass.
196 ///
197 /// Pipeline may proceed normally; working tree is clean.
198 ResidualFilesNone,
199}