Skip to main content

scud/commands/weave/
explain.rs

1use anyhow::Result;
2use colored::Colorize;
3use std::path::PathBuf;
4
5use scud_core::weave::{Decision, Event};
6
7use super::check::{build_coordinator, core_storage};
8
9pub fn run(project_root: Option<PathBuf>, event_json: &str) -> Result<()> {
10    let storage = core_storage(project_root);
11    let event: Event = serde_json::from_str(event_json)
12        .map_err(|e| anyhow::anyhow!("Invalid event JSON: {}", e))?;
13
14    let (coord, _tag, _phase) = build_coordinator(&storage)?;
15
16    println!("{}", "Event:".blue().bold());
17    println!("  Kind:   {}", event.kind);
18    if let Some(ref agent) = event.agent {
19        println!("  Agent:  {}", agent);
20    }
21    if let Some(ref target) = event.target {
22        println!("  Target: {}", target);
23    }
24    if let Some(ref task_id) = event.task_id {
25        println!("  Task:   {}", task_id);
26    }
27    println!();
28
29    // Full evaluation including roles
30    let decision = coord.evaluate_full(&event);
31
32    match &decision {
33        Decision::Proceed => {
34            println!("{}", "PROCEED".green().bold());
35            println!("No b-threads blocked this event.");
36
37            // Show which threads were checked
38            let checked: Vec<_> = coord.threads.iter().filter(|t| t.enabled).collect();
39            if !checked.is_empty() {
40                println!("\n{}", "Threads evaluated:".dimmed());
41                for t in checked {
42                    println!("  {} {} - passed", t.id.cyan(), t.name);
43                }
44            }
45        }
46        Decision::Wait { reason, thread_id } => {
47            println!("{}", "WAIT".yellow().bold());
48            println!("Thread: {}", thread_id.cyan());
49            println!("Reason: {}", reason);
50            println!("\nThe prerequisite has not been satisfied yet.");
51        }
52        Decision::Blocked { reason, thread_id } => {
53            println!("{}", "BLOCKED".red().bold());
54            println!("Thread: {}", thread_id.cyan());
55            println!("Reason: {}", reason);
56
57            // Show lock details if relevant
58            if !coord.active_locks.is_empty() {
59                println!("\n{}", "Active locks:".dimmed());
60                for (key, lock) in &coord.active_locks {
61                    println!(
62                        "  {} -> {} (task: {})",
63                        key,
64                        lock.holder_agent,
65                        lock.task_id.as_deref().unwrap_or("-"),
66                    );
67                }
68            }
69        }
70    }
71
72    Ok(())
73}