memstead_cli/commands/
check.rs1use clap::Parser;
14use memstead_base::EntityId;
15use memstead_base::check::{CHECK_KINDS, CheckKind, VERDICTS, Verdict};
16use memstead_base::vcs::Actor;
17
18use crate::CliError;
19use crate::output::{ExitKind, print_json, print_markdown};
20use crate::setup::CliContext;
21
22#[derive(Parser, Debug)]
23pub struct Args {
24 pub id: String,
26
27 #[arg(long)]
30 pub verdict: String,
31
32 #[arg(long)]
35 pub method: Option<String>,
36
37 #[arg(long)]
44 pub kind: Option<String>,
45}
46
47pub fn run(ctx: &CliContext, args: Args) -> anyhow::Result<()> {
48 let Some(verdict) = Verdict::from_wire(&args.verdict) else {
49 return Err(CliError::new(
50 ExitKind::Validation,
51 "INVALID_VERDICT",
52 format!(
53 "unknown verdict {:?} — the vocabulary is: {}",
54 args.verdict,
55 VERDICTS.join(", ")
56 ),
57 )
58 .into());
59 };
60 let kind = match args.kind.as_deref() {
61 None => CheckKind::Verification,
62 Some(s) => CheckKind::from_wire(s).ok_or_else(|| {
63 CliError::new(
64 ExitKind::Validation,
65 "INVALID_CHECK_KIND",
66 format!(
67 "unknown check kind {s:?} — the vocabulary is: {}",
68 CHECK_KINDS.join(", ")
69 ),
70 )
71 })?,
72 };
73 let id = EntityId::canonical(&args.id);
74 let mut engine = ctx.cli_engine()?.into_base();
75 let client = crate::setup::cli_client_id();
76 let record = engine
77 .record_check(
78 id.mem(),
79 id.as_ref(),
80 verdict,
81 kind,
82 args.method.as_deref(),
83 Actor::Cli,
84 Some(&client),
85 )
86 .map_err(CliError::from_engine_op)?;
87 let (state, _) = match kind {
88 CheckKind::Verification => engine.entity_check_state(id.mem(), id.as_ref()),
89 CheckKind::Conformance => engine.entity_conformance_state(id.mem(), id.as_ref()),
90 }
91 .map_err(CliError::from_engine_op)?;
92 if ctx.json {
93 print_json(&serde_json::json!({
94 "entity": record.entity,
95 "verdict": record.verdict,
96 "check_state": state.as_str(),
97 "kind": record.kind.as_deref().unwrap_or("verification"),
98 "schema_ref": record.schema_ref,
99 "role": record.role,
100 "ts": record.ts,
101 "method": record.method,
102 }))?;
103 return Ok(());
104 }
105 print_markdown(&format!(
106 "Check recorded: `{}` — kind `{}`, verdict **{}**, state `{}` (role: {})",
107 record.entity,
108 record.kind.as_deref().unwrap_or("verification"),
109 record.verdict,
110 state.as_str(),
111 record.role
112 ));
113 Ok(())
114}