code wiki / (root) / nx_gate_lib.nx

nx_gate_lib.nx source

↩ module page · 161 lines · 6955 B

1// nx_gate_lib.nx -- THE SHARED BASE FOR GATE ORGANS (gl_*), authored 2026-07-25 to eat debt seq938. 2// 3// WHY THIS EXISTS: nx_feed_gate, nx_p384_ecdh_gate and nx_tls12_prf_gate were each written with a PRIVATE 4// copy of the same six helpers (slen/puts/putn/bcat/bcatn/contains) under three different prefixes -- 5// fdg_ / pkg_ / tpg_. That is the exact drift the flip family already paid to fix with nx_flip_lib.nx's 6// fx_* base: a fix to one copy fixes ONE gate, and the family silently diverges. Same mistake, same cure. 7// 8// It also fixes the contract every gate member must honour, so a new gate inherits it instead of 9// re-deriving it: 10// (1) print FAILURES ONLY -- a roster of PASS lines buries the failure the gate exists to surface, 11// and the plan-runner snippet cap (200B) will truncate it away entirely. 12// (2) emit a `verdict=GREEN|RED pass=N/M` anchor LAST so the D001 judge and the beat can read it. 13// (3) counts[0]=total counts[1]=pass, so a case can never be "counted" without being adjudicated. 14// (4) a case asserts BOTH an exit code AND a required output substring -- an exit code alone lets a 15// silently-wrong organ pass, and a substring alone lets a crashed one pass. 16// 17// license_tier: ORIGINAL No hw writes (Rule 26). 18import "nx_syscalls.nx" 19import "nx_tool_run.nx" 20 21const GL_OUTCAP: i64 = 1048576 // per-case fork capture (1 MiB: some probed pages exceed 64KB) 22const GL_BUF: i64 = 262144 23const GL_AVCAP: i64 = 192 24const GL_SCRATCH: i64 = 32 25const GL_EXIT_RED: i64 = 1 26 27func gl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 28func gl_puts(s: *u8) -> i64 { sys_write(1, s, gl_slen(s)); return 0 } 29func gl_putn(v: i64) -> i64 { 30 let b: *u8 = sys_mmap(24) 31 var m: i64 = v 32 if m == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 33 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 34 var nd: i64 = 0 35 var t: i64 = m 36 while t > 0 { nd = nd + 1; t = t / 10 } 37 var i: i64 = nd - 1 38 while i >= 0 { b[i] = (48 + (m % 10)) as u8; m = m / 10; i = i - 1 } 39 sys_write(1, b, nd) 40 return 0 41} 42// append a NUL-terminated string into a buffer at offset o; returns the new offset 43func gl_bcat(b: *u8, o: i64, s: *u8) -> i64 { 44 var i: i64 = 0 45 var oo: i64 = o 46 while s[i] != (0 as u8) { b[oo] = s[i]; oo = oo + 1; i = i + 1 } 47 return oo 48} 49// append a signed decimal into a buffer at offset o; returns the new offset 50func gl_bcatn(b: *u8, o: i64, v: i64) -> i64 { 51 var oo: i64 = o 52 var m: i64 = v 53 if m < 0 { b[oo] = 45 as u8; oo = oo + 1; m = 0 - m } 54 if m == 0 { b[oo] = 48 as u8; return oo + 1 } 55 let tb: *u8 = sys_mmap(24) 56 var nd: i64 = 0 57 while m > 0 { tb[nd] = (48 + (m % 10)) as u8; m = m / 10; nd = nd + 1 } 58 var i: i64 = nd - 1 59 while i >= 0 { b[oo] = tb[i]; oo = oo + 1; i = i - 1 } 60 return oo 61} 62// does haystack[0..n) contain the NUL-terminated needle? 63func gl_contains(h: *u8, n: i64, needle: *u8) -> i64 { 64 var m: i64 = 0 65 while needle[m] != (0 as u8) { m = m + 1 } 66 if m == 0 { return 1 } 67 if m > n { return 0 } 68 var i: i64 = 0 69 var found: i64 = 0 70 while i <= n - m { 71 if found == 0 { 72 var j: i64 = 0 73 var ok: i64 = 1 74 while j < m { 75 if ok == 1 { if h[i+j] != needle[j] { ok = 0 } } 76 j = j + 1 77 } 78 if ok == 1 { found = 1 } 79 } 80 i = i + 1 81 } 82 return found 83} 84// adjudicate an already-computed boolean. counts[0]=total counts[1]=pass. FAILURES ONLY are printed. 85func gl_check(nm: *u8, ok: i64, counts: *i64) -> i64 { 86 counts[0] = counts[0] + 1 87 if ok == 1 { counts[1] = counts[1] + 1; return 0 } 88 gl_puts("FAIL " as *u8); gl_puts(nm); gl_puts("\n" as *u8) 89 return 0 90} 91// fork a live organ and assert BOTH its exit code AND a required output substring. 92// Buffered variant: FAIL rows accumulate into pb at offset po; returns the new offset. 93func gl_case(nm: *u8, path: *u8, av: *i64, want_exit: i64, want_sub: *u8, 94 counts: *i64, pb: *u8, po: i64) -> i64 { 95 let out: *u8 = sys_mmap(GL_OUTCAP) 96 let ol: *i64 = sys_mmap(GL_SCRATCH) as *i64 97 let rc: i64 = tr_run_capture(path, av, out, GL_OUTCAP, ol) 98 var ok: i64 = 1 99 if rc != want_exit { ok = 0 } 100 if gl_contains(out, ol[0], want_sub) == 0 { ok = 0 } 101 counts[0] = counts[0] + 1 102 if ok == 1 { counts[1] = counts[1] + 1; return po } 103 var o: i64 = po 104 o = gl_bcat(pb, o, "FAIL " as *u8) 105 o = gl_bcat(pb, o, nm) 106 o = gl_bcat(pb, o, " exit=" as *u8); o = gl_bcatn(pb, o, rc) 107 o = gl_bcat(pb, o, " want_exit=" as *u8); o = gl_bcatn(pb, o, want_exit) 108 o = gl_bcat(pb, o, " want=" as *u8); o = gl_bcat(pb, o, want_sub) 109 o = gl_bcat(pb, o, "\n" as *u8) 110 return o 111} 112// build a 1-URL argv vector for the common "fork <elf> <url>" case 113func gl_av1(path: *u8, a1: *u8) -> *i64 { 114 let av: *i64 = sys_mmap(GL_AVCAP) as *i64 115 av[0] = path as i64 116 av[1] = a1 as i64 117 av[2] = 0 118 return av 119} 120// APPEND one durable verdict line to a log path. WHY THIS EXISTS (measured 2026-07-25): the tickless clock 121// daemon's clk_dispatch_run forks a job, wait4()s it, and counts it as dispatched whenever it RAN -- it does 122// NOT distinguish exit 0 from exit 1, and the child's stdout goes NOWHERE. So an hourly gate that turns RED 123// turns red in a VACUUM: nothing records it and nothing alerts. Rather than change the shared dispatcher 124// (blast radius: every clock job in the ecosystem), each gate now writes its OWN durable evidence -- the 125// same knowledge/status/*.log idiom the auction/census organs already use. 126func gl_log(path: *u8, banner: *u8, counts: *i64) -> i64 { 127 let fd: i64 = sys_openat_append(path, 0x1a4) 128 if fd < 0 { return 0 - 1 } 129 let b: *u8 = sys_mmap(512) 130 var o: i64 = 0 131 o = gl_bcatn(b, o, sys_now_realtime_sec()) 132 o = gl_bcat(b, o, " " as *u8) 133 o = gl_bcat(b, o, banner) 134 o = gl_bcat(b, o, " verdict=" as *u8) 135 if counts[1] == counts[0] { o = gl_bcat(b, o, "GREEN" as *u8) } else { o = gl_bcat(b, o, "RED" as *u8) } 136 o = gl_bcat(b, o, " pass=" as *u8) 137 o = gl_bcatn(b, o, counts[1]) 138 o = gl_bcat(b, o, "/" as *u8) 139 o = gl_bcatn(b, o, counts[0]) 140 b[o] = 10 as u8 141 o = o + 1 142 sys_write(fd, b, o) 143 sys_close(fd) 144 return 0 145} 146 147// emit the D001 verdict anchor LAST, then flush buffered FAIL rows. Returns the process exit code. 148func gl_verdict(banner: *u8, counts: *i64, ref: *u8, pb: *u8, po: i64) -> i64 { 149 gl_puts(banner) 150 gl_puts("\nverdict=" as *u8) 151 if counts[1] == counts[0] { gl_puts("GREEN" as *u8) } else { gl_puts("RED" as *u8) } 152 gl_puts(" pass=" as *u8); gl_putn(counts[1]) 153 gl_puts("/" as *u8); gl_putn(counts[0]) 154 if ref[0] != (0 as u8) { gl_puts(" " as *u8); gl_puts(ref) } 155 gl_puts("\n" as *u8) 156 if po > 0 { sys_write(1, pb, po) } 157 if counts[1] == counts[0] { return 0 } 158 return GL_EXIT_RED 159} 160 161func main() -> i64 { return 0 }