metrale_telemetry/
spec_confidence.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-10-04: Draft outcomes by drafter confidence: for each draft a verify step reached
4//! (every draft before it was accepted), its top-1 log-probability bucket and whether it was
5//! accepted. `met bench spec-cost` fits the acceptance calibration of `--spec-cost-model
6//! measured` from these counts, so P(accept | bucket) is conditional on reaching the draft,
7//! which is how the planner chains it.
8//!
9//! Owner: telemetry.
10//! Invariants: a non-finite log-probability is counted in `overflow`, never in a bucket; a
11//! positive one (rounding above 0) lands in the last bucket.
12
13use crate::instrument::Counter;
14
15/// 2026-10-04: Ascending upper edges of the buckets, in natural-log probability; a draft
16/// lands in the first bucket whose edge is >= its log-probability. Fine near 0, where most
17/// MTP drafts sit; the last edge is 0.
18pub const EDGES: [f32; 10] = [
19    -4.0, -2.0, -1.0, -0.5, -0.25, -0.1, -0.05, -0.02, -0.005, 0.0,
20];
21
22#[derive(Debug)]
23pub struct ConfidenceOutcomes {
24    /// 2026-10-04: `cells[b][accepted]`: reached drafts in bucket `b`.
25    cells: [[Counter; 2]; EDGES.len()],
26    pub overflow: Counter,
27}
28
29impl Default for ConfidenceOutcomes {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl ConfidenceOutcomes {
36    pub const fn new() -> Self {
37        Self {
38            cells: [const { [const { Counter::new() }; 2] }; EDGES.len()],
39            overflow: Counter::new(),
40        }
41    }
42
43    /// 2026-10-04: The bucket of log-probability `lp`; `None` when it is not finite.
44    pub fn bucket(lp: f32) -> Option<usize> {
45        if !lp.is_finite() {
46            return None;
47        }
48        Some(
49            EDGES
50                .iter()
51                .position(|&e| lp <= e)
52                .unwrap_or(EDGES.len() - 1),
53        )
54    }
55
56    pub(crate) fn record(&self, lp: f32, accepted: bool) {
57        match Self::bucket(lp) {
58            Some(b) => self.cells[b][usize::from(accepted)].add(1),
59            None => self.overflow.add(1),
60        }
61    }
62
63    /// 2026-10-04: Reached drafts in bucket `b` with outcome `accepted`.
64    pub fn count(&self, b: usize, accepted: bool) -> u64 {
65        self.cells
66            .get(b)
67            .map_or(0, |c| c[usize::from(accepted)].get())
68    }
69
70    pub fn is_empty(&self) -> bool {
71        self.cells.iter().flatten().all(|c| c.get() == 0)
72    }
73}
74
75#[cfg(test)]
76#[path = "spec_confidence_tests.rs"]
77mod tests;