ralph-agent-loop 0.3.1

A Rust CLI for managing AI agent loops with a structured JSON task queue
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
//! Centralized constants for the Ralph CLI.
//!
//! This module consolidates all magic numbers, limits, and default values
//! to improve maintainability and prevent drift between duplicated values.
//!
//! Responsibilities:
//! - Provide a single source of truth for compile-time constants.
//! - Organize constants by domain (buffers, limits, timeouts, UI, etc.).
//! - Prevent accidental drift between duplicated constant definitions.
//!
//! Not handled here:
//! - Runtime configuration values (see `crate::config`).
//! - User-customizable thresholds (see `crate::contracts::Config`).
//!
//! Invariants/assumptions:
//! - All constants are `pub` within their submodule; visibility is controlled by module exports.
//! - Constants that appear in multiple places must be defined here and imported elsewhere.

/// Buffer size limits for output handling and memory management.
pub mod buffers {
    /// Maximum size for ANSI buffer (10MB).
    /// Reduced from 100MB to prevent memory pressure during runner execution.
    pub const MAX_ANSI_BUFFER_SIZE: usize = 10 * 1024 * 1024;

    /// Maximum line length before truncation (10MB).
    /// Reduced from 100MB to prevent memory pressure with runaway runner output.
    pub const MAX_LINE_LENGTH: usize = 10 * 1024 * 1024;

    /// Maximum buffer size for stream processing (10MB).
    /// Reduced from 100MB to prevent memory pressure during long-running tasks.
    pub const MAX_BUFFER_SIZE: usize = 10 * 1024 * 1024;

    /// Maximum log lines to retain for interactive log viewers.
    pub const MAX_LOG_LINES: usize = 10_000;

    /// Maximum tool value length before truncation.
    pub const TOOL_VALUE_MAX_LEN: usize = 160;

    /// Maximum instruction file size (128KB).
    pub const MAX_INSTRUCTION_BYTES: usize = 128 * 1024;

    /// Maximum stdout capture size for timeouts (128KB).
    pub const TIMEOUT_STDOUT_CAPTURE_MAX_BYTES: usize = 128 * 1024;

    /// Maximum bounded capture size for managed subprocess stdout/stderr tails.
    pub const MANAGED_SUBPROCESS_CAPTURE_MAX_BYTES: usize = 256 * 1024;

    /// Maximum bounded capture size for CI gate stdout/stderr tails.
    pub const MANAGED_SUBPROCESS_CI_CAPTURE_MAX_BYTES: usize = 4 * 1024 * 1024;

    /// Number of output tail lines to display.
    pub const OUTPUT_TAIL_LINES: usize = 20;

    /// Maximum characters per output tail line.
    pub const OUTPUT_TAIL_LINE_MAX_CHARS: usize = 200;
}

/// Operational limits and thresholds.
pub mod limits {
    /// Auto-retry limit for CI gate failures.
    pub const CI_GATE_AUTO_RETRY_LIMIT: u8 = 10;

    /// Maximum automatic recovery attempts after runner signal termination.
    pub const MAX_SIGNAL_RESUMES: u8 = 5;

    /// Number of consecutive CI failures with the same error pattern before escalation.
    /// After this many identical failures, Ralph stops retrying and requires intervention.
    pub const CI_FAILURE_ESCALATION_THRESHOLD: u8 = 3;

    /// Maximum consecutive failures before aborting run loop.
    pub const MAX_CONSECUTIVE_FAILURES: u32 = 50;

    /// Maximum IDs to generate per invocation.
    pub const MAX_COUNT: usize = 100;

    /// Maximum lock cleanup retry attempts.
    pub const MAX_RETRIES: u32 = 3;

    /// Minimum environment variable value length for redaction.
    pub const MIN_ENV_VALUE_LEN: usize = 6;

    /// Default queue file size warning threshold (KB).
    pub const DEFAULT_SIZE_WARNING_THRESHOLD_KB: u32 = 500;

    /// Default task count warning threshold.
    pub const DEFAULT_TASK_COUNT_WARNING_THRESHOLD: u32 = 500;

    /// Maximum LFS pointer file size (bytes).
    pub const MAX_POINTER_SIZE: u64 = 1024;

    /// Maximum number of queue backup files to retain in `.ralph/cache`.
    pub const MAX_QUEUE_BACKUP_FILES: usize = 50;

