code wiki / _hdl_build / nx_pub_recover_gate.nx

nx_pub_recover_gate.nx source

↩ module page · 86 lines · 5514 B

1// nx_pub_recover_gate.nx -- SOVEREIGN gate for the publisher's recovery DECISION (nx_pub_recover). 2// Proves: (1) a WEDGED daemon (from the monitor's metrics) -> exactly ONE idempotent recovery request 3// (both /library + /media map to the same reader daemon -> deduped to 1); (2) IDEMPOTENT re-run -> 0 new; 4// (3) NEG-CONTROL all-green metrics -> 0 (no healthy daemon ever requested); (4) LIAR-KILL the owner-only 5// sites.elf (landing/status) is UNMAPPED -> never auto-requested even when wedged (coordinate, don't solo). 6// Per-run /tmp test files (no clobber of the real apm_metrics.tsv / recovery_queue.tsv). license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_pub_recover.nx" // pr_recover / pr_n / pr_s / pr_field / pr_daemon_for / pr_has (main stripped on import) 9import "nx_gate_verdict.nx" 10 11const GT_MET: *u8 = "/tmp/pr_test_metrics.tsv" 12const GT_Q: *u8 = "/tmp/pr_test_queue.tsv" 13 14func gt_uw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 15func gt_wn(v: i64) -> i64 { let b: *u8 = sys_mmap(24); let e: i64 = pr_n(b, 0, v); sys_write(1, b, e); return 0 } 16func gt_write(path: *u8, buf: *u8, len: i64) -> i64 { 17 let fd: i64 = sys_openat_wr(path, 0x1a4); if fd < 0 { return 0 - 1 } 18 sys_write(fd, buf, len); sys_close(fd); return 0 19} 20// append one apm_metrics row (epoch label url conc oks nres min p50 p95 MAX stalls timeouts errs) with field9=max. 21func gt_row(buf: *u8, off: i64, url: *u8, maxv: i64) -> i64 { 22 var o: i64 = off 23 o = pr_n(buf, o, 1782007783); buf[o]=9 as u8; o=o+1 // epoch 24 o = pr_s(buf, o, "lbl" as *u8); buf[o]=9 as u8; o=o+1 // label 25 o = pr_s(buf, o, url); buf[o]=9 as u8; o=o+1 // url (field2) 26 o = pr_s(buf, o, "1" as *u8); buf[o]=9 as u8; o=o+1 // conc 27 o = pr_s(buf, o, "1" as *u8); buf[o]=9 as u8; o=o+1 // oks 28 o = pr_s(buf, o, "1" as *u8); buf[o]=9 as u8; o=o+1 // nres 29 o = pr_n(buf, o, maxv); buf[o]=9 as u8; o=o+1 // min 30 o = pr_n(buf, o, maxv); buf[o]=9 as u8; o=o+1 // p50 31 o = pr_n(buf, o, maxv); buf[o]=9 as u8; o=o+1 // p95 32 o = pr_n(buf, o, maxv); buf[o]=9 as u8; o=o+1 // max (field9) 33 o = pr_s(buf, o, "0" as *u8); buf[o]=9 as u8; o=o+1 // stalls 34 o = pr_s(buf, o, "0" as *u8); buf[o]=9 as u8; o=o+1 // timeouts 35 o = pr_s(buf, o, "0" as *u8); buf[o]=10 as u8; o=o+1 // errs + newline 36 return o 37} 38 39func main(argc: i64, argv: *i64) -> i64 { 40 var pass: i64 = 0; var total: i64 = 0 41 42 // ---- T1: wedged /library + /media (both -> reader) + green / + green /wiki ---- 43 let m: *u8 = sys_mmap(4096); var o: i64 = 0 44 o = gt_row(m, o, "https://nishifamily.com/" as *u8, 762) 45 o = gt_row(m, o, "https://nishifamily.com/wiki" as *u8, 810) 46 o = gt_row(m, o, "https://nishifamily.com/library" as *u8, 20832) 47 o = gt_row(m, o, "https://nishifamily.com/media" as *u8, 20832) 48 gt_write(GT_MET, m, o) 49 gt_write(GT_Q, "" as *u8, 0) // empty queue 50 let e1: i64 = pr_recover(GT_MET, GT_Q, 5000) 51 total = total + 1; if e1 == 1 { pass = pass + 1; gt_uw("[PASS] T1 wedged lib+media -> 1 deduped request\n" as *u8) } else { gt_uw("[FAIL] T1 expected 1 got " as *u8); gt_wn(e1); gt_uw("\n" as *u8) } 52 53 // ---- T2: IDEMPOTENT re-run -> 0 new (reader already PENDING) ---- 54 let e2: i64 = pr_recover(GT_MET, GT_Q, 5000) 55 total = total + 1; if e2 == 0 { pass = pass + 1; gt_uw("[PASS] T2 idempotent re-run -> 0 new\n" as *u8) } else { gt_uw("[FAIL] T2 expected 0 got " as *u8); gt_wn(e2); gt_uw("\n" as *u8) } 56 57 // ---- T3: NEG-CONTROL all-green -> 0 (no healthy daemon ever requested) ---- 58 var o2: i64 = 0 59 o2 = gt_row(m, o2, "https://nishifamily.com/" as *u8, 762) 60 o2 = gt_row(m, o2, "https://nishifamily.com/library" as *u8, 740) 61 o2 = gt_row(m, o2, "https://nishifamily.com/media" as *u8, 690) 62 gt_write(GT_MET, m, o2) 63 gt_write(GT_Q, "" as *u8, 0) 64 let e3: i64 = pr_recover(GT_MET, GT_Q, 5000) 65 total = total + 1; if e3 == 0 { pass = pass + 1; gt_uw("[PASS] T3 neg-control all-green -> 0\n" as *u8) } else { gt_uw("[FAIL] T3 expected 0 got " as *u8); gt_wn(e3); gt_uw("\n" as *u8) } 66 67 // ---- T4: LIAR-KILL -- wedged landing/ (sites.elf, owner-only/unmapped) -> never auto-requested ---- 68 var o3: i64 = 0 69 o3 = gt_row(m, o3, "https://nishifamily.com/" as *u8, 25000) // landing WEDGED, but unmapped 70 o3 = gt_row(m, o3, "https://nishifamily.com/status.html" as *u8, 25000) 71 gt_write(GT_MET, m, o3) 72 gt_write(GT_Q, "" as *u8, 0) 73 let e4: i64 = pr_recover(GT_MET, GT_Q, 5000) 74 total = total + 1; if e4 == 0 { pass = pass + 1; gt_uw("[PASS] T4 liar-kill: wedged-but-unmapped sites.elf -> 0 (coordinate, not solo)\n" as *u8) } else { gt_uw("[FAIL] T4 expected 0 got " as *u8); gt_wn(e4); gt_uw("\n" as *u8) } 75 76 gt_uw("=== nx_pub_recover_gate " as *u8); gt_wn(pass); gt_uw("/" as *u8); gt_wn(total) 77 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 78 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 79 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 80 let ctr__dry: *i64 = gv_ctr() 81 ctr__dry[0] = pass 82 ctr__dry[1] = total 83 let rc__dry: i64 = gv_verdict("PUB-RECOVER-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 84 sys_exit(rc__dry) 85 return rc__dry 86}