Skip to main content

batuta/falsification/
performance_waste.rs

1//! Section 5: Performance & Waste (Muda) Elimination (PW-01 to PW-15)
2//!
3//! Toyota Way efficiency principles applied to compute.
4//!
5//! # TPS Principles
6//!
7//! - **Muda (Waste)**: Waiting, Transport, Motion, Overprocessing elimination
8//! - **Jidoka**: Cost-based backend selection
9//! - **Genchi Genbutsu**: Measure actual performance
10
11use super::types::{CheckItem, Evidence, EvidenceType, Severity};
12use std::path::Path;
13use std::time::Instant;
14
15/// Evaluate all Performance & Waste checks.
16pub fn evaluate_all(project_path: &Path) -> Vec<CheckItem> {
17    vec![
18        check_pcie_rule(project_path),
19        check_simd_speedup(project_path),
20        check_wasm_performance(project_path),
21        check_inference_latency(project_path),
22        check_batch_efficiency(project_path),
23        check_parallel_scaling(project_path),
24        check_model_loading(project_path),
25        check_startup_time(project_path),
26        check_test_suite_time(project_path),
27        check_overprocessing(project_path),
28        check_zero_copy(project_path),
29        check_cache_efficiency(project_path),
30        check_cost_model(project_path),
31        check_transport_minimization(project_path),
32        check_inventory_minimization(project_path),
33    ]
34}
35
36/// PW-01: 5× PCIe Rule Validation
37pub fn check_pcie_rule(project_path: &Path) -> CheckItem {
38    let start = Instant::now();
39    let mut item = CheckItem::new(
40        "PW-01",
41        "5× PCIe Rule Validation",
42        "GPU dispatch beneficial when compute > 5× transfer",
43    )
44    .with_severity(Severity::Major)
45    .with_tps("Cost-based backend selection");
46
47    let has_gpu = check_for_pattern(project_path, &["wgpu", "cuda", "gpu", "GPU"]);
48    let has_cost_model =
49        check_for_pattern(project_path, &["cost_model", "crossover", "dispatch_threshold"]);
50
51    item = item.with_evidence(Evidence {
52        evidence_type: EvidenceType::StaticAnalysis,
53        description: format!("PCIe rule: gpu={}, cost_model={}", has_gpu, has_cost_model),
54        data: None,
55        files: Vec::new(),
56    });
57
58    if !has_gpu || has_cost_model {
59        item = item.pass();
60    } else {
61        item = item.partial("GPU usage without cost model");
62    }
63
64    item.finish_timed(start)
65}
66
67/// PW-02: SIMD Speedup Verification
68pub fn check_simd_speedup(project_path: &Path) -> CheckItem {
69    let start = Instant::now();
70    let mut item = CheckItem::new(
71        "PW-02",
72        "SIMD Speedup Verification",
73        "AVX2 provides >2× speedup over scalar",
74    )
75    .with_severity(Severity::Major)
76    .with_tps("Muda (Waiting) reduction");
77
78    let has_simd =
79        check_for_pattern(project_path, &["simd", "avx2", "avx512", "neon", "target_feature"]);
80    let has_benchmarks = project_path.join("benches").exists();
81
82    item = item.with_evidence(Evidence {
83        evidence_type: EvidenceType::StaticAnalysis,
84        description: format!("SIMD: impl={}, benchmarks={}", has_simd, has_benchmarks),
85        data: None,
86        files: Vec::new(),
87    });
88
89    if has_simd && has_benchmarks {
90        item = item.pass();
91    } else if has_simd {
92        item = item.partial("SIMD without speedup benchmarks");
93    } else {
94        item = item.partial("No SIMD optimization");
95    }
96
97    item.finish_timed(start)
98}
99
100/// PW-03: WASM Performance Ratio
101pub fn check_wasm_performance(project_path: &Path) -> CheckItem {
102    let start = Instant::now();
103    let mut item = CheckItem::new(
104        "PW-03",
105        "WASM Performance Ratio",
106        "WASM achieves 50-90% native performance",
107    )
108    .with_severity(Severity::Major)
109    .with_tps("Edge deployment efficiency");
110
111    let has_wasm = check_for_pattern(project_path, &["wasm", "wasm32", "wasm-bindgen"]);
112    let has_perf_tests = check_for_pattern(project_path, &["wasm_bench", "native_comparison"]);
113
114    item = item.with_evidence(Evidence {
115        evidence_type: EvidenceType::StaticAnalysis,
116        description: format!("WASM perf: wasm={}, benchmarks={}", has_wasm, has_perf_tests),
117        data: None,
118        files: Vec::new(),
119    });
120
121    if !has_wasm || has_perf_tests {
122        item = item.pass();
123    } else {
124        item = item.partial("WASM without performance comparison");
125    }
126
127    item.finish_timed(start)
128}
129
130/// PW-04: Inference Latency SLA
131pub fn check_inference_latency(project_path: &Path) -> CheckItem {
132    let start = Instant::now();
133    let mut item = CheckItem::new("PW-04", "Inference Latency SLA", "Inference <50ms/token on CPU")
134        .with_severity(Severity::Major)
135        .with_tps("Muda (Waiting) elimination");
136
137    let has_inference = check_for_pattern(project_path, &["inference", "infer", "predict"]);
138    let has_latency_tests = check_for_pattern(project_path, &["latency", "p99", "benchmark"]);
139
140    item = item.with_evidence(Evidence {
141        evidence_type: EvidenceType::StaticAnalysis,
142        description: format!("Latency: inference={}, tests={}", has_inference, has_latency_tests),
143        data: None,
144        files: Vec::new(),
145    });
146
147    if !has_inference || has_latency_tests {
148        item = item.pass();
149    } else {
150        item = item.partial("Inference without latency benchmarks");
151    }
152
153    item.finish_timed(start)
154}
155
156/// PW-05: Batch Processing Efficiency
157pub fn check_batch_efficiency(project_path: &Path) -> CheckItem {
158    let start = Instant::now();
159    let mut item = CheckItem::new(
160        "PW-05",
161        "Batch Processing Efficiency",
162        "Batching provides near-linear throughput scaling",
163    )
164    .with_severity(Severity::Major)
165    .with_tps("Resource utilization");
166
167    let has_batching = check_for_pattern(project_path, &["batch", "Batch", "batch_size"]);
168    let has_scaling_tests =
169        check_for_pattern(project_path, &["batch_scaling", "throughput", "batch_bench"]);
170
171    item = item.with_evidence(Evidence {
172        evidence_type: EvidenceType::StaticAnalysis,
173        description: format!("Batch: impl={}, tests={}", has_batching, has_scaling_tests),
174        data: None,
175        files: Vec::new(),
176    });
177
178    if !has_batching || has_scaling_tests {
179        item = item.pass();
180    } else {
181        item = item.partial("Batching without scaling verification");
182    }
183
184    item.finish_timed(start)
185}
186
187/// PW-06: Parallel Scaling Efficiency
188pub fn check_parallel_scaling(project_path: &Path) -> CheckItem {
189    let start = Instant::now();
190    let mut item = CheckItem::new(
191        "PW-06",
192        "Parallel Scaling Efficiency",
193        "Multi-threaded operations scale with cores",
194    )
195    .with_severity(Severity::Major)
196    .with_tps("Resource utilization");
197
198    let has_parallel = check_for_pattern(project_path, &["rayon", "parallel", "thread", "spawn"]);
199    let has_scaling_tests =
200        check_for_pattern(project_path, &["parallel_bench", "scaling", "amdahl"]);
201
202    item = item.with_evidence(Evidence {
203        evidence_type: EvidenceType::StaticAnalysis,
204        description: format!("Parallel: impl={}, tests={}", has_parallel, has_scaling_tests),
205        data: None,
206        files: Vec::new(),
207    });
208
209    if has_parallel && has_scaling_tests {
210        item = item.pass();
211    } else if has_parallel {
212        item = item.partial("Parallelization without scaling benchmarks");
213    } else {
214        item = item.partial("No parallel optimization");
215    }
216
217    item.finish_timed(start)
218}
219
220/// PW-07: Model Loading Time
221pub fn check_model_loading(project_path: &Path) -> CheckItem {
222    let start = Instant::now();
223    let mut item = CheckItem::new("PW-07", "Model Loading Time", "Model loading <2s per GB")
224        .with_severity(Severity::Minor)
225        .with_tps("Muda (Waiting)");
226
227    let has_model_loading = check_for_pattern(project_path, &["load_model", "ModelLoader", "mmap"]);
228    let has_loading_tests = check_for_pattern(project_path, &["load_bench", "loading_time"]);
229
230    item = item.with_evidence(Evidence {
231        evidence_type: EvidenceType::StaticAnalysis,
232        description: format!("Loading: impl={}, tests={}", has_model_loading, has_loading_tests),
233        data: None,
234        files: Vec::new(),
235    });
236
237    if !has_model_loading || has_loading_tests {
238        item = item.pass();
239    } else {
240        item = item.partial("Model loading without benchmarks");
241    }
242
243    item.finish_timed(start)
244}
245
246/// PW-08: Startup Time
247pub fn check_startup_time(project_path: &Path) -> CheckItem {
248    let start = Instant::now();
249    let mut item = CheckItem::new("PW-08", "Startup Time", "CLI startup <100ms")
250        .with_severity(Severity::Minor)
251        .with_tps("Developer experience");
252
253    // Check for hyperfine in CI or Makefile
254    let makefile = project_path.join("Makefile");
255    let has_startup_bench = makefile
256        .exists()
257        .then(|| std::fs::read_to_string(&makefile).ok())
258        .flatten()
259        .map(|c| c.contains("hyperfine") || c.contains("startup"))
260        .unwrap_or(false);
261
262    item = item.with_evidence(Evidence {
263        evidence_type: EvidenceType::StaticAnalysis,
264        description: format!("Startup: benchmark={}", has_startup_bench),
265        data: None,
266        files: Vec::new(),
267    });
268
269    if has_startup_bench {
270        item = item.pass();
271    } else {
272        item = item.partial("No startup time benchmarking");
273    }
274
275    item.finish_timed(start)
276}
277
278/// PW-09: Test Suite Performance
279pub fn check_test_suite_time(project_path: &Path) -> CheckItem {
280    let start = Instant::now();
281    let mut item = CheckItem::new("PW-09", "Test Suite Performance", "Full test suite <5 minutes")
282        .with_severity(Severity::Major)
283        .with_tps("Muda (Waiting) in CI");
284
285    // Check for nextest (faster test runner)
286    let has_nextest = project_path.join(".config/nextest.toml").exists();
287    let has_parallel_tests = check_for_pattern(project_path, &["nextest", "test-threads"]);
288
289    item = item.with_evidence(Evidence {
290        evidence_type: EvidenceType::StaticAnalysis,
291        description: format!("Test perf: nextest={}, parallel={}", has_nextest, has_parallel_tests),
292        data: None,
293        files: Vec::new(),
294    });
295
296    if has_nextest || has_parallel_tests {
297        item = item.pass();
298    } else {
299        item = item.partial("Tests without optimization (consider nextest)");
300    }
301
302    item.finish_timed(start)
303}
304
305/// PW-10: Overprocessing Detection
306pub fn check_overprocessing(project_path: &Path) -> CheckItem {
307    let start = Instant::now();
308    let mut item = CheckItem::new(
309        "PW-10",
310        "Overprocessing Detection",
311        "Model complexity justified by improvement",
312    )
313    .with_severity(Severity::Major)
314    .with_tps("Muda (Overprocessing)");
315
316    let has_baseline = check_for_pattern(project_path, &["baseline", "simple_model", "comparison"]);
317    let has_complexity_analysis =
318        check_for_pattern(project_path, &["complexity", "flops", "parameters"]);
319
320    item = item.with_evidence(Evidence {
321        evidence_type: EvidenceType::StaticAnalysis,
322        description: format!(
323            "Overprocessing: baseline={}, analysis={}",
324            has_baseline, has_complexity_analysis
325        ),
326        data: None,
327        files: Vec::new(),
328    });
329
330    if has_baseline {
331        item = item.pass();
332    } else {
333        let is_complex = check_for_pattern(project_path, &["transformer", "neural", "deep"]);
334        if !is_complex {
335            item = item.pass();
336        } else {
337            item = item.partial("Complex models without baseline comparison");
338        }
339    }
340
341    item.finish_timed(start)
342}
343
344/// PW-11: Zero-Copy Operation Verification
345pub fn check_zero_copy(project_path: &Path) -> CheckItem {
346    let start = Instant::now();
347    let mut item = CheckItem::new(
348        "PW-11",
349        "Zero-Copy Operation Verification",
350        "Hot paths operate without allocation",
351    )
352    .with_severity(Severity::Minor)
353    .with_tps("Muda (Motion) — memory efficiency");
354
355    let has_zero_copy =
356        check_for_pattern(project_path, &["zero_copy", "no_alloc", "in_place", "&mut"]);
357    let has_alloc_tests =
358        check_for_pattern(project_path, &["allocation_free", "heaptrack", "alloc_count"]);
359
360    item = item.with_evidence(Evidence {
361        evidence_type: EvidenceType::StaticAnalysis,
362        description: format!("Zero-copy: impl={}, tests={}", has_zero_copy, has_alloc_tests),
363        data: None,
364        files: Vec::new(),
365    });
366
367    if has_alloc_tests {
368        item = item.pass();
369    } else if has_zero_copy {
370        item = item.partial("Zero-copy patterns (verify with tests)");
371    } else {
372        item = item.partial("No explicit zero-copy optimization");
373    }
374
375    item.finish_timed(start)
376}
377
378/// PW-12: Cache Efficiency
379pub fn check_cache_efficiency(project_path: &Path) -> CheckItem {
380    let start = Instant::now();
381    let mut item = CheckItem::new("PW-12", "Cache Efficiency", "Cache >90% hit ratio")
382        .with_severity(Severity::Minor)
383        .with_tps("Muda (Waiting) reduction");
384
385    let has_cache = check_for_pattern(project_path, &["cache", "Cache", "lru", "memoize"]);
386    let has_cache_metrics =
387        check_for_pattern(project_path, &["hit_ratio", "cache_stats", "cache_hit"]);
388
389    item = item.with_evidence(Evidence {
390        evidence_type: EvidenceType::StaticAnalysis,
391        description: format!("Cache: impl={}, metrics={}", has_cache, has_cache_metrics),
392        data: None,
393        files: Vec::new(),
394    });
395
396    if !has_cache || has_cache_metrics {
397        item = item.pass();
398    } else {
399        item = item.partial("Cache without efficiency metrics");
400    }
401
402    item.finish_timed(start)
403}
404
405/// PW-13: Cost Model Accuracy
406pub fn check_cost_model(project_path: &Path) -> CheckItem {
407    let start = Instant::now();
408    let mut item = CheckItem::new(
409        "PW-13",
410        "Cost Model Accuracy",
411        "Backend selection predicts optimal choice >90%",
412    )
413    .with_severity(Severity::Major)
414    .with_tps("Intelligent automation (Jidoka)");
415
416    let has_cost_model =
417        check_for_pattern(project_path, &["cost_model", "CostModel", "backend_selection"]);
418    let has_accuracy_tests = check_for_pattern(project_path, &["prediction_accuracy", "cost_test"]);
419
420    item = item.with_evidence(Evidence {
421        evidence_type: EvidenceType::StaticAnalysis,
422        description: format!("Cost model: impl={}, tests={}", has_cost_model, has_accuracy_tests),
423        data: None,
424        files: Vec::new(),
425    });
426
427    if !has_cost_model || has_accuracy_tests {
428        item = item.pass();
429    } else {
430        item = item.partial("Cost model without accuracy verification");
431    }
432
433    item.finish_timed(start)
434}
435
436/// PW-14: Data Transport Minimization
437pub fn check_transport_minimization(project_path: &Path) -> CheckItem {
438    let start = Instant::now();
439    let mut item = CheckItem::new(
440        "PW-14",
441        "Data Transport Minimization",
442        "Data movement minimized through co-location",
443    )
444    .with_severity(Severity::Minor)
445    .with_tps("Muda (Transport)");
446
447    let has_colocation =
448        check_for_pattern(project_path, &["colocation", "locality", "data_parallel"]);
449
450    item = item.with_evidence(Evidence {
451        evidence_type: EvidenceType::StaticAnalysis,
452        description: format!("Transport: colocation={}", has_colocation),
453        data: None,
454        files: Vec::new(),
455    });
456
457    let has_distributed = check_for_pattern(project_path, &["distributed", "network", "remote"]);
458    if !has_distributed || has_colocation {
459        item = item.pass();
460    } else {
461        item = item.partial("Distributed compute without locality optimization");
462    }
463
464    item.finish_timed(start)
465}
466
467/// PW-15: Inventory (Data) Minimization
468pub fn check_inventory_minimization(project_path: &Path) -> CheckItem {
469    let start = Instant::now();
470    let mut item = CheckItem::new("PW-15", "Inventory Minimization", "No hoarded unused data")
471        .with_severity(Severity::Minor)
472        .with_tps("Muda (Inventory)");
473
474    let has_lifecycle =
475        check_for_pattern(project_path, &["lifecycle", "retention", "ttl", "expiration"]);
476    let has_cleanup = check_for_pattern(project_path, &["cleanup", "prune", "garbage_collect"]);
477
478    item = item.with_evidence(Evidence {
479        evidence_type: EvidenceType::StaticAnalysis,
480        description: format!("Inventory: lifecycle={}, cleanup={}", has_lifecycle, has_cleanup),
481        data: None,
482        files: Vec::new(),
483    });
484
485    let stores_data = check_for_pattern(project_path, &["store", "persist", "save"]);
486    if !stores_data || has_lifecycle || has_cleanup {
487        item = item.pass();
488    } else {
489        item = item.partial("Data storage without lifecycle management");
490    }
491
492    item.finish_timed(start)
493}
494
495fn check_for_pattern(project_path: &Path, patterns: &[&str]) -> bool {
496    super::helpers::source_contains_pattern(project_path, patterns)
497}
498
499#[cfg(test)]
500mod tests {
501    use super::*;
502    use std::path::PathBuf;
503
504    #[test]
505    fn test_evaluate_all_returns_15_items() {
506        let path = PathBuf::from(".");
507        let items = evaluate_all(&path);
508        assert_eq!(items.len(), 15);
509    }
510
511    #[test]
512    fn test_all_items_have_tps_principle() {
513        let path = PathBuf::from(".");
514        for item in evaluate_all(&path) {
515            assert!(!item.tps_principle.is_empty(), "Item {} missing TPS", item.id);
516        }
517    }
518
519    #[test]
520    fn test_all_items_have_evidence() {
521        let path = PathBuf::from(".");
522        for item in evaluate_all(&path) {
523            assert!(!item.evidence.is_empty(), "Item {} missing evidence", item.id);
524        }
525    }
526
527    #[test]
528    fn test_check_pcie_rule() {
529        let path = PathBuf::from(".");
530        let item = check_pcie_rule(&path);
531        assert_eq!(item.id, "PW-01");
532        assert!(item.name.contains("PCIe"));
533        assert_eq!(item.severity, Severity::Major);
534        assert!(item.tps_principle.contains("Cost-based"));
535    }
536
537    #[test]
538    fn test_check_simd_speedup() {
539        let path = PathBuf::from(".");
540        let item = check_simd_speedup(&path);
541        assert_eq!(item.id, "PW-02");
542        assert!(item.name.contains("SIMD"));
543        assert_eq!(item.severity, Severity::Major);
544        assert!(item.tps_principle.contains("Muda"));
545    }
546
547    #[test]
548    fn test_check_wasm_performance() {
549        let path = PathBuf::from(".");
550        let item = check_wasm_performance(&path);
551        assert_eq!(item.id, "PW-03");
552        assert!(item.name.contains("WASM"));
553        assert_eq!(item.severity, Severity::Major);
554    }
555
556    #[test]
557    fn test_check_inference_latency() {
558        let path = PathBuf::from(".");
559        let item = check_inference_latency(&path);
560        assert_eq!(item.id, "PW-04");
561        assert!(item.name.contains("Inference"));
562        assert_eq!(item.severity, Severity::Major);
563    }
564
565    #[test]
566    fn test_check_batch_efficiency() {
567        let path = PathBuf::from(".");
568        let item = check_batch_efficiency(&path);
569        assert_eq!(item.id, "PW-05");
570        assert!(item.name.contains("Batch"));
571        assert_eq!(item.severity, Severity::Major);
572    }
573
574    #[test]
575    fn test_check_parallel_scaling() {
576        let path = PathBuf::from(".");
577        let item = check_parallel_scaling(&path);
578        assert_eq!(item.id, "PW-06");
579        assert!(item.name.contains("Parallel"));
580        assert_eq!(item.severity, Severity::Major);
581    }
582
583    #[test]
584    fn test_check_model_loading() {
585        let path = PathBuf::from(".");
586        let item = check_model_loading(&path);
587        assert_eq!(item.id, "PW-07");
588        assert!(item.name.contains("Model Loading"));
589        assert_eq!(item.severity, Severity::Minor);
590    }
591
592    #[test]
593    fn test_check_startup_time() {
594        let path = PathBuf::from(".");
595        let item = check_startup_time(&path);
596        assert_eq!(item.id, "PW-08");
597        assert!(item.name.contains("Startup"));
598        assert_eq!(item.severity, Severity::Minor);
599    }
600
601    #[test]
602    fn test_check_test_suite_time() {
603        let path = PathBuf::from(".");
604        let item = check_test_suite_time(&path);
605        assert_eq!(item.id, "PW-09");
606        assert!(item.name.contains("Test Suite"));
607        assert_eq!(item.severity, Severity::Major);
608    }
609
610    #[test]
611    fn test_check_overprocessing() {
612        let path = PathBuf::from(".");
613        let item = check_overprocessing(&path);
614        assert_eq!(item.id, "PW-10");
615        assert!(item.name.contains("Overprocessing"));
616        assert_eq!(item.severity, Severity::Major);
617    }
618
619    #[test]
620    fn test_check_zero_copy() {
621        let path = PathBuf::from(".");
622        let item = check_zero_copy(&path);
623        assert_eq!(item.id, "PW-11");
624        assert!(item.name.contains("Zero-Copy"));
625        assert_eq!(item.severity, Severity::Minor);
626    }
627
628    #[test]
629    fn test_check_cache_efficiency() {
630        let path = PathBuf::from(".");
631        let item = check_cache_efficiency(&path);
632        assert_eq!(item.id, "PW-12");
633        assert!(item.name.contains("Cache"));
634        assert_eq!(item.severity, Severity::Minor);
635    }
636
637    #[test]
638    fn test_check_cost_model() {
639        let path = PathBuf::from(".");
640        let item = check_cost_model(&path);
641        assert_eq!(item.id, "PW-13");
642        assert!(item.name.contains("Cost Model"));
643        assert_eq!(item.severity, Severity::Major);
644    }
645
646    #[test]
647    fn test_check_transport_minimization() {
648        let path = PathBuf::from(".");
649        let item = check_transport_minimization(&path);
650        assert_eq!(item.id, "PW-14");
651        assert!(item.name.contains("Transport"));
652        assert_eq!(item.severity, Severity::Minor);
653    }
654
655    #[test]
656    fn test_check_inventory_minimization() {
657        let path = PathBuf::from(".");
658        let item = check_inventory_minimization(&path);
659        assert_eq!(item.id, "PW-15");
660        assert!(item.name.contains("Inventory"));
661        assert_eq!(item.severity, Severity::Minor);
662    }
663
664    #[test]
665    fn test_item_ids_are_unique() {
666        let path = PathBuf::from(".");
667        let items = evaluate_all(&path);
668        let mut ids: Vec<&str> = items.iter().map(|i| i.id.as_str()).collect();
669        ids.sort();
670        ids.dedup();
671        assert_eq!(ids.len(), 15, "All item IDs should be unique");
672    }
673
674    #[test]
675    fn test_item_names_are_descriptive() {
676        let path = PathBuf::from(".");
677        for item in evaluate_all(&path) {
678            assert!(item.name.len() >= 10, "Item {} name too short: {}", item.id, item.name);
679        }
680    }
681
682    // =========================================================================
683    // Coverage Gap: check_overprocessing branch where complex && !baseline
684    // =========================================================================
685
686    #[test]
687    fn test_check_overprocessing_complex_without_baseline() {
688        // Create a temp project with "transformer" but no "baseline"
689        let temp_dir = std::env::temp_dir().join("test_pw10_complex");
690        let _ = std::fs::remove_dir_all(&temp_dir);
691        std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
692
693        // Has complex patterns but no baseline
694        std::fs::write(
695            temp_dir.join("src/model.rs"),
696            "pub struct TransformerBlock { layers: Vec<NeuralLayer> }\npub fn deep_forward() {}",
697        )
698        .expect("unexpected failure");
699
700        let result = check_overprocessing(&temp_dir);
701        assert_eq!(result.id, "PW-10");
702        // Should be partial: "Complex models without baseline comparison"
703        assert_eq!(result.status, super::super::types::CheckStatus::Partial);
704        assert!(result.rejection_reason.as_deref().unwrap_or("").contains("baseline"));
705
706        let _ = std::fs::remove_dir_all(&temp_dir);
707    }
708
709    #[test]
710    fn test_check_overprocessing_not_complex_no_baseline() {
711        // Project with no baseline AND no complex patterns -> pass
712        let temp_dir = std::env::temp_dir().join("test_pw10_simple");
713        let _ = std::fs::remove_dir_all(&temp_dir);
714        std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
715
716        std::fs::write(temp_dir.join("src/lib.rs"), "pub fn add(a: i32, b: i32) -> i32 { a + b }")
717            .expect("unexpected failure");
718
719        let result = check_overprocessing(&temp_dir);
720        assert_eq!(result.id, "PW-10");
721        assert_eq!(result.status, super::super::types::CheckStatus::Pass);
722
723        let _ = std::fs::remove_dir_all(&temp_dir);
724    }
725
726    #[test]
727    fn test_check_overprocessing_with_baseline() {
728        // Project with baseline pattern -> pass
729        let temp_dir = std::env::temp_dir().join("test_pw10_baseline");
730        let _ = std::fs::remove_dir_all(&temp_dir);
731        std::fs::create_dir_all(temp_dir.join("src")).expect("mkdir failed");
732
733        std::fs::write(
734            temp_dir.join("src/lib.rs"),
735            "pub fn baseline_comparison() -> f64 { 0.0 }\npub fn transformer_forward() {}",
736        )
737        .expect("unexpected failure");
738
739        let result = check_overprocessing(&temp_dir);
740        assert_eq!(result.id, "PW-10");
741        assert_eq!(result.status, super::super::types::CheckStatus::Pass);
742
743        let _ = std::fs::remove_dir_all(&temp_dir);
744    }
745
746    // =====================================================================
747    // Coverage: additional branch coverage with tempdir
748    // =====================================================================
749
750    fn empty_dir() -> tempfile::TempDir {
751        tempfile::TempDir::new().expect("Failed to create temp dir")
752    }
753
754    #[test]
755    fn test_pcie_rule_gpu_no_cost_model() {
756        let dir = empty_dir();
757        let src_dir = dir.path().join("src");
758        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
759        std::fs::write(src_dir.join("gpu.rs"), "fn gpu_compute() { use wgpu::Device; }")
760            .expect("unexpected failure");
761        let item = check_pcie_rule(dir.path());
762        assert_eq!(item.id, "PW-01");
763        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
764        assert!(item
765            .rejection_reason
766            .as_ref()
767            .expect("unexpected failure")
768            .contains("GPU usage without cost model"));
769    }
770
771    #[test]
772    fn test_simd_no_benchmarks() {
773        let dir = empty_dir();
774        let src_dir = dir.path().join("src");
775        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
776        std::fs::write(
777            src_dir.join("simd.rs"),
778            "#[target_feature(enable = \"avx2\")] fn simd_dot() {}",
779        )
780        .expect("unexpected failure");
781        let item = check_simd_speedup(dir.path());
782        assert_eq!(item.id, "PW-02");
783        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
784        assert!(item
785            .rejection_reason
786            .as_ref()
787            .expect("unexpected failure")
788            .contains("SIMD without speedup benchmarks"));
789    }
790
791    #[test]
792    fn test_simd_no_simd_at_all() {
793        let dir = empty_dir();
794        let item = check_simd_speedup(dir.path());
795        assert_eq!(item.id, "PW-02");
796        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
797        assert!(item
798            .rejection_reason
799            .as_ref()
800            .expect("unexpected failure")
801            .contains("No SIMD optimization"));
802    }
803
804    #[test]
805    fn test_simd_with_benchmarks() {
806        let dir = empty_dir();
807        let src_dir = dir.path().join("src");
808        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
809        std::fs::write(
810            src_dir.join("simd.rs"),
811            "#[target_feature(enable = \"avx2\")] fn simd_dot() {}",
812        )
813        .expect("unexpected failure");
814        std::fs::create_dir_all(dir.path().join("benches")).expect("mkdir failed");
815        let item = check_simd_speedup(dir.path());
816        assert_eq!(item.id, "PW-02");
817        assert_eq!(item.status, super::super::types::CheckStatus::Pass);
818    }
819
820    #[test]
821    fn test_parallel_no_scaling_tests() {
822        let dir = empty_dir();
823        let src_dir = dir.path().join("src");
824        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
825        std::fs::write(src_dir.join("par.rs"), "use rayon::prelude::*; fn parallel_map() {}")
826            .expect("unexpected failure");
827        let item = check_parallel_scaling(dir.path());
828        assert_eq!(item.id, "PW-06");
829        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
830        assert!(item
831            .rejection_reason
832            .as_ref()
833            .expect("unexpected failure")
834            .contains("Parallelization without scaling"));
835    }
836
837    #[test]
838    fn test_parallel_no_parallel() {
839        let dir = empty_dir();
840        let item = check_parallel_scaling(dir.path());
841        assert_eq!(item.id, "PW-06");
842        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
843        assert!(item
844            .rejection_reason
845            .as_ref()
846            .expect("unexpected failure")
847            .contains("No parallel optimization"));
848    }
849
850    #[test]
851    fn test_parallel_with_scaling_tests() {
852        let dir = empty_dir();
853        let src_dir = dir.path().join("src");
854        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
855        std::fs::write(
856            src_dir.join("par.rs"),
857            "use rayon::prelude::*; fn scaling() {} fn amdahl() {}",
858        )
859        .expect("unexpected failure");
860        let item = check_parallel_scaling(dir.path());
861        assert_eq!(item.id, "PW-06");
862        assert_eq!(item.status, super::super::types::CheckStatus::Pass);
863    }
864
865    #[test]
866    fn test_zero_copy_patterns_no_tests() {
867        let dir = empty_dir();
868        let src_dir = dir.path().join("src");
869        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
870        std::fs::write(
871            src_dir.join("zc.rs"),
872            "fn process_in_place(data: &mut [f32]) { /* zero_copy */ }",
873        )
874        .expect("unexpected failure");
875        let item = check_zero_copy(dir.path());
876        assert_eq!(item.id, "PW-11");
877        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
878        assert!(item
879            .rejection_reason
880            .as_ref()
881            .expect("unexpected failure")
882            .contains("Zero-copy patterns"));
883    }
884
885    #[test]
886    fn test_zero_copy_no_patterns() {
887        let dir = empty_dir();
888        let item = check_zero_copy(dir.path());
889        assert_eq!(item.id, "PW-11");
890        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
891        assert!(item
892            .rejection_reason
893            .as_ref()
894            .expect("unexpected failure")
895            .contains("No explicit zero-copy"));
896    }
897
898    #[test]
899    fn test_zero_copy_with_alloc_tests() {
900        let dir = empty_dir();
901        let src_dir = dir.path().join("src");
902        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
903        std::fs::write(
904            src_dir.join("test.rs"),
905            "fn allocation_free_test() { let c = alloc_count(); }",
906        )
907        .expect("unexpected failure");
908        let item = check_zero_copy(dir.path());
909        assert_eq!(item.id, "PW-11");
910        assert_eq!(item.status, super::super::types::CheckStatus::Pass);
911    }
912
913    #[test]
914    fn test_startup_time_with_hyperfine() {
915        let dir = empty_dir();
916        std::fs::write(dir.path().join("Makefile"), "bench:\n\thyperfine ./target/release/app")
917            .expect("unexpected failure");
918        let item = check_startup_time(dir.path());
919        assert_eq!(item.id, "PW-08");
920        assert_eq!(item.status, super::super::types::CheckStatus::Pass);
921    }
922
923    #[test]
924    fn test_startup_time_no_makefile() {
925        let dir = empty_dir();
926        let item = check_startup_time(dir.path());
927        assert_eq!(item.id, "PW-08");
928        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
929    }
930
931    #[test]
932    fn test_startup_time_makefile_no_hyperfine() {
933        let dir = empty_dir();
934        std::fs::write(dir.path().join("Makefile"), "build:\n\tcargo build --release")
935            .expect("unexpected failure");
936        let item = check_startup_time(dir.path());
937        assert_eq!(item.id, "PW-08");
938        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
939    }
940
941    #[test]
942    fn test_startup_time_makefile_with_startup_keyword() {
943        let dir = empty_dir();
944        std::fs::write(dir.path().join("Makefile"), "bench-startup:\n\ttime ./app")
945            .expect("fs write failed");
946        let item = check_startup_time(dir.path());
947        assert_eq!(item.id, "PW-08");
948        assert_eq!(item.status, super::super::types::CheckStatus::Pass);
949    }
950
951    #[test]
952    fn test_test_suite_with_nextest_config() {
953        let dir = empty_dir();
954        let config_dir = dir.path().join(".config");
955        std::fs::create_dir_all(&config_dir).expect("mkdir failed");
956        std::fs::write(config_dir.join("nextest.toml"), "[profile.default]\n")
957            .expect("fs write failed");
958        let item = check_test_suite_time(dir.path());
959        assert_eq!(item.id, "PW-09");
960        assert_eq!(item.status, super::super::types::CheckStatus::Pass);
961    }
962
963    #[test]
964    fn test_test_suite_no_nextest() {
965        let dir = empty_dir();
966        let item = check_test_suite_time(dir.path());
967        assert_eq!(item.id, "PW-09");
968        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
969    }
970
971    #[test]
972    fn test_wasm_no_perf_tests() {
973        let dir = empty_dir();
974        let src_dir = dir.path().join("src");
975        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
976        std::fs::write(src_dir.join("wasm.rs"), "use wasm_bindgen::prelude::*;")
977            .expect("fs write failed");
978        let item = check_wasm_performance(dir.path());
979        assert_eq!(item.id, "PW-03");
980        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
981        assert!(item
982            .rejection_reason
983            .as_ref()
984            .expect("unexpected failure")
985            .contains("WASM without performance comparison"));
986    }
987
988    #[test]
989    fn test_inference_no_latency() {
990        let dir = empty_dir();
991        let src_dir = dir.path().join("src");
992        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
993        std::fs::write(
994            src_dir.join("serve.rs"),
995            "fn inference(model: &Model) -> Vec<f32> { vec![] }",
996        )
997        .expect("unexpected failure");
998        let item = check_inference_latency(dir.path());
999        assert_eq!(item.id, "PW-04");
1000        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1001    }
1002
1003    #[test]
1004    fn test_batch_no_scaling() {
1005        let dir = empty_dir();
1006        let src_dir = dir.path().join("src");
1007        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1008        std::fs::write(src_dir.join("batch.rs"), "fn batch_process(batch_size: usize) {}")
1009            .expect("unexpected failure");
1010        let item = check_batch_efficiency(dir.path());
1011        assert_eq!(item.id, "PW-05");
1012        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1013    }
1014
1015    #[test]
1016    fn test_model_loading_no_benchmarks() {
1017        let dir = empty_dir();
1018        let src_dir = dir.path().join("src");
1019        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1020        std::fs::write(src_dir.join("loader.rs"), "fn load_model(path: &str) { mmap(path); }")
1021            .expect("unexpected failure");
1022        let item = check_model_loading(dir.path());
1023        assert_eq!(item.id, "PW-07");
1024        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1025    }
1026
1027    #[test]
1028    fn test_cache_no_metrics() {
1029        let dir = empty_dir();
1030        let src_dir = dir.path().join("src");
1031        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1032        std::fs::write(src_dir.join("cache.rs"), "struct LruCache {} fn memoize() {}")
1033            .expect("unexpected failure");
1034        let item = check_cache_efficiency(dir.path());
1035        assert_eq!(item.id, "PW-12");
1036        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1037    }
1038
1039    #[test]
1040    fn test_cost_model_no_tests() {
1041        let dir = empty_dir();
1042        let src_dir = dir.path().join("src");
1043        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1044        std::fs::write(src_dir.join("cost.rs"), "struct CostModel {} fn backend_selection() {}")
1045            .expect("unexpected failure");
1046        let item = check_cost_model(dir.path());
1047        assert_eq!(item.id, "PW-13");
1048        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1049    }
1050
1051    #[test]
1052    fn test_transport_distributed_no_colocation() {
1053        let dir = empty_dir();
1054        let src_dir = dir.path().join("src");
1055        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1056        std::fs::write(src_dir.join("dist.rs"), "fn distributed(remote: &str) { network_send(); }")
1057            .expect("unexpected failure");
1058        let item = check_transport_minimization(dir.path());
1059        assert_eq!(item.id, "PW-14");
1060        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1061    }
1062
1063    #[test]
1064    fn test_inventory_no_lifecycle() {
1065        let dir = empty_dir();
1066        let src_dir = dir.path().join("src");
1067        std::fs::create_dir_all(&src_dir).expect("mkdir failed");
1068        std::fs::write(src_dir.join("storage.rs"), "fn store(key: &str) { persist(); save(); }")
1069            .expect("unexpected failure");
1070        let item = check_inventory_minimization(dir.path());
1071        assert_eq!(item.id, "PW-15");
1072        assert_eq!(item.status, super::super::types::CheckStatus::Partial);
1073    }
1074
1075    #[test]
1076    fn test_evaluate_all_empty_project() {
1077        let dir = empty_dir();
1078        let items = evaluate_all(dir.path());
1079        assert_eq!(items.len(), 15);
1080        for item in &items {
1081            assert!(!item.evidence.is_empty(), "Item {} missing evidence", item.id);
1082        }
1083    }
1084}