deepstrike_core/runtime/
event_log.rs1use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum Primitive {
19 Syscall,
21 Sched,
23 Mm,
25}
26
27impl Primitive {
28 pub fn label(self) -> &'static str {
29 match self {
30 Self::Syscall => "syscall",
31 Self::Sched => "sched",
32 Self::Mm => "mm",
33 }
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
40#[serde(rename_all = "snake_case")]
41pub enum KernelEventCategory {
42 Syscall,
44 Sched,
46 Mm,
48 Proc,
50 Ipc,
52}
53
54impl KernelEventCategory {
55 pub fn primitive(self) -> Primitive {
58 match self {
59 Self::Syscall => Primitive::Syscall,
60 Self::Sched | Self::Proc | Self::Ipc => Primitive::Sched,
61 Self::Mm => Primitive::Mm,
62 }
63 }
64}
65
66pub fn primitive_for_kind(kind: &str) -> Primitive {
68 category_for_kind(kind).primitive()
69}
70
71pub fn category_for_kind(kind: &str) -> KernelEventCategory {
73 match kind {
74 "tool_gated" | "capability_changed" => KernelEventCategory::Syscall,
75 "suspended"
76 | "resumed"
77 | "budget_exceeded"
78 | "checkpoint_taken"
79 | "rollbacked"
80 | "milestone_advanced"
81 | "milestone_blocked"
82 | "milestone_evidence" => KernelEventCategory::Sched,
83 "compressed"
84 | "page_out"
85 | "page_in"
86 | "page_in_requested"
87 | "renewed"
88 | "context_renewed"
89 | "large_result_spooled" => KernelEventCategory::Mm,
90 "agent_process_changed" | "agent_spawned" | "workflow_batch_spawned"
91 | "workflow_completed" | "agent_preempted" => KernelEventCategory::Proc,
92 "signal_disposed" => KernelEventCategory::Ipc,
93 "memory_written" | "memory_queried" | "memory_validation_failed" => KernelEventCategory::Mm,
94 _ => KernelEventCategory::Sched,
95 }
96}
97
98pub const KERNEL_OBSERVATION_KINDS: &[&str] = &[
100 "compressed",
101 "page_out",
102 "page_in_requested",
103 "renewed",
104 "rollbacked",
105 "capability_changed",
106 "milestone_advanced",
107 "milestone_blocked",
108 "milestone_evidence",
109 "checkpoint_taken",
110 "agent_process_changed",
111 "workflow_batch_spawned",
112 "workflow_completed",
113 "agent_preempted",
114 "tool_gated",
115 "signal_disposed",
116 "budget_exceeded",
117 "suspended",
118 "resumed",
119 "memory_written",
120 "memory_queried",
121 "memory_validation_failed",
122];
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn maps_observation_kinds_to_categories() {
130 assert_eq!(category_for_kind("tool_gated"), KernelEventCategory::Syscall);
131 assert_eq!(category_for_kind("page_out"), KernelEventCategory::Mm);
132 assert_eq!(category_for_kind("agent_process_changed"), KernelEventCategory::Proc);
133 assert_eq!(category_for_kind("signal_disposed"), KernelEventCategory::Ipc);
134 assert_eq!(category_for_kind("suspended"), KernelEventCategory::Sched);
135 }
136
137 #[test]
138 fn kernel_observation_kinds_cover_abi_surface() {
139 assert!(KERNEL_OBSERVATION_KINDS.contains(&"page_out"));
140 assert!(KERNEL_OBSERVATION_KINDS.contains(&"resumed"));
141 }
142
143 #[test]
144 fn categories_roll_up_to_three_primitives() {
145 assert_eq!(KernelEventCategory::Syscall.primitive(), Primitive::Syscall);
147 assert_eq!(KernelEventCategory::Sched.primitive(), Primitive::Sched);
148 assert_eq!(KernelEventCategory::Proc.primitive(), Primitive::Sched);
149 assert_eq!(KernelEventCategory::Ipc.primitive(), Primitive::Sched);
150 assert_eq!(KernelEventCategory::Mm.primitive(), Primitive::Mm);
151 }
152
153 #[test]
154 fn every_kernel_observation_kind_maps_to_a_primitive() {
155 for kind in KERNEL_OBSERVATION_KINDS {
157 let p = primitive_for_kind(kind);
158 assert!(matches!(p, Primitive::Syscall | Primitive::Sched | Primitive::Mm));
159 }
160 assert_eq!(primitive_for_kind("agent_process_changed"), Primitive::Sched);
161 assert_eq!(primitive_for_kind("signal_disposed"), Primitive::Sched);
162 assert_eq!(primitive_for_kind("tool_gated"), Primitive::Syscall);
163 assert_eq!(primitive_for_kind("page_out"), Primitive::Mm);
164 }
165}