spec_driven_docs/commands/
assess.rs1use crate::cli::assess::AssessArgs;
7use crate::context::AppContext;
8use crate::error::AppError;
9use crate::output;
10use crate::services::assess::assess;
11
12pub fn run(ctx: &AppContext, args: AssessArgs) -> Result<(), AppError> {
19 let target = if args.target.is_absolute() {
20 args.target
21 } else if args.target == "." {
22 ctx.cwd.clone()
23 } else {
24 return Err(AppError::Usage("target must be absolute or .".to_string()));
25 };
26 let report = assess(&target)?;
27 if args.json {
28 return output::json(&report);
29 }
30 output::line(format!(
31 "classification: {}",
32 report.classification.as_str()
33 ));
34 output::line(format!("instance: {}", report.instance.instance));
35 output::line(format!("doc roots: {}", join_or_none(&report.doc_roots)));
36 output::line(format!(
37 "populated doc roots: {}",
38 join_or_none(&report.populated_doc_roots)
39 ));
40 output::line(format!("document files: {}", report.documents.count));
41 output::line(format!(
42 "methodology markers: {}",
43 join_or_none(&report.methodology_markers)
44 ));
45 for (profile, existing) in &report.collisions {
46 output::line(format!("collisions ({profile}): {}", existing.len()));
47 }
48 Ok(())
49}
50
51fn join_or_none(items: &[String]) -> String {
52 if items.is_empty() {
53 "none".to_string()
54 } else {
55 items.join(", ")
56 }
57}