Skip to main content

ralph/
constants.rs

1//! Centralized constants for the Ralph CLI.
2//!
3//! This module consolidates all magic numbers, limits, and default values
4//! to improve maintainability and prevent drift between duplicated values.
5//!
6//! Responsibilities:
7//! - Provide a single source of truth for compile-time constants.
8//! - Organize constants by domain (buffers, limits, timeouts, UI, etc.).
9//! - Prevent accidental drift between duplicated constant definitions.
10//!
11//! Not handled here:
12//! - Runtime configuration values (see `crate::config`).
13//! - User-customizable thresholds (see `crate::contracts::Config`).
14//!
15//! Invariants/assumptions:
16//! - All constants are `pub` within their submodule; visibility is controlled by module exports.
17//! - Constants that appear in multiple places must be defined here and imported elsewhere.
18
19/// Buffer size limits for output handling and memory management.
20pub mod buffers {
21    /// Maximum size for ANSI buffer (10MB).
22    /// Reduced from 100MB to prevent memory pressure during runner execution.
23    pub const MAX_ANSI_BUFFER_SIZE: usize = 10 * 1024 * 1024;
24
25    /// Maximum line length before truncation (10MB).
26    /// Reduced from 100MB to prevent memory pressure with runaway runner output.
27    pub const MAX_LINE_LENGTH: usize = 10 * 1024 * 1024;
28
29    /// Maximum buffer size for stream processing (10MB).
30    /// Reduced from 100MB to prevent memory pressure during long-running tasks.
31    pub const MAX_BUFFER_SIZE: usize = 10 * 1024 * 1024;
32
33    /// Maximum log lines to retain for interactive log viewers.
34    pub const MAX_LOG_LINES: usize = 10_000;
35
36    /// Maximum tool value length before truncation.
37    pub const TOOL_VALUE_MAX_LEN: usize = 160;
38
39    /// Maximum instruction file size (128KB).
40    pub const MAX_INSTRUCTION_BYTES: usize = 128 * 1024;
41
42    /// Maximum stdout capture size for timeouts (128KB).
43    pub const TIMEOUT_STDOUT_CAPTURE_MAX_BYTES: usize = 128 * 1024;
44
45    /// Maximum bounded capture size for managed subprocess stdout/stderr tails.
46    pub const MANAGED_SUBPROCESS_CAPTURE_MAX_BYTES: usize = 256 * 1024;
47
48    /// Maximum bounded capture size for CI gate stdout/stderr tails.
49    pub const MANAGED_SUBPROCESS_CI_CAPTURE_MAX_BYTES: usize = 4 * 1024 * 1024;
50
51    /// Number of output tail lines to display.
52    pub const OUTPUT_TAIL_LINES: usize = 20;
53
54    /// Maximum characters per output tail line.
55    pub const OUTPUT_TAIL_LINE_MAX_CHARS: usize = 200;
56}
57
58/// Operational limits and thresholds.
59pub mod limits {
60    /// Auto-retry limit for CI gate failures.
61    pub const CI_GATE_AUTO_RETRY_LIMIT: u8 = 10;
62
63    /// Maximum automatic recovery attempts after runner signal termination.
64    pub const MAX_SIGNAL_RESUMES: u8 = 5;
65
66    /// Number of consecutive CI failures with the same error pattern before escalation.
67    /// After this many identical failures, Ralph stops retrying and requires intervention.
68    pub const CI_FAILURE_ESCALATION_THRESHOLD: u8 = 3;
69
70    /// Maximum consecutive failures before aborting run loop.
71    pub const MAX_CONSECUTIVE_FAILURES: u32 = 50;
72
73    /// Maximum IDs to generate per invocation.
74    pub const MAX_COUNT: usize = 100;
75
76    /// Maximum lock cleanup retry attempts.
77    pub const MAX_RETRIES: u32 = 3;
78
79    /// Minimum environment variable value length for redaction.
80    pub const MIN_ENV_VALUE_LEN: usize = 6;
81
82    /// Default queue file size warning threshold (KB).
83    pub const DEFAULT_SIZE_WARNING_THRESHOLD_KB: u32 = 500;
84
85    /// Default task count warning threshold.
86    pub const DEFAULT_TASK_COUNT_WARNING_THRESHOLD: u32 = 500;
87
88    /// Maximum LFS pointer file size (bytes).
89    pub const MAX_POINTER_SIZE: u64 = 1024;
90
91    /// Maximum number of queue backup files to retain in `.ralph/cache`.
92    pub const MAX_QUEUE_BACKUP_FILES: usize = 50;
93
94    /// Maximum number of undo snapshots to retain in `.ralph/cache/undo`.
95    pub const MAX_UNDO_SNAPSHOTS: usize = 20;
96}
97
98/// Timeout and interval durations.
99pub mod timeouts {
100    use std::time::Duration;
101
102    /// Default session timeout in hours.
103    pub const DEFAULT_SESSION_TIMEOUT_HOURS: u64 = 24;
104
105    /// Spinner animation update interval in milliseconds.
106    pub const SPINNER_UPDATE_INTERVAL_MS: u64 = 80;
107
108    /// Temporary file retention period (7 days).
109    ///
110    /// Files older than this are cleaned up:
111    /// - On CLI startup (main.rs)
112    /// - When building runner commands (with_temp_prompt_file)
113    /// - When running `ralph cleanup` command
114    ///
115    /// Default: 7 days. This balances keeping safeguard dumps available for
116    /// debugging against preventing indefinite accumulation.
117    pub const TEMP_RETENTION: Duration = Duration::from_secs(60 * 60 * 24 * 7);
118
119    /// Lock cleanup retry delays in milliseconds.
120    pub const DELAYS_MS: [u64; 3] = [10, 50, 100];
121
122    /// Managed subprocess timeout for short probes (doctor, availability checks).
123    pub const MANAGED_SUBPROCESS_PROBE_TIMEOUT: Duration = Duration::from_secs(15);
124
125    /// Managed subprocess timeout for short-lived metadata probes.
126    pub const MANAGED_SUBPROCESS_METADATA_TIMEOUT: Duration = Duration::from_secs(10);
127
128    /// Managed subprocess timeout for standard git operations.
129    pub const MANAGED_SUBPROCESS_GIT_TIMEOUT: Duration = Duration::from_secs(120);
130
131    /// Managed subprocess timeout for GitHub CLI operations.
132    pub const MANAGED_SUBPROCESS_GH_TIMEOUT: Duration = Duration::from_secs(180);
133
134    /// Managed subprocess timeout for processor plugin hooks.
135    pub const MANAGED_SUBPROCESS_PLUGIN_TIMEOUT: Duration = Duration::from_secs(300);
136
137    /// Managed subprocess timeout for app launches routed through platform launchers.
138    pub const MANAGED_SUBPROCESS_APP_LAUNCH_TIMEOUT: Duration = Duration::from_secs(20);
139
140    /// Managed subprocess timeout for notification media playback commands.
141    pub const MANAGED_SUBPROCESS_MEDIA_PLAYBACK_TIMEOUT: Duration = Duration::from_secs(20);
142
143    /// Managed subprocess timeout for CI gate execution.
144    pub const MANAGED_SUBPROCESS_CI_TIMEOUT: Duration = Duration::from_secs(60 * 30);
145
146    /// Grace period after SIGINT before escalating to SIGKILL for managed subprocesses.
147    pub const MANAGED_SUBPROCESS_INTERRUPT_GRACE: Duration = Duration::from_secs(2);
148
149    /// Polling cadence for managed subprocess wait loops.
150    pub const MANAGED_SUBPROCESS_POLL_INTERVAL: Duration = Duration::from_millis(50);
151
152    /// Best-effort reap timeout after a managed subprocess receives SIGKILL.
153    pub const MANAGED_SUBPROCESS_REAP_TIMEOUT: Duration = Duration::from_secs(5);
154
155    /// Polling cadence for cancellation-aware retry waits.
156    pub const MANAGED_RETRY_POLL_INTERVAL: Duration = Duration::from_millis(50);
157
158    /// How long terminal worker records are retained before stale pruning.
159    ///
160    /// This prevents immediate task reselection while avoiding permanent capacity blockers.
161    pub const PARALLEL_TERMINAL_WORKER_TTL: Duration =
162        Duration::from_secs(60 * 60 * DEFAULT_SESSION_TIMEOUT_HOURS);
163}
164
165/// UI layout and dimension constants.
166pub mod ui {
167    /// Threshold for narrow layout mode.
168    pub const NARROW_LAYOUT_WIDTH: u16 = 90;
169
170    /// Minimum width for board view.
171    pub const BOARD_MIN_WIDTH: u16 = 100;
172
173    /// Gutter width between columns.
174    pub const COLUMN_GUTTER: u16 = 1;
175
176    /// Number of task builder fields.
177    pub const TASK_BUILDER_FIELD_COUNT: usize = 7;
178}
179
180/// Queue configuration constants.
181pub mod queue {
182    /// Default queue ID prefix.
183    pub const DEFAULT_ID_PREFIX: &str = "RQ";
184
185    /// Default queue file path (relative to repo root).
186    pub const DEFAULT_QUEUE_FILE: &str = ".ralph/queue.jsonc";
187
188    /// Default done file path (relative to repo root).
189    pub const DEFAULT_DONE_FILE: &str = ".ralph/done.jsonc";
190
191    /// Default config file path (relative to repo root).
192    pub const DEFAULT_CONFIG_FILE: &str = ".ralph/config.jsonc";
193
194    /// Default maximum dependency depth.
195    pub const DEFAULT_MAX_DEPENDENCY_DEPTH: u8 = 10;
196
197    /// Aging threshold: warning days (low priority).
198    pub const AGING_WARNING_DAYS: u32 = 7;
199
200    /// Aging threshold: stale days (medium priority).
201    pub const AGING_STALE_DAYS: u32 = 14;
202
203    /// Aging threshold: rotten days (high priority).
204    pub const AGING_ROTTEN_DAYS: u32 = 30;
205}
206
207/// Git-related constants.
208pub mod git {
209    /// Default branch prefix for parallel execution.
210    pub const DEFAULT_BRANCH_PREFIX: &str = "ralph/";
211
212    /// Sample task ID for branch validation.
213    pub const SAMPLE_TASK_ID: &str = "RQ-0001";
214}
215
216/// Runner-related constants.
217pub mod runner {
218    /// Default CI gate command.
219    pub const DEFAULT_CI_GATE_COMMAND: &str = "make ci";
220
221    /// Supported phase values (1-3).
222    pub const MIN_PHASES: u8 = 1;
223    pub const MAX_PHASES: u8 = 3;
224
225    /// Minimum iterations value.
226    pub const MIN_ITERATIONS: u8 = 1;
227    pub const MIN_ITERATIONS_U32: u32 = 1;
228
229    /// Minimum workers for parallel execution.
230    pub const MIN_PARALLEL_WORKERS: u8 = 2;
231
232    /// Minimum merge retries.
233    pub const MIN_MERGE_RETRIES: u8 = 1;
234}
235
236/// File paths and directory names.
237pub mod paths {
238    /// Session state filename.
239    pub const SESSION_FILENAME: &str = "session.jsonc";
240
241    /// Stop signal filename.
242    pub const STOP_SIGNAL_FILE: &str = "stop_requested";
243
244    /// Migration history file path.
245    pub const MIGRATION_HISTORY_PATH: &str = ".ralph/cache/migrations.jsonc";
246
247    /// Productivity stats filename.
248    pub const STATS_FILENAME: &str = "productivity.jsonc";
249
250    /// Ralph temp directory name.
251    pub const RALPH_TEMP_DIR_NAME: &str = "ralph";
252
253    /// Legacy prompt temp file prefix.
254    pub const LEGACY_PROMPT_PREFIX: &str = "ralph_prompt_";
255
256    /// Ralph temp file prefix.
257    pub const RALPH_TEMP_PREFIX: &str = "ralph_";
258
259    /// Worker prompt override path.
260    pub const WORKER_OVERRIDE_PATH: &str = ".ralph/prompts/worker.md";
261
262    /// Scan prompt override path.
263    pub const SCAN_OVERRIDE_PATH: &str = ".ralph/prompts/scan.md";
264
265    /// Task builder prompt override path.
266    pub const TASK_BUILDER_OVERRIDE_PATH: &str = ".ralph/prompts/task_builder.md";
267
268    /// Environment variable for raw dump mode.
269    pub const ENV_RAW_DUMP: &str = "RALPH_RAW_DUMP";
270
271    /// Environment variable for the runner actually used (set by Ralph when spawning runners).
272    /// Used for analytics tracking in task custom fields.
273    pub const ENV_RUNNER_USED: &str = "RALPH_RUNNER_USED";
274
275    /// Environment variable for the model actually used (set by Ralph when spawning runners).
276    /// Used for analytics tracking in task custom fields.
277    pub const ENV_MODEL_USED: &str = "RALPH_MODEL_USED";
278}
279
280/// Version constants for schemas and templates.
281pub mod versions {
282    /// README template version.
283    pub const README_VERSION: u32 = 7;
284
285    /// Session state schema version.
286    pub const SESSION_STATE_VERSION: u32 = 1;
287
288    /// Migration history schema version.
289    pub const HISTORY_VERSION: u32 = 1;
290
291    /// Productivity stats schema version.
292    pub const STATS_SCHEMA_VERSION: u32 = 1;
293
294    /// Execution history schema version.
295    pub const EXECUTION_HISTORY_VERSION: u32 = 1;
296
297    /// Template version string.
298    pub const TEMPLATE_VERSION: &str = "1.0.0";
299}
300
301/// Default values for models and configuration.
302pub mod defaults {
303    /// Default Gemini model name.
304    pub const DEFAULT_GEMINI_MODEL: &str = "gemini-3-flash-preview";
305
306    /// Default Claude model name.
307    pub const DEFAULT_CLAUDE_MODEL: &str = "sonnet";
308
309    /// Default Cursor model name.
310    pub const DEFAULT_CURSOR_MODEL: &str = "auto";
311
312    /// Opencode prompt file message.
313    pub const OPENCODE_PROMPT_FILE_MESSAGE: &str = "Follow the attached prompt file verbatim.";
314
315    /// Fallback message for Phase 2 final response.
316    pub const PHASE2_FINAL_RESPONSE_FALLBACK: &str = "(Phase 2 final response unavailable.)";
317
318    /// Git LFS pointer file prefix.
319    pub const LFS_POINTER_PREFIX: &str = "version https://git-lfs.github.com/spec/v1";
320
321    /// Redaction placeholder text.
322    pub const REDACTED: &str = "[REDACTED]";
323
324    /// Sentinel RFC3339 timestamp used only when formatting "now" fails.
325    ///
326    /// This value is intentionally "obviously wrong" in modern persisted data so
327    /// fallback usage is detectable during debugging/audits.
328    pub const FALLBACK_RFC3339: &str = "1970-01-01T00:00:00.000000000Z";
329
330    /// Default task ID width.
331    pub const DEFAULT_ID_WIDTH: usize = 4;
332}
333
334/// UI symbols and emoji.
335pub mod symbols {
336    /// Celebration sparkles emoji.
337    pub const SPARKLES: &str = "✨";
338
339    /// Streak fire emoji.
340    pub const FIRE: &str = "🔥";
341
342    /// Achievement star emoji.
343    pub const STAR: &str = "⭐";
344
345    /// Completion checkmark.
346    pub const CHECKMARK: &str = "✓";
347}
348
349/// Spinner animation frames.
350pub mod spinners {
351    /// Default braille spinner frames.
352    pub const DEFAULT_SPINNER_FRAMES: &[&str] = &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
353}
354
355/// Milestone and achievement thresholds.
356pub mod milestones {
357    /// Task count milestones for achievements.
358    pub const MILESTONE_THRESHOLDS: &[u64] = &[10, 50, 100, 250, 500, 1000, 2500, 5000];
359}
360
361/// AGENTS.md section requirements.
362pub mod agents_md {
363    /// Required sections in AGENTS.md.
364    pub const REQUIRED_SECTIONS: &[&str] =
365        &["Non-Negotiables", "Repository Map", "Build, Test, and CI"];
366
367    /// Recommended sections for a complete AGENTS.md.
368    pub const RECOMMENDED_SECTIONS: &[&str] = &[
369        "Non-Negotiables",
370        "Repository Map",
371        "Build, Test, and CI",
372        "Testing",
373        "Workflow Contracts",
374        "Configuration",
375        "Git Hygiene",
376        "Documentation Maintenance",
377        "Troubleshooting",
378    ];
379}
380
381/// Custom field keys for analytics/observability data.
382pub mod custom_fields {
383    /// Key for the runner actually used (observational, not intent).
384    pub const RUNNER_USED: &str = "runner_used";
385
386    /// Key for the model actually used (observational, not intent).
387    pub const MODEL_USED: &str = "model_used";
388}
389
390/// Error message templates for consistent error formatting.
391pub mod error_messages {
392    /// Config update instruction suffix.
393    pub const CONFIG_UPDATE_INSTRUCTION: &str = "Update .ralph/config.jsonc";
394
395    /// Template for invalid config value errors.
396    pub fn invalid_config_value(
397        field: &str,
398        value: impl std::fmt::Display,
399        reason: &str,
400    ) -> String {
401        format!("Invalid {field}: {value}. {reason}. Update .ralph/config.jsonc.")
402    }
403}
404
405/// Status classification keywords for theme/styling.
406pub mod status_keywords {
407    /// Keywords indicating error status.
408    pub const ERROR: &[&str] = &[
409        "error", "fail", "failed", "denied", "timeout", "cancel", "canceled",
410    ];
411
412    /// Keywords indicating in-progress/warning status.
413    pub const IN_PROGRESS: &[&str] = &[
414        "running",
415        "started",
416        "pending",
417        "queued",
418        "in_progress",
419        "working",
420    ];
421
422    /// Keywords indicating success status.
423    pub const SUCCESS: &[&str] = &[
424        "completed",
425        "success",
426        "succeeded",
427        "ok",
428        "done",
429        "finished",
430    ];
431}