code wiki / _hdl_build / nx_vizsla_ics_gate.nx

nx_vizsla_ics_gate.nx source

↩ module page · 436 lines · 16784 B

1// nx_vizsla_ics_gate.nx -- VIZSLA R-CAL.4 gate: RFC 5545 .ics EXPORT is gate-proven against 2// construction-known fixtures. GENUINE COMPOSITION: forks the blessed calendar organ to LOAD the 3// store, then the ics organ to EXPORT it -- the gate never fabricates store bytes itself. 4// 5// fixture (loaded via nx_vizsla_calendar, seg-6201): 6// EVENT launch 2026-06-20 10:00 +90 title "pizza,night;launch" (TEXT-escape exercise) 7// EVENT ride 2026-07-03 08:00 +120 title 86-char token (75-octet folding exercise) 8// EVENT far 2026-09-01 08:00 +60 out-of-window (exclusion exercise) 9// RRULE standup 2026-06-01 WEEKLY/2 x6 -> native RRULE passthrough 10// RRULE bday 2024-02-29 YEARLY/1 x50 -> intersects window via last-occurrence (2073) 11// window 2026-06-01..2026-07-31 => events=2 rules=2 => 4 VEVENTs. 12// 13// Rows: 14// 1 export-ok exit 0 + VIZSLA-ICS-VERDICT events=2 rules=2 15// 2 vcalendar-frame BEGIN:VCALENDAR + VERSION:2.0 + PRODID + END:VCALENDAR 16// 3 crlf-strict every LF preceded by CR (RFC5545 line ends), >=10 lines 17// 4 vevent-count exactly 4 BEGIN:VEVENT 18// 5 dtstart-dtend launch DTSTART:20260620T100000 + DTEND:20260620T113000 19// 6 uid-stable UID:launch-20260620@nishi.vizsla 20// 7 rrule-weekly RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=6 21// 8 rrule-yearly RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=50 22// 9 summary-escaping SUMMARY:pizza\,night\;launch (backslash-escaped , and ;) 23// 10 fold-75 no physical line >75 octets + a CRLF+space continuation + folded=1 24// 11 window-exclusion UID:far- ABSENT (out-of-window event not exported) 25// 12 export-determinism two exports byte-identical (no clocks in the artifact) 26// 13 loud-fail-bad-date export from=2026-13-99 => exit 1 [negative control] 27// 14 loud-fail-unwritable export into a nonexistent dir => exit 1 [negative control] 28// Evidence: VIZSLA-ICS-GATE -> stdout + knowledge/status/vizsla_gate.log; exit 0 iff 14/14. 29// spec: knowledge/research/2026-06-22-vizsla-sclass-roadmap.md license_tier: ORIGINAL 30import "nx_syscalls.nx" 31import "nx_gate_verdict.nx" 32 33func ig_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 34func ig_p(s: *u8) -> i64 { sys_write(1, s, ig_slen(s)); return 0 } 35 36func ig_cat(dst: *u8, off: i64, s: *u8) -> i64 { 37 var i: i64 = 0 38 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 39 return off + i 40} 41 42func ig_catn(dst: *u8, off: i64, v: i64) -> i64 { 43 var o: i64 = off 44 var m: i64 = v 45 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 46 let t: *u8 = sys_mmap(28) 47 var k: i64 = 0 48 if m == 0 { t[0] = 48 as u8; k = 1 } 49 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 50 var i: i64 = 0 51 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 52 return o + k 53} 54 55func ig_write(path: *u8, content: *u8) -> i64 { 56 let fd: i64 = sys_openat_wr(path, 0x1a4) 57 if fd < 0 { return 0 - 1 } 58 sys_write(fd, content, ig_slen(content)) 59 sys_close(fd) 60 return 0 61} 62 63func ig_readall(path: *u8, szout: *i64) -> *u8 { 64 let fd: i64 = sys_openat_rd(path) 65 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 } 66 let sz: i64 = sys_lseek(fd, 0, 2) 67 sys_lseek(fd, 0, 0) 68 let buf: *u8 = sys_mmap(sz + 64) 69 var got: i64 = 0 70 var n: i64 = 1 71 while n > 0 { 72 n = sys_read(fd, (buf as i64 + got) as *u8, 65536) 73 if n > 0 { got = got + n } 74 } 75 sys_close(fd) 76 szout[0] = got 77 return buf 78} 79 80func ig_runv(elf: *u8, args: *i64, outpath: *u8) -> i64 { 81 let pid: i64 = sys_fork() 82 if pid == 0 { 83 if (outpath as i64) != 0 { 84 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 85 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 86 } 87 let argv: *i64 = sys_mmap(128) as *i64 88 argv[0] = elf as i64 89 var i: i64 = 0 90 var go: i64 = 1 91 while go == 1 { 92 if args[i] == 0 { go = 0 } else { 93 argv[i + 1] = args[i] 94 i = i + 1 95 } 96 } 97 argv[i + 1] = 0 98 let envp: *i64 = sys_mmap(16) as *i64 99 envp[0] = 0 100 sys_execve(elf, argv, envp) 101 sys_exit(127) 102 } 103 let st: *i64 = sys_mmap(16) as *i64 104 sys_wait4(pid, st, 0) 105 let sig: i64 = st[0] & 0x7f 106 if sig != 0 { return 128 + sig } 107 return (st[0] >> 8) & 0xff 108} 109 110func ig_has(path: *u8, needle: *u8) -> i64 { 111 let szp: *i64 = sys_mmap(16) as *i64 112 let b: *u8 = ig_readall(path, szp) 113 let sz: i64 = szp[0] 114 let n: i64 = ig_slen(needle) 115 if sz < n { return 0 } 116 var i: i64 = 0 117 while i + n <= sz { 118 var ok: i64 = 1 119 var j: i64 = 0 120 while j < n { 121 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 } 122 } 123 if ok == 1 { return 1 } 124 i = i + 1 125 } 126 return 0 127} 128 129func ig_count(path: *u8, needle: *u8) -> i64 { 130 let szp: *i64 = sys_mmap(16) as *i64 131 let b: *u8 = ig_readall(path, szp) 132 let sz: i64 = szp[0] 133 let n: i64 = ig_slen(needle) 134 var cnt: i64 = 0 135 if sz < n { return 0 } 136 var i: i64 = 0 137 while i + n <= sz { 138 var ok: i64 = 1 139 var j: i64 = 0 140 while j < n { 141 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 } 142 } 143 if ok == 1 { cnt = cnt + 1; i = i + n } else { i = i + 1 } 144 } 145 return cnt 146} 147 148// every LF preceded by CR; returns line count if strict, else -1 149func ig_crlf_lines(path: *u8) -> i64 { 150 let szp: *i64 = sys_mmap(16) as *i64 151 let b: *u8 = ig_readall(path, szp) 152 let sz: i64 = szp[0] 153 if sz <= 0 { return 0 - 1 } 154 var lines: i64 = 0 155 var i: i64 = 0 156 while i < sz { 157 if b[i] == (10 as u8) { 158 if i == 0 { return 0 - 1 } 159 if b[i - 1] != (13 as u8) { return 0 - 1 } 160 lines = lines + 1 161 } 162 i = i + 1 163 } 164 return lines 165} 166 167// longest physical line in octets EXCLUDING the CRLF terminator 168func ig_maxline(path: *u8) -> i64 { 169 let szp: *i64 = sys_mmap(16) as *i64 170 let b: *u8 = ig_readall(path, szp) 171 let sz: i64 = szp[0] 172 var mx: i64 = 0 173 var cur: i64 = 0 174 var i: i64 = 0 175 while i < sz { 176 if b[i] == (10 as u8) { 177 var l: i64 = cur - 1 178 if l < 0 { l = 0 } 179 if l > mx { mx = l } 180 cur = 0 181 } else { 182 cur = cur + 1 183 } 184 i = i + 1 185 } 186 if cur > mx { mx = cur } 187 return mx 188} 189 190func ig_fileeq(p1: *u8, p2: *u8) -> i64 { 191 let s1: *i64 = sys_mmap(16) as *i64 192 let s2: *i64 = sys_mmap(16) as *i64 193 let b1: *u8 = ig_readall(p1, s1) 194 let b2: *u8 = ig_readall(p2, s2) 195 if s1[0] != s2[0] { return 0 } 196 if s1[0] <= 0 { return 0 } 197 var i: i64 = 0 198 while i < s1[0] { 199 if b1[i] != b2[i] { return 0 } 200 i = i + 1 201 } 202 return 1 203} 204 205func ig_row(name: *u8, pass: i64) -> i64 { 206 ig_p("ROW " as *u8) 207 ig_p(name) 208 if pass == 1 { ig_p(" PASS\n" as *u8) } else { ig_p(" FAIL\n" as *u8) } 209 return pass 210} 211 212func ig_args(a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8) -> *i64 { 213 let a: *i64 = sys_mmap(64) as *i64 214 a[0] = a1 as i64 215 a[1] = a2 as i64 216 a[2] = a3 as i64 217 a[3] = a4 as i64 218 a[4] = a5 as i64 219 a[5] = 0 220 return a 221} 222 223func ig_ensure(elf: *u8, organ: *u8) -> i64 { 224 let pr: i64 = sys_openat_rd(elf) 225 if pr >= 0 { sys_close(pr); return 0 } 226 ig_p(" instrument missing -> rebuilding via durable runner\n" as *u8) 227 ig_runv("_offc/nx_sov_build_run.elf" as *u8, ig_args(organ, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzi_rebuild.out" as *u8) 228 return 0 229} 230 231func main(argc: i64, argv: *i64) -> i64 { 232 ig_p("=== VIZSLA ICS GATE: RFC 5545 export KATs (frame/CRLF/UID/RRULE/escape/fold) ===\n" as *u8) 233 let cal: *u8 = "buildroot/_build/nx_vizsla_calendar.sov.elf" as *u8 234 let ics: *u8 = "buildroot/_build/nx_vizsla_ics.sov.elf" as *u8 235 ig_ensure(cal, "nx_vizsla_calendar" as *u8) 236 ig_ensure(ics, "nx_vizsla_ics" as *u8) 237 238 let pfx: *u8 = sys_mmap(128) 239 var po: i64 = 0 240 po = ig_cat(pfx, po, "/tmp/vziE" as *u8) 241 po = ig_catn(pfx, po, sys_now_us()) 242 po = ig_cat(pfx, po, "-" as *u8) 243 pfx[po] = 0 as u8 244 245 let fx: *u8 = "EVENT launch 2026-06-20 600 90 pizza,night;launch\nEVENT ride 2026-07-03 480 120 the-really-long-annual-friends-camping-trip-planning-weekend-at-the-lake-house-edition\nEVENT far 2026-09-01 480 60 out-of-window\nRRULE standup 2026-06-01 540 30 WEEKLY 2 6 biweekly-standup\nRRULE bday 2024-02-29 540 60 YEARLY 1 50 leap-birthday\n" as *u8 246 ig_write("/tmp/vzi_fx.txt" as *u8, fx) 247 248 var pass: i64 = 0 249 var r: i64 = 0 250 251 let rcl: i64 = ig_runv(cal, ig_args("load" as *u8, "/tmp/vzi_fx.txt" as *u8, pfx, "6201" as *u8, 0 as *u8), "/tmp/vzi_load.txt" as *u8) 252 if rcl != 0 { ig_p("FIXTURE LOAD FAILED -- gate cannot proceed\n" as *u8) } 253 254 // row 1: export ok + verdict counts 255 let outp: *u8 = "/tmp/vzi_out.ics" as *u8 256 let rc1: i64 = ig_runv(ics, ig_args("export" as *u8, pfx, "2026-06-01" as *u8, "2026-07-31" as *u8, outp), "/tmp/vzi_r1.txt" as *u8) 257 r = 0 258 if rc1 == 0 { 259 if ig_has("/tmp/vzi_r1.txt" as *u8, "VIZSLA-ICS-VERDICT events=2 rules=2" as *u8) == 1 { r = 1 } 260 } 261 pass = pass + ig_row("export-ok" as *u8, r) 262 263 // row 2: VCALENDAR frame 264 r = 0 265 if ig_has(outp, "BEGIN:VCALENDAR" as *u8) == 1 { 266 if ig_has(outp, "VERSION:2.0" as *u8) == 1 { 267 if ig_has(outp, "PRODID:-//Nishi//Vizsla Calendar//EN" as *u8) == 1 { 268 if ig_has(outp, "END:VCALENDAR" as *u8) == 1 { r = 1 } 269 } 270 } 271 } 272 pass = pass + ig_row("vcalendar-frame" as *u8, r) 273 274 // row 3: strict CRLF line ends 275 let nl: i64 = ig_crlf_lines(outp) 276 r = 0 277 if nl >= 10 { r = 1 } 278 pass = pass + ig_row("crlf-strict" as *u8, r) 279 280 // row 4: exactly 4 VEVENTs 281 r = 0 282 if ig_count(outp, "BEGIN:VEVENT" as *u8) == 4 { 283 if ig_count(outp, "END:VEVENT" as *u8) == 4 { r = 1 } 284 } 285 pass = pass + ig_row("vevent-count" as *u8, r) 286 287 // row 5: DTSTART/DTEND of launch 288 r = 0 289 if ig_has(outp, "DTSTART:20260620T100000" as *u8) == 1 { 290 if ig_has(outp, "DTEND:20260620T113000" as *u8) == 1 { r = 1 } 291 } 292 pass = pass + ig_row("dtstart-dtend" as *u8, r) 293 294 // row 6: stable UID 295 r = ig_has(outp, "UID:launch-20260620@nishi.vizsla" as *u8) 296 pass = pass + ig_row("uid-stable" as *u8, r) 297 298 // row 7: WEEKLY RRULE passthrough 299 r = ig_has(outp, "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=6" as *u8) 300 pass = pass + ig_row("rrule-weekly" as *u8, r) 301 302 // row 8: YEARLY RRULE passthrough (the birthday substrate) 303 r = ig_has(outp, "RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=50" as *u8) 304 pass = pass + ig_row("rrule-yearly" as *u8, r) 305 306 // row 9: TEXT escaping (needle built byte-wise: SUMMARY:pizza\,night\;launch) 307 let esc: *u8 = sys_mmap(64) 308 var eo: i64 = 0 309 eo = ig_cat(esc, eo, "SUMMARY:pizza" as *u8) 310 esc[eo] = 92 as u8; eo = eo + 1 311 eo = ig_cat(esc, eo, ",night" as *u8) 312 esc[eo] = 92 as u8; eo = eo + 1 313 eo = ig_cat(esc, eo, ";launch" as *u8) 314 esc[eo] = 0 as u8 315 r = ig_has(outp, esc) 316 pass = pass + ig_row("summary-escaping" as *u8, r) 317 318 // row 10: 75-octet folding (no long physical line + a CRLF+SPACE continuation + folded=1) 319 let contn: *u8 = sys_mmap(8) 320 contn[0] = 13 as u8 321 contn[1] = 10 as u8 322 contn[2] = 32 as u8 323 contn[3] = 0 as u8 324 r = 0 325 if ig_maxline(outp) <= 75 { 326 if ig_has(outp, contn) == 1 { 327 if ig_has("/tmp/vzi_r1.txt" as *u8, "folded=1" as *u8) == 1 { r = 1 } 328 } 329 } 330 pass = pass + ig_row("fold-75" as *u8, r) 331 332 // row 11: out-of-window event excluded 333 r = 0 334 if ig_has(outp, "UID:far-" as *u8) == 0 { r = 1 } 335 pass = pass + ig_row("window-exclusion" as *u8, r) 336 337 // row 12: determinism (re-export byte-identical) 338 ig_runv(ics, ig_args("export" as *u8, pfx, "2026-06-01" as *u8, "2026-07-31" as *u8, "/tmp/vzi_out2.ics" as *u8), "/tmp/vzi_r12.txt" as *u8) 339 r = ig_fileeq(outp, "/tmp/vzi_out2.ics" as *u8) 340 pass = pass + ig_row("export-determinism" as *u8, r) 341 342 // row 13: loud-fail bad date (negative control) 343 let rc13: i64 = ig_runv(ics, ig_args("export" as *u8, pfx, "2026-13-99" as *u8, "2026-07-31" as *u8, "/tmp/vzi_bad.ics" as *u8), "/tmp/vzi_r13.txt" as *u8) 344 r = 0 345 if rc13 == 1 { r = 1 } 346 pass = pass + ig_row("loud-fail-bad-date" as *u8, r) 347 348 // row 14: loud-fail unwritable out path (negative control) 349 let rc14: i64 = ig_runv(ics, ig_args("export" as *u8, pfx, "2026-06-01" as *u8, "2026-07-31" as *u8, "/tmp/no_such_dir_vzi/out.ics" as *u8), "/tmp/vzi_r14.txt" as *u8) 350 r = 0 351 if rc14 == 1 { r = 1 } 352 pass = pass + ig_row("loud-fail-unwritable" as *u8, r) 353 354 // ===== IMPORT round-trip: the .ics we just exported -> a fresh store the calendar organ reads ===== 355 let pfxI: *u8 = sys_mmap(128) 356 var pio: i64 = 0 357 pio = ig_cat(pfxI, pio, "/tmp/vziI" as *u8) 358 pio = ig_catn(pfxI, pio, sys_now_us()) 359 pio = ig_cat(pfxI, pio, "-" as *u8) 360 pfxI[pio] = 0 as u8 361 362 // row 15: import the exported .ics -> events=2 rules=2 new=4 363 let rc15: i64 = ig_runv(ics, ig_args("import" as *u8, outp, pfxI, "6301" as *u8, 0 as *u8), "/tmp/vzi_r15.txt" as *u8) 364 r = 0 365 if rc15 == 0 { 366 if ig_has("/tmp/vzi_r15.txt" as *u8, "VIZSLA-ICS-IMPORT events=2 rules=2 new=4 dup_instore=0 segment=seg-6301" as *u8) == 1 { r = 1 } 367 } 368 pass = pass + ig_row("import-ok" as *u8, r) 369 370 // row 16: the imported single event is queryable through the real calendar organ 371 let rc16: i64 = ig_runv(cal, ig_args("day" as *u8, pfxI, "2026-07-03" as *u8, 0 as *u8, 0 as *u8), "/tmp/vzi_r16.txt" as *u8) 372 r = 0 373 if rc16 == 0 { 374 if ig_has("/tmp/vzi_r16.txt" as *u8, "VIZSLA-CAL-EVENT date=2026-07-03 start=08:00 end=10:00 dur=120 id=ride" as *u8) == 1 { r = 1 } 375 } 376 pass = pass + ig_row("import-event-queryable" as *u8, r) 377 378 // row 17: the imported RRULEs expand -- YEARLY birthday (Feb clamp) + WEEKLY interval survive 379 let rc17: i64 = ig_runv(cal, ig_args("expand" as *u8, pfxI, "2026-01-01" as *u8, "2026-07-31" as *u8, 0 as *u8), "/tmp/vzi_r17.txt" as *u8) 380 r = 0 381 if rc17 == 0 { 382 if ig_has("/tmp/vzi_r17.txt" as *u8, "VIZSLA-CAL-OCC id=bday date=2026-02-28 start=09:00 end=10:00 freq=YEARLY" as *u8) == 1 { 383 if ig_has("/tmp/vzi_r17.txt" as *u8, "VIZSLA-CAL-OCC id=standup date=2026-06-15 start=09:00 end=09:30 freq=WEEKLY" as *u8) == 1 { r = 1 } 384 } 385 } 386 pass = pass + ig_row("import-rrule-queryable" as *u8, r) 387 388 // row 18: re-import is CID-idempotent (never-lose additive plane) 389 let rc18: i64 = ig_runv(ics, ig_args("import" as *u8, outp, pfxI, "6302" as *u8, 0 as *u8), "/tmp/vzi_r18.txt" as *u8) 390 r = 0 391 if rc18 == 0 { 392 if ig_has("/tmp/vzi_r18.txt" as *u8, "new=0 dup_instore=4 segment=none" as *u8) == 1 { r = 1 } 393 } 394 pass = pass + ig_row("import-idempotent" as *u8, r) 395 396 // row 19: import missing file (negative control) 397 let rc19: i64 = ig_runv(ics, ig_args("import" as *u8, "/tmp/vzi_nope.ics" as *u8, pfxI, "6303" as *u8, 0 as *u8), "/tmp/vzi_r19.txt" as *u8) 398 r = 0 399 if rc19 == 1 { r = 1 } 400 pass = pass + ig_row("import-loud-fail" as *u8, r) 401 402 let permil: i64 = (pass * 1000) / 19 403 let logfd: i64 = sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4) 404 var fdi: i64 = 0 405 while fdi < 2 { 406 var fd: i64 = 1 407 if fdi == 1 { fd = logfd } 408 if fd > 0 { 409 let line: *u8 = sys_mmap(256) 410 var o: i64 = 0 411 o = ig_cat(line, o, "VIZSLA-ICS-GATE epoch=" as *u8) 412 o = ig_catn(line, o, sys_now_realtime_sec()) 413 o = ig_cat(line, o, " rows=19 pass=" as *u8) 414 o = ig_catn(line, o, pass) 415 o = ig_cat(line, o, " permil=" as *u8) 416 o = ig_catn(line, o, permil) 417 if pass == 19 { 418 o = ig_cat(line, o, " verdict=GREEN\n" as *u8) 419 } else { 420 o = ig_cat(line, o, " verdict=RED\n" as *u8) 421 } 422 sys_write(fd, line, o) 423 } 424 fdi = fdi + 1 425 } 426 if logfd > 0 { sys_close(logfd) } 427 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 428 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 429 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 430 let ctr__dry: *i64 = gv_ctr() 431 ctr__dry[0] = pass 432 ctr__dry[1] = 19 433 let rc__dry: i64 = gv_verdict("VIZSLA-ICS-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 434 sys_exit(rc__dry) 435 return rc__dry 436}