Skip to main content

ralph_workflow/reducer/event/
lifecycle.rs

1//! Pipeline lifecycle events (start, stop, resume).
2//!
3//! These events control the overall pipeline execution lifecycle,
4//! distinct from phase-specific transitions.
5
6use serde::{Deserialize, Serialize};
7
8/// Pipeline lifecycle events (start, stop, resume).
9///
10/// These events control the overall pipeline execution lifecycle,
11/// distinct from phase-specific transitions. Use these for:
12///
13/// - Starting or resuming a pipeline run
14/// - Completing a successful pipeline execution
15///
16/// # When to Use
17///
18/// - `Started`: When a fresh pipeline run begins
19/// - `Resumed`: When resuming from a checkpoint
20/// - `Completed`: When all phases complete successfully
21///
22/// # ⚠️ FROZEN - DO NOT ADD VARIANTS ⚠️
23///
24/// This enum is **FROZEN**. Adding new variants is **PROHIBITED**.
25///
26/// ## Why is this frozen?
27///
28/// Lifecycle events control pipeline flow (start/stop/completion). Allowing effect
29/// handlers to emit new lifecycle events would violate the core architectural principle:
30/// **handlers describe what happened; reducers decide what happens next.**
31///
32/// ## What to do instead
33///
34/// If you need to express new observations or failures:
35///
36/// 1. **Reuse existing phase/category events** - Use `PlanningEvent`, `DevelopmentEvent`,
37///    `ReviewEvent`, `CommitEvent`, etc. to describe what happened within that phase.
38///    Example: `PlanningEvent::PlanXmlMissing` instead of creating a generic "Aborted" event.
39///
40/// 2. **Return errors from the event loop** - For truly unrecoverable failures (permission
41///    errors, invariant violations), return `Err` from the effect handler. The outer runner
42///    will handle termination, not the reducer.
43///
44/// 3. **Handle in orchestration** - Some conditions don't need events at all and can be
45///    handled in the effect handler or runner logic.
46///
47/// ## Enforcement
48///
49/// The freeze policy is enforced by the `lifecycle_event_is_frozen` test in the parent module,
50/// which will fail to compile if new variants are added. This is intentional.
51#[derive(Clone, Serialize, Deserialize, Debug)]
52pub enum LifecycleEvent {
53    /// Pipeline execution started fresh (not from checkpoint).
54    Started,
55    /// Pipeline execution resumed from a previous state.
56    Resumed {
57        /// Whether this resume is from a persisted checkpoint.
58        from_checkpoint: bool,
59    },
60    /// Pipeline execution completed successfully.
61    Completed,
62    /// Gitignore entries ensured in the repository.
63    GitignoreEntriesEnsured {
64        /// Entries that were added to .gitignore.
65        added: Vec<String>,
66        /// Entries that were already present.
67        existing: Vec<String>,
68        /// Whether .gitignore was created.
69        created: bool,
70    },
71}