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 /// Per-rule template written to stdout. Tokens: {RESULT} {ID} {QUESTION} {CODE} {WHY} {CMD}.
59 #[arg(long, value_name = "TEMPLATE")]
60 pub emit_each: Option<String>,
61
62 /// Summary template written to stdout. Tokens: {RESULT} {OK} {ERRORS} {WARNED} {PENDING} {BROKEN} {SKIPPED} {TOTAL} {REASON}.
63 #[arg(long, alias = "emit-stdout", value_name = "TEMPLATE")]
64 pub emit: Option<String>,
65
66 /// Summary template written to stderr (same tokens as --emit).
67 #[arg(long, value_name = "TEMPLATE")]
68 pub emit_stderr: Option<String>,
69
70 /// Default per-rule bound in seconds (fractional allowed); a rule's own timeout field overrides it. A timed-out probe is BROKEN.
71 #[arg(long, value_name = "SECS")]
72 pub timeout: Option<f64>,
73
74 #[command(flatten)]
75 pub heartbeat: HeartbeatOpts,
76
77 /// Print agent usage docs (md or json) and exit.
78 #[arg(long, value_enum, num_args = 0..=1, default_missing_value = "md")]
79 pub explain: Option<Format>,
80}