    /// Maximum number of undo snapshots to retain in `.ralph/cache/undo`.
    pub const MAX_UNDO_SNAPSHOTS: usize = 20;
}

/// Timeout and interval durations.
pub mod timeouts {
    use std::time::Duration;

    /// Default session timeout in hours.
    pub const DEFAULT_SESSION_TIMEOUT_HOURS: u64 = 24;

    /// Spinner animation update interval in milliseconds.
    pub const SPINNER_UPDATE_INTERVAL_MS: u64 = 80;

    /// Temporary file retention period (7 days).
    ///
    /// Files older than this are cleaned up:
    /// - On CLI startup (main.rs)
    /// - When building runner commands (with_temp_prompt_file)
    /// - When running `ralph cleanup` command
    ///
    /// Default: 7 days. This balances keeping safeguard dumps available for
    /// debugging against preventing indefinite accumulation.
    pub const TEMP_RETENTION: Duration = Duration::from_secs(60 * 60 * 24 * 7);

    /// Lock cleanup retry delays in milliseconds.
    pub const DELAYS_MS: [u64; 3] = [10, 50, 100];

    /// Managed subprocess timeout for short probes (doctor, availability checks).
    pub const MANAGED_SUBPROCESS_PROBE_TIMEOUT: Duration = Duration::from_secs(15);

    /// Managed subprocess timeout for short-lived metadata probes.
    pub const MANAGED_SUBPROCESS_METADATA_TIMEOUT: Duration = Duration::from_secs(10);

    /// Managed subprocess timeout for standard git operations.
    pub const MANAGED_SUBPROCESS_GIT_TIMEOUT: Duration = Duration::from_secs(120);

    /// Managed subprocess timeout for GitHub CLI operations.
    pub const MANAGED_SUBPROCESS_GH_TIMEOUT: Duration = Duration::from_secs(180);

    /// Managed subprocess timeout for processor plugin hooks.
    pub const MANAGED_SUBPROCESS_PLUGIN_TIMEOUT: Duration = Duration::from_secs(300);

    /// Managed subprocess timeout for app launches routed through platform launchers.
    pub const MANAGED_SUBPROCESS_APP_LAUNCH_TIMEOUT: Duration = Duration::from_secs(20);

    /// Managed subprocess timeout for notification media playback commands.
    pub const MANAGED_SUBPROCESS_MEDIA_PLAYBACK_TIMEOUT: Duration = Duration::from_secs(20);

    /// Managed subprocess timeout for CI gate execution.
    pub const MANAGED_SUBPROCESS_CI_TIMEOUT: Duration = Duration::from_secs(60 * 30);

    /// Grace period after SIGINT before escalating to SIGKILL for managed subprocesses.
    pub const MANAGED_SUBPROCESS_INTERRUPT_GRACE: Duration = Duration::from_secs(2);

    /// Polling cadence for managed subprocess wait loops.
    pub const MANAGED_SUBPROCESS_POLL_INTERVAL: Duration = Duration::from_millis(50);

    /// Best-effort reap timeout after a managed subprocess receives SIGKILL.
    pub const MANAGED_SUBPROCESS_REAP_TIMEOUT: Duration = Duration::from_secs(5);

    /// Polling cadence for cancellation-aware retry waits.
    pub const MANAGED_RETRY_POLL_INTERVAL: Duration = Duration::from_millis(50);

    /// How long terminal worker records are retained before stale pruning.
    ///
    /// This prevents immediate task reselection while avoiding permanent capacity blockers.
    pub const PARALLEL_TERMINAL_WORKER_TTL: Duration =
        Duration::from_secs(60 * 60 * DEFAULT_SESSION_TIMEOUT_HOURS);
}

/// UI layout and dimension constants.
pub mod ui {
    /// Threshold for narrow layout mode.
    pub const NARROW_LAYOUT_WIDTH: u16 = 90;

    /// Minimum width for board view.
    pub const BOARD_MIN_WIDTH: u16 = 100;

    /// Gutter width between columns.
    pub const COLUMN_GUTTER: u16 = 1;

    /// Number of task builder fields.
    pub const TASK_BUILDER_FIELD_COUNT: usize = 7;
}

/// Queue configuration constants.
pub mod queue {
    /// Default queue ID prefix.
    pub const DEFAULT_ID_PREFIX: &str = "RQ";

