Skip to main content

intent_engine/cli_handlers/
plan_command.rs

1use crate::backend::PlanBackend;
2use crate::error::Result;
3use crate::plan::PlanResult;
4
5/// Format and display the result of a plan execution.
6///
7/// The caller is responsible for:
8/// - Reading stdin and parsing JSON
9/// - Processing @file directives
10/// - Constructing the plan executor with appropriate project path / default parent
11/// - Executing the plan via `PlanBackend::execute`
12/// - Cleaning up included files
13///
14/// This function only handles the output formatting, which is shared across backends.
15pub fn print_plan_result(result: &PlanResult, format: &str) -> Result<()> {
16    if format == "json" {
17        println!("{}", serde_json::to_string_pretty(result)?);
18    } else if result.success {
19        println!("Plan executed successfully");
20        println!();
21        println!("Created: {} tasks", result.created_count);
22        println!("Updated: {} tasks", result.updated_count);
23        if result.deleted_count > 0 {
24            println!("Deleted: {} tasks", result.deleted_count);
25        }
26        if result.cascade_deleted_count > 0 {
27            println!("Cascade deleted: {} tasks", result.cascade_deleted_count);
28        }
29        println!("Dependencies: {}", result.dependency_count);
30        println!();
31        println!("Task ID mapping:");
32        for (name, id) in &result.task_id_map {
33            println!("  {} -> #{}", name, id);
34        }
35
36        if !result.warnings.is_empty() {
37            println!();
38            println!("Warnings:");
39            for warning in &result.warnings {
40                println!("  - {}", warning);
41            }
42        }
43
44        if let Some(focused) = &result.focused_task {
45            println!();
46            println!("Current focus:");
47            println!("  ID: {}", focused.task.id);
48            println!("  Name: {}", focused.task.name);
49            println!("  Status: {}", focused.task.status);
50            if let Some(parent_id) = focused.task.parent_id {
51                println!("  Parent: #{}", parent_id);
52            }
53            if let Some(priority) = focused.task.priority {
54                println!("  Priority: {}", priority);
55            }
56            if let Some(spec) = &focused.task.spec {
57                println!("  Spec: {}", spec);
58            }
59            println!("  Owner: {}", focused.task.owner);
60            if let Some(ts) = focused.task.first_todo_at {
61                println!("  First todo: {}", ts.format("%Y-%m-%d %H:%M:%S UTC"));
62            }
63            if let Some(ts) = focused.task.first_doing_at {
64                println!("  First doing: {}", ts.format("%Y-%m-%d %H:%M:%S UTC"));
65            }
66            if let Some(ts) = focused.task.first_done_at {
67                println!("  First done: {}", ts.format("%Y-%m-%d %H:%M:%S UTC"));
68            }
69
70            if let Some(events_summary) = &focused.events_summary {
71                println!();
72                println!("  Event history:");
73                println!("    Total events: {}", events_summary.total_count);
74                if !events_summary.recent_events.is_empty() {
75                    println!("    Recent:");
76                    for event in events_summary.recent_events.iter().take(3) {
77                        println!(
78                            "      [{}] {}: {}",
79                            event.log_type,
80                            event.timestamp.format("%Y-%m-%d %H:%M:%S"),
81                            event.discussion_data
82                        );
83                    }
84                }
85            }
86        }
87    } else {
88        eprintln!("Plan failed");
89        if let Some(error) = &result.error {
90            eprintln!("Error: {}", error);
91        }
92        std::process::exit(1);
93    }
94
95    Ok(())
96}
97
98/// Execute a plan and print the result.
99///
100/// Convenience function that combines execution and formatting.
101pub async fn execute_and_print(
102    plan_mgr: &impl PlanBackend,
103    request: &crate::plan::PlanRequest,
104    format: &str,
105) -> Result<PlanResult> {
106    let result = plan_mgr.execute(request).await?;
107    print_plan_result(&result, format)?;
108    Ok(result)
109}