1use crate::edd::{EmcComplianceReport, ExperimentResult};
7
8pub fn print_version() {
10 println!("simular {}", env!("CARGO_PKG_VERSION"));
11}
12
13pub fn print_help() {
15 println!(
16 r"simular - Unified Simulation Engine for the Sovereign AI Stack
17
18USAGE:
19 simular <COMMAND> [OPTIONS]
20
21COMMANDS:
22 run <experiment.yaml> Run an experiment
23 --seed <N> Override the experiment seed
24 -v, --verbose Enable verbose output
25
26 verify <experiment.yaml> Verify reproducibility across multiple runs
27 --runs <N> Number of verification runs (default: 3)
28
29 emc-check <experiment.yaml> Check EMC compliance and generate report
30
31 emc-validate <file.emc.yaml> Validate an EMC file against the schema
32
33 list-emc List available EMCs in the library
34
35 help Show this help message
36 version Show version information
37
38EXAMPLES:
39 simular run experiments/harmonic_oscillator.yaml
40 simular run experiments/harmonic_oscillator.yaml --seed 12345
41 simular verify experiments/harmonic_oscillator.yaml --runs 5
42 simular emc-check experiments/littles_law.yaml
43
44EDD COMPLIANCE:
45 All experiments are validated against the four pillars of EDD:
46 1. Prove It - Every simulation has an EMC reference
47 2. Fail It - Verification tests are executed
48 3. Seed It - Explicit seed is required
49 4. Falsify It - Falsification criteria are checked
50
51For more information, see: https://github.com/paiml/simular
52"
53 );
54}
55
56pub fn print_experiment_result(result: &ExperimentResult, verbose: bool) {
63 let status = if result.passed { "PASSED" } else { "FAILED" };
64 let status_symbol = if result.passed { "✓" } else { "✗" };
65
66 print_header(&result.name, &result.experiment_id, result.seed);
67 print_verification(&result.verification, verbose);
68 print_falsification(&result.falsification, verbose);
69 print_reproducibility(result.reproducibility.as_ref());
70 print_execution(&result.execution);
71 print_warnings(&result.warnings);
72 print_footer(status_symbol, status);
73}
74
75fn print_header(name: &str, id: &str, seed: u64) {
76 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
77 println!("Experiment: {name}");
78 println!("ID: {id}");
79 println!("Seed: {seed}");
80 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
81}
82
83fn print_verification(verification: &crate::edd::VerificationSummary, verbose: bool) {
84 println!("Verification Tests:");
85 println!(" Total: {}", verification.total);
86 println!(" Passed: {}", verification.passed);
87 println!(" Failed: {}", verification.failed);
88
89 if verbose && !verification.tests.is_empty() {
90 println!();
91 for test in &verification.tests {
92 let sym = if test.passed { "✓" } else { "✗" };
93 println!(" {} {}: {}", sym, test.id, test.name);
94 if let Some(ref err) = test.error {
95 if !test.passed {
96 println!(" Error: {err}");
97 }
98 }
99 }
100 }
101}
102
103fn print_falsification(falsification: &crate::edd::FalsificationSummary, verbose: bool) {
104 println!("\nFalsification Criteria:");
105 println!(" Total: {}", falsification.total);
106 println!(" Passed: {}", falsification.passed);
107 println!(" Triggered: {}", falsification.triggered);
108
109 if falsification.jidoka_triggered {
110 println!(" Jidoka: TRIGGERED (stop-on-error)");
111 }
112
113 if verbose && !falsification.criteria.is_empty() {
114 println!();
115 for crit in &falsification.criteria {
116 let sym = if crit.triggered { "✗" } else { "✓" };
117 println!(" {} {}: {}", sym, crit.id, crit.name);
118 if crit.triggered {
119 println!(" Condition: {}", crit.condition);
120 }
121 }
122 }
123}
124
125fn print_reproducibility(_reproducibility: Option<&crate::edd::ReproducibilitySummary>) {
126 }
128
129fn print_execution(execution: &crate::edd::ExecutionMetrics) {
130 println!("\nExecution:");
131 println!(" Duration: {} ms", execution.duration_ms);
132 println!(" Replications: {}", execution.replications);
133}
134
135fn print_warnings(warnings: &[String]) {
136 if !warnings.is_empty() {
137 println!("\nWarnings:");
138 for warning in warnings {
139 println!(" ! {warning}");
140 }
141 }
142}
143
144fn print_footer(status_symbol: &str, status: &str) {
145 println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
146 println!("{status_symbol} Result: {status}");
147 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
148}
149
150pub fn print_emc_report(report: &EmcComplianceReport) {
156 let status = if report.passed {
157 "COMPLIANT"
158 } else {
159 "NON-COMPLIANT"
160 };
161 let sym = if report.passed { "✓" } else { "✗" };
162
163 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
164 println!("EMC Compliance Report: {}", report.experiment_name);
165 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
166
167 println!("EDD Compliance Checklist:");
169 let check = |passed: bool| if passed { "✓" } else { "✗" };
170
171 println!(
172 " {} EDD-01: EMC Reference",
173 check(report.edd_compliance.edd_01_emc_reference)
174 );
175 println!(
176 " {} EDD-02: Verification Tests",
177 check(report.edd_compliance.edd_02_verification_tests)
178 );
179 println!(
180 " {} EDD-03: Seed Specified",
181 check(report.edd_compliance.edd_03_seed_specified)
182 );
183 println!(
184 " {} EDD-04: Falsification Criteria",
185 check(report.edd_compliance.edd_04_falsification_criteria)
186 );
187 println!(
188 " {} EDD-05: Hypothesis (Optional)",
189 check(report.edd_compliance.edd_05_hypothesis)
190 );
191
192 if !report.schema_errors.is_empty() {
194 println!("\nSchema Errors:");
195 for err in &report.schema_errors {
196 println!(" ✗ {err}");
197 }
198 }
199
200 if !report.emc_errors.is_empty() {
202 println!("\nEMC Errors:");
203 for err in &report.emc_errors {
204 println!(" ✗ {err}");
205 }
206 }
207
208 if !report.warnings.is_empty() {
210 println!("\nWarnings:");
211 for warning in &report.warnings {
212 println!(" ! {warning}");
213 }
214 }
215
216 println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
217 println!("{sym} Result: {status}");
218 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
219}
220
221pub fn print_emc_validation_results(
229 yaml: &serde_yaml::Value,
230 errors: &[String],
231 warnings: &[String],
232) {
233 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
234 if let Some(name) = yaml
235 .get("identity")
236 .and_then(|i| i.get("name"))
237 .and_then(|n| n.as_str())
238 {
239 println!("EMC: {name}");
240 }
241 if let Some(id) = yaml.get("emc_id").and_then(|id| id.as_str()) {
242 println!("ID: {id}");
243 }
244 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
245
246 let check = |b: bool| if b { "✓" } else { "✗" };
247 println!("Schema Validation:");
248 println!(" {} emc_version", check(yaml.get("emc_version").is_some()));
249 println!(" {} emc_id", check(yaml.get("emc_id").is_some()));
250 println!(" {} identity", check(yaml.get("identity").is_some()));
251 println!(
252 " {} governing_equation",
253 check(yaml.get("governing_equation").is_some())
254 );
255 println!(
256 " {} analytical_derivation",
257 check(yaml.get("analytical_derivation").is_some())
258 );
259 println!(
260 " {} domain_of_validity",
261 check(yaml.get("domain_of_validity").is_some())
262 );
263 println!(
264 " {} verification_tests",
265 check(yaml.get("verification_tests").is_some())
266 );
267 println!(
268 " {} falsification_criteria",
269 check(yaml.get("falsification_criteria").is_some())
270 );
271
272 if !errors.is_empty() {
273 println!("\nErrors:");
274 for err in errors {
275 println!(" ✗ {err}");
276 }
277 }
278 if !warnings.is_empty() {
279 println!("\nWarnings:");
280 for w in warnings {
281 println!(" ! {w}");
282 }
283 }
284
285 let (status, sym) = if errors.is_empty() {
286 ("VALID", "✓")
287 } else {
288 ("INVALID", "✗")
289 };
290 println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
291 println!("{sym} Result: {status}");
292 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
293}