lean_ctx/core/
safety_needles.rs1const SAFETY_NEEDLES: &[&str] = &[
2 "CRITICAL",
3 "FATAL",
4 "panic",
5 "FAILED",
6 "unhealthy",
7 "Exited",
8 "OOMKilled",
9 "DETACHED HEAD",
10 "detached",
11 "vulnerability",
12 "CVE-",
13 "denied",
14 "unauthorized",
15 "forbidden",
16 "error",
17 "ERROR",
18 "WARNING",
19 "WARN",
20 "fail",
21 "segfault",
22 "Segmentation fault",
23 "SIGSEGV",
24 "SIGKILL",
25 "killed",
26 "out of memory",
27 "stack overflow",
28 "permission denied",
29 "certificate",
30 "expired",
31 "corrupt",
32];
33
34pub fn is_safety_relevant(line: &str) -> bool {
35 let lower = line.to_ascii_lowercase();
36 SAFETY_NEEDLES
37 .iter()
38 .any(|needle| lower.contains(&needle.to_ascii_lowercase()))
39}
40
41pub fn extract_safety_lines(lines: &[&str], max: usize) -> Vec<String> {
42 lines
43 .iter()
44 .filter(|l| is_safety_relevant(l))
45 .take(max)
46 .map(std::string::ToString::to_string)
47 .collect()
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn detects_critical() {
56 assert!(is_safety_relevant("CRITICAL: disk full"));
57 assert!(is_safety_relevant("container unhealthy"));
58 assert!(is_safety_relevant("CVE-2024-12345 found"));
59 assert!(is_safety_relevant("error: something broke"));
60 assert!(is_safety_relevant("permission denied"));
61 }
62
63 #[test]
64 fn ignores_normal_lines() {
65 assert!(!is_safety_relevant("compiled successfully"));
66 assert!(!is_safety_relevant("200 OK"));
67 assert!(!is_safety_relevant("all tests passed"));
68 }
69
70 #[test]
71 fn extracts_limited_safety_lines() {
72 let lines = vec![
73 "line 1",
74 "ERROR: something",
75 "line 3",
76 "CRITICAL: disk",
77 "line 5",
78 "WARNING: old version",
79 ];
80 let result = extract_safety_lines(&lines, 2);
81 assert_eq!(result.len(), 2);
82 assert!(result[0].contains("ERROR"));
83 assert!(result[1].contains("CRITICAL"));
84 }
85}