use crate::cli::diagnose::DiagnoseArgs;
use crate::cli::handlers::cache::CacheCommand;
use crate::cli::handlers::memory::MemoryCommand;
use crate::cli::{
AnalysisType, BigOOutputFormat, ComplexityOutputFormat, ComprehensiveOutputFormat,
ContextFormat, DagType, DeadCodeOutputFormat, DeepContextCacheStrategy, DeepContextDagType,
DeepContextOutputFormat, DefectPredictionOutputFormat, DemoProtocol, DuplicateOutputFormat,
DuplicateType, EnforceOutputFormat, EntropyOutputFormat, EntropySeverity, ExplainLevel,
GraphMetricType, GraphMetricsOutputFormat, IncrementalCoverageOutputFormat,
LintHotspotOutputFormat, MakefileOutputFormat, NameSimilarityOutputFormat, OutputFormat,
ProofAnnotationOutputFormat, PropertyTypeFilter, ProvabilityOutputFormat, QualityCheckType,
QualityGateOutputFormat, QualityProfile, RefactorAutoOutputFormat, RefactorDocsOutputFormat,
RefactorMode, RefactorOutputFormat, ReportOutputFormat, SatdOutputFormat, SatdSeverity,
SearchScope, SymbolTableOutputFormat, SymbolTypeFilter, TdgOutputFormat,
VerificationMethodFilter, WasmOutputFormat,
};
use crate::models::churn::ChurnOutputFormat;
use clap::{Parser, Subcommand};
use serde_json::Value;
use std::path::PathBuf;
#[derive(Parser)]
#[command(
name = "pmat",
about = "Professional project quantitative scaffolding and analysis toolkit",
version,
long_about = None
)]
#[cfg_attr(test, derive(Debug))]
pub struct Cli {
#[arg(long, value_enum, global = true)]
pub mode: Option<Mode>,
#[arg(short, long, global = true)]
pub verbose: bool,
#[arg(long, global = true)]
pub debug: bool,
#[arg(long, global = true)]
pub trace: bool,
#[arg(long, global = true, env = "RUST_LOG")]
pub trace_filter: Option<String>,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Clone, Debug, clap::ValueEnum, PartialEq)]
pub enum Mode {
Cli,
Mcp,
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum Commands {
#[command(visible_aliases = &["gen", "g"])]
Generate {
category: String,
template: String,
#[arg(short = 'p', long = "param", value_parser = crate::cli::args::parse_key_val)]
params: Vec<(String, Value)>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
create_dirs: bool,
},
Scaffold {
#[command(subcommand)]
command: ScaffoldCommands,
},
List {
#[arg(long)]
toolchain: Option<String>,
#[arg(long)]
category: Option<String>,
#[arg(long, value_enum, default_value = "table")]
format: OutputFormat,
},
Search {
query: String,
#[arg(long)]
toolchain: Option<String>,
#[arg(long, default_value_t = 20)]
limit: usize,
},
Validate {
uri: String,
#[arg(short = 'p', long = "param", value_parser = crate::cli::args::parse_key_val)]
params: Vec<(String, Value)>,
},
Context {
#[arg(long, short = 't')]
toolchain: Option<String>,
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, value_enum, default_value = "markdown")]
format: ContextFormat,
#[arg(long)]
include_large_files: bool,
#[arg(long)]
skip_expensive_metrics: bool,
},
#[command(subcommand)]
Analyze(AnalyzeCommands),
#[command(subcommand)]
Qdd(QddCommands),
Demo {
#[arg(short, long)]
path: Option<PathBuf>,
#[arg(long)]
url: Option<String>,
#[arg(long)]
repo: Option<String>,
#[arg(short, long, value_enum, default_value = "table")]
format: OutputFormat,
#[arg(long, value_enum, default_value = "http")]
protocol: DemoProtocol,
#[arg(long)]
show_api: bool,
#[arg(long)]
no_browser: bool,
#[arg(long)]
port: Option<u16>,
#[arg(long)]
cli: bool,
#[arg(long, default_value_t = 15)]
target_nodes: usize,
#[arg(long, default_value_t = 0.1)]
centrality_threshold: f64,
#[arg(long, default_value_t = 3)]
merge_threshold: usize,
#[arg(long)]
debug: bool,
#[arg(long)]
debug_output: Option<PathBuf>,
#[arg(long, default_value_t = true)]
skip_vendor: bool,
#[arg(long = "no-skip-vendor")]
no_skip_vendor: bool,
#[arg(long)]
max_line_length: Option<usize>,
},
QualityGate {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long)]
file: Option<PathBuf>,
#[arg(short = 'f', long, value_enum, default_value = "summary")]
format: QualityGateOutputFormat,
#[arg(long)]
fail_on_violation: bool,
#[arg(long, value_delimiter = ',')]
checks: Vec<QualityCheckType>,
#[arg(long, default_value = "15.0")]
max_dead_code: f64,
#[arg(long, default_value = "2.0")]
min_entropy: f64,
#[arg(long, default_value = "50")]
max_complexity_p99: u32,
#[arg(long)]
include_provability: bool,
#[arg(short = 'o', long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
},
Report {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(short = 'f', long, value_enum, default_value = "json")]
output_format: ReportOutputFormat,
#[arg(long = "txt", conflicts_with = "output_format")]
text: bool,
#[arg(long = "md", conflicts_with = "output_format")]
markdown: bool,
#[arg(long = "csv", conflicts_with = "output_format")]
csv: bool,
#[arg(long)]
include_visualizations: bool,
#[arg(long, default_value_t = true)]
include_executive_summary: bool,
#[arg(long, default_value_t = true)]
include_recommendations: bool,
#[arg(long, value_delimiter = ',', default_value = "all")]
analyses: Vec<AnalysisType>,
#[arg(long, default_value_t = 50)]
confidence_threshold: u8,
#[arg(short = 'o', long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
},
Serve {
#[arg(long, default_value_t = 8080)]
port: u16,
#[arg(long, default_value = "127.0.0.1")]
host: String,
#[arg(long)]
cors: bool,
#[arg(long, value_enum, default_value = "http")]
transport: ServeTransport,
},
Diagnose(DiagnoseArgs),
#[command(subcommand)]
Enforce(EnforceCommands),
#[command(subcommand)]
Refactor(RefactorCommands),
#[command(subcommand)]
Roadmap(RoadmapCommands),
Test {
#[arg(value_enum, default_value = "performance")]
suite: TestSuite,
#[arg(long, default_value = "3")]
iterations: usize,
#[arg(long)]
memory: bool,
#[arg(long)]
throughput: bool,
#[arg(long)]
regression: bool,
#[arg(long, default_value = "300")]
timeout: u64,
#[arg(short = 'o', long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
},
Memory {
#[command(subcommand)]
command: MemoryCommand,
},
Cache {
#[command(subcommand)]
command: CacheCommand,
},
Telemetry {
#[arg(long)]
system: bool,
#[arg(long)]
service: Option<String>,
#[arg(long)]
reset: bool,
#[arg(long)]
test_event: bool,
},
Config {
#[arg(long)]
show: bool,
#[arg(long)]
edit: bool,
#[arg(long)]
validate: bool,
#[arg(long)]
reset: bool,
#[arg(long)]
section: Option<String>,
#[arg(long, action = clap::ArgAction::Append)]
set: Vec<String>,
#[arg(long)]
config_path: Option<PathBuf>,
},
Agent {
#[command(subcommand)]
command: AgentCommands,
},
Tdg {
#[arg(default_value = ".")]
path: PathBuf,
#[command(subcommand)]
command: Option<TdgCommand>,
#[arg(long, value_enum, default_value = "table")]
format: TdgOutputFormat,
#[arg(long)]
config: Option<PathBuf>,
#[arg(short, long)]
quiet: bool,
#[arg(long)]
include_components: bool,
#[arg(long)]
min_grade: Option<String>,
#[arg(short, long)]
output: Option<PathBuf>,
},
}
#[derive(Clone, Debug, clap::ValueEnum)]
#[cfg_attr(test, derive(PartialEq))]
pub enum DiagnosticOutputFormat {
Plain,
Human,
Json,
Yaml,
Table,
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
#[derive(Clone)]
pub enum StorageCommand {
Stats {
#[arg(long)]
detailed: bool,
},
Cleanup {
#[arg(long, default_value = "3600")]
max_age: u64,
},
Migrate {
#[arg(long)]
backend: String,
#[arg(long)]
path: Option<PathBuf>,
},
Flush,
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
#[derive(Clone)]
pub enum TdgCommand {
Compare {
source1: PathBuf,
source2: PathBuf,
},
Diagnostics {
#[arg(long)]
detailed: bool,
#[arg(long)]
storage: bool,
#[arg(long)]
scheduler: bool,
#[arg(long)]
adaptive: bool,
#[arg(long)]
resources: bool,
#[arg(long)]
all: bool,
#[arg(long, value_enum, default_value = "human")]
format: DiagnosticOutputFormat,
},
Storage {
#[command(subcommand)]
command: StorageCommand,
},
Dashboard {
#[arg(short, long, default_value = "8080")]
port: u16,
#[arg(long, default_value = "127.0.0.1")]
host: String,
#[arg(long)]
open: bool,
#[arg(long, default_value = "5")]
update_interval: u64,
},
#[command(subcommand)]
Config(ConfigCommands),
#[command(subcommand)]
Hooks(HooksCommands),
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum AnalyzeCommands {
Churn {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(short = 'd', long, default_value_t = 30)]
days: u32,
#[arg(long, value_enum, default_value = "summary")]
format: ChurnOutputFormat,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, default_value_t = 10)]
top_files: usize,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
exclude: Vec<String>,
},
Complexity {
#[arg(short = 'p', long, default_value = ".")]
path: PathBuf,
#[arg(long, hide = true)]
project_path: Option<PathBuf>,
#[arg(long, conflicts_with = "include")]
file: Option<PathBuf>,
#[arg(long, value_delimiter = ',', conflicts_with_all = ["file", "include"])]
files: Vec<PathBuf>,
#[arg(long)]
toolchain: Option<String>,
#[arg(long, value_enum, default_value = "summary")]
format: ComplexityOutputFormat,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
max_cyclomatic: Option<u16>,
#[arg(long)]
max_cognitive: Option<u16>,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
watch: bool,
#[arg(long, default_value_t = 10)]
top_files: usize,
#[arg(long)]
fail_on_violation: bool,
#[arg(long, default_value = "60")]
timeout: u64,
},
Dag {
#[arg(long, value_enum, default_value = "full-dependency")]
dag_type: DagType,
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
max_depth: Option<usize>,
#[arg(long)]
target_nodes: Option<usize>,
#[arg(long)]
filter_external: bool,
#[arg(long)]
show_complexity: bool,
#[arg(long)]
include_duplicates: bool,
#[arg(long)]
include_dead_code: bool,
#[arg(long)]
enhanced: bool,
},
#[command(name = "dead-code")]
DeadCode {
#[arg(long, short = 'p', default_value = ".")]
path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: DeadCodeOutputFormat,
#[arg(long, short = 't')]
top_files: Option<usize>,
#[arg(long, short = 'u')]
include_unreachable: bool,
#[arg(long, default_value = "10")]
min_dead_lines: usize,
#[arg(long)]
include_tests: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
fail_on_violation: bool,
#[arg(long, default_value = "15.0")]
max_percentage: f64,
#[arg(long, default_value = "60")]
timeout: u64,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
exclude: Vec<String>,
},
#[command(name = "satd")]
Satd {
#[arg(long, short = 'p', default_value = ".")]
path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: SatdOutputFormat,
#[arg(long, value_enum)]
severity: Option<SatdSeverity>,
#[arg(long)]
critical_only: bool,
#[arg(long)]
include_tests: bool,
#[arg(long)]
strict: bool,
#[arg(long)]
evolution: bool,
#[arg(long, default_value_t = 30)]
days: u32,
#[arg(long)]
metrics: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, default_value_t = 10)]
top_files: usize,
#[arg(long)]
fail_on_violation: bool,
#[arg(long, default_value = "60")]
timeout: u64,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
exclude: Vec<String>,
},
#[command(name = "deep-context")]
DeepContext {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, value_enum, default_value = "markdown")]
format: DeepContextOutputFormat,
#[arg(long)]
full: bool,
#[arg(long, value_delimiter = ',')]
include: Vec<String>,
#[arg(long, value_delimiter = ',')]
exclude: Vec<String>,
#[arg(long, default_value_t = 30)]
period_days: u32,
#[arg(long, value_enum, default_value = "call-graph")]
dag_type: DeepContextDagType,
#[arg(long)]
max_depth: Option<usize>,
#[arg(long = "include-pattern")]
include_patterns: Vec<String>,
#[arg(long = "exclude-pattern")]
exclude_patterns: Vec<String>,
#[arg(long, value_enum, default_value = "normal")]
cache_strategy: DeepContextCacheStrategy,
#[arg(long)]
parallel: Option<usize>,
#[arg(long)]
verbose: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
#[command(name = "tdg")]
Tdg {
#[arg(long, short = 'p', default_value = ".")]
path: PathBuf,
#[arg(short, long, default_value = "1.5")]
threshold: f64,
#[arg(short = 'n', long, default_value = "10")]
top_files: usize,
#[arg(short, long, value_enum, default_value = "table")]
format: TdgOutputFormat,
#[arg(long)]
include_components: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
critical_only: bool,
#[arg(long)]
verbose: bool,
},
#[command(name = "lint-hotspot")]
LintHotspot {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long)]
file: Option<PathBuf>,
#[arg(short = 'f', long, value_enum, default_value = "summary")]
format: LintHotspotOutputFormat,
#[arg(long, default_value_t = 5.0)]
max_density: f64,
#[arg(long, default_value_t = 0.8)]
min_confidence: f64,
#[arg(long)]
enforce: bool,
#[arg(long)]
dry_run: bool,
#[arg(long)]
enforcement_metadata: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(
long,
default_value = "-W warnings -W clippy::pedantic -W clippy::nursery -W clippy::cargo"
)]
clippy_flags: String,
#[arg(long, default_value = "10")]
top_files: usize,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
exclude: Vec<String>,
},
Makefile {
#[arg(help = "Path to Makefile to analyze")]
path: PathBuf,
#[arg(
long,
value_delimiter = ',',
default_value = "all",
help = "Comma-separated list of rules to apply"
)]
rules: Vec<String>,
#[arg(long, value_enum, default_value = "human")]
format: MakefileOutputFormat,
#[arg(long, help = "Automatically fix issues where possible")]
fix: bool,
#[arg(
long,
default_value = "4.4",
help = "GNU Make version to check compatibility against"
)]
gnu_version: String,
#[arg(long, default_value = "10")]
top_files: usize,
},
Provability {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, value_delimiter = ',')]
functions: Vec<String>,
#[arg(long, default_value_t = 10)]
analysis_depth: usize,
#[arg(long, value_enum, default_value = "summary")]
format: ProvabilityOutputFormat,
#[arg(long)]
high_confidence_only: bool,
#[arg(long)]
include_evidence: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, default_value = "10")]
top_files: usize,
},
Duplicates {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, default_value = "all")]
detection_type: DuplicateType,
#[arg(long, default_value = "0.85")]
threshold: f32,
#[arg(long, default_value = "5")]
min_lines: usize,
#[arg(long, default_value = "128")]
max_tokens: usize,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: DuplicateOutputFormat,
#[arg(long)]
perf: bool,
#[arg(long)]
include: Option<String>,
#[arg(long)]
exclude: Option<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, default_value = "10")]
top_files: usize,
},
DefectPrediction {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, default_value = "0.5")]
confidence_threshold: f32,
#[arg(long, default_value = "10")]
min_lines: usize,
#[arg(long)]
include_low_confidence: bool,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: DefectPredictionOutputFormat,
#[arg(long)]
high_risk_only: bool,
#[arg(long)]
include_recommendations: bool,
#[arg(long)]
include: Option<String>,
#[arg(long)]
exclude: Option<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
Comprehensive {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, conflicts_with = "files")]
file: Option<PathBuf>,
#[arg(long, value_delimiter = ',', conflicts_with = "file")]
files: Vec<PathBuf>,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: ComprehensiveOutputFormat,
#[arg(long, default_value = "true")]
include_duplicates: bool,
#[arg(long, default_value = "true")]
include_dead_code: bool,
#[arg(long, default_value = "true")]
include_defects: bool,
#[arg(long, default_value = "true")]
include_complexity: bool,
#[arg(long, default_value = "true")]
include_tdg: bool,
#[arg(long, default_value = "0.5")]
confidence_threshold: f32,
#[arg(long, default_value = "10")]
min_lines: usize,
#[arg(long)]
include: Option<String>,
#[arg(long)]
exclude: Option<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long)]
executive_summary: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
GraphMetrics {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, value_delimiter = ',', default_value = "all")]
metrics: Vec<GraphMetricType>,
#[arg(long, value_delimiter = ',')]
pagerank_seeds: Vec<String>,
#[arg(long, default_value = "0.85")]
damping_factor: f32,
#[arg(long, default_value = "100")]
max_iterations: usize,
#[arg(long, default_value = "0.001")]
convergence_threshold: f64,
#[arg(long)]
export_graphml: bool,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: GraphMetricsOutputFormat,
#[arg(long)]
include: Option<String>,
#[arg(long)]
exclude: Option<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long, default_value = "20")]
top_k: usize,
#[arg(long, default_value = "0.001")]
min_centrality: f64,
},
NameSimilarity {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
query: String,
#[arg(long, default_value = "10")]
top_k: usize,
#[arg(long)]
phonetic: bool,
#[arg(long, value_enum, default_value = "all")]
scope: SearchScope,
#[arg(long, default_value = "0.3")]
threshold: f32,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: NameSimilarityOutputFormat,
#[arg(long)]
include: Option<String>,
#[arg(long)]
exclude: Option<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long)]
fuzzy: bool,
#[arg(long)]
case_sensitive: bool,
},
ProofAnnotations {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: ProofAnnotationOutputFormat,
#[arg(long)]
high_confidence_only: bool,
#[arg(long)]
include_evidence: bool,
#[arg(long, value_enum)]
property_type: Option<PropertyTypeFilter>,
#[arg(long, value_enum)]
verification_method: Option<VerificationMethodFilter>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long)]
clear_cache: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
IncrementalCoverage {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'b', default_value = "main")]
base_branch: String,
#[arg(long, short = 't')]
target_branch: Option<String>,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: IncrementalCoverageOutputFormat,
#[arg(long, default_value = "80.0")]
coverage_threshold: f64,
#[arg(long)]
changed_files_only: bool,
#[arg(long)]
detailed: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long)]
cache_dir: Option<PathBuf>,
#[arg(long)]
force_refresh: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
SymbolTable {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: SymbolTableOutputFormat,
#[arg(long, value_enum)]
filter: Option<SymbolTypeFilter>,
#[arg(long, short = 'q')]
query: Option<String>,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
exclude: Vec<String>,
#[arg(long)]
show_unreferenced: bool,
#[arg(long)]
show_references: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
BigO {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: BigOOutputFormat,
#[arg(long, default_value = "50")]
confidence_threshold: u8,
#[arg(long)]
analyze_space: bool,
#[arg(long)]
include: Vec<String>,
#[arg(long)]
exclude: Vec<String>,
#[arg(long)]
high_complexity_only: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
AssemblyScript {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: ComplexityOutputFormat,
#[arg(long)]
wasm_complexity: bool,
#[arg(long)]
memory_analysis: bool,
#[arg(long)]
security: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, default_value = "30")]
timeout: u64,
#[arg(long)]
perf: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
WebAssembly {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: ComplexityOutputFormat,
#[arg(long, default_value = "true")]
include_binary: bool,
#[arg(long, default_value = "true")]
include_text: bool,
#[arg(long)]
memory_analysis: bool,
#[arg(long)]
security: bool,
#[arg(long)]
complexity: bool,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
#[arg(long, default_value = "10")]
top_files: usize,
},
Clippy {
#[arg(long, short = 'p', default_value = ".")]
project_path: PathBuf,
#[arg(long, short = 'c', default_value = "high")]
confidence: String,
#[arg(long)]
dry_run: bool,
#[arg(long, value_delimiter = ',')]
fix_codes: Vec<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
perf: bool,
},
Entropy {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long, value_enum, default_value = "summary")]
format: EntropyOutputFormat,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long, value_enum, default_value = "medium")]
min_severity: EntropySeverity,
#[arg(long, default_value_t = 20)]
top_violations: usize,
#[arg(long)]
file: Option<PathBuf>,
#[arg(long)]
include_tests: bool,
},
Wasm {
wasm_file: PathBuf,
#[arg(long, short = 'f', value_enum, default_value = "summary")]
format: WasmOutputFormat,
#[arg(long)]
verify: bool,
#[arg(long)]
security: bool,
#[arg(long)]
profile: bool,
#[arg(long)]
baseline: Option<PathBuf>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
verbose: bool,
},
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum QddCommands {
Create {
#[arg(long, value_enum, default_value = "function")]
code_type: QddCodeType,
#[arg(long)]
name: String,
#[arg(long)]
purpose: String,
#[arg(long, value_enum, default_value = "standard")]
profile: QddQualityProfile,
#[arg(long, value_parser = parse_parameter)]
input: Vec<(String, String)>,
#[arg(long, default_value = "()")]
output: String,
#[arg(short, long)]
output_file: Option<PathBuf>,
},
Refactor {
#[arg(short, long)]
file: PathBuf,
#[arg(long)]
function: Option<String>,
#[arg(long, value_enum, default_value = "standard")]
profile: QddQualityProfile,
#[arg(long)]
max_complexity: Option<u32>,
#[arg(long)]
min_coverage: Option<u32>,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
dry_run: bool,
},
Validate {
#[arg(short, long, default_value = ".")]
path: PathBuf,
#[arg(long, value_enum, default_value = "standard")]
profile: QddQualityProfile,
#[arg(long, value_enum, default_value = "summary")]
format: QddOutputFormat,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
strict: bool,
},
}
#[derive(clap::ValueEnum, Clone)]
#[cfg_attr(test, derive(Debug))]
pub enum QddCodeType {
Function,
Module,
Service,
Test,
}
#[derive(clap::ValueEnum, Clone, Copy, Debug)]
pub enum QddQualityProfile {
Extreme,
Standard,
Relaxed,
}
#[derive(clap::ValueEnum, Clone)]
#[cfg_attr(test, derive(Debug))]
pub enum QddOutputFormat {
Summary,
Detailed,
Json,
Markdown,
}
fn parse_parameter(s: &str) -> Result<(String, String), String> {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() != 2 {
return Err("Parameter must be in format type:name".to_string());
}
Ok((parts[0].to_string(), parts[1].to_string()))
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum EnforceCommands {
Extreme {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long)]
single_file_mode: bool,
#[arg(long)]
file: Option<PathBuf>,
#[arg(long)]
dry_run: bool,
#[arg(long, value_enum, default_value = "extreme")]
profile: QualityProfile,
#[arg(long, default_value_t = true)]
show_progress: bool,
#[arg(short = 'f', long, value_enum, default_value = "summary")]
format: EnforceOutputFormat,
#[arg(short = 'o', long)]
output: Option<PathBuf>,
#[arg(long, default_value_t = 100)]
max_iterations: u32,
#[arg(long)]
target_improvement: Option<f32>,
#[arg(long)]
max_time: Option<u64>,
#[arg(long)]
apply_suggestions: bool,
#[arg(long)]
validate_only: bool,
#[arg(long)]
list_violations: bool,
#[arg(long)]
config: Option<PathBuf>,
#[arg(long)]
ci_mode: bool,
#[arg(long)]
include: Option<String>,
#[arg(long)]
exclude: Option<String>,
#[arg(long)]
cache_dir: Option<PathBuf>,
#[arg(long)]
clear_cache: bool,
},
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum RefactorCommands {
Serve {
#[arg(long, value_enum, default_value = "batch")]
refactor_mode: RefactorMode,
#[arg(short = 'c', long)]
config: Option<PathBuf>,
#[arg(short = 'p', long, default_value = ".")]
project: PathBuf,
#[arg(long, default_value = "4")]
parallel: usize,
#[arg(long, default_value = "512")]
memory_limit: usize,
#[arg(long, default_value = "10")]
batch_size: usize,
#[arg(long)]
priority: Option<String>,
#[arg(long)]
checkpoint_dir: Option<PathBuf>,
#[arg(long)]
resume: bool,
#[arg(long)]
auto_commit: Option<String>,
#[arg(long)]
max_runtime: Option<u64>,
},
Interactive {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long, value_enum, default_value = "detailed")]
explain: ExplainLevel,
#[arg(long, default_value = "refactor_state.json")]
checkpoint: PathBuf,
#[arg(long, default_value = "20")]
target_complexity: u16,
#[arg(long)]
steps: Option<u32>,
#[arg(long)]
config: Option<PathBuf>,
},
Status {
#[arg(long, default_value = "refactor_state.json")]
checkpoint: PathBuf,
#[arg(long, value_enum, default_value = "json")]
format: RefactorOutputFormat,
},
Resume {
#[arg(long, default_value = "refactor_state.json")]
checkpoint: PathBuf,
#[arg(long, default_value = "10")]
steps: u32,
#[arg(long, value_enum)]
explain: Option<ExplainLevel>,
},
Auto {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long)]
single_file_mode: bool,
#[arg(long)]
file: Option<PathBuf>,
#[arg(long, default_value = "100")]
max_iterations: u32,
#[arg(long, value_enum, default_value = "extreme")]
quality_profile: QualityProfile,
#[arg(short = 'f', long, value_enum, default_value = "detailed")]
format: RefactorAutoOutputFormat,
#[arg(long)]
dry_run: bool,
#[arg(long)]
skip_compilation: bool,
#[arg(long)]
skip_tests: bool,
#[arg(long)]
checkpoint: Option<PathBuf>,
#[arg(short = 'v', long)]
verbose: bool,
#[arg(long, value_delimiter = ',')]
exclude: Vec<String>,
#[arg(long, value_delimiter = ',')]
include: Vec<String>,
#[arg(long)]
ignore_file: Option<PathBuf>,
#[arg(long, short = 't')]
test: Option<PathBuf>,
#[arg(long)]
test_name: Option<String>,
#[arg(long)]
github_issue: Option<String>,
#[arg(long)]
bug_report_path: Option<PathBuf>,
},
Docs {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(long, default_value_t = true)]
include_docs: bool,
#[arg(long, default_value_t = true)]
include_root: bool,
#[arg(long, value_delimiter = ',')]
additional_dirs: Vec<PathBuf>,
#[arg(short = 'f', long, value_enum, default_value = "summary")]
format: RefactorDocsOutputFormat,
#[arg(long)]
dry_run: bool,
#[arg(
long,
value_delimiter = ',',
default_value = "fix-*,test-*,temp-*,tmp-*,*_TEMP*,*_TMP*,FAST_*,FIX_*,ZERO_DEFECTS_*"
)]
temp_patterns: Vec<String>,
#[arg(
long,
value_delimiter = ',',
default_value = "*_STATUS.md,*_PROGRESS.md,*_COMPLETE.md,final_verification.md,overnight-*.md"
)]
status_patterns: Vec<String>,
#[arg(
long,
value_delimiter = ',',
default_value = "*.mmd,optimization_state.json,complexity_report.json,satd_report.json"
)]
artifact_patterns: Vec<String>,
#[arg(long, value_delimiter = ',')]
custom_patterns: Vec<String>,
#[arg(long, default_value_t = 0)]
min_age_days: u32,
#[arg(long, default_value_t = 10)]
max_size_mb: u64,
#[arg(long, default_value_t = true)]
recursive: bool,
#[arg(
long,
value_delimiter = ',',
default_value = "README.md,LICENSE*,CHANGELOG*,CONTRIBUTING*"
)]
preserve_patterns: Vec<String>,
#[arg(short = 'o', long)]
output: Option<PathBuf>,
#[arg(long)]
auto_remove: bool,
#[arg(long)]
backup: bool,
#[arg(long, default_value = ".refactor-docs-backup")]
backup_dir: PathBuf,
#[arg(long)]
perf: bool,
},
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mode_enum() {
assert_eq!(Mode::Cli, Mode::Cli);
assert_ne!(Mode::Cli, Mode::Mcp);
}
#[test]
#[ignore = "Stack overflow issue - needs investigation"]
fn test_cli_parse_empty() {
let result = Cli::try_parse_from(["pmat", "list"]);
match result {
Ok(_) => {
}
Err(e) => {
panic!("CLI parsing failed: {}", e);
}
}
}
#[test]
fn test_mode_variants() {
let cli_mode = Mode::Cli;
let mcp_mode = Mode::Mcp;
assert_eq!(cli_mode, Mode::Cli);
assert_eq!(mcp_mode, Mode::Mcp);
assert_ne!(cli_mode, mcp_mode);
}
#[test]
fn test_diagnostic_output_format_variants() {
let plain = DiagnosticOutputFormat::Plain;
let json = DiagnosticOutputFormat::Json;
let yaml = DiagnosticOutputFormat::Yaml;
assert_eq!(plain, DiagnosticOutputFormat::Plain);
assert_eq!(json, DiagnosticOutputFormat::Json);
assert_eq!(yaml, DiagnosticOutputFormat::Yaml);
}
#[test]
fn test_storage_command_variants() {
let stats = StorageCommand::Stats { detailed: false };
let cleanup = StorageCommand::Cleanup { max_age: 3600 };
let migrate = StorageCommand::Migrate {
backend: "sled".to_string(),
path: None,
};
let _migrate2 = StorageCommand::Migrate {
backend: "rocksdb".to_string(),
path: None,
};
match stats {
StorageCommand::Stats { detailed } => assert!(!detailed),
_ => panic!("Unexpected variant"),
}
match cleanup {
StorageCommand::Cleanup { max_age } => assert_eq!(max_age, 3600),
_ => panic!("Unexpected variant"),
}
match migrate {
StorageCommand::Migrate { backend, path: _ } => {
assert_eq!(backend, "rocksdb");
}
_ => panic!("Expected Migrate variant"),
}
}
#[test]
fn test_tdg_command_variants() {
let compare = TdgCommand::Compare {
source1: PathBuf::from("file1.rs"),
source2: PathBuf::from("file2.rs"),
};
let diagnostics = TdgCommand::Diagnostics {
detailed: true,
storage: false,
scheduler: false,
adaptive: false,
resources: false,
all: false,
format: DiagnosticOutputFormat::Human,
};
let dashboard = TdgCommand::Dashboard {
port: 8080,
open: true,
host: "127.0.0.1".to_string(),
update_interval: 5,
};
match compare {
TdgCommand::Compare { source1, source2 } => {
assert_eq!(source1, PathBuf::from("file1.rs"));
assert_eq!(source2, PathBuf::from("file2.rs"));
}
_ => panic!("Expected Compare variant"),
}
match diagnostics {
TdgCommand::Diagnostics { detailed, .. } => {
assert!(detailed);
}
_ => panic!("Expected Diagnostics variant"),
}
match dashboard {
TdgCommand::Dashboard {
port,
open,
host,
update_interval,
} => {
assert_eq!(port, 8080);
assert!(open);
assert_eq!(host, "127.0.0.1");
assert_eq!(update_interval, 5);
}
_ => panic!("Expected Dashboard variant"),
}
}
#[test]
fn test_analyze_commands_variants() {
let complexity = AnalyzeCommands::Complexity {
path: PathBuf::from("."),
project_path: None,
file: Some(PathBuf::from("test.rs")),
files: vec![PathBuf::from("lib.rs")],
toolchain: Some("rust".to_string()),
format: ComplexityOutputFormat::Json,
output: None,
max_cyclomatic: Some(10),
max_cognitive: Some(15),
include: vec!["**/*.rs".to_string()],
watch: false,
top_files: 5,
fail_on_violation: true,
timeout: 60,
};
let churn = AnalyzeCommands::Churn {
project_path: PathBuf::from("."),
days: 30,
format: ChurnOutputFormat::Json,
output: None,
top_files: 10,
include: vec![],
exclude: vec![],
};
match complexity {
AnalyzeCommands::Complexity {
path,
file,
max_cyclomatic,
top_files,
..
} => {
assert_eq!(path, PathBuf::from("."));
assert_eq!(file, Some(PathBuf::from("test.rs")));
assert_eq!(max_cyclomatic, Some(10));
assert_eq!(top_files, 5);
}
_ => panic!("Expected Complexity variant"),
}
match churn {
AnalyzeCommands::Churn {
project_path,
days,
top_files,
..
} => {
assert_eq!(project_path, PathBuf::from("."));
assert_eq!(days, 30);
assert_eq!(top_files, 10);
}
_ => panic!("Expected Churn variant"),
}
}
#[test]
fn test_enforce_commands_variants() {
}
#[test]
fn test_refactor_commands_variants() {
}
#[test]
fn test_scaffold_commands_variants() {
let project = ScaffoldCommands::Project {
toolchain: "rust".to_string(),
templates: vec!["cli".to_string(), "lib".to_string()],
params: vec![("name".to_string(), Value::String("test".to_string()))],
parallel: 4,
};
let agent = ScaffoldCommands::Agent {
name: "test-agent".to_string(),
template: "basic".to_string(),
features: vec!["logging".to_string()],
quality: "strict".to_string(),
output: None,
force: false,
dry_run: false,
interactive: false,
deterministic_core: Some("state-machine".to_string()),
probabilistic_wrapper: None,
};
match project {
ScaffoldCommands::Project {
toolchain,
templates,
params,
parallel,
} => {
assert_eq!(toolchain, "rust");
assert_eq!(templates, vec!["cli", "lib"]);
assert_eq!(params.len(), 1);
assert_eq!(parallel, 4);
}
_ => panic!("Expected Project variant"),
}
match agent {
ScaffoldCommands::Agent {
name,
template,
features,
quality,
output,
force,
dry_run,
interactive,
deterministic_core,
probabilistic_wrapper,
} => {
assert_eq!(name, "test-agent");
assert_eq!(template, "basic");
assert_eq!(features, vec!["logging"]);
assert_eq!(quality, "strict");
assert!(output.is_none());
assert!(!force);
assert!(!dry_run);
assert!(!interactive);
assert_eq!(deterministic_core, Some("state-machine".to_string()));
assert!(probabilistic_wrapper.is_none());
}
_ => panic!("Expected Agent variant"),
}
}
#[test]
fn test_roadmap_commands_variants() {
let init = RoadmapCommands::Init {
version: "v2.6.0".to_string(),
title: "Test Sprint".to_string(),
duration_days: 14,
priority: "P0".to_string(),
};
let start = RoadmapCommands::Start {
task_id: "task-123".to_string(),
create_branch: false,
};
let complete = RoadmapCommands::Complete {
task_id: "task-123".to_string(),
skip_quality_check: true,
};
match init {
RoadmapCommands::Init {
version,
title,
duration_days,
priority,
} => {
assert_eq!(version, "v2.6.0");
assert_eq!(title, "Test Sprint");
assert_eq!(duration_days, 14);
assert_eq!(priority, "P0");
}
_ => panic!("Expected Init variant"),
}
match start {
RoadmapCommands::Start {
task_id,
create_branch,
} => {
assert_eq!(task_id, "task-123");
assert!(!create_branch);
}
_ => panic!("Expected Start variant"),
}
match complete {
RoadmapCommands::Complete {
task_id,
skip_quality_check,
} => {
assert_eq!(task_id, "task-123");
assert!(skip_quality_check);
}
_ => panic!("Expected Complete variant"),
}
}
#[test]
fn test_test_suite_variants() {
let performance = TestSuite::Performance;
let integration = TestSuite::Integration;
let property = TestSuite::Property;
let memory = TestSuite::Memory;
assert_eq!(performance, TestSuite::Performance);
assert_eq!(integration, TestSuite::Integration);
assert_eq!(property, TestSuite::Property);
assert_eq!(memory, TestSuite::Memory);
}
#[test]
fn test_serve_transport_variants() {
let http = ServeTransport::Http;
let websocket = ServeTransport::WebSocket;
assert_eq!(http, ServeTransport::Http);
assert_eq!(websocket, ServeTransport::WebSocket);
}
#[test]
fn test_agent_commands_variants() {
let status = AgentCommands::Status {
pid_file: None,
format: OutputFormat::Json,
};
let stop = AgentCommands::Stop {
pid_file: None,
force: false,
timeout: 10,
};
match status {
AgentCommands::Status { format, .. } => {
assert_eq!(format, OutputFormat::Json);
}
_ => panic!("Expected Status variant"),
}
match stop {
AgentCommands::Stop { force, timeout, .. } => {
assert!(!force);
assert_eq!(timeout, 10);
}
_ => panic!("Expected Stop variant"),
}
}
#[test]
fn test_commands_generate_variant() {
let generate = Commands::Generate {
category: "makefile".to_string(),
template: "rust/cli".to_string(),
params: vec![("name".to_string(), Value::String("test".to_string()))],
output: Some(PathBuf::from("Makefile")),
create_dirs: true,
};
match generate {
Commands::Generate {
category,
template,
params,
output,
create_dirs,
} => {
assert_eq!(category, "makefile");
assert_eq!(template, "rust/cli");
assert_eq!(params.len(), 1);
assert_eq!(output, Some(PathBuf::from("Makefile")));
assert!(create_dirs);
}
_ => panic!("Expected Generate variant"),
}
}
#[test]
fn test_commands_list_variant() {
let list = Commands::List {
toolchain: Some("rust".to_string()),
category: Some("cli".to_string()),
format: OutputFormat::Json,
};
match list {
Commands::List {
toolchain,
category,
format,
} => {
assert_eq!(toolchain, Some("rust".to_string()));
assert_eq!(category, Some("cli".to_string()));
assert_eq!(format, OutputFormat::Json);
}
_ => panic!("Expected List variant"),
}
}
#[test]
fn test_commands_search_variant() {
let search = Commands::Search {
query: "rust cli".to_string(),
toolchain: Some("rust".to_string()),
limit: 10,
};
match search {
Commands::Search {
query,
toolchain,
limit,
} => {
assert_eq!(query, "rust cli");
assert_eq!(toolchain, Some("rust".to_string()));
assert_eq!(limit, 10);
}
_ => panic!("Expected Search variant"),
}
}
#[test]
fn test_commands_validate_variant() {
let validate = Commands::Validate {
uri: "template://rust/cli".to_string(),
params: vec![("name".to_string(), Value::String("test".to_string()))],
};
match validate {
Commands::Validate { uri, params } => {
assert_eq!(uri, "template://rust/cli");
assert_eq!(params.len(), 1);
}
_ => panic!("Expected Validate variant"),
}
}
#[test]
fn test_commands_context_variant() {
let context = Commands::Context {
toolchain: Some("rust".to_string()),
project_path: PathBuf::from("."),
output: Some(PathBuf::from("context.md")),
format: ContextFormat::Markdown,
include_large_files: false,
skip_expensive_metrics: true,
};
match context {
Commands::Context {
toolchain,
project_path,
output,
format,
include_large_files,
skip_expensive_metrics,
} => {
assert_eq!(toolchain, Some("rust".to_string()));
assert_eq!(project_path, PathBuf::from("."));
assert_eq!(output, Some(PathBuf::from("context.md")));
assert_eq!(format, ContextFormat::Markdown);
assert!(!include_large_files);
assert!(skip_expensive_metrics);
}
_ => panic!("Expected Context variant"),
}
}
#[test]
fn test_commands_serve_variant() {
let serve = Commands::Serve {
host: "127.0.0.1".to_string(),
port: 3000,
cors: true,
transport: ServeTransport::Http,
};
match serve {
Commands::Serve {
host, port, cors, ..
} => {
assert_eq!(host, "127.0.0.1");
assert_eq!(port, 3000);
assert!(cors);
}
_ => panic!("Expected Serve variant"),
}
}
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum ScaffoldCommands {
Project {
toolchain: String,
#[arg(short, long, value_delimiter = ',')]
templates: Vec<String>,
#[arg(short = 'p', long = "param", value_parser = crate::cli::args::parse_key_val)]
params: Vec<(String, Value)>,
#[arg(long, default_value_t = num_cpus::get())]
parallel: usize,
},
Agent {
#[arg(short, long)]
name: String,
#[arg(short, long)]
template: String,
#[arg(short, long, value_delimiter = ',')]
features: Vec<String>,
#[arg(short = 'q', long, default_value = "strict")]
quality: String,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(long)]
force: bool,
#[arg(long)]
dry_run: bool,
#[arg(short, long)]
interactive: bool,
#[arg(long)]
deterministic_core: Option<String>,
#[arg(long)]
probabilistic_wrapper: Option<String>,
},
ListTemplates,
ValidateTemplate {
path: PathBuf,
},
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum RoadmapCommands {
Init {
#[arg(long)]
version: String,
#[arg(long)]
title: String,
#[arg(long, default_value = "14")]
duration_days: u32,
#[arg(long, default_value = "P0")]
priority: String,
},
Todos {
#[arg(long)]
sprint: Option<String>,
#[arg(long, default_value = "todos.md")]
output: PathBuf,
#[arg(long)]
include_quality_gates: bool,
},
Start {
task_id: String,
#[arg(long)]
create_branch: bool,
},
Complete {
task_id: String,
#[arg(long)]
skip_quality_check: bool,
},
Status {
#[arg(long)]
sprint: Option<String>,
#[arg(long)]
task: Option<String>,
#[arg(long, value_enum, default_value = "human")]
format: OutputFormat,
},
Validate {
#[arg(long)]
sprint: String,
#[arg(long)]
strict: bool,
},
QualityCheck {
#[arg(long)]
task_id: String,
},
}
#[derive(Clone, Debug, clap::ValueEnum, PartialEq)]
pub enum TestSuite {
Performance,
Property,
Integration,
Regression,
Memory,
Throughput,
All,
}
#[derive(Clone, Debug, clap::ValueEnum)]
#[cfg_attr(test, derive(PartialEq))]
pub enum ServeTransport {
Http,
WebSocket,
HttpSse,
Both,
All,
}
#[derive(Subcommand)]
#[cfg_attr(test, derive(Debug))]
pub enum AgentCommands {
Start {
#[arg(short = 'p', long, default_value = ".")]
project_path: PathBuf,
#[arg(short = 'c', long)]
config: Option<PathBuf>,
#[arg(long)]
working_dir: Option<PathBuf>,
#[arg(long)]
pid_file: Option<PathBuf>,
#[arg(long)]
log_file: Option<PathBuf>,
#[arg(long)]
foreground: bool,
#[arg(long, default_value = "30")]
health_interval: u64,
#[arg(long, default_value = "500")]
max_memory_mb: u64,
#[arg(long)]
no_auto_restart: bool,
},
Stop {
#[arg(long)]
pid_file: Option<PathBuf>,
#[arg(long)]
force: bool,
#[arg(long, default_value = "10")]
timeout: u64,
},
Status {
#[arg(long)]
pid_file: Option<PathBuf>,
#[arg(long, value_enum, default_value = "json")]
format: OutputFormat,
},
Monitor {
#[arg(short = 'p', long)]
project_path: PathBuf,
#[arg(long)]
project_id: Option<String>,
#[arg(long)]
thresholds: Option<PathBuf>,
},
Unmonitor {
#[arg(short = 'i', long)]
project_id: String,
},
Health {
#[arg(long)]
pid_file: Option<PathBuf>,
#[arg(long)]
detailed: bool,
},
Reload {
#[arg(long)]
pid_file: Option<PathBuf>,
#[arg(short = 'c', long)]
config: Option<PathBuf>,
},
QualityGate {
#[arg(short = 'p', long)]
project: String,
#[arg(long)]
file: Option<PathBuf>,
#[arg(long, value_enum, default_value = "summary")]
format: QualityGateOutputFormat,
},
McpServer {
#[arg(short = 'c', long)]
config: Option<PathBuf>,
#[arg(long)]
debug: bool,
},
}
#[derive(Subcommand, Clone)]
#[cfg_attr(test, derive(Debug))]
pub enum ConfigCommands {
Show {
#[arg(long, value_enum, default_value = "json")]
format: ConfigFormat,
},
Get {
key: String,
},
Validate {
#[arg(long)]
fix: bool,
},
Sources,
}
#[derive(Subcommand, Clone)]
#[cfg_attr(test, derive(Debug))]
pub enum HooksCommands {
Install {
#[arg(long)]
force: bool,
#[arg(long, default_value = "true")]
backup: bool,
},
Uninstall {
#[arg(long)]
restore_backup: bool,
},
Status,
Verify {
#[arg(long)]
fix: bool,
},
Refresh,
}
#[derive(Debug, Clone, clap::ValueEnum)]
#[cfg_attr(test, derive(PartialEq))]
pub enum ConfigFormat {
Json,
Toml,
Env,
}
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}