1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
use clap::Parser;
use std::path::PathBuf;
#[derive(Parser, Clone)]
pub struct CalibrateArgs {
/// Path to a run.json file to analyze (if omitted, reads from DB)
#[arg(long)]
pub run: Option<PathBuf>,
#[arg(long, default_value = ".eval/eval.db")]
pub db: PathBuf,
/// Test suite name (required if using --db)
#[arg(long)]
pub suite: Option<String>,
/// Number of recent runs to include from DB
#[arg(long, default_value_t = 200)]
pub last: u32,
/// Output JSON path
#[arg(long, default_value = "calibration.json")]
pub out: PathBuf,
/// Target tail for recommended min score (e.g. 0.10 for p10)
#[arg(long, default_value_t = 0.10)]
pub target_tail: f64,
}
#[derive(clap::Args, Debug, Clone)]
pub struct DoctorArgs {
#[arg(long)]
pub config: Option<std::path::PathBuf>,
#[arg(long)]
pub trace_file: Option<std::path::PathBuf>,
#[arg(long)]
pub baseline: Option<std::path::PathBuf>,
#[arg(long)]
pub db: Option<std::path::PathBuf>,
#[arg(long, default_value = "false")]
pub replay_strict: bool,
#[arg(long, default_value = "text")]
pub format: String, // text|json
#[arg(long)]
pub out: Option<std::path::PathBuf>,
/// Diagnose and offer/apply automated fixes for known issues
#[arg(long)]
pub fix: bool,
/// Apply all available fixes without interactive confirmation
#[arg(long)]
pub yes: bool,
/// Preview fixes without writing files
#[arg(long)]
pub dry_run: bool,
}
#[derive(clap::Args, Debug, Clone)]
pub struct WatchArgs {
#[arg(long, default_value = "eval.yaml")]
pub config: std::path::PathBuf,
#[arg(long)]
pub trace_file: Option<std::path::PathBuf>,
#[arg(long)]
pub baseline: Option<std::path::PathBuf>,
#[arg(long, default_value = ".eval/eval.db")]
pub db: std::path::PathBuf,
#[arg(long)]
pub strict: bool,
#[arg(long, default_value = "false")]
pub replay_strict: bool,
/// Clear terminal before each rerun
#[arg(long)]
pub clear: bool,
/// Debounce file events before rerunning (milliseconds)
#[arg(long, default_value_t = 350)]
pub debounce_ms: u64,
}
#[derive(clap::ValueEnum, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum MaxRisk {
Low,
Medium,
High,
}
#[derive(clap::Args, Debug, Clone)]
pub struct FixArgs {
#[arg(long, default_value = "assay.yaml")]
pub config: std::path::PathBuf,
#[arg(long)]
pub trace_file: Option<std::path::PathBuf>,
#[arg(long)]
pub baseline: Option<std::path::PathBuf>,
#[arg(long, default_value = "false")]
pub replay_strict: bool,
/// Apply all suggested patches without prompting
#[arg(long)]
pub yes: bool,
/// Do not write files; show diffs of what would change
#[arg(long)]
pub dry_run: bool,
/// Only apply patch(es) with these id(s). Can be repeated.
#[arg(long)]
pub only: Vec<String>,
/// Skip patches above this risk level
#[arg(long, value_enum, default_value_t = MaxRisk::High)]
pub max_risk: MaxRisk,
/// List suggested patches (after --only/--max-risk filtering) and exit
#[arg(long)]
pub list: bool,
}
#[derive(clap::Args, Debug, Clone)]
pub struct SandboxArgs {
/// Command to run in the sandbox
#[arg(allow_hyphen_values = true, required = true, trailing_var_arg = true)]
pub command: Vec<String>,
/// Path to policy file (optional)
#[arg(long, short)]
pub policy: Option<std::path::PathBuf>,
/// Working directory for command
#[arg(long, short)]
pub workdir: Option<std::path::PathBuf>,
/// Timeout in seconds
#[arg(long)]
pub timeout: Option<u64>,
/// Active enforcement: hard-block unauthorized actions
#[arg(long)]
pub enforce: bool,
/// Dry-run mode: allow and log unauthorized actions (exit 4 if they occur)
#[arg(long, conflicts_with = "enforce")]
pub dry_run: bool,
/// Fail if policy cannot be enforced (exit 2)
#[arg(long)]
pub fail_closed: bool,
/// Enforce the network policy as a Landlock TCP-connect port allowlist (ABI >= 4). Allowlist-only:
/// `net.allow` must be explicit TCP ports; any IP/CIDR, host, non-TCP protocol, range, deny rule,
/// or port 0 fails closed. Requires --enforce.
#[arg(long = "enforce-net", requires = "enforce")]
pub enforce_net: bool,
/// With --enforce-net, run a self-probe before the workload: from inside the enforcing ruleset,
/// attempt one connect to an ephemeral denied port. Only a real block (EACCES + the harness
/// listener never reached) writes the `probe` block into enforcement_health.v1. A probe that does
/// not prove a block does not fail the run; it is reported, never silently dropped.
#[arg(long = "probe-enforcement", requires = "enforce_net")]
pub probe_enforcement: bool,
/// Write the `assay.enforcement_health.v1` artifact (Landlock TCP-connect domain) to this path.
/// A requested artifact that cannot be written is a command failure, never a silent absence.
#[arg(long = "enforcement-health")]
pub enforcement_health: Option<PathBuf>,
/// Strict env mode: only safe base vars + explicit allows
#[arg(long = "env-strict")]
pub env_strict: bool,
/// Strip execution-influence vars (LD_PRELOAD, etc.)
#[arg(long = "env-strip-exec")]
pub env_strip_exec: bool,
/// Allow specific env vars through the filter (comma-separated or repeated)
#[arg(long = "env-allow", value_delimiter = ',')]
pub env_allow: Option<Vec<String>>,
/// DANGER: Pass all env vars without scrubbing
#[arg(long = "env-passthrough")]
pub env_passthrough: bool,
/// Force a safe PATH (/usr/bin:/bin on Linux)
#[arg(long = "env-safe-path")]
pub env_safe_path: bool,
/// Profile execution and generate policy suggestion at this path
#[arg(long)]
pub profile: Option<PathBuf>,
/// Profile output format: yaml | json (default: yaml)
#[arg(long, default_value = "yaml")]
pub profile_format: String,
/// Optional path for human-readable profile report
#[arg(long)]
pub profile_report: Option<PathBuf>,
/// Emit observed effects as a canonical evidence bundle (.tar.gz) at this path.
/// Requires --profile (the bundle is built from the profiled observations).
#[arg(long, requires = "profile")]
pub bundle: Option<PathBuf>,
/// Emit observed tool effects as OTel GenAI execute_tool spans (semconv JSONL)
/// at this path, each carrying the claim-class outcome. Requires --profile.
#[arg(long = "otel-jsonl", requires = "profile")]
pub otel_jsonl: Option<PathBuf>,
/// Show detailed sandbox setup
#[arg(long, short)]
pub verbose: bool,
/// Suppress banner output
#[arg(long, short)]
pub quiet: bool,
}