Skip to main content

coding_tools/cli/
ct_check.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Jonathan Shook
3
4//! The `ct-check` command grammar (see [`crate::cli`]); the `ct-check` bin is a
5//! thin parse-and-dispatch wrapper over this `Cli`.
6
7use std::path::PathBuf;
8
9use clap::Parser;
10
11use crate::explain::Format;
12use crate::pattern;
13use crate::pulse::HeartbeatOpts;
14
15#[derive(Parser, Debug)]
16#[command(
17    name = "ct-check",
18    version,
19    about = "Verify the project's recorded invariants from .ct/rules.jsonc (read-only).",
20    long_about = "ct-check runs the rule store's probes in order and reports each rule as SUCCESS, \
21                  ERROR, WARN, PENDING, or BROKEN (also reachable as `ct check`). It never writes \
22                  anything; rules are recorded with ct-rules. See `ct-check --explain` for \
23                  agent-oriented documentation."
24)]
25pub struct Cli {
26    /// Rule store. Default: the nearest .ct/rules.jsonc walking upward from the current directory.
27    #[arg(long)]
28    pub file: Option<PathBuf>,
29
30    /// Select rules whose id matches (substring->glob->regex promoted, anchored).
31    #[arg(long)]
32    pub id: Option<String>,
33
34    /// Pin how --id is interpreted (promotion off): literal, glob, or regex.
35    #[arg(long, value_enum)]
36    pub mode: Option<pattern::Mode>,
37
38    /// Select rules carrying any of these tags (comma-separated).
39    #[arg(long, value_delimiter = ',')]
40    pub tag: Vec<String>,
41
42    /// Stop after the first enforced violation; remaining rules are reported as skipped.
43    #[arg(long)]
44    pub fail_fast: bool,
45
46    /// Print the selected rules (id, lanes, question, tags); run nothing.
47    #[arg(long)]
48    pub list: bool,
49
50    /// Suppress per-rule lines and the default summary.
51    #[arg(long)]
52    pub quiet: bool,
53
54    /// Emit a structured JSON result instead of text (overrides the emit templates).
55    #[arg(long)]
56    pub json: bool,
57
58    /// Like `--json`, but pretty-printed (indented).
59    #[arg(long)]
60    pub json_pretty: bool,
61
62    /// Per-rule template written to stdout. Tokens: {RESULT} {ID} {QUESTION} {CODE} {WHY} {CMD}.
63    #[arg(long, value_name = "TEMPLATE")]
64    pub emit_each: Option<String>,
65
66    /// Summary template written to stdout. Tokens: {RESULT} {OK} {ERRORS} {WARNED} {PENDING} {BROKEN} {SKIPPED} {TOTAL} {REASON}.
67    #[arg(long, alias = "emit-stdout", value_name = "TEMPLATE")]
68    pub emit: Option<String>,
69
70    /// Summary template written to stderr (same tokens as --emit).
71    #[arg(long, value_name = "TEMPLATE")]
72    pub emit_stderr: Option<String>,
73
74    /// Default per-rule bound in seconds (fractional allowed); a rule's own timeout field overrides it. A timed-out probe is BROKEN.
75    #[arg(long, value_name = "SECS")]
76    pub timeout: Option<f64>,
77
78    #[command(flatten)]
79    pub heartbeat: HeartbeatOpts,
80
81    /// Print agent usage docs (md or json) and exit.
82    #[arg(long, value_enum, num_args = 0..=1, default_missing_value = "md")]
83    pub explain: Option<Format>,
84}