Skip to main content

ralph_workflow/reducer/state/pipeline/
prompt_permissions.rs

1//! PROMPT.md permission lifecycle tracking.
2//!
3//! This state tracks the permission protection lifecycle for PROMPT.md:
4//! - Locked at pipeline start (best-effort read-only)
5//! - Restored on all graceful termination paths (success and failure)
6//!
7//! # Cleanup Guarantees
8//!
9//! Multiple safety layers ensure PROMPT.md is restored to writable state:
10//!
11//! 1. **Reducer-driven (normal path)**: `Effect::RestorePromptPermissions` during
12//!    Finalizing phase or on interrupt (Ctrl+C or programmatic). Note: On interrupt,
13//!    restoration is attempted unconditionally regardless of `restore_needed` state,
14//!    since prior crashed runs may have left PROMPT.md read-only.
15//!
16//! 2. **RAII guard (panic/early return)**: `AgentPhaseGuard::drop()` restores
17//!    permissions even when the reducer event loop doesn't complete.
18//!
19//! 3. **Startup cleanup (SIGKILL/crash)**: On next Ralph run, startup code
20//!    restores PROMPT.md permissions from prior crashed runs.
21//!
22//! Note: SIGKILL and power loss cannot be intercepted; recovery happens on
23//! next startup.
24
25use serde::{Deserialize, Serialize};
26
27/// Tracks PROMPT.md permission lifecycle for reducer-driven protection.
28///
29/// # State Transitions
30///
31/// 1. **Startup**: `locked=false, restore_needed=false, restored=false`
32/// 2. **After `LockPromptPermissions` effect**: `locked=true, restore_needed=true`
33/// 3. **After `RestorePromptPermissions` effect**: `locked=false, restore_needed=false, restored=true`
34///
35/// # Resume Safety
36///
37/// All fields are checkpointed. On resume:
38/// - If locked but not restored, orchestration will derive `RestorePromptPermissions`
39/// - If already restored, no further action needed
40///
41/// This state is serialized in `PipelineCheckpoint.prompt_permissions` to ensure
42/// pending restores are honored after resume.
43#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
44pub struct PromptPermissionsState {
45    /// True if `LockPromptPermissions` effect has been attempted.
46    pub locked: bool,
47
48    /// True if restoration is needed (set when lock is attempted, even if it fails).
49    pub restore_needed: bool,
50
51    /// True if `RestorePromptPermissions` effect has completed.
52    pub restored: bool,
53
54    /// Warning message from last permission operation (for observability).
55    pub last_warning: Option<String>,
56}