use anyhow::Result;
use clap::Args;
use serde_json::Value;
use crate::config::Config;
#[derive(Debug, Args)]
pub struct WorkflowArgs {
#[arg(long, default_value = "20")]
pub last: usize,
#[arg(long)]
pub json: bool,
}
pub fn run(cfg: &Config, args: WorkflowArgs) -> Result<()> {
let dot_asd = cfg
.db_path
.parent()
.filter(|p| !p.as_os_str().is_empty())
.map(|p| p.join(".asd"))
.unwrap_or_else(|| std::path::PathBuf::from(".asd"));
let sessions_path = dot_asd.join("workflow-sessions.jsonl");
let raw = std::fs::read_to_string(&sessions_path).unwrap_or_default();
let mut sessions: Vec<Value> = raw
.lines()
.filter(|l| !l.trim().is_empty())
.filter_map(|l| serde_json::from_str(l).ok())
.collect();
sessions.reverse();
sessions.truncate(args.last);
if args.json {
let out = serde_json::json!({
"sessions": sessions,
"count": sessions.len(),
});
println!("{}", serde_json::to_string_pretty(&out)?);
return Ok(());
}
if sessions.is_empty() {
eprintln!("asd: no workflow sessions recorded yet — run `asd task-close` first");
return Ok(());
}
println!(
"{:<28} {:<22} {:<8} {:<6} {}",
"closed_at", "workflow_type", "ev_score", "syms", "missing_steps"
);
println!("{}", "-".repeat(90));
for s in &sessions {
let closed_at = s.get("closed_at").and_then(Value::as_str).unwrap_or("—");
let wf_type = s
.get("workflow_type")
.and_then(Value::as_str)
.unwrap_or("—");
let ev_score = s
.get("evidence_score")
.and_then(Value::as_f64)
.map(|f| format!("{:.2}", f))
.unwrap_or_else(|| "—".to_string());
let syms = s
.get("symbols_annotated")
.and_then(Value::as_u64)
.map(|n| n.to_string())
.unwrap_or_else(|| "—".to_string());
let missing = s
.get("missing_steps")
.and_then(Value::as_array)
.map(|arr| {
arr.iter()
.filter_map(Value::as_str)
.collect::<Vec<_>>()
.join(", ")
})
.unwrap_or_default();
let missing_display = if missing.is_empty() {
"—".to_string()
} else {
missing
};
let ts = if closed_at.len() > 27 {
&closed_at[..27]
} else {
closed_at
};
println!(
"{:<28} {:<22} {:<8} {:<6} {}",
ts, wf_type, ev_score, syms, missing_display
);
}
Ok(())
}