Skip to main content

telltale_vm/vm/
vm_config_and_observability.rs

1/// VM configuration.
2#[derive(Debug, Clone, Serialize, Deserialize)]
3pub struct VMConfig {
4    /// Migration-safe config schema version.
5    #[serde(default = "default_config_schema_version")]
6    pub config_schema_version: u32,
7    /// Scheduling policy.
8    pub sched_policy: SchedPolicy,
9    /// Default buffer configuration for new sessions.
10    pub buffer_config: BufferConfig,
11    /// Maximum number of concurrent sessions.
12    pub max_sessions: usize,
13    /// Maximum number of concurrent coroutines.
14    pub max_coroutines: usize,
15    /// Number of registers per coroutine.
16    pub num_registers: u16,
17    /// Simulated time per scheduler round.
18    pub tick_duration: Duration,
19    /// Guard layers configured for the VM.
20    pub guard_layers: Vec<GuardLayerConfig>,
21    /// Whether speculative execution is enabled.
22    pub speculation_enabled: bool,
23    /// Determinism profile for replay/equivalence behavior.
24    pub determinism_mode: DeterminismMode,
25    /// Effect determinism tier used by admission and envelope artifacts.
26    #[serde(default)]
27    pub effect_determinism_tier: EffectDeterminismTier,
28    /// Output-condition policy for commit eligibility of observable outputs.
29    pub output_condition_policy: OutputConditionPolicy,
30    /// Monitor mode for pre-dispatch type checks.
31    #[serde(default)]
32    pub monitor_mode: MonitorMode,
33    /// Flow policy for epistemic knowledge checks.
34    #[serde(default)]
35    pub flow_policy: FlowPolicy,
36    /// Deterministic cost charged for each instruction dispatch.
37    #[serde(default = "default_instruction_cost")]
38    pub instruction_cost: usize,
39    /// Initial cost budget assigned to each coroutine.
40    #[serde(default = "default_initial_cost_budget")]
41    pub initial_cost_budget: usize,
42    /// Whether threaded scheduler may admit same-session picks when footprint-disjoint.
43    #[serde(default)]
44    pub footprint_guided_wave_widening: bool,
45    /// Runtime tuning profile used by instrumentation/benchmark harnesses.
46    #[serde(default)]
47    pub runtime_tuning_profile: RuntimeTuningProfile,
48    /// Round semantics mode used by threaded scheduler.
49    #[serde(default)]
50    pub threaded_round_semantics: ThreadedRoundSemantics,
51    /// Effect-trace capture mode for integration/perf tuning.
52    #[serde(default)]
53    pub effect_trace_capture_mode: EffectTraceCaptureMode,
54    /// Runtime payload hardening mode for inbound/outbound messages.
55    #[serde(default)]
56    pub payload_validation_mode: PayloadValidationMode,
57    /// Upper bound for VM payload values in estimated wire bytes.
58    #[serde(default = "default_max_payload_bytes")]
59    pub max_payload_bytes: usize,
60    /// Enable runtime host-contract assertions with deterministic diagnostics.
61    #[serde(default)]
62    pub host_contract_assertions: bool,
63}
64
65impl Default for VMConfig {
66    fn default() -> Self {
67        Self {
68            config_schema_version: default_config_schema_version(),
69            sched_policy: SchedPolicy::Cooperative,
70            buffer_config: BufferConfig::default(),
71            max_sessions: 256,
72            max_coroutines: 1024,
73            num_registers: 16,
74            tick_duration: Duration::from_millis(1),
75            guard_layers: Vec::new(),
76            speculation_enabled: false,
77            determinism_mode: DeterminismMode::Full,
78            effect_determinism_tier: EffectDeterminismTier::StrictDeterministic,
79            output_condition_policy: OutputConditionPolicy::AllowAll,
80            monitor_mode: MonitorMode::SessionTypePrecheck,
81            flow_policy: FlowPolicy::AllowAll,
82            instruction_cost: 1,
83            initial_cost_budget: usize::MAX,
84            footprint_guided_wave_widening: false,
85            runtime_tuning_profile: RuntimeTuningProfile::Standard,
86            threaded_round_semantics: ThreadedRoundSemantics::CanonicalOneStep,
87            effect_trace_capture_mode: EffectTraceCaptureMode::Full,
88            payload_validation_mode: PayloadValidationMode::Structural,
89            max_payload_bytes: default_max_payload_bytes(),
90            host_contract_assertions: false,
91        }
92    }
93}
94
95impl VMConfig {
96    /// Assert VM configuration invariants required for safe state initialization.
97    ///
98    /// # Panics
99    ///
100    /// Panics when a required invariant is violated.
101    pub fn assert_invariants(&self) {
102        assert!(
103            self.config_schema_version >= 1,
104            "config_schema_version must be >= 1"
105        );
106        assert!(self.max_sessions > 0, "max_sessions must be > 0");
107        assert!(self.max_coroutines > 0, "max_coroutines must be > 0");
108        assert!(self.num_registers > 0, "num_registers must be > 0");
109        assert!(self.instruction_cost > 0, "instruction_cost must be > 0");
110        assert!(self.max_payload_bytes > 0, "max_payload_bytes must be > 0");
111    }
112}
113
114/// Observable event emitted by the VM.
115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
116pub struct TickedObsEvent {
117    /// Scheduler tick when the wrapped event occurred.
118    pub tick: u64,
119    /// Underlying observable event payload.
120    pub event: ObsEvent,
121}
122
123/// Observable event emitted by the VM.
124#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
125pub enum ObsEvent {
126    /// Value sent on an edge.
127    Sent {
128        /// Scheduler tick when the event occurred.
129        tick: u64,
130        /// Session-scoped edge for this send.
131        edge: Edge,
132        /// Session ID.
133        session: SessionId,
134        /// Sender role.
135        from: String,
136        /// Receiver role.
137        to: String,
138        /// Message label.
139        label: String,
140    },
141    /// Value received on an edge.
142    Received {
143        /// Scheduler tick when the event occurred.
144        tick: u64,
145        /// Session-scoped edge for this receive.
146        edge: Edge,
147        /// Session ID.
148        session: SessionId,
149        /// Sender role.
150        from: String,
151        /// Receiver role.
152        to: String,
153        /// Message label.
154        label: String,
155    },
156    /// Label offered on an edge.
157    Offered {
158        /// Scheduler tick when the event occurred.
159        tick: u64,
160        /// Session-scoped edge for this offer.
161        edge: Edge,
162        /// Label offered.
163        label: String,
164    },
165    /// Label chosen on an edge.
166    Chose {
167        /// Scheduler tick when the event occurred.
168        tick: u64,
169        /// Session-scoped edge for this choice.
170        edge: Edge,
171        /// Label chosen.
172        label: String,
173    },
174    /// Session opened.
175    Opened {
176        /// Scheduler tick when the event occurred.
177        tick: u64,
178        /// Session ID.
179        session: SessionId,
180        /// Participating roles.
181        roles: Vec<String>,
182    },
183    /// Session closed.
184    Closed {
185        /// Scheduler tick when the event occurred.
186        tick: u64,
187        /// Session ID.
188        session: SessionId,
189    },
190    /// Session epoch advanced.
191    EpochAdvanced {
192        /// Scheduler tick when the event occurred.
193        tick: u64,
194        /// Session ID.
195        sid: SessionId,
196        /// New epoch number.
197        epoch: usize,
198    },
199    /// Coroutine halted.
200    Halted {
201        /// Scheduler tick when the event occurred.
202        tick: u64,
203        /// Coroutine ID.
204        coro_id: usize,
205    },
206    /// Effect handler invoked.
207    Invoked {
208        /// Scheduler tick when the event occurred.
209        tick: u64,
210        /// Coroutine ID.
211        coro_id: usize,
212        /// Role name.
213        role: String,
214    },
215    /// Guard layer acquired.
216    Acquired {
217        /// Scheduler tick when the event occurred.
218        tick: u64,
219        /// Session ID.
220        session: SessionId,
221        /// Role name.
222        role: String,
223        /// Guard layer identifier.
224        layer: String,
225    },
226    /// Guard layer released.
227    Released {
228        /// Scheduler tick when the event occurred.
229        tick: u64,
230        /// Session ID.
231        session: SessionId,
232        /// Role name.
233        role: String,
234        /// Guard layer identifier.
235        layer: String,
236    },
237    /// Endpoint transferred between coroutines.
238    Transferred {
239        /// Scheduler tick when the event occurred.
240        tick: u64,
241        /// Session ID.
242        session: SessionId,
243        /// Role name.
244        role: String,
245        /// Source coroutine.
246        from: usize,
247        /// Target coroutine.
248        to: usize,
249    },
250    /// Speculation forked for a ghost session.
251    Forked {
252        /// Scheduler tick when the event occurred.
253        tick: u64,
254        /// Session ID.
255        session: SessionId,
256        /// Ghost session id.
257        ghost: usize,
258    },
259    /// Speculation joined.
260    Joined {
261        /// Scheduler tick when the event occurred.
262        tick: u64,
263        /// Session ID.
264        session: SessionId,
265    },
266    /// Speculation aborted.
267    Aborted {
268        /// Scheduler tick when the event occurred.
269        tick: u64,
270        /// Session ID.
271        session: SessionId,
272    },
273    /// Knowledge fact tagged.
274    Tagged {
275        /// Scheduler tick when the event occurred.
276        tick: u64,
277        /// Session ID.
278        session: SessionId,
279        /// Role name.
280        role: String,
281        /// Fact payload.
282        fact: String,
283    },
284    /// Knowledge fact checked.
285    Checked {
286        /// Scheduler tick when the event occurred.
287        tick: u64,
288        /// Session ID.
289        session: SessionId,
290        /// Role name.
291        role: String,
292        /// Target role.
293        target: String,
294        /// Whether the flow policy permitted the fact.
295        permitted: bool,
296    },
297    /// Coroutine faulted.
298    Faulted {
299        /// Scheduler tick when the event occurred.
300        tick: u64,
301        /// Coroutine ID.
302        coro_id: usize,
303        /// The fault.
304        fault: Fault,
305    },
306    /// Output-condition verification was evaluated at commit time.
307    OutputConditionChecked {
308        /// Scheduler tick when the event occurred.
309        tick: u64,
310        /// Predicate reference that was checked.
311        predicate_ref: String,
312        /// Optional witness reference used by the check.
313        witness_ref: Option<String>,
314        /// Opaque output digest checked by the verifier.
315        output_digest: String,
316        /// Verification outcome.
317        passed: bool,
318    },
319}
320
321/// The VM execution result for a single step.
322#[derive(Debug)]
323pub enum StepResult {
324    /// A coroutine executed an instruction and may continue.
325    Continue,
326    /// No coroutines are ready (all blocked or done).
327    Stuck,
328    /// All coroutines have completed.
329    AllDone,
330}
331
332/// Terminal status returned by bounded VM run APIs.
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
334pub enum RunStatus {
335    /// All coroutines reached terminal states.
336    AllDone,
337    /// No runnable coroutines remain (blocked/stuck).
338    Stuck,
339    /// `max_rounds`/`max_steps` budget was exhausted before termination.
340    MaxRoundsExceeded,
341}
342
343/// Debug metadata for the most recent scheduler-dispatched step.
344#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
345pub enum SchedExecStatus {
346    /// Instruction continued execution.
347    Continue,
348    /// Instruction yielded cooperative control.
349    Yielded,
350    /// Instruction blocked.
351    Blocked,
352    /// Coroutine halted normally.
353    Halted,
354    /// Coroutine faulted.
355    Faulted,
356}
357
358/// Debug metadata for the most recent scheduler-dispatched step.
359#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
360pub struct SchedStepDebug {
361    /// Selected coroutine id.
362    pub selected_coro: usize,
363    /// Instruction-step execution status.
364    pub exec_status: SchedExecStatus,
365}