Skip to main content

ralph_workflow/config/
mod.rs

1//! Configuration Module
2//!
3//! Handles environment variables and configuration for Ralph.
4//!
5//! # Key Types
6//!
7//! - [`Config`] - Runtime configuration used during pipeline execution
8//! - [`Verbosity`] - Output verbosity levels (Quiet, Normal, Verbose, Full, Debug)
9//! - [`ReviewDepth`] - Review thoroughness (Standard, Comprehensive, Security, Incremental)
10//! - [`UnifiedConfig`] - Full configuration file representation
11//!
12//! # Configuration Sources
13//!
14//! Ralph configuration is loaded from (in order of priority):
15//!
16//! 1. `~/.config/ralph-workflow.toml` (primary, unified config)
17//! 2. Environment variables (`RALPH_*`) as overrides
18//! 3. CLI arguments (final override)
19//!
20//! # Module Structure
21//!
22//! - [`types`] - Core configuration types (Config, ReviewDepth, Verbosity)
23//! - [`truncation`] - Truncation limits for verbosity levels
24//! - [`parser`] - Environment variable parsing (legacy)
25//! - [`unified`] - Unified configuration format types
26//! - [`loader`] - Unified configuration loader with env overrides
27//! - [`path_resolver`] - Configuration path resolution with dependency injection
28
29pub mod loader;
30pub mod parser;
31pub mod path_resolver;
32pub mod truncation;
33pub mod types;
34pub mod unified;
35
36// Re-export main types at module level for convenience
37pub use types::{Config, ReviewDepth, Verbosity};
38
39// Re-export unified config types for --init-global handling
40pub use unified::{
41    unified_config_path, CcsAliasConfig, CcsConfig, ConfigInitResult as UnifiedConfigInitResult,
42    UnifiedConfig,
43};
44
45// Re-export config environment types for dependency injection
46pub use path_resolver::{ConfigEnvironment, MemoryConfigEnvironment, RealConfigEnvironment};
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn test_verbosity_from_u8() {
54        assert_eq!(Verbosity::from(0), Verbosity::Quiet);
55        assert_eq!(Verbosity::from(1), Verbosity::Normal);
56        assert_eq!(Verbosity::from(2), Verbosity::Verbose);
57        assert_eq!(Verbosity::from(3), Verbosity::Full);
58        assert_eq!(Verbosity::from(4), Verbosity::Debug);
59        assert_eq!(Verbosity::from(100), Verbosity::Debug);
60    }
61
62    #[test]
63    fn test_truncate_limits() {
64        // Quiet has reduced limits
65        assert_eq!(Verbosity::Quiet.truncate_limit("text"), 80);
66        assert_eq!(Verbosity::Quiet.truncate_limit("tool_input"), 40);
67
68        // Normal has conservative limits for manageable output
69        assert_eq!(Verbosity::Normal.truncate_limit("text"), 1000);
70        assert_eq!(Verbosity::Normal.truncate_limit("tool_input"), 300);
71        assert_eq!(Verbosity::Normal.truncate_limit("tool_result"), 500);
72
73        // Verbose (default) has conservative limits for reasonable output
74        assert_eq!(Verbosity::Verbose.truncate_limit("text"), 2000);
75        assert_eq!(Verbosity::Verbose.truncate_limit("tool_input"), 300);
76        assert_eq!(Verbosity::Verbose.truncate_limit("tool_result"), 500);
77
78        // Full and Debug have unlimited
79        assert_eq!(Verbosity::Full.truncate_limit("text"), 999_999);
80        assert_eq!(Verbosity::Debug.truncate_limit("text"), 999_999);
81    }
82
83    #[test]
84    fn test_verbosity_helpers() {
85        assert!(!Verbosity::Quiet.is_debug());
86        assert!(!Verbosity::Normal.is_debug());
87        assert!(!Verbosity::Verbose.is_debug());
88        assert!(!Verbosity::Full.is_debug());
89        assert!(Verbosity::Debug.is_debug());
90
91        assert!(!Verbosity::Quiet.is_verbose());
92        assert!(!Verbosity::Normal.is_verbose());
93        assert!(Verbosity::Verbose.is_verbose());
94        assert!(Verbosity::Full.is_verbose());
95        assert!(Verbosity::Debug.is_verbose());
96
97        // show_tool_input: true for Normal and above, false for Quiet
98        assert!(!Verbosity::Quiet.show_tool_input());
99        assert!(Verbosity::Normal.show_tool_input());
100        assert!(Verbosity::Verbose.show_tool_input());
101        assert!(Verbosity::Full.show_tool_input());
102        assert!(Verbosity::Debug.show_tool_input());
103    }
104
105    #[test]
106    fn test_review_depth_from_str() {
107        // Standard aliases
108        assert_eq!(
109            ReviewDepth::from_str("standard"),
110            Some(ReviewDepth::Standard)
111        );
112        assert_eq!(
113            ReviewDepth::from_str("default"),
114            Some(ReviewDepth::Standard)
115        );
116        assert_eq!(ReviewDepth::from_str("normal"), Some(ReviewDepth::Standard));
117
118        // Comprehensive aliases
119        assert_eq!(
120            ReviewDepth::from_str("comprehensive"),
121            Some(ReviewDepth::Comprehensive)
122        );
123        assert_eq!(
124            ReviewDepth::from_str("thorough"),
125            Some(ReviewDepth::Comprehensive)
126        );
127        assert_eq!(
128            ReviewDepth::from_str("full"),
129            Some(ReviewDepth::Comprehensive)
130        );
131
132        // Security aliases
133        assert_eq!(
134            ReviewDepth::from_str("security"),
135            Some(ReviewDepth::Security)
136        );
137        assert_eq!(ReviewDepth::from_str("secure"), Some(ReviewDepth::Security));
138        assert_eq!(
139            ReviewDepth::from_str("security-focused"),
140            Some(ReviewDepth::Security)
141        );
142
143        // Incremental aliases
144        assert_eq!(
145            ReviewDepth::from_str("incremental"),
146            Some(ReviewDepth::Incremental)
147        );
148        assert_eq!(
149            ReviewDepth::from_str("diff"),
150            Some(ReviewDepth::Incremental)
151        );
152        assert_eq!(
153            ReviewDepth::from_str("changed"),
154            Some(ReviewDepth::Incremental)
155        );
156
157        // Case insensitivity
158        assert_eq!(
159            ReviewDepth::from_str("SECURITY"),
160            Some(ReviewDepth::Security)
161        );
162        assert_eq!(
163            ReviewDepth::from_str("Comprehensive"),
164            Some(ReviewDepth::Comprehensive)
165        );
166
167        // Invalid values
168        assert_eq!(ReviewDepth::from_str("invalid"), None);
169        assert_eq!(ReviewDepth::from_str(""), None);
170    }
171
172    #[test]
173    fn test_review_depth_default() {
174        assert_eq!(ReviewDepth::default(), ReviewDepth::Standard);
175    }
176
177    #[test]
178    fn test_review_depth_description() {
179        assert!(ReviewDepth::Standard.description().contains("Balanced"));
180        assert!(ReviewDepth::Comprehensive
181            .description()
182            .contains("In-depth"));
183        assert!(ReviewDepth::Security.description().contains("OWASP"));
184        assert!(ReviewDepth::Incremental.description().contains("git diff"));
185    }
186}