    /// Default queue file path (relative to repo root).
    pub const DEFAULT_QUEUE_FILE: &str = ".ralph/queue.jsonc";

    /// Default done file path (relative to repo root).
    pub const DEFAULT_DONE_FILE: &str = ".ralph/done.jsonc";

    /// Default config file path (relative to repo root).
    pub const DEFAULT_CONFIG_FILE: &str = ".ralph/config.jsonc";

    /// Default maximum dependency depth.
    pub const DEFAULT_MAX_DEPENDENCY_DEPTH: u8 = 10;

    /// Aging threshold: warning days (low priority).
    pub const AGING_WARNING_DAYS: u32 = 7;

    /// Aging threshold: stale days (medium priority).
    pub const AGING_STALE_DAYS: u32 = 14;

    /// Aging threshold: rotten days (high priority).
    pub const AGING_ROTTEN_DAYS: u32 = 30;
}

/// Git-related constants.
pub mod git {
    /// Default branch prefix for parallel execution.
    pub const DEFAULT_BRANCH_PREFIX: &str = "ralph/";

    /// Sample task ID for branch validation.
    pub const SAMPLE_TASK_ID: &str = "RQ-0001";
}

/// Runner-related constants.
pub mod runner {
    /// Default CI gate command.
    pub const DEFAULT_CI_GATE_COMMAND: &str = "make ci";

    /// Supported phase values (1-3).
    pub const MIN_PHASES: u8 = 1;
    pub const MAX_PHASES: u8 = 3;

    /// Minimum iterations value.
    pub const MIN_ITERATIONS: u8 = 1;
    pub const MIN_ITERATIONS_U32: u32 = 1;

    /// Minimum workers for parallel execution.
    pub const MIN_PARALLEL_WORKERS: u8 = 2;

    /// Minimum merge retries.
    pub const MIN_MERGE_RETRIES: u8 = 1;
}

/// File paths and directory names.
pub mod paths {
    /// Session state filename.
    pub const SESSION_FILENAME: &str = "session.jsonc";

    /// Stop signal filename.
    pub const STOP_SIGNAL_FILE: &str = "stop_requested";

    /// Migration history file path.
    pub const MIGRATION_HISTORY_PATH: &str = ".ralph/cache/migrations.jsonc";

    /// Productivity stats filename.
    pub const STATS_FILENAME: &str = "productivity.jsonc";

    /// Ralph temp directory name.
    pub const RALPH_TEMP_DIR_NAME: &str = "ralph";

    /// Legacy prompt temp file prefix.
    pub const LEGACY_PROMPT_PREFIX: &str = "ralph_prompt_";

    /// Ralph temp file prefix.
    pub const RALPH_TEMP_PREFIX: &str = "ralph_";

    /// Worker prompt override path.
    pub const WORKER_OVERRIDE_PATH: &str = ".ralph/prompts/worker.md";

    /// Scan prompt override path.
    pub const SCAN_OVERRIDE_PATH: &str = ".ralph/prompts/scan.md";

    /// Task builder prompt override path.
    pub const TASK_BUILDER_OVERRIDE_PATH: &str = ".ralph/prompts/task_builder.md";

    /// Environment variable for raw dump mode.
    pub const ENV_RAW_DUMP: &str = "RALPH_RAW_DUMP";

    /// Environment variable for the runner actually used (set by Ralph when spawning runners).
    /// Used for analytics tracking in task custom fields.
    pub const ENV_RUNNER_USED: &str = "RALPH_RUNNER_USED";

    /// Environment variable for the model actually used (set by Ralph when spawning runners).
    /// Used for analytics tracking in task custom fields.
    pub const ENV_MODEL_USED: &str = "RALPH_MODEL_USED";
}

/// Version constants for schemas and templates.
pub mod versions {
    /// README template version.
    pub const README_VERSION: u32 = 6;

    /// Session state schema version.
    pub const SESSION_STATE_VERSION: u32 = 1;

    /// Migration history schema version.
    pub const HISTORY_VERSION: u32 = 1;

    /// Productivity stats schema version.
    pub const STATS_SCHEMA_VERSION: u32 = 1;

    /// Execution history schema version.
    pub const EXECUTION_HISTORY_VERSION: u32 = 1;

    /// Template version string.
    pub const TEMPLATE_VERSION: &str = "1.0.0";
}

