Skip to main content

mur_core/workflow/
shadow.rs

1//! Shadow mode utilities — pretty-print shadow execution plans.
2
3use crate::types::ExecutionResult;
4
5/// Format a shadow execution result for display.
6pub fn format_shadow_report(result: &ExecutionResult) -> String {
7    let mut lines = Vec::new();
8
9    lines.push(format!(
10        "🔮 Shadow Execution Plan — {}",
11        result.workflow_id
12    ));
13    lines.push(format!("   {} steps total\n", result.steps_total));
14
15    for (i, step) in result.step_results.iter().enumerate() {
16        let status = if step.success { "✅" } else { "❌" };
17        lines.push(format!("  {}  Step {}: {}", status, i + 1, step.step_name));
18        for line in step.output.lines() {
19            lines.push(format!("      {}", line));
20        }
21        lines.push(String::new());
22    }
23
24    if result.success {
25        lines.push("  ✅ All steps would succeed".into());
26    } else if let Some(ref err) = result.error {
27        lines.push(format!("  ❌ Would fail: {}", err));
28    }
29
30    lines.push(String::new());
31    lines.push("  Run without --shadow to execute for real.".into());
32
33    lines.join("\n")
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use crate::types::{ExecutionResult, StepResult};
40    use chrono::Utc;
41    use uuid::Uuid;
42
43    #[test]
44    fn test_format_shadow_report() {
45        let now = Utc::now();
46        let result = ExecutionResult {
47            execution_id: Uuid::new_v4(),
48            workflow_id: "test-wf".into(),
49            steps_completed: 2,
50            steps_total: 2,
51            success: true,
52            duration_ms: 0,
53            total_cost: 0.0,
54            step_results: vec![
55                StepResult {
56                    step_name: "check".into(),
57                    success: true,
58                    output: "[shadow] Would execute: echo hi".into(),
59                    duration_ms: 0,
60                    cost: 0.0,
61                    model_used: None,
62                    error: None,
63                },
64                StepResult {
65                    step_name: "deploy".into(),
66                    success: true,
67                    output: "[shadow] Would execute: deploy.sh".into(),
68                    duration_ms: 0,
69                    cost: 0.0,
70                    model_used: None,
71                    error: None,
72                },
73            ],
74            shadow: true,
75            error: None,
76            started_at: now,
77            finished_at: now,
78        };
79
80        let report = format_shadow_report(&result);
81        assert!(report.contains("Shadow Execution Plan"));
82        assert!(report.contains("check"));
83        assert!(report.contains("deploy"));
84        assert!(report.contains("All steps would succeed"));
85    }
86}