Skip to main content

vyre_runtime/megakernel/telemetry/
evidence.rs

1//! Release and benchmark evidence envelopes derived from a telemetry
2//! snapshot: the required IO/residency metric families and the caller-owned
3//! decode capacity record.
4
5use super::ring_state::RingOccupancy;
6
7/// Schema version for IO/runtime evidence emitted from megakernel telemetry.
8pub const RUNTIME_IO_EVIDENCE_SCHEMA_VERSION: u32 = 1;
9
10/// Required metric families for runtime IO/residency evidence.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum RuntimeEvidenceMetricFamily {
13    /// Ring occupancy metrics are present.
14    Ring,
15    /// Control-buffer decode metrics are present.
16    Control,
17    /// Host/device copy accounting metrics are present.
18    Copy,
19    /// Resident device-byte metrics are present.
20    Residency,
21}
22
23impl RuntimeEvidenceMetricFamily {
24    /// Stable evidence-family token.
25    #[must_use]
26    pub const fn as_str(self) -> &'static str {
27        match self {
28            Self::Ring => "ring",
29            Self::Control => "control",
30            Self::Copy => "copy",
31            Self::Residency => "residency",
32        }
33    }
34}
35
36/// Coverage bits for the required runtime evidence metric families.
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
38pub struct RuntimeEvidenceMetricCoverage {
39    /// Ring occupancy metrics are present.
40    pub ring: bool,
41    /// Control-buffer decode metrics are present.
42    pub control: bool,
43    /// Host/device copy accounting metrics are present.
44    pub copy: bool,
45    /// Resident device-byte metrics are present.
46    pub residency: bool,
47}
48
49impl RuntimeEvidenceMetricCoverage {
50    /// Coverage with every runtime evidence family present.
51    #[must_use]
52    pub const fn complete() -> Self {
53        Self {
54            ring: true,
55            control: true,
56            copy: true,
57            residency: true,
58        }
59    }
60
61    /// Missing required metric families.
62    #[must_use]
63    pub fn missing_families(self) -> Vec<RuntimeEvidenceMetricFamily> {
64        let mut missing = Vec::new();
65        if !self.ring {
66            missing.push(RuntimeEvidenceMetricFamily::Ring);
67        }
68        if !self.control {
69            missing.push(RuntimeEvidenceMetricFamily::Control);
70        }
71        if !self.copy {
72            missing.push(RuntimeEvidenceMetricFamily::Copy);
73        }
74        if !self.residency {
75            missing.push(RuntimeEvidenceMetricFamily::Residency);
76        }
77        missing
78    }
79}
80
81/// Runtime-owned IO/residency evidence envelope for release and benchmark artifacts.
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct ResidentRuntimeEvidence {
84    /// Runtime evidence schema version.
85    pub schema_version: u32,
86    /// Device-resident bytes retained by the dispatch family.
87    pub resident_device_bytes: u64,
88    /// Host-visible copy bytes still required for this evidence sample.
89    pub host_copy_bytes: u64,
90    /// Host copy bytes avoided by resident handles or device-side IO.
91    pub host_copy_avoided_bytes: u64,
92    /// Ring occupancy snapshot.
93    pub ring_occupancy: RingOccupancy,
94    /// Control-buffer decode cost in nanoseconds.
95    pub control_decode_ns: u64,
96    /// Ring decode cost in nanoseconds.
97    pub ring_decode_ns: u64,
98    /// Required metric-family coverage.
99    pub coverage: RuntimeEvidenceMetricCoverage,
100}
101
102impl ResidentRuntimeEvidence {
103    /// Construct a complete runtime evidence envelope.
104    #[must_use]
105    pub const fn complete(
106        resident_device_bytes: u64,
107        host_copy_bytes: u64,
108        host_copy_avoided_bytes: u64,
109        ring_occupancy: RingOccupancy,
110        control_decode_ns: u64,
111        ring_decode_ns: u64,
112    ) -> Self {
113        Self {
114            schema_version: RUNTIME_IO_EVIDENCE_SCHEMA_VERSION,
115            resident_device_bytes,
116            host_copy_bytes,
117            host_copy_avoided_bytes,
118            ring_occupancy,
119            control_decode_ns,
120            ring_decode_ns,
121            coverage: RuntimeEvidenceMetricCoverage::complete(),
122        }
123    }
124
125    /// Metric families missing from this evidence envelope.
126    #[must_use]
127    pub fn missing_metric_families(&self) -> Vec<RuntimeEvidenceMetricFamily> {
128        self.coverage.missing_families()
129    }
130
131    /// Whether all required runtime evidence families are present.
132    #[must_use]
133    pub fn is_complete(&self) -> bool {
134        self.schema_version == RUNTIME_IO_EVIDENCE_SCHEMA_VERSION
135            && self.missing_metric_families().is_empty()
136    }
137
138    /// Avoided host-copy bytes in basis points of total relevant copy volume.
139    #[must_use]
140    pub fn host_copy_avoidance_bps(&self) -> u16 {
141        let total = u128::from(self.host_copy_bytes)
142            .saturating_add(u128::from(self.host_copy_avoided_bytes));
143        if total == 0 {
144            return 0;
145        }
146        let bps = u128::from(self.host_copy_avoided_bytes).saturating_mul(10_000) / total;
147        bps.min(10_000) as u16
148    }
149}
150
151#[cfg(test)]
152mod evidence_tests {
153    use super::*;
154
155    #[test]
156    fn runtime_evidence_reports_missing_metric_families() {
157        let evidence = ResidentRuntimeEvidence {
158            schema_version: RUNTIME_IO_EVIDENCE_SCHEMA_VERSION,
159            resident_device_bytes: 0,
160            host_copy_bytes: 0,
161            host_copy_avoided_bytes: 0,
162            ring_occupancy: RingOccupancy::default(),
163            control_decode_ns: 0,
164            ring_decode_ns: 0,
165            coverage: RuntimeEvidenceMetricCoverage {
166                ring: true,
167                control: false,
168                copy: true,
169                residency: false,
170            },
171        };
172
173        let missing = evidence
174            .missing_metric_families()
175            .into_iter()
176            .map(RuntimeEvidenceMetricFamily::as_str)
177            .collect::<Vec<_>>();
178
179        assert_eq!(missing, vec!["control", "residency"]);
180        assert!(!evidence.is_complete());
181    }
182
183    #[test]
184    fn runtime_evidence_records_copy_avoidance_and_occupancy() {
185        let evidence = ResidentRuntimeEvidence::complete(
186            4096,
187            1024,
188            3072,
189            RingOccupancy {
190                empty: 1,
191                published: 2,
192                claimed: 3,
193                done: 4,
194                wait_io: 5,
195                yield_count: 6,
196                requeue: 7,
197                fault: 8,
198                unknown: 9,
199            },
200            11,
201            13,
202        );
203
204        assert!(evidence.is_complete());
205        assert_eq!(evidence.resident_device_bytes, 4096);
206        assert_eq!(evidence.ring_occupancy.total_slots(), 45);
207        assert_eq!(evidence.ring_occupancy.queue_depth(), 40);
208        assert_eq!(evidence.host_copy_avoidance_bps(), 7500);
209    }
210}
211
212/// Schema version for telemetry decode capacity evidence.
213pub const TELEMETRY_DECODE_CAPACITY_SCHEMA_VERSION: u32 = 1;
214
215/// Evidence that a telemetry decode used caller-owned output and scratch buffers.
216#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub struct TelemetryDecodeCapacityEvidence {
218    /// Evidence schema version.
219    pub schema_version: u32,
220    /// Number of decoded ring slots in the output snapshot.
221    pub decoded_slot_count: usize,
222    /// Capacity of the caller-owned ring-slot output buffer.
223    pub slot_output_capacity: usize,
224    /// Number of decoded route-window rows in the output snapshot.
225    pub decoded_window_count: usize,
226    /// Capacity of the caller-owned route-window output buffer.
227    pub window_output_capacity: usize,
228    /// Capacity retained for sorted window-opcode scratch.
229    pub window_opcode_scratch_capacity: usize,
230    /// Capacity retained for route-window accumulator scratch.
231    pub window_accumulator_scratch_capacity: usize,
232    /// True when evidence was produced from caller-owned scratch.
233    pub uses_caller_owned_scratch: bool,
234}
235
236impl TelemetryDecodeCapacityEvidence {
237    /// Return true when output and scratch capacities cover the decoded rows.
238    #[must_use]
239    pub fn is_complete(self) -> bool {
240        self.schema_version == TELEMETRY_DECODE_CAPACITY_SCHEMA_VERSION
241            && self.uses_caller_owned_scratch
242            && self.slot_output_capacity >= self.decoded_slot_count
243            && self.window_output_capacity >= self.decoded_window_count
244            && self.window_accumulator_scratch_capacity >= self.decoded_window_count
245    }
246}