Skip to main content

kernel/event/record/
control.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//! What the city records about its own founding, about a run being
7//! stopped or handed on, and about the governance lines no writer
8//! records yet.
9//!
10//! Three kinds of this family carry a type that lives elsewhere, and
11//! the struct is that type rather than a copy of it: `gate_denied` and
12//! `budget_limit` carry an [`AxError`](crate::AxError) laid flat, the
13//! carrier table in `kernel::error` being the authority on which code
14//! lands under which kind; `approval_requested` carries an
15//! [`ApprovalItem`](crate::ApprovalItem). `result_offloaded` stays with
16//! `runtime::sieve`, whose account it flattens in.
17
18use serde::{Deserialize, Serialize};
19
20use crate::address::Address;
21use crate::locator::Locator;
22
23/// `city_initialized`: the first line of every history. The city's name
24/// is the record's own `addr`, so the payload holds nothing.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
26#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
27pub struct CityInitialized {}
28
29/// `building_created`: a building now stands at `addr`, laid out from
30/// `template`, or found already standing when `adopted`.
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
32#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
33pub struct BuildingCreated {
34    #[cfg_attr(feature = "schema", schemars(with = "String"))]
35    pub addr: Address,
36    /// The template's own name, as `city::BuildingTemplate::name`
37    /// spells it.
38    pub template: String,
39    /// Written only on an adoption, as the hand-written writer left it.
40    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
41    pub adopted: bool,
42}
43
44/// `building_configured`: which faces of a building's own layer one
45/// reconfiguration wrote. The values themselves stay in the files.
46#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
48pub struct BuildingConfigured {
49    #[cfg_attr(feature = "schema", schemars(with = "String"))]
50    pub addr: Address,
51    pub sandbox: bool,
52    pub mcp: bool,
53    pub desktop: bool,
54    pub context: bool,
55}
56
57/// `cancel_received`: the turn saw the stop. The run it belongs to is
58/// the envelope's, so the payload holds nothing.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
60#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
61pub struct CancelReceived {}
62
63/// `handoff_written`: the five sections a successor starts from.
64///
65/// `runtime::handoff::Handoff` is the only way to hold a valid one; this
66/// is what it writes, so its refusal of an empty must-read list is not
67/// re-checked by a reader.
68#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
69#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
70pub struct HandoffWritten {
71    #[cfg_attr(feature = "schema", schemars(with = "Vec<String>"))]
72    pub must_read: Vec<Locator>,
73    pub overview: String,
74    pub progress: String,
75    pub context: String,
76    pub next_step: String,
77}
78
79/// `watchdog_fired`: what the watchdog did, and how often it has had to.
80#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
81#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
82pub struct WatchdogFired {
83    #[serde(flatten)]
84    pub action: FiredAction,
85    /// How many corrective steers this run has been given.
86    pub corrections: u32,
87    /// How many provider failures this run has met.
88    pub provider_failures: u32,
89}
90
91/// What the watchdog did, in the word the line carries.
92#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
93#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
94#[serde(tag = "action", rename_all = "snake_case")]
95pub enum FiredAction {
96    /// The model was told it is repeating itself.
97    Steer { text: String },
98    /// The same call will be made again, no earlier than `until_ms`,
99    /// because of the failure whose stable code and subject are named
100    /// here.
101    BackOff {
102        until_ms: u64,
103        code: String,
104        subject: String,
105    },
106    /// The same call goes out at once on another account of the
107    /// provider, because of the failure whose stable code and subject are
108    /// named here (`crates/kernel/spec/AccountRecovery.lean` ยง8-86).
109    Switch {
110        to: crate::ServerLabel,
111        code: String,
112        subject: String,
113    },
114    /// The run was frozen.
115    Freeze { reason: String },
116}
117
118/// `gate_checked`: a gate let an action through.
119///
120/// No production line records this kind, so no bytes fix its shape; the
121/// struct is empty by decision, because the action it admitted is the
122/// next line of the same run and a copy here would be a second spelling
123/// of it.
124#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
125#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
126pub struct GateChecked {}
127
128/// `policy_created` and `policy_revoked`: a standing rule named `id`
129/// came into force or left it.
130///
131/// No line records either kind yet, so no bytes fix the shape. The
132/// struct holds the rule's name alone by decision: the rule's text is a
133/// governed document, which `governed_document_written` already records,
134/// and a copy here would be its second authority.
135#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
136#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
137pub struct PolicyChanged {
138    pub id: String,
139}
140
141#[cfg(test)]
142#[allow(
143    clippy::unwrap_used,
144    clippy::expect_used,
145    clippy::panic,
146    clippy::indexing_slicing,
147    reason = "test code"
148)]
149mod tests;