#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KillPhase {
Graceful,
Escalate,
Verify,
}
impl KillPhase {
pub fn label(self) -> &'static str {
match self {
KillPhase::Graceful => "GRACEFUL",
KillPhase::Escalate => "ESCALATE",
KillPhase::Verify => "VERIFY",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KillStep {
pub phase: KillPhase,
pub pid: u32,
pub grace_ms: u64,
}
pub const DEFAULT_GRACE_MS: u64 = 2_000;
pub fn plan_kill(root_pid: u32, grace_ms: u64) -> Vec<KillStep> {
vec![
KillStep {
phase: KillPhase::Graceful,
pid: root_pid,
grace_ms,
},
KillStep {
phase: KillPhase::Escalate,
pid: root_pid,
grace_ms: 0,
},
KillStep {
phase: KillPhase::Verify,
pid: root_pid,
grace_ms: 0,
},
]
}
pub fn advance(phase: KillPhase, survivors: bool) -> Option<KillPhase> {
match (phase, survivors) {
(KillPhase::Graceful, true) => Some(KillPhase::Escalate),
(KillPhase::Graceful, false) => Some(KillPhase::Verify),
(KillPhase::Escalate, _) => Some(KillPhase::Verify),
(KillPhase::Verify, false) => None,
(KillPhase::Verify, true) => None,
}
}
pub fn cleanup_ok(phase: KillPhase, survivors: bool) -> bool {
phase == KillPhase::Verify && !survivors
}
pub const MAX_EXTINCTION_DEADLINE_MS: u64 = 500;
pub const FAIL_CLOSED_EXTINCTION_EXIT_CODE: i32 = 125;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PlatformExtinctionTier {
LinuxTier1Proven,
WindowsTier3Proven,
MacOsTier2BestEffort,
}
impl PlatformExtinctionTier {
pub fn is_authoritative(self) -> bool {
matches!(self, Self::LinuxTier1Proven | Self::WindowsTier3Proven)
}
pub fn label(self) -> &'static str {
match self {
Self::LinuxTier1Proven => "Linux (cgroups v2 — Proven)",
Self::WindowsTier3Proven => "Windows (Job Object — Proven)",
Self::MacOsTier2BestEffort => "macOS (Multi-Phase Sweep — Best-Effort)",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtinctionProof {
pub platform: PlatformExtinctionTier,
pub surviving_processes: usize,
pub surviving_resources: usize,
pub elapsed_ms: u64,
pub mathematically_proven: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtinctionBreach {
pub platform: PlatformExtinctionTier,
pub exit_code: i32,
pub reason: String,
pub surviving_processes: usize,
pub surviving_resources: usize,
pub elapsed_ms: u64,
}
pub struct ExtinctionVerifier;
impl ExtinctionVerifier {
pub fn verify(
platform: PlatformExtinctionTier,
surviving_processes: usize,
surviving_resources: usize,
elapsed_ms: u64,
) -> Result<ExtinctionProof, ExtinctionBreach> {
if surviving_processes > 0 {
return Err(ExtinctionBreach {
platform,
exit_code: FAIL_CLOSED_EXTINCTION_EXIT_CODE,
reason: format!(
"Lifecycle breach: {} descendant processes escaped extinction boundary",
surviving_processes
),
surviving_processes,
surviving_resources,
elapsed_ms,
});
}
if surviving_resources > 0 {
return Err(ExtinctionBreach {
platform,
exit_code: FAIL_CLOSED_EXTINCTION_EXIT_CODE,
reason: format!(
"Resource breach: {} execution resources (pipes/mounts/IPC) leaked",
surviving_resources
),
surviving_processes,
surviving_resources,
elapsed_ms,
});
}
if elapsed_ms > MAX_EXTINCTION_DEADLINE_MS {
return Err(ExtinctionBreach {
platform,
exit_code: FAIL_CLOSED_EXTINCTION_EXIT_CODE,
reason: format!(
"Extinction deadline exceeded: elapsed {}ms > {}ms max limit",
elapsed_ms, MAX_EXTINCTION_DEADLINE_MS
),
surviving_processes,
surviving_resources,
elapsed_ms,
});
}
Ok(ExtinctionProof {
platform,
surviving_processes: 0,
surviving_resources: 0,
elapsed_ms,
mathematically_proven: platform.is_authoritative(),
})
}
}
#[cfg(test)]
mod proctree_tests {
use super::*;
#[test]
fn plan_always_has_all_three_steps_in_order() {
let plan = plan_kill(4242, DEFAULT_GRACE_MS);
let phases: Vec<KillPhase> = plan.iter().map(|s| s.phase).collect();
assert_eq!(
phases,
vec![KillPhase::Graceful, KillPhase::Escalate, KillPhase::Verify]
);
assert!(plan.iter().all(|s| s.pid == 4242));
assert_eq!(plan[0].grace_ms, DEFAULT_GRACE_MS);
}
#[test]
fn graceful_with_survivors_must_escalate() {
assert_eq!(
advance(KillPhase::Graceful, true),
Some(KillPhase::Escalate)
);
assert_eq!(advance(KillPhase::Graceful, false), Some(KillPhase::Verify));
}
#[test]
fn verify_is_terminal_and_honest() {
assert_eq!(advance(KillPhase::Escalate, true), Some(KillPhase::Verify));
assert_eq!(advance(KillPhase::Verify, true), None);
assert_eq!(advance(KillPhase::Verify, false), None);
assert!(cleanup_ok(KillPhase::Verify, false));
assert!(!cleanup_ok(KillPhase::Verify, true));
assert!(!cleanup_ok(KillPhase::Escalate, false));
}
#[test]
fn test_extinction_theorem_verification_pass() {
let proof = ExtinctionVerifier::verify(PlatformExtinctionTier::LinuxTier1Proven, 0, 0, 120)
.expect("linux extinction must verify");
assert_eq!(proof.surviving_processes, 0);
assert_eq!(proof.surviving_resources, 0);
assert!(proof.mathematically_proven);
}
#[test]
fn test_extinction_theorem_macos_best_effort() {
let proof =
ExtinctionVerifier::verify(PlatformExtinctionTier::MacOsTier2BestEffort, 0, 0, 80)
.expect("macos extinction best effort");
assert_eq!(proof.surviving_processes, 0);
assert!(!proof.mathematically_proven, "macOS is non-authoritative");
}
#[test]
fn test_extinction_theorem_surviving_pid_fails_closed() {
let breach = ExtinctionVerifier::verify(PlatformExtinctionTier::LinuxTier1Proven, 1, 0, 50)
.unwrap_err();
assert_eq!(breach.exit_code, 125);
assert!(breach.reason.contains("Lifecycle breach"));
}
#[test]
fn test_extinction_theorem_deadline_exceeded_fails_closed() {
let breach =
ExtinctionVerifier::verify(PlatformExtinctionTier::LinuxTier1Proven, 0, 0, 501)
.unwrap_err();
assert_eq!(breach.exit_code, 125);
assert!(breach.reason.contains("Extinction deadline exceeded"));
}
}