kernel/event/moment.rs
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! Which lines record the moment their own event happened, read from the
7//! line's kind and version (`crates/kernel/spec/Event.lean` ยง8-4, "what the envelope `t`
8//! records"). A reader asks here rather than comparing neighbouring
9//! lines' `t` or guessing from the build that exported them.
10
11use super::{EventKind, EventRecord, TimeMs};
12use crate::consts_external::EVENT_LOG_V;
13
14/// The first ledger version whose waited-for lines record their own
15/// moment; a line written before carries its turn's stamp there.
16const MOMENTS_SINCE_V: u32 = 2;
17
18// A build that writes an older version than the one moments start at
19// would answer `None` for every line it writes itself.
20const _: () = assert!(MOMENTS_SINCE_V <= EVENT_LOG_V);
21
22impl EventKind {
23 /// Whether a line of this kind records the moment its own event
24 /// happened: a model attempt sent, a reply whole, a tool call started,
25 /// a call's answer. The roster of those four kinds.
26 pub fn records_a_moment(&self) -> bool {
27 matches!(
28 self,
29 EventKind::ModelCalled
30 | EventKind::ModelReturned
31 | EventKind::ToolCalled
32 | EventKind::ToolResult
33 )
34 }
35}
36
37impl EventRecord {
38 /// This line's own moment: `Some(t)` for a kind that
39 /// [`records_a_moment`](EventKind::records_a_moment), written at a
40 /// version that measures it; `None` for every other line. A `None` on
41 /// one of those four kinds means the moment was not measured, not
42 /// that it took no time.
43 pub fn moment(&self) -> Option<TimeMs> {
44 (self.v() >= MOMENTS_SINCE_V && self.kind().records_a_moment()).then(|| self.t())
45 }
46}
47
48#[cfg(test)]
49#[allow(clippy::unwrap_used, reason = "test code")]
50mod tests;