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"
| "budget_usage_reported"
| "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_delivery_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_delivery_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_delivery_disposed"),
Primitive::Sched
);
assert_eq!(primitive_for_kind("tool_gated"), Primitive::Syscall);
assert_eq!(primitive_for_kind("page_out"), Primitive::Mm);
}
}