Skip to main content

ralph_workflow/cli/handlers/
dry_run.rs

1//! Dry run command handler.
2//!
3//! This module provides validation of Ralph setup without running any agents.
4
5use crate::checkpoint::{checkpoint_exists, load_checkpoint};
6use crate::config::Config;
7use crate::files::validate_prompt_md;
8use crate::language_detector::detect_stack_summary;
9use crate::logger::Logger;
10use std::path::Path;
11
12/// Handle --dry-run command.
13///
14/// Validates the setup without running any agents:
15/// - Checks PROMPT.md exists and has required sections
16/// - Validates agent configuration
17/// - Reports detected project stack
18/// - Shows checkpoint status if available
19///
20/// # Arguments
21///
22/// * `logger` - Logger for status output
23/// * `_colors` - Color configuration (unused but kept for API consistency)
24/// * `config` - The current Ralph configuration
25/// * `developer_agent` - Name of the developer agent
26/// * `reviewer_agent` - Name of the reviewer agent
27/// * `repo_root` - Path to the repository root
28///
29/// # Returns
30///
31/// Returns `Ok(())` if validation passes, or an error if PROMPT.md validation fails.
32pub fn handle_dry_run(
33    logger: &Logger,
34    _colors: crate::logger::Colors,
35    config: &Config,
36    developer_agent: &str,
37    reviewer_agent: &str,
38    repo_root: &Path,
39) -> anyhow::Result<()> {
40    logger.header("DRY RUN: Validation", crate::logger::Colors::cyan);
41
42    // Validate PROMPT.md using the utility function
43    // Dry run is non-interactive by definition
44    let validation = validate_prompt_md(config.behavior.strict_validation, false);
45
46    // Report errors first
47    for err in &validation.errors {
48        logger.error(err);
49    }
50
51    // Report warnings
52    for warn in &validation.warnings {
53        logger.warn(&format!("{warn} (recommended)"));
54    }
55
56    // Bail if validation failed
57    if !validation.is_valid() {
58        anyhow::bail!("Dry run failed: PROMPT.md validation errors");
59    }
60
61    // Report successes
62    if validation.has_goal {
63        logger.success("PROMPT.md has Goal section");
64    }
65    if validation.has_acceptance {
66        logger.success("PROMPT.md has acceptance checks section");
67    }
68    if validation.is_perfect() {
69        logger.success("PROMPT.md validation passed with no warnings");
70    }
71
72    logger.success(&format!("Developer agent: {developer_agent}"));
73    logger.success(&format!("Reviewer agent: {reviewer_agent}"));
74    logger.success(&format!("Developer iterations: {}", config.developer_iters));
75    logger.success(&format!("Reviewer passes: {}", config.reviewer_reviews));
76
77    // Check for checkpoint
78    if checkpoint_exists() {
79        logger.info("Checkpoint found - can resume with --resume");
80        if let Ok(Some(cp)) = load_checkpoint() {
81            logger.info(&format!("  Phase: {}", cp.phase));
82            logger.info(&format!("  Progress: {}", cp.description()));
83            logger.info(&format!("  Saved at: {}", cp.timestamp));
84        }
85    }
86
87    // Detect stack - use the convenience function for simple display
88    logger.success(&format!(
89        "Detected stack: {}",
90        detect_stack_summary(repo_root)
91    ));
92
93    logger.success("Dry run validation complete");
94    Ok(())
95}