1use anyhow::Result;
2use colored::Colorize;
3use std::path::PathBuf;
4use std::process::Command;
5
6use crate::commands::helpers::flatten_all_tasks;
7use crate::storage::Storage;
8
9pub fn run(project_root: Option<PathBuf>) -> Result<()> {
10 let storage = Storage::new(project_root);
11
12 if !storage.is_initialized() {
13 println!("{}", "SCUD not initialized. Run: scud init".yellow());
14 return Ok(());
15 }
16
17 println!("{}", "SCUD Session Warmup".cyan().bold());
18 println!("{}", "=".repeat(50).dimmed());
19
20 let cwd = std::env::current_dir()?;
22 println!("\n{} {}", "Working directory:".bold(), cwd.display());
23
24 println!("\n{}", "Recent commits:".bold());
26 match Command::new("git")
27 .args(["log", "--oneline", "-5", "--no-decorate"])
28 .output()
29 {
30 Ok(output) if output.status.success() => {
31 let commits = String::from_utf8_lossy(&output.stdout);
32 if commits.trim().is_empty() {
33 println!(" {}", "(no commits yet)".dimmed());
34 } else {
35 for line in commits.lines() {
36 println!(" {}", line.dimmed());
37 }
38 }
39 }
40 _ => println!(" {}", "(not a git repository)".dimmed()),
41 }
42
43 println!("\n{}", "Task status:".bold());
45 match storage.get_active_group()? {
46 Some(tag) => {
47 println!(" Active tag: {}", tag.green());
48
49 if let Ok(phase) = storage.load_group(&tag) {
51 let stats = phase.get_stats();
52 println!(
53 " Progress: {}/{} tasks done ({}%)",
54 stats.done.to_string().green(),
55 stats.total,
56 if stats.total > 0 {
57 (stats.done * 100 / stats.total).to_string()
58 } else {
59 "0".to_string()
60 }
61 );
62 println!(
63 " Status: {} pending, {} in-progress, {} blocked",
64 stats.pending.to_string().yellow(),
65 stats.in_progress.to_string().cyan(),
66 stats.blocked.to_string().red()
67 );
68 }
69 }
70 None => {
71 println!(" {}", "No active tag set".yellow());
72 println!(" Run: scud tags <tag-name>");
73 }
74 }
75
76 println!("\n{}", "Current assignments:".bold());
78 let tasks = storage.load_tasks()?;
79 let mut found_assignments = false;
80
81 for (tag, phase) in &tasks {
82 for task in &phase.tasks {
83 if let Some(ref assigned_to) = task.assigned_to {
84 found_assignments = true;
85 let status_str = task.status.as_str();
86 println!(
87 " {} | {} | {} | {}",
88 tag.dimmed(),
89 task.id.cyan(),
90 assigned_to.yellow(),
91 status_str
92 );
93 }
94 }
95 }
96 if !found_assignments {
97 println!(" {}", "(no assignments)".dimmed());
98 }
99
100 println!("\n{}", "Next available task:".bold());
102 let all_tasks_flat = flatten_all_tasks(&tasks);
103 if let Some(tag) = storage.get_active_group()? {
104 if let Some(phase) = tasks.get(&tag) {
105 let available: Vec<_> = phase
106 .tasks
107 .iter()
108 .filter(|t| {
109 t.status == crate::models::TaskStatus::Pending
110 && t.has_dependencies_met_refs(&all_tasks_flat)
111 })
112 .collect();
113
114 if let Some(task) = available.first() {
115 println!(
116 " {} {} (complexity: {})",
117 task.id.cyan(),
118 task.title,
119 task.complexity
120 );
121 println!(" Run: {}", "scud set-status <task-id> in-progress".green());
122 } else if phase
123 .tasks
124 .iter()
125 .all(|t| t.status == crate::models::TaskStatus::Done)
126 {
127 println!(" {}", "All tasks complete!".green());
128 } else {
129 println!(" {}", "(no tasks available - check dependencies)".yellow());
130 }
131 }
132 } else {
133 println!(" {}", "(set active tag first)".dimmed());
134 }
135
136 println!("\n{}", "=".repeat(50).dimmed());
137 println!(
138 "Ready to work. Use {} to find your next task.",
139 "scud next".cyan()
140 );
141
142 Ok(())
143}