/// Default values for models and configuration.
pub mod defaults {
    /// Default Gemini model name.
    pub const DEFAULT_GEMINI_MODEL: &str = "gemini-3-flash-preview";

    /// Default Claude model name.
    pub const DEFAULT_CLAUDE_MODEL: &str = "sonnet";

    /// Default Cursor model name.
    pub const DEFAULT_CURSOR_MODEL: &str = "auto";

    /// Opencode prompt file message.
    pub const OPENCODE_PROMPT_FILE_MESSAGE: &str = "Follow the attached prompt file verbatim.";

    /// Fallback message for Phase 2 final response.
    pub const PHASE2_FINAL_RESPONSE_FALLBACK: &str = "(Phase 2 final response unavailable.)";

    /// Git LFS pointer file prefix.
    pub const LFS_POINTER_PREFIX: &str = "version https://git-lfs.github.com/spec/v1";

    /// Redaction placeholder text.
    pub const REDACTED: &str = "[REDACTED]";

    /// Sentinel RFC3339 timestamp used only when formatting "now" fails.
    ///
    /// This value is intentionally "obviously wrong" in modern persisted data so
    /// fallback usage is detectable during debugging/audits.
    pub const FALLBACK_RFC3339: &str = "1970-01-01T00:00:00.000000000Z";

    /// Default task ID width.
    pub const DEFAULT_ID_WIDTH: usize = 4;
}

/// UI symbols and emoji.
pub mod symbols {
    /// Celebration sparkles emoji.
    pub const SPARKLES: &str = "";

    /// Streak fire emoji.
    pub const FIRE: &str = "🔥";

    /// Achievement star emoji.
    pub const STAR: &str = "";

    /// Completion checkmark.
    pub const CHECKMARK: &str = "";
}

/// Spinner animation frames.
pub mod spinners {
    /// Default braille spinner frames.
    pub const DEFAULT_SPINNER_FRAMES: &[&str] = &["", "", "", "", "", "", "", "", "", ""];
}

/// Milestone and achievement thresholds.
pub mod milestones {
    /// Task count milestones for achievements.
    pub const MILESTONE_THRESHOLDS: &[u64] = &[10, 50, 100, 250, 500, 1000, 2500, 5000];
}

/// AGENTS.md section requirements.
pub mod agents_md {
    /// Required sections in AGENTS.md.
    pub const REQUIRED_SECTIONS: &[&str] =
        &["Non-Negotiables", "Repository Map", "Build, Test, and CI"];

    /// Recommended sections for a complete AGENTS.md.
    pub const RECOMMENDED_SECTIONS: &[&str] = &[
        "Non-Negotiables",
        "Repository Map",
        "Build, Test, and CI",
        "Testing",
        "Workflow Contracts",
        "Configuration",
        "Git Hygiene",
        "Documentation Maintenance",
        "Troubleshooting",
    ];
}

/// Custom field keys for analytics/observability data.
pub mod custom_fields {
    /// Key for the runner actually used (observational, not intent).
    pub const RUNNER_USED: &str = "runner_used";

    /// Key for the model actually used (observational, not intent).
    pub const MODEL_USED: &str = "model_used";
}

/// Error message templates for consistent error formatting.
pub mod error_messages {
    /// Config update instruction suffix.
    pub const CONFIG_UPDATE_INSTRUCTION: &str = "Update .ralph/config.jsonc";

    /// Template for invalid config value errors.
    pub fn invalid_config_value(
        field: &str,
        value: impl std::fmt::Display,
        reason: &str,
    ) -> String {
        format!("Invalid {field}: {value}. {reason}. Update .ralph/config.jsonc.")
    }
}

/// Status classification keywords for theme/styling.
pub mod status_keywords {
    /// Keywords indicating error status.
    pub const ERROR: &[&str] = &[
        "error", "fail", "failed", "denied", "timeout", "cancel", "canceled",
    ];

    /// Keywords indicating in-progress/warning status.
    pub const IN_PROGRESS: &[&str] = &[
        "running",
        "started",
        "pending",
        "queued",
        "in_progress",
        "working",
    ];

    /// Keywords indicating success status.
    pub const SUCCESS: &[&str] = &[
        "completed",
        "success",
        "succeeded",
        "ok",
        "done",
        "finished",
    ];
}