use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Primitive {
Syscall,
Sched,
Mm,
}
impl Primitive {
pub fn label(self) -> &'static str {
match self {
Self::Syscall => "syscall",
Self::Sched => "sched",
Self::Mm => "mm",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum KernelEventCategory {
Syscall,
Sched,
Mm,
Proc,
Ipc,
}
impl KernelEventCategory {
pub fn primitive(self) -> Primitive {
match self {
Self::Syscall => Primitive::Syscall,
Self::Sched | Self::Proc | Self::Ipc => Primitive::Sched,
Self::Mm => Primitive::Mm,
}
}
}
pub fn primitive_for_kind(kind: &str) -> Primitive {
category_for_kind(kind).primitive()
}
pub fn category_for_kind(kind: &str) -> KernelEventCategory {
match kind {
"tool_gated" | "capability_changed" => KernelEventCategory::Syscall,
"suspended"
| "resumed"
| "budget_exceeded"
| "checkpoint_taken"
| "rollbacked"
| "milestone_advanced"
| "milestone_blocked" => KernelEventCategory::Sched,
"compressed"
| "page_out"
| "page_in"
| "renewed"
| "context_renewed"
| "large_result_spooled" => KernelEventCategory::Mm,
"agent_process_changed" | "agent_spawned" | "workflow_batch_spawned"
| "workflow_completed" | "agent_preempted" => KernelEventCategory::Proc,
"signal_disposed" => KernelEventCategory::Ipc,
"memory_written" | "memory_queried" | "memory_validation_failed" => KernelEventCategory::Mm,
_ => KernelEventCategory::Sched,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn maps_observation_kinds_to_categories() {
assert_eq!(category_for_kind("tool_gated"), KernelEventCategory::Syscall);
assert_eq!(category_for_kind("page_out"), KernelEventCategory::Mm);
assert_eq!(category_for_kind("agent_process_changed"), KernelEventCategory::Proc);
assert_eq!(category_for_kind("signal_disposed"), KernelEventCategory::Ipc);
assert_eq!(category_for_kind("suspended"), KernelEventCategory::Sched);
}
#[test]
fn categories_roll_up_to_three_primitives() {
assert_eq!(KernelEventCategory::Syscall.primitive(), Primitive::Syscall);
assert_eq!(KernelEventCategory::Sched.primitive(), Primitive::Sched);
assert_eq!(KernelEventCategory::Proc.primitive(), Primitive::Sched);
assert_eq!(KernelEventCategory::Ipc.primitive(), Primitive::Sched);
assert_eq!(KernelEventCategory::Mm.primitive(), Primitive::Mm);
}
#[test]
fn every_kernel_observation_kind_maps_to_a_primitive() {
assert_eq!(primitive_for_kind("agent_process_changed"), Primitive::Sched);
assert_eq!(primitive_for_kind("signal_disposed"), Primitive::Sched);
assert_eq!(primitive_for_kind("tool_gated"), Primitive::Syscall);
assert_eq!(primitive_for_kind("page_out"), Primitive::Mm);
}
}