|
1 | 1 | // SPDX-License-Identifier: MPL-2.0 |
2 | 2 |
|
3 | 3 | //! Minimal GUI for reviewing assault reports, system images, and temporal diffs. |
| 4 | +//! |
| 5 | +//! This module is compiled only when the `gui` feature is enabled because the |
| 6 | +//! `eframe`/`egui` dependency chain raises MSRV above the 1.85.0 baseline. |
| 7 | +//! The text-only `gui --headless` path lives in [`super::gui_text`] and is |
| 8 | +//! always compiled. |
4 | 9 |
|
5 | 10 | use crate::mass_panic::imaging::SystemImage; |
6 | 11 | use crate::mass_panic::temporal::TemporalDiff; |
@@ -65,99 +70,6 @@ impl ReportGui { |
65 | 70 | Ok(()) |
66 | 71 | } |
67 | 72 |
|
68 | | - /// Run without a display server: print a structured text summary of all panels. |
69 | | - /// |
70 | | - /// Safe to call in CI or headless environments with no Wayland/X11 display. |
71 | | - /// Promotes the gui subcommand from Grade E to Grade D. |
72 | | - pub fn run_headless(report: AssaultReport) -> Result<()> { |
73 | | - let assail = &report.assail_report; |
74 | | - let formatter = ReportFormatter::new(); |
75 | | - |
76 | | - println!("PANIC-ATTACK GUI REPORT (headless)"); |
77 | | - println!(); |
78 | | - |
79 | | - println!("=== Summary ==="); |
80 | | - println!("Language: {:?}", assail.language); |
81 | | - println!( |
82 | | - "Score: {:.1}/100", |
83 | | - report.overall_assessment.robustness_score |
84 | | - ); |
85 | | - println!("Crashes: {}", report.total_crashes); |
86 | | - println!("Signatures: {}", report.total_signatures); |
87 | | - println!("Weak points: {}", assail.weak_points.len()); |
88 | | - println!("Frameworks: {:?}", assail.frameworks); |
89 | | - println!(); |
90 | | - |
91 | | - println!("=== Assail ==="); |
92 | | - println!("Program: {}", assail.program_path.display()); |
93 | | - println!( |
94 | | - "Stats: lines={} unsafe={} panics={} unwraps={}", |
95 | | - assail.statistics.total_lines, |
96 | | - assail.statistics.unsafe_blocks, |
97 | | - assail.statistics.panic_sites, |
98 | | - assail.statistics.unwrap_calls |
99 | | - ); |
100 | | - for wp in &assail.weak_points { |
101 | | - let loc = wp |
102 | | - .location |
103 | | - .as_deref() |
104 | | - .or(wp.file.as_deref()) |
105 | | - .unwrap_or("<unknown>"); |
106 | | - println!( |
107 | | - " [{:?}] {:?} @ {} — {}", |
108 | | - wp.severity, wp.category, loc, wp.description |
109 | | - ); |
110 | | - } |
111 | | - println!(); |
112 | | - |
113 | | - println!("=== File Risk ==="); |
114 | | - for detail in formatter.file_risk_details(assail) { |
115 | | - println!(" {}", detail); |
116 | | - } |
117 | | - println!(); |
118 | | - |
119 | | - println!("=== Matrix ==="); |
120 | | - println!( |
121 | | - "Dependency edges: {} Taint rows: {}", |
122 | | - assail.dependency_graph.edges.len(), |
123 | | - assail.taint_matrix.rows.len() |
124 | | - ); |
125 | | - for detail in formatter.taint_matrix_details(assail) { |
126 | | - println!(" {}", detail); |
127 | | - } |
128 | | - println!(); |
129 | | - |
130 | | - println!("=== Attacks ==="); |
131 | | - for result in &report.attack_results { |
132 | | - let status = if result.skipped { |
133 | | - "skipped" |
134 | | - } else if result.success { |
135 | | - "passed" |
136 | | - } else { |
137 | | - "failed" |
138 | | - }; |
139 | | - println!( |
140 | | - " {:?}: {} crashes={} duration={:.2}s", |
141 | | - result.axis, |
142 | | - status, |
143 | | - result.crashes.len(), |
144 | | - result.duration.as_secs_f64() |
145 | | - ); |
146 | | - } |
147 | | - println!(); |
148 | | - |
149 | | - println!("=== Assessment ==="); |
150 | | - for issue in &report.overall_assessment.critical_issues { |
151 | | - println!(" CRITICAL: {}", issue); |
152 | | - } |
153 | | - for rec in &report.overall_assessment.recommendations { |
154 | | - println!(" REC: {}", rec); |
155 | | - } |
156 | | - println!(); |
157 | | - |
158 | | - Ok(()) |
159 | | - } |
160 | | - |
161 | 73 | /// Attempt to load a JSON file as either an `AssaultReport`, `SystemImage`, |
162 | 74 | /// or `TemporalDiff`. Detection is format-based: we try each in turn and |
163 | 75 | /// keep the first successful parse. |
|
0 commit comments