Skip to main content

kernel/event/
kind.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//! Event kinds: the closed set and its window classes.
7
8use serde::{Deserialize, Serialize};
9
10mod window;
11pub use window::WindowClass;
12
13/// The closed event vocabulary.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
15#[serde(rename_all = "snake_case")]
16#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
17pub enum EventKind {
18    // Genesis and space (4).
19    CityInitialized,
20    BuildingCreated,
21    /// A person changed what one building's runs may reach.
22    ///
23    /// The payload says which faces were written, never what they now
24    /// hold: `CONFIG.toml` is the authority for what a run is governed
25    /// by, and a copy of it here would be a second one. What this adds
26    /// is the fact the file cannot carry - that the change happened,
27    /// when, and to which building.
28    BuildingConfigured,
29    /// A person took a building out of the city.
30    ///
31    /// The payload names the building and where its files are kept
32    /// under the reserved subtree; nothing is deleted, and every record
33    /// the building wrote stays in this history.
34    BuildingRemoved,
35    // Base set (19).
36    /// A session started at an address: the shape the last one froze
37    /// was forgotten, and the summary it left was carried or not.
38    ///
39    /// A separate kind from `run_started` because it is a separate
40    /// fact: the first run of a session and the fifth are both
41    /// `run_started`, and only this line says where one session ended
42    /// and the next began. `carried` is recorded even when it is
43    /// false, because "this session carries nothing" is the answer to
44    /// the question a person asks when the model behaves as if it had
45    /// never met them.
46    SessionOpened,
47    RunStarted,
48    RunForked,
49    PromptAssembled,
50    /// One request's cache shape, and which of its regions moved since
51    /// the request before it. The line that turns a cache miss into a
52    /// named cause: system, tools or the conversation. It measures the
53    /// request rather than deciding any of its bytes, which is why it is
54    /// record-only.
55    PromptShapeCompared,
56    ModelCalled,
57    ModelReturned,
58    ToolCalled,
59    ToolResult,
60    ResultOffloaded,
61    GateChecked,
62    GateDenied,
63    CheckpointCommitted,
64    HandoffWritten,
65    SteerReceived,
66    CancelReceived,
67    WatchdogFired,
68    BudgetLimit,
69    RunFrozen,
70    LogTruncated,
71    // Collaboration (19).
72    SignalEnqueued,
73    SignalConsumed,
74    DraftHeld,
75    DraftResolved,
76    GoalRegistered,
77    GoalConflict,
78    ArbitrationVerdict,
79    RepairStarted,
80    RepairReused,
81    WorktreeOpened,
82    PrOpened,
83    PrMerged,
84    PrRejected,
85    RoadmapClaimed,
86    RoadmapFinished,
87    RoadmapReleased,
88    /// A branch was divided into children. The plan grew rather than
89    /// moved, which is a different fact from any row changing state and
90    /// is the only one that changes what the denominator is made of.
91    RoadmapSplit,
92    /// A node cannot proceed, and why. Distinct from `roadmap_released`:
93    /// a released node is back in the ready set, a blocked one is red
94    /// and everything behind it is waiting.
95    RoadmapBlocked,
96    /// A city was given a goal to keep working towards, or that goal
97    /// was paused, resumed or cleared. Recorded because it is the one
98    /// thing in the city that starts work without a person asking, and
99    /// "who set this running" has to be answerable afterwards.
100    PursuitChanged,
101    // Governance and facilities (18).
102    ApprovalRequested,
103    ApprovalResolved,
104    PolicyCreated,
105    PolicyRevoked,
106    TaintPromoted,
107    CrossBuildingTransfer,
108    CityHalted,
109    BackpressureShed,
110    DigestInvalidated,
111    EndpointAttached,
112    /// What a base URL says it serves, asked before anything is
113    /// attached. A separate fact from `EndpointAttached`: a person may
114    /// look at what a key buys and register none of it.
115    EndpointProbed,
116    EndpointLost,
117    ModelSelected,
118    ProviderDegraded,
119    /// A subscription login an older build began. This build signs in
120    /// to no subscription and writes none; the kind stays so a ledger
121    /// that holds one still reads, and nothing reads its payload
122    /// (`crates/gateway/Spec.lean` §8-5).
123    LoginStarted,
124    EvalRun,
125    AssetArchived,
126    CredentialLent,
127    // Privacy and Discard (5).
128    SecretCaptured,
129    SecretEgressBlocked,
130    FileDiscarded,
131    DiscardRestored,
132    AutonomyChanged,
133    // Unified history (2).
134    WentBack,
135    FileRestored,
136    /// One of the three documents that govern a city was written by a
137    /// person. Recorded because what governs a city decides what every
138    /// later run is given, and "who changed this, and when" has to be
139    /// answerable from the one history rather than from a file's
140    /// modification time.
141    GovernedDocumentWritten,
142    /// A person wrote one of a building's own spine documents.
143    SpineDocumentWritten,
144    /// One of the documents a dispatch stands under — the city's
145    /// `CONFIG.toml`, or a building's `CONFIG.toml` or `RULES.toml` —
146    /// holds other bytes than the last line booked. Booked after the city
147    /// agreed to the work and before the run reads a rule, so a replay
148    /// names the entry the change reached the city in.
149    RulesChanged,
150    /// A person asked to connect an outside application, and the broker
151    /// that holds its OAuth opened a consent session.
152    ///
153    /// The request is history and belongs here; **where that application
154    /// stands right now is not, and is deliberately absent from the
155    /// payload** (`crates/wire/Spec.lean` §8-35b): a recorded standing
156    /// would still read "connected" an hour after the person revoked
157    /// it. The consent page's own url is absent for a second reason -
158    /// it is a capability, and anybody replaying this log would be
159    /// holding one.
160    ToolkitLinkOpened,
161
162    // The two faces of an endpoint that are not the conversation (2).
163    /// One call to an attached endpoint's embeddings face, and what came
164    /// back for it. The vectors are absent for the reason `ModelCalled`
165    /// carries no request body: a replay recomputes them from the inputs
166    /// the call recorded.
167    EmbeddingCalled,
168    /// One call to an attached endpoint's rerank face, and how many
169    /// passages and ranks it was about.
170    RerankCalled,
171
172    // The adviser port, consulted about the window (3).
173    /// A judgment was asked of the adviser port about the window.
174    ///
175    /// Asking decides nothing on its own: whether the bytes the model
176    /// reads include the item in question is decided by the answer, or
177    /// by the fallback when none came.
178    AdviserAsked,
179    /// The adviser answered. This is the line a replay reads instead of
180    /// asking again, which is why the answer decides model-request bytes
181    /// and the question that produced it does not.
182    AdviserAnswered,
183    /// No adviser answer was used, and why. The deterministic strategy
184    /// answered instead, and this is the only line that says so: without
185    /// it a window an adviser shaped and a window the city's own policy
186    /// shaped would fold to the same history.
187    AdviserFellBack,
188
189    // Keep-warm (1).
190    /// One keep-warm renewal a worker sent for a room's cached prefix:
191    /// what the provider reported it cost, or its refusal. The request is
192    /// absent because it resends a prefix the run already recorded.
193    CacheRenewed,
194
195    // Harness residents (2).
196    /// One thing an official harness reported during a run: a piece of
197    /// its answer or reasoning, a tool call it started and its status,
198    /// or a permission it asked for and the city's answer. Written after
199    /// the harness said it, and never read back as a decision of the city.
200    HarnessReported,
201    /// The harness's answer to the city's prompt: the stop reason and the
202    /// text it answered with this turn, written as the stop reason arrives
203    /// and before the run freezes.
204    HarnessAnswered,
205
206    // The remote door (5).
207    /// The person opened the remote door: until when, and the address a
208    /// device reaches it at.
209    RemoteOpened,
210    /// The remote door closed, and who closed it: the person at the
211    /// console, a device that locked it behind itself, or its own time.
212    RemoteClosed,
213    /// A device presented a good pairing code and the city keeps it.
214    DevicePaired,
215    /// The person took a device's pairing away.
216    DeviceRevoked,
217    /// A paired device proved its key and holds a remote session.
218    RemoteSessionStarted,
219
220    // Documents (4).
221    /// A save through the page landed: which document, from which
222    /// version to which, and how long it now is; never the text.
223    DocumentWritten,
224    /// A run suggested replacing one stretch of one document version.
225    ProposalOffered,
226    /// A person decided a proposal card, sentence by sentence.
227    ProposalDecided,
228    /// The run that offered a card took it back while it was open.
229    ProposalWithdrawn,
230
231    // Sessions and the shelf (3).
232    /// The room's run policy, changed while a session is open
233    /// (`crates/kernel/spec/Event/Record.lean` D21).
234    RunPolicyChanged,
235    /// The name a person gave one session (D22).
236    SessionNamed,
237    /// One audit of one version of a skill on the shelf (D23).
238    SkillAudited,
239
240    // The reply wait (2).
241    /// A run that sent with `wait` stopped at its safe point for a reply
242    /// (`crates/kernel/spec/Event/Record.lean` D32).
243    SignalWaitStarted,
244    /// The one line that ends a `signal_wait_started`: the reply came,
245    /// the deadline passed, or the run left its room (D32).
246    SignalWaitEnded,
247
248    // Where a letter landed (1).
249    /// Where the accounting thread put one `signal_enqueued`: a running
250    /// run's slot, the queue, or a knock (`crates/kernel/spec/Event/Record.lean` D38).
251    SignalLanded,
252
253    // The shelf (1).
254    /// One version of a skill landed on a shelf through the city's door,
255    /// and where it came from (`crates/kernel/spec/Event/Record.lean` D23).
256    SkillShelved,
257}
258
259impl EventKind {
260    /// Every kind, in the order the SPEC table lists them. Data face for counting tests
261    /// and `xtask specalign`.
262    pub const ALL: [EventKind; 96] = [
263        EventKind::CityInitialized,
264        EventKind::BuildingCreated,
265        EventKind::BuildingConfigured,
266        EventKind::BuildingRemoved,
267        EventKind::SessionOpened,
268        EventKind::RunStarted,
269        EventKind::RunForked,
270        EventKind::PromptAssembled,
271        EventKind::PromptShapeCompared,
272        EventKind::ModelCalled,
273        EventKind::ModelReturned,
274        EventKind::ToolCalled,
275        EventKind::ToolResult,
276        EventKind::ResultOffloaded,
277        EventKind::GateChecked,
278        EventKind::GateDenied,
279        EventKind::CheckpointCommitted,
280        EventKind::HandoffWritten,
281        EventKind::SteerReceived,
282        EventKind::CancelReceived,
283        EventKind::WatchdogFired,
284        EventKind::BudgetLimit,
285        EventKind::RunFrozen,
286        EventKind::LogTruncated,
287        EventKind::SignalEnqueued,
288        EventKind::SignalConsumed,
289        EventKind::DraftHeld,
290        EventKind::DraftResolved,
291        EventKind::GoalRegistered,
292        EventKind::GoalConflict,
293        EventKind::ArbitrationVerdict,
294        EventKind::RepairStarted,
295        EventKind::RepairReused,
296        EventKind::WorktreeOpened,
297        EventKind::PrOpened,
298        EventKind::PrMerged,
299        EventKind::PrRejected,
300        EventKind::RoadmapClaimed,
301        EventKind::RoadmapFinished,
302        EventKind::RoadmapReleased,
303        EventKind::RoadmapSplit,
304        EventKind::RoadmapBlocked,
305        EventKind::PursuitChanged,
306        EventKind::ApprovalRequested,
307        EventKind::ApprovalResolved,
308        EventKind::PolicyCreated,
309        EventKind::PolicyRevoked,
310        EventKind::TaintPromoted,
311        EventKind::CrossBuildingTransfer,
312        EventKind::CityHalted,
313        EventKind::BackpressureShed,
314        EventKind::DigestInvalidated,
315        EventKind::EndpointAttached,
316        EventKind::EndpointProbed,
317        EventKind::EndpointLost,
318        EventKind::ModelSelected,
319        EventKind::ProviderDegraded,
320        EventKind::LoginStarted,
321        EventKind::EvalRun,
322        EventKind::AssetArchived,
323        EventKind::CredentialLent,
324        EventKind::SecretCaptured,
325        EventKind::SecretEgressBlocked,
326        EventKind::FileDiscarded,
327        EventKind::DiscardRestored,
328        EventKind::AutonomyChanged,
329        EventKind::WentBack,
330        EventKind::FileRestored,
331        EventKind::GovernedDocumentWritten,
332        EventKind::SpineDocumentWritten,
333        EventKind::RulesChanged,
334        EventKind::ToolkitLinkOpened,
335        EventKind::EmbeddingCalled,
336        EventKind::RerankCalled,
337        EventKind::AdviserAsked,
338        EventKind::AdviserAnswered,
339        EventKind::AdviserFellBack,
340        EventKind::CacheRenewed,
341        EventKind::HarnessReported,
342        EventKind::HarnessAnswered,
343        EventKind::RemoteOpened,
344        EventKind::RemoteClosed,
345        EventKind::DevicePaired,
346        EventKind::DeviceRevoked,
347        EventKind::RemoteSessionStarted,
348        EventKind::DocumentWritten,
349        EventKind::ProposalOffered,
350        EventKind::ProposalDecided,
351        EventKind::ProposalWithdrawn,
352        EventKind::RunPolicyChanged,
353        EventKind::SessionNamed,
354        EventKind::SkillAudited,
355        EventKind::SignalWaitStarted,
356        EventKind::SignalWaitEnded,
357        EventKind::SignalLanded,
358        EventKind::SkillShelved,
359    ];
360}
361
362#[cfg(test)]
363#[allow(
364    clippy::unwrap_used,
365    clippy::expect_used,
366    clippy::panic,
367    clippy::indexing_slicing,
368    reason = "test code"
369)]
370mod tests;