code wiki / _hdl_build / nx_vizsla_remind_gate.nx

nx_vizsla_remind_gate.nx source

↩ module page · 311 lines · 13197 B

1// nx_vizsla_remind_gate.nx -- VIZSLA REMINDER gate: lead-time due scan + sent-once ledger 2// proven against hand-computed fixtures. COMPOSITION: the calendar side is loaded through the 3// REAL nx_vizsla_calendar organ; birthdays come from the relate CONTACT file format. 4// 5// calendar: launch 07-21, soon 07-08, far 08-30(out), RRULE standup WEEKLY x4 (07-01..07-22) 6// contacts: mom 07-14, dad 07-08, alex -, leap 02-29 7// A) today=2026-07-07 leads=14,7,1,0 -> due=5 (launch@14, soon@1, standup-0708@1, mom@7, dad@1) 8// B) today=2026-07-21 -> due=2 (launch@0 day-of, standup-0722@1) 9// C) today=2027-02-27 leads=1, no calendar -> leap birthday clamps to 2027-02-28 -> due@1 10// D) mark launch sent -> re-mark new=0 -> B re-run with ledger: launch SENT-SKIPPED, due=1 11// 12// Rows: 1 fixture-loads 2 due-verdict 3 due-event-lead14 4 due-recurring 5 due-birthday7 13// 6 due-birthday1 7 due-day-of 8 leap-clamp 9 mark-sent 10 mark-idempotent 14// 11 sent-skipped 12 due-determinism 13 loud-fail-bad-today[neg] 14 loud-fail-bad-leads[neg] 15// Evidence: VIZSLA-REM-GATE -> stdout + knowledge/status/vizsla_gate.log; exit 0 iff 14/14. 16// spec: knowledge/research/2026-06-22-vizsla-sclass-roadmap.md license_tier: ORIGINAL 17import "nx_syscalls.nx" 18import "nx_gate_verdict.nx" 19 20func rg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 21func rg_p(s: *u8) -> i64 { sys_write(1, s, rg_slen(s)); return 0 } 22 23func rg_cat(dst: *u8, off: i64, s: *u8) -> i64 { 24 var i: i64 = 0 25 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 26 return off + i 27} 28 29func rg_catn(dst: *u8, off: i64, v: i64) -> i64 { 30 var o: i64 = off 31 var m: i64 = v 32 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 33 let t: *u8 = sys_mmap(28) 34 var k: i64 = 0 35 if m == 0 { t[0] = 48 as u8; k = 1 } 36 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 37 var i: i64 = 0 38 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 39 return o + k 40} 41 42func rg_write(path: *u8, content: *u8) -> i64 { 43 let fd: i64 = sys_openat_wr(path, 0x1a4) 44 if fd < 0 { return 0 - 1 } 45 sys_write(fd, content, rg_slen(content)) 46 sys_close(fd) 47 return 0 48} 49 50func rg_readall(path: *u8, szout: *i64) -> *u8 { 51 let fd: i64 = sys_openat_rd(path) 52 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 } 53 let sz: i64 = sys_lseek(fd, 0, 2) 54 sys_lseek(fd, 0, 0) 55 let buf: *u8 = sys_mmap(sz + 64) 56 var got: i64 = 0 57 var n: i64 = 1 58 while n > 0 { 59 n = sys_read(fd, (buf as i64 + got) as *u8, 65536) 60 if n > 0 { got = got + n } 61 } 62 sys_close(fd) 63 szout[0] = got 64 return buf 65} 66 67func rg_runv(elf: *u8, args: *i64, outpath: *u8) -> i64 { 68 let pid: i64 = sys_fork() 69 if pid == 0 { 70 if (outpath as i64) != 0 { 71 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 72 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 73 } 74 let argv: *i64 = sys_mmap(128) as *i64 75 argv[0] = elf as i64 76 var i: i64 = 0 77 var go: i64 = 1 78 while go == 1 { 79 if args[i] == 0 { go = 0 } else { 80 argv[i + 1] = args[i] 81 i = i + 1 82 } 83 } 84 argv[i + 1] = 0 85 let envp: *i64 = sys_mmap(16) as *i64 86 envp[0] = 0 87 sys_execve(elf, argv, envp) 88 sys_exit(127) 89 } 90 let st: *i64 = sys_mmap(16) as *i64 91 sys_wait4(pid, st, 0) 92 let sig: i64 = st[0] & 0x7f 93 if sig != 0 { return 128 + sig } 94 return (st[0] >> 8) & 0xff 95} 96 97func rg_has(path: *u8, needle: *u8) -> i64 { 98 let szp: *i64 = sys_mmap(16) as *i64 99 let b: *u8 = rg_readall(path, szp) 100 let sz: i64 = szp[0] 101 let n: i64 = rg_slen(needle) 102 if sz < n { return 0 } 103 var i: i64 = 0 104 while i + n <= sz { 105 var ok: i64 = 1 106 var j: i64 = 0 107 while j < n { 108 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 } 109 } 110 if ok == 1 { return 1 } 111 i = i + 1 112 } 113 return 0 114} 115 116func rg_fileeq(p1: *u8, p2: *u8) -> i64 { 117 let s1: *i64 = sys_mmap(16) as *i64 118 let s2: *i64 = sys_mmap(16) as *i64 119 let b1: *u8 = rg_readall(p1, s1) 120 let b2: *u8 = rg_readall(p2, s2) 121 if s1[0] != s2[0] { return 0 } 122 if s1[0] <= 0 { return 0 } 123 var i: i64 = 0 124 while i < s1[0] { 125 if b1[i] != b2[i] { return 0 } 126 i = i + 1 127 } 128 return 1 129} 130 131func rg_row(name: *u8, pass: i64) -> i64 { 132 rg_p("ROW " as *u8) 133 rg_p(name) 134 if pass == 1 { rg_p(" PASS\n" as *u8) } else { rg_p(" FAIL\n" as *u8) } 135 return pass 136} 137 138func rg_args(a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8, a6: *u8, a7: *u8, a8: *u8) -> *i64 { 139 let a: *i64 = sys_mmap(128) as *i64 140 a[0] = a1 as i64 141 a[1] = a2 as i64 142 a[2] = a3 as i64 143 a[3] = a4 as i64 144 a[4] = a5 as i64 145 a[5] = a6 as i64 146 a[6] = a7 as i64 147 a[7] = a8 as i64 148 a[8] = 0 149 return a 150} 151 152func rg_ensure(elf: *u8, organ: *u8) -> i64 { 153 let pr: i64 = sys_openat_rd(elf) 154 if pr >= 0 { sys_close(pr); return 0 } 155 rg_p(" instrument missing -> rebuilding via durable runner\n" as *u8) 156 rg_runv("_offc/nx_sov_build_run.elf" as *u8, rg_args(organ, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_rebuild.out" as *u8) 157 return 0 158} 159 160func rg_mkpfx(tag: *u8, us: i64) -> *u8 { 161 let pfx: *u8 = sys_mmap(128) 162 var po: i64 = 0 163 po = rg_cat(pfx, po, tag) 164 po = rg_catn(pfx, po, us) 165 po = rg_cat(pfx, po, "-" as *u8) 166 pfx[po] = 0 as u8 167 return pfx 168} 169 170func main(argc: i64, argv: *i64) -> i64 { 171 rg_p("=== VIZSLA REMIND GATE: lead-time due scan + sent-once ledger KATs ===\n" as *u8) 172 let rem: *u8 = "buildroot/_build/nx_vizsla_remind.sov.elf" as *u8 173 let cal: *u8 = "buildroot/_build/nx_vizsla_calendar.sov.elf" as *u8 174 rg_ensure(rem, "nx_vizsla_remind" as *u8) 175 rg_ensure(cal, "nx_vizsla_calendar" as *u8) 176 177 let us: i64 = sys_now_us() 178 let pfxR: *u8 = rg_mkpfx("/tmp/vzrR" as *u8, us) 179 let pfxS: *u8 = rg_mkpfx("/tmp/vzrS" as *u8, us) 180 181 rg_write("/tmp/vzr_cal.txt" as *u8, "EVENT launch 2026-07-21 600 90 team-launch\nEVENT soon 2026-07-08 540 30 checkin\nEVENT far 2026-08-30 540 30 too-far\nRRULE standup 2026-07-01 540 30 WEEKLY 1 4 weekly-standup\n" as *u8) 182 rg_write("/tmp/vzr_ct.txt" as *u8, "TIER inner 7\nCONTACT mom Mom inner 07-14\nCONTACT dad Dad inner 07-08\nCONTACT alex Alex inner -\nCONTACT leap Leapy inner 02-29\n" as *u8) 183 184 var pass: i64 = 0 185 var r: i64 = 0 186 187 // row 1: calendar fixture loads through the real organ 188 let rc1: i64 = rg_runv(cal, rg_args("load" as *u8, "/tmp/vzr_cal.txt" as *u8, pfxR, "6601" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_l1.txt" as *u8) 189 r = 0 190 if rc1 == 0 { 191 if rg_has("/tmp/vzr_l1.txt" as *u8, "VIZSLA-CAL-LOAD scanned=4 new=4" as *u8) == 1 { r = 1 } 192 } 193 pass = pass + rg_row("fixture-loads" as *u8, r) 194 195 // rows 2-6: due at 2026-07-07 196 let rc2: i64 = rg_runv(rem, rg_args("due" as *u8, pfxR, "/tmp/vzr_ct.txt" as *u8, "2026-07-07" as *u8, "14,7,1,0" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r2.txt" as *u8) 197 r = 0 198 if rc2 == 0 { 199 if rg_has("/tmp/vzr_r2.txt" as *u8, "VIZSLA-REM-VERDICT today=2026-07-07 maxlead=14 due=5 due_events=3 due_birthdays=2 skipped_sent=0" as *u8) == 1 { r = 1 } 200 } 201 pass = pass + rg_row("due-verdict" as *u8, r) 202 203 r = rg_has("/tmp/vzr_r2.txt" as *u8, "VIZSLA-REM-DUE kind=event id=launch date=2026-07-21 in=14 title=team-launch" as *u8) 204 pass = pass + rg_row("due-event-lead14" as *u8, r) 205 206 r = rg_has("/tmp/vzr_r2.txt" as *u8, "VIZSLA-REM-DUE kind=event id=standup date=2026-07-08 in=1 title=weekly-standup" as *u8) 207 pass = pass + rg_row("due-recurring" as *u8, r) 208 209 r = rg_has("/tmp/vzr_r2.txt" as *u8, "VIZSLA-REM-DUE kind=birthday id=mom date=2026-07-14 in=7 title=Mom" as *u8) 210 pass = pass + rg_row("due-birthday7" as *u8, r) 211 212 r = rg_has("/tmp/vzr_r2.txt" as *u8, "VIZSLA-REM-DUE kind=birthday id=dad date=2026-07-08 in=1 title=Dad" as *u8) 213 pass = pass + rg_row("due-birthday1" as *u8, r) 214 215 // row 7: day-of (lead 0) at 2026-07-21 216 let rc7: i64 = rg_runv(rem, rg_args("due" as *u8, pfxR, "/tmp/vzr_ct.txt" as *u8, "2026-07-21" as *u8, "14,7,1,0" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r7.txt" as *u8) 217 r = 0 218 if rc7 == 0 { 219 if rg_has("/tmp/vzr_r7.txt" as *u8, "VIZSLA-REM-DUE kind=event id=launch date=2026-07-21 in=0 title=team-launch" as *u8) == 1 { 220 if rg_has("/tmp/vzr_r7.txt" as *u8, "VIZSLA-REM-VERDICT today=2026-07-21 maxlead=14 due=2 due_events=2 due_birthdays=0 skipped_sent=0" as *u8) == 1 { r = 1 } 221 } 222 } 223 pass = pass + rg_row("due-day-of" as *u8, r) 224 225 // row 8: Feb-29 birthday clamps in a non-leap year 226 let rc8: i64 = rg_runv(rem, rg_args("due" as *u8, "-" as *u8, "/tmp/vzr_ct.txt" as *u8, "2027-02-27" as *u8, "1" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r8.txt" as *u8) 227 r = 0 228 if rc8 == 0 { 229 if rg_has("/tmp/vzr_r8.txt" as *u8, "VIZSLA-REM-DUE kind=birthday id=leap date=2027-02-28 in=1 title=Leapy" as *u8) == 1 { r = 1 } 230 } 231 pass = pass + rg_row("leap-clamp" as *u8, r) 232 233 // rows 9-10: sent ledger mark + idempotence 234 let rc9: i64 = rg_runv(rem, rg_args("mark" as *u8, pfxS, "event" as *u8, "launch" as *u8, "2026-07-21" as *u8, "6602" as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r9.txt" as *u8) 235 r = 0 236 if rc9 == 0 { 237 if rg_has("/tmp/vzr_r9.txt" as *u8, "VIZSLA-REM-MARK k=event id=launch date=2026-07-21 new=1" as *u8) == 1 { r = 1 } 238 } 239 pass = pass + rg_row("mark-sent" as *u8, r) 240 241 let rc10: i64 = rg_runv(rem, rg_args("mark" as *u8, pfxS, "event" as *u8, "launch" as *u8, "2026-07-21" as *u8, "6603" as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r10.txt" as *u8) 242 r = 0 243 if rc10 == 0 { 244 if rg_has("/tmp/vzr_r10.txt" as *u8, "VIZSLA-REM-MARK k=event id=launch date=2026-07-21 new=0" as *u8) == 1 { r = 1 } 245 } 246 pass = pass + rg_row("mark-idempotent" as *u8, r) 247 248 // row 11: sent notice skipped, others still due 249 let rc11: i64 = rg_runv(rem, rg_args("due" as *u8, pfxR, "/tmp/vzr_ct.txt" as *u8, "2026-07-21" as *u8, "14,7,1,0" as *u8, pfxS, 0 as *u8, 0 as *u8), "/tmp/vzr_r11.txt" as *u8) 250 r = 0 251 if rc11 == 0 { 252 if rg_has("/tmp/vzr_r11.txt" as *u8, "VIZSLA-REM-SENT-SKIP kind=event id=launch date=2026-07-21" as *u8) == 1 { 253 if rg_has("/tmp/vzr_r11.txt" as *u8, "VIZSLA-REM-VERDICT today=2026-07-21 maxlead=14 due=1 due_events=1 due_birthdays=0 skipped_sent=1" as *u8) == 1 { 254 if rg_has("/tmp/vzr_r11.txt" as *u8, "VIZSLA-REM-DUE kind=event id=launch" as *u8) == 0 { r = 1 } 255 } 256 } 257 } 258 pass = pass + rg_row("sent-skipped" as *u8, r) 259 260 // row 12: determinism 261 rg_runv(rem, rg_args("due" as *u8, pfxR, "/tmp/vzr_ct.txt" as *u8, "2026-07-07" as *u8, "14,7,1,0" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r12.txt" as *u8) 262 r = rg_fileeq("/tmp/vzr_r2.txt" as *u8, "/tmp/vzr_r12.txt" as *u8) 263 pass = pass + rg_row("due-determinism" as *u8, r) 264 265 // row 13: bad today (negative control) 266 let rc13: i64 = rg_runv(rem, rg_args("due" as *u8, pfxR, "/tmp/vzr_ct.txt" as *u8, "2026-13-99" as *u8, "14,7,1,0" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r13.txt" as *u8) 267 r = 0 268 if rc13 == 1 { r = 1 } 269 pass = pass + rg_row("loud-fail-bad-today" as *u8, r) 270 271 // row 14: bad leads (negative control) 272 let rc14: i64 = rg_runv(rem, rg_args("due" as *u8, pfxR, "/tmp/vzr_ct.txt" as *u8, "2026-07-07" as *u8, "x,1" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzr_r14.txt" as *u8) 273 r = 0 274 if rc14 == 1 { r = 1 } 275 pass = pass + rg_row("loud-fail-bad-leads" as *u8, r) 276 277 let permil: i64 = (pass * 1000) / 14 278 let logfd: i64 = sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4) 279 var fdi: i64 = 0 280 while fdi < 2 { 281 var fd: i64 = 1 282 if fdi == 1 { fd = logfd } 283 if fd > 0 { 284 let line: *u8 = sys_mmap(256) 285 var o: i64 = 0 286 o = rg_cat(line, o, "VIZSLA-REM-GATE epoch=" as *u8) 287 o = rg_catn(line, o, sys_now_realtime_sec()) 288 o = rg_cat(line, o, " rows=14 pass=" as *u8) 289 o = rg_catn(line, o, pass) 290 o = rg_cat(line, o, " permil=" as *u8) 291 o = rg_catn(line, o, permil) 292 if pass == 14 { 293 o = rg_cat(line, o, " verdict=GREEN\n" as *u8) 294 } else { 295 o = rg_cat(line, o, " verdict=RED\n" as *u8) 296 } 297 sys_write(fd, line, o) 298 } 299 fdi = fdi + 1 300 } 301 if logfd > 0 { sys_close(logfd) } 302 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 303 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 304 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 305 let ctr__dry: *i64 = gv_ctr() 306 ctr__dry[0] = pass 307 ctr__dry[1] = 14 308 let rc__dry: i64 = gv_verdict("VIZSLA-REMIND-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 309 sys_exit(rc__dry) 310 return rc__dry 311}