Skip to main content

agentstatedeveloper_cli/commands/
trust.rs

1//! `asd trust` — emit the State Trust Score for the current workspace.
2//!
3//! Quick machine-readable answer to: "Can I rely on ASD for this task?"
4//!
5//! # Output (JSON)
6//!
7//! ```json
8//! {
9//!   "score": 0.92,
10//!   "level": "high",
11//!   "reasons": ["fresh_index", "ledger_annotated", "sidecar_hydrated"],
12//!   "blocking": false,
13//!   "signals": { ... }
14//! }
15//! ```
16//!
17//! Exit code is 0 unless `--fail-blocked` is set and `blocking` is true.
18
19use anyhow::Result;
20use clap::Args;
21
22use agentstatedeveloper_core::compute_trust_score;
23
24use crate::config::Config;
25
26#[derive(Debug, Args)]
27pub struct TrustArgs {
28    /// Exit 1 when the trust score is in the "blocked" level.
29    /// Useful for CI pre-flight checks before expensive agent runs.
30    #[arg(long)]
31    pub fail_blocked: bool,
32
33    /// Suppress the human-readable summary and emit only the JSON object.
34    /// (JSON is always emitted; this suppresses the extra narrative line.)
35    #[arg(long)]
36    pub quiet: bool,
37}
38
39pub fn run(cfg: &Config, args: TrustArgs) -> Result<()> {
40    let trust = compute_trust_score(&cfg.db_path);
41
42    let json_str = serde_json::to_string_pretty(&trust.to_json())?;
43    println!("{json_str}");
44
45    if !args.quiet {
46        eprintln!(
47            "asd trust: {} ({:.0}%)  — {}",
48            trust.level.to_uppercase(),
49            trust.score * 100.0,
50            trust.reasons.join(", ")
51        );
52    }
53
54    if args.fail_blocked && trust.blocking {
55        std::process::exit(1);
56    }
57
58    Ok(())
59}