metrale_bench/benchmarks/serve_matrix/
score.rs1use super::plan::Plan;
13
14pub const COHERENCE_MIN_PASS: usize = 2;
17
18pub const TPS_TOLERANCE: f64 = 0.10;
20
21#[derive(Clone, Debug, Default, PartialEq, Eq)]
25pub enum Signal {
26 Pass,
27 Fail(String),
28 NotApplicable(String),
29 #[default]
32 NotRun,
33}
34
35impl Signal {
36 pub fn is_fail(&self) -> bool {
37 matches!(self, Signal::Fail(_))
38 }
39
40 pub fn text(&self) -> &str {
41 match self {
42 Signal::Pass => "PASS",
43 Signal::Fail(_) => "FAIL",
44 Signal::NotApplicable(_) => "N/A",
45 Signal::NotRun => "—",
46 }
47 }
48
49 pub fn detail(&self) -> Option<&str> {
51 match self {
52 Signal::Fail(d) | Signal::NotApplicable(d) => Some(d),
53 _ => None,
54 }
55 }
56}
57
58#[derive(Clone, Debug, Default, PartialEq)]
60pub struct Signals {
61 pub identity: Signal,
64 pub coherence_pass: usize,
65 pub coherence_total: usize,
66 pub codegen: Signal,
67 pub tool_call: Signal,
68 pub long_ctx: Signal,
70 pub tps: Option<f64>,
73}
74
75#[derive(Clone, Debug, PartialEq)]
77pub enum Outcome {
78 Probed(Box<Signals>),
80 BootFailed(String),
83 NotReached,
86}
87
88#[derive(Clone, Debug, PartialEq)]
90pub struct RoundResult {
91 pub label: String,
92 pub outcome: Outcome,
93 pub baseline_tps: Option<f64>,
95}
96
97impl RoundResult {
98 pub fn signals(&self) -> Option<&Signals> {
99 match &self.outcome {
100 Outcome::Probed(s) => Some(s),
101 _ => None,
102 }
103 }
104
105 pub fn bars(&self) -> Vec<String> {
107 let signals = match &self.outcome {
108 Outcome::BootFailed(why) => return vec![format!("did-not-boot ({why})")],
111 Outcome::NotReached => return vec!["no-result".into()],
112 Outcome::Probed(s) => s,
113 };
114 let mut fails = Vec::new();
115 for (name, signal, allows_not_applicable) in [
118 ("wrong-model", &signals.identity, false),
119 ("codegen", &signals.codegen, false),
120 ("tool_call", &signals.tool_call, true),
121 ] {
122 match signal {
123 Signal::Pass => {}
124 Signal::NotApplicable(_) if allows_not_applicable => {}
125 Signal::NotApplicable(_) => fails.push(format!("{name}(not-applicable)")),
126 Signal::Fail(_) => fails.push(name.to_string()),
127 Signal::NotRun => fails.push(format!("{name}(not-probed)")),
128 }
129 }
130 let coherence_bar = COHERENCE_MIN_PASS.min(signals.coherence_total);
131 if signals.coherence_total == 0
132 || signals.coherence_pass < coherence_bar
133 || signals.coherence_pass > signals.coherence_total
134 {
135 fails.push(format!(
136 "coherence({}/{})",
137 signals.coherence_pass, signals.coherence_total
138 ));
139 }
140 if let Some(tps) = signals.tps {
141 if !tps.is_finite() {
142 fails.push("tps(non-finite)".into());
143 } else if tps <= 0.0 {
144 fails.push("tps(0)".into());
145 } else if let Some(base) = self
146 .baseline_tps
147 .filter(|baseline| baseline.is_finite() && *baseline > 0.0)
148 {
149 let floor = base * (1.0 - TPS_TOLERANCE);
150 if tps < floor {
151 fails.push(format!("tps({tps:.1}<{floor:.1})"));
152 }
153 }
154 }
155 fails
156 }
157
158 pub fn tps_note(&self) -> Option<&'static str> {
161 let tps = self.signals()?.tps?;
162 if tps.is_finite()
163 && tps > 0.0
164 && self
165 .baseline_tps
166 .filter(|baseline| baseline.is_finite() && *baseline > 0.0)
167 .is_none()
168 {
169 return Some("no baseline — liveness only");
170 }
171 None
172 }
173}
174
175#[derive(Clone, Debug, Default, PartialEq)]
177pub struct Tally {
178 pub verified: usize,
179 pub planned: usize,
180 pub skipped: usize,
181 pub excluded: usize,
182 pub failures: Vec<(String, Vec<String>)>,
184}
185
186impl Tally {
187 pub fn passed(&self) -> bool {
188 self.planned > 0 && self.failures.is_empty()
189 }
190}
191
192pub fn tally(plan: &Plan, results: &[RoundResult]) -> Tally {
195 let mut out = Tally {
196 planned: plan.planned_count(),
197 skipped: plan.skipped().count(),
198 excluded: plan.excluded_count(),
199 ..Tally::default()
200 };
201 for round in plan.planned() {
202 let label = round.label();
203 let bars = match results.iter().find(|r| r.label == label) {
204 Some(r) => r.bars(),
205 None => vec!["no-result".into()],
206 };
207 if bars.is_empty() {
208 out.verified += 1;
209 } else {
210 out.failures.push((label, bars));
211 }
212 }
213 out
214}
215
216pub fn verdict_text(tally: &Tally, plan: &Plan) -> String {
219 let coverage = format!(
220 "{}/{} planned checkpoints verified",
221 tally.verified, tally.planned
222 );
223 let mut extra = Vec::new();
224 if tally.skipped > 0 {
225 let names: Vec<String> = plan
226 .skipped()
227 .take(3)
228 .map(|(r, why)| format!("{} ({})", r.model, why.reason()))
229 .collect();
230 extra.push(format!(
231 "{} not runnable on this box: {}{}",
232 tally.skipped,
233 names.join(", "),
234 if tally.skipped > 3 { ", …" } else { "" }
235 ));
236 }
237 if tally.excluded > 0 {
238 extra.push(format!("{} outside the filter", tally.excluded));
239 }
240 let tail = if extra.is_empty() {
241 String::new()
242 } else {
243 format!(" · {}", extra.join(" · "))
244 };
245 if tally.failures.is_empty() {
246 return format!("{coverage}{tail}");
247 }
248 let detail: Vec<String> = tally
249 .failures
250 .iter()
251 .map(|(label, bars)| format!("{label}: {}", bars.join(", ")))
252 .collect();
253 format!(
254 "{coverage}{tail} — {} below bar: {}",
255 tally.failures.len(),
256 detail.join(" · ")
257 )
258}
259
260#[cfg(test)]
261#[path = "score_tests.rs"]
262mod tests;