//! Module: evidence::command
//!
//! Responsibility: build `canic evidence` Clap command definitions and usage text.
//! Does not own: command dispatch, option parsing, policy evaluation, or report rendering.
//! Boundary: passive CLI surface construction for evidence commands.
use crate::cli::clap::{passthrough_subcommand, render_usage, value_arg};
use clap::{ArgGroup, Command as ClapCommand};
use super::options::{EvidenceCompareFormat, EvidenceGateFormat};
pub(super) fn usage() -> String {
render_usage(evidence_command)
}
pub(super) fn compare_usage() -> String {
render_usage(evidence_compare_command)
}
pub(super) fn gate_usage() -> String {
render_usage(evidence_gate_command)
}
pub(super) fn evidence_command() -> ClapCommand {
ClapCommand::new("evidence")
.bin_name("canic evidence")
.about("Evaluate and compare stable Canic evidence envelopes")
.disable_help_flag(true)
.subcommand(passthrough_subcommand(
ClapCommand::new("gate")
.about("Evaluate one EvidenceEnvelopeV1 against a CI policy")
.disable_help_flag(true),
))
.subcommand(passthrough_subcommand(
ClapCommand::new("compare")
.about("Compare two EvidenceEnvelopeV1 JSON files")
.disable_help_flag(true),
))
}
pub(super) fn evidence_gate_command() -> ClapCommand {
ClapCommand::new("gate")
.bin_name("canic evidence gate")
.about("Evaluate one EvidenceEnvelopeV1 against a CI policy")
.disable_help_flag(true)
.arg(
value_arg("policy")
.long("policy")
.value_name("path")
.required(true),
)
.arg(
value_arg("envelope")
.long("envelope")
.value_name("path")
.required(false),
)
.arg(
value_arg("manifest")
.long("manifest")
.value_name("path")
.required(false),
)
.arg(
value_arg("format")
.long("format")
.value_name("text|json|envelope-json")
.default_value("text")
.value_parser(clap::value_parser!(EvidenceGateFormat)),
)
.arg(value_arg("output").long("output").value_name("path"))
.group(
ArgGroup::new("gate-input")
.args(["envelope", "manifest"])
.required(true)
.multiple(false),
)
.after_help(
"Examples:\n canic evidence gate --policy ci/canic-policy.toml --envelope artifacts/canic/build-provenance.json\n canic evidence gate --policy ci/canic-policy.toml --manifest ci/canic-evidence.toml --format json --output artifacts/canic/policy-gate-report.json\n\nReads exactly one policy file and either one existing EvidenceEnvelopeV1 or one project evidence manifest. The gate is passive: it does not run builds, deploy, discover live state, mutate inputs, or turn policy success into deployment truth.",
)
}
pub(super) fn evidence_compare_command() -> ClapCommand {
ClapCommand::new("compare")
.bin_name("canic evidence compare")
.about("Compare two EvidenceEnvelopeV1 JSON files")
.disable_help_flag(true)
.arg(
value_arg("left")
.long("left")
.value_name("file")
.required(true),
)
.arg(
value_arg("right")
.long("right")
.value_name("file")
.required(true),
)
.arg(
value_arg("format")
.long("format")
.value_name("text|json")
.default_value("text")
.value_parser(clap::value_parser!(EvidenceCompareFormat)),
)
.after_help(
"Compares stable envelope fields and ignores generated_at, canic_version, and the nested payload body. The payload_sha256 field is compared.",
)
}