code wiki / (root) / nx_heal_gate.nx

nx_heal_gate.nx source

↩ module page · 69 lines · 4203 B

1// nx_heal_gate.nx -- gates the consolidated heal-plane tool on SYNTHETIC fixtures (asserts the lib's 2// RETURN VALUES, not stdout): a DOWN service is detected + counted; an all-UP snap is GREEN; log tail 3// counts lines; an ABSENT plane log is graceful; remediation events are counted across planes. 4// Runner must clean /tmp/healgate first. Exit 0 only on all-PASS. license_tier: ORIGINAL expect_exit: 0 5import "nx_heal_lib.nx" 6 7const GATE_CHECKS: i64 = 9 8const OLD_AGE: i64 = 100000 // classifier fixture: clearly a long-lived parent 9const YOUNG_AGE: i64 = 45 // classifier fixture: clearly a fresh restart 10const SOME_REMED: i64 = 3 // classifier fixture: recent heal-plane remediations 11const DIR_MODE: i64 = 0x1ed // 0755 12const FIX_LOG_LINES: i64 = 3 // fixture tools_selfheal.log line count 13const FIX_EVENTS: i64 = 3 // fixture remediation event count 14 15func hg_check(name: *u8, ok: i64, pass: *i64) -> i64 { 16 nh_puts("T " as *u8); nh_puts(name); nh_puts(" -> " as *u8) 17 if ok == 1 { nh_puts("PASS\n" as *u8); pass[0] = pass[0] + 1 } else { nh_puts("FAIL\n" as *u8) } 18 return 0 19} 20func hg_write(dir: *u8, name: *u8, body: *u8) -> i64 { 21 let p: *u8 = sys_mmap(512) 22 nh_path(p, dir, name) 23 var n: i64 = 0 24 while body[n] != (0 as u8) { n = n + 1 } 25 return ss_writefile(p, body, n) 26} 27 28func main(argc: i64, argv: *i64) -> i64 { 29 let pass: *i64 = sys_mmap(16) as *i64 30 pass[0] = 0 31 // fixture A: one service DOWN, logs + events present 32 let da: *u8 = "/tmp/healgate/a" as *u8 33 sys_mkdir("/tmp/healgate" as *u8, DIR_MODE) 34 sys_mkdir(da, DIR_MODE) 35 hg_write(da, "mgmt_snap.json" as *u8, "SUP 1\nSVC alpha.elf 1001 UP 1 0 0 0\nSVC beta.elf 1002 UP 1 0 0 0\nSVC gamma.elf 1003 DOWN 1 0 0 0\n" as *u8) 36 hg_write(da, "selfheal_status.tsv" as *u8, "tools\tOK\nedge\tOK\n" as *u8) 37 hg_write(da, "tools_selfheal.log" as *u8, "100 UNHEALTHY tools :18096 code=000 consecutive=1\n101 REMEDIATE-DONE relaunched serve; remediations_last_hour=1\n102 OK tools :18096 code=200 (was unhealthy x1 -> recovered)\n" as *u8) 38 hg_write(da, "tools_remediations.log" as *u8, "100\n200\n300\n" as *u8) 39 // fixture B: everything UP, no logs at all (fresh plane) 40 let db: *u8 = "/tmp/healgate/b" as *u8 41 sys_mkdir(db, DIR_MODE) 42 hg_write(db, "mgmt_snap.json" as *u8, "SUP 1\nSVC alpha.elf 1001 UP 1 0 0 0\n" as *u8) 43 44 // T1 a DOWN service is detected and counted (returns down-count 1) 45 hg_check("status-detects-down" as *u8, (nh_status(da) == 1) as i64, pass) 46 // T2 all-UP snap returns 0 (GREEN) even with zero selfheal logs (graceful) 47 hg_check("status-all-up-green" as *u8, (nh_status(db) == 0) as i64, pass) 48 // T3 log tail reports the fixture's line count 49 hg_check("log-tools-linecount" as *u8, (nh_log(da, "tools" as *u8) == FIX_LOG_LINES) as i64, pass) 50 // T4 absent plane log is graceful (0, no crash) 51 hg_check("log-edge-absent-graceful" as *u8, (nh_log(da, "edge" as *u8) == 0) as i64, pass) 52 // T5 remediation events counted across planes (3 tools + 0 edge) 53 hg_check("remediations-counted" as *u8, (nh_remediations(da) == FIX_EVENTS) as i64, pass) 54 55 // T6-T9: the PURE why-classifier (the diagnose verb's brain) on synthetic evidence 56 // no process -> DOWN 57 hg_check("classify-down" as *u8, (nh_classify(0, 0 - 1, 0) == NH_V_DOWN) as i64, pass) 58 // long-lived parent -> STABLE (pid churn = workers = monitor false-positive, NOT a crash loop) 59 hg_check("classify-stable-forkmodel" as *u8, (nh_classify(SOME_REMED, OLD_AGE, 0) == NH_V_STABLE) as i64, pass) 60 // young + recent heal remediations -> the selfheal is bouncing it 61 hg_check("classify-loop-healplane" as *u8, (nh_classify(1, YOUNG_AGE, SOME_REMED) == NH_V_LOOP_HEAL) as i64, pass) 62 // young + NO heal remediations -> untracked restarter (guard/reconcile/crash) 63 hg_check("classify-loop-untracked" as *u8, (nh_classify(1, YOUNG_AGE, 0) == NH_V_LOOP_UNTRACKED) as i64, pass) 64 65 nh_puts("HEAL-GATE pass=" as *u8); nh_putn(pass[0]); nh_puts("/" as *u8); nh_putn(GATE_CHECKS); nh_puts(" verdict=" as *u8) 66 if pass[0] == GATE_CHECKS { nh_puts("GREEN\n" as *u8); return 0 } 67 nh_puts("RED\n" as *u8) 68 return 1 69}