code wiki / _hdl_build / nx_vizsla_group_gate.nx

nx_vizsla_group_gate.nx source

↩ module page · 352 lines · 15608 B

1// nx_vizsla_group_gate.nx -- VIZSLA GROUP gate: multi-member find-a-time + slot poll proven 2// against HAND-COMPUTED intersection fixtures. GENUINE COMPOSITION: member calendars are loaded 3// through the real nx_vizsla_calendar organ (cal: + rec: records), then nx_vizsla_group reads 4// those member stores -- nothing is mocked. 5// 6// member calendars (2026-07-10): 7// alice: 09:00-10:00 planning, 13:00-14:00 lunch 8// bob: 10:00-12:00 work, RRULE gym DAILY x2 15:00-16:00 (07-10 + 07-11) 9// group busy union 07-10: [540,720) [780,840) [900,960) 10// free in [480,1320): [480,540) [720,780) [840,900) [960,1320) 11// findtime dur=60 07-10 -> 4 candidates (08:00,12:00,14:00,16:00 windows) 12// findtime dur=90 07-10..07-11 -> 3 (evening 07-10 + two 07-11 windows; short gaps drop) 13// 07-11 dur=60 -> free ends 15:00 where bob's RECURRING gym starts 14// poll p1: s1 2026-07-10 16:00+90, s2 2026-07-11 08:00+90 15// initial votes: all 4 yes -> tie 2-2 -> winner=s1 (lexicographic tie-break) 16// bob changes s1 to no LATER (2026-07-09) -> s1 1-1, s2 2 -> winner=s2 (latest-wins) 17// 18// Rows: 19// 1 fixture-cal-loads alice+bob calendars load via the real organ (new=2 each) 20// 2 group-load 9 records (3 MEMBER + 2 SLOT + 4 VOTE) new=9 seg-6303 21// 3 idempotent-reload new=0 dup_instore=9 (law 10) 22// 4 findtime-members g1 has members=2 (carol is g2 -- roster isolation) candidates=4 23// 5 findtime-morning-slot 08:00-09:00 fits=1 24// 6 findtime-gap-slot 12:00-13:00 fits=1 (between-meetings gap found) 25// 7 findtime-evening-slot 16:00-22:00 fits=6 26// 8 findtime-dur90 2 days dur=90 -> candidates=3 (short windows honestly dropped) 27// 9 recurring-blocks 07-11 free window ENDS 15:00 at bob's recurring gym 28// 10 tally-tie-lexicographic winner=s1 yes=2 on the 2-2 tie 29// 11 tally-latest-wins after bob's later no: s1 yes=1 no=1, winner=s2 yes=2 30// 12 findtime-determinism byte-identical twice 31// 13 loud-fail-unknown-gid findtime ghost -> exit 1 [negative control] 32// 14 loud-fail-bad-date findtime from=2026-13-99 -> exit 1 [negative control] 33// 15 loud-fail-bad-vote VOTE maybe -> load exit 1 [negative control] 34// Evidence: VIZSLA-GRP-GATE -> stdout + knowledge/status/vizsla_gate.log; exit 0 iff 15/15. 35// spec: knowledge/research/2026-06-22-vizsla-sclass-roadmap.md license_tier: ORIGINAL 36import "nx_syscalls.nx" 37 38func gg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 39func gg_p(s: *u8) -> i64 { sys_write(1, s, gg_slen(s)); return 0 } 40 41func gg_cat(dst: *u8, off: i64, s: *u8) -> i64 { 42 var i: i64 = 0 43 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 44 return off + i 45} 46 47func gg_catn(dst: *u8, off: i64, v: i64) -> i64 { 48 var o: i64 = off 49 var m: i64 = v 50 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 51 let t: *u8 = sys_mmap(28) 52 var k: i64 = 0 53 if m == 0 { t[0] = 48 as u8; k = 1 } 54 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 55 var i: i64 = 0 56 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 57 return o + k 58} 59 60func gg_write(path: *u8, content: *u8) -> i64 { 61 let fd: i64 = sys_openat_wr(path, 0x1a4) 62 if fd < 0 { return 0 - 1 } 63 sys_write(fd, content, gg_slen(content)) 64 sys_close(fd) 65 return 0 66} 67 68func gg_readall(path: *u8, szout: *i64) -> *u8 { 69 let fd: i64 = sys_openat_rd(path) 70 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 } 71 let sz: i64 = sys_lseek(fd, 0, 2) 72 sys_lseek(fd, 0, 0) 73 let buf: *u8 = sys_mmap(sz + 64) 74 var got: i64 = 0 75 var n: i64 = 1 76 while n > 0 { 77 n = sys_read(fd, (buf as i64 + got) as *u8, 65536) 78 if n > 0 { got = got + n } 79 } 80 sys_close(fd) 81 szout[0] = got 82 return buf 83} 84 85func gg_runv(elf: *u8, args: *i64, outpath: *u8) -> i64 { 86 let pid: i64 = sys_fork() 87 if pid == 0 { 88 if (outpath as i64) != 0 { 89 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 90 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 91 } 92 let argv: *i64 = sys_mmap(128) as *i64 93 argv[0] = elf as i64 94 var i: i64 = 0 95 var go: i64 = 1 96 while go == 1 { 97 if args[i] == 0 { go = 0 } else { 98 argv[i + 1] = args[i] 99 i = i + 1 100 } 101 } 102 argv[i + 1] = 0 103 let envp: *i64 = sys_mmap(16) as *i64 104 envp[0] = 0 105 sys_execve(elf, argv, envp) 106 sys_exit(127) 107 } 108 let st: *i64 = sys_mmap(16) as *i64 109 sys_wait4(pid, st, 0) 110 let sig: i64 = st[0] & 0x7f 111 if sig != 0 { return 128 + sig } 112 return (st[0] >> 8) & 0xff 113} 114 115func gg_has(path: *u8, needle: *u8) -> i64 { 116 let szp: *i64 = sys_mmap(16) as *i64 117 let b: *u8 = gg_readall(path, szp) 118 let sz: i64 = szp[0] 119 let n: i64 = gg_slen(needle) 120 if sz < n { return 0 } 121 var i: i64 = 0 122 while i + n <= sz { 123 var ok: i64 = 1 124 var j: i64 = 0 125 while j < n { 126 if b[i + j] != needle[j] { ok = 0; j = n } else { j = j + 1 } 127 } 128 if ok == 1 { return 1 } 129 i = i + 1 130 } 131 return 0 132} 133 134func gg_fileeq(p1: *u8, p2: *u8) -> i64 { 135 let s1: *i64 = sys_mmap(16) as *i64 136 let s2: *i64 = sys_mmap(16) as *i64 137 let b1: *u8 = gg_readall(p1, s1) 138 let b2: *u8 = gg_readall(p2, s2) 139 if s1[0] != s2[0] { return 0 } 140 if s1[0] <= 0 { return 0 } 141 var i: i64 = 0 142 while i < s1[0] { 143 if b1[i] != b2[i] { return 0 } 144 i = i + 1 145 } 146 return 1 147} 148 149func gg_row(name: *u8, pass: i64) -> i64 { 150 gg_p("ROW " as *u8) 151 gg_p(name) 152 if pass == 1 { gg_p(" PASS\n" as *u8) } else { gg_p(" FAIL\n" as *u8) } 153 return pass 154} 155 156func gg_args(a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8, a6: *u8, a7: *u8, a8: *u8) -> *i64 { 157 let a: *i64 = sys_mmap(128) as *i64 158 a[0] = a1 as i64 159 a[1] = a2 as i64 160 a[2] = a3 as i64 161 a[3] = a4 as i64 162 a[4] = a5 as i64 163 a[5] = a6 as i64 164 a[6] = a7 as i64 165 a[7] = a8 as i64 166 a[8] = 0 167 return a 168} 169 170func gg_ensure(elf: *u8, organ: *u8) -> i64 { 171 let pr: i64 = sys_openat_rd(elf) 172 if pr >= 0 { sys_close(pr); return 0 } 173 gg_p(" instrument missing -> rebuilding via durable runner\n" as *u8) 174 gg_runv("_offc/nx_sov_build_run.elf" as *u8, gg_args(organ, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_rebuild.out" as *u8) 175 return 0 176} 177 178func gg_mkpfx(tag: *u8, us: i64) -> *u8 { 179 let pfx: *u8 = sys_mmap(128) 180 var po: i64 = 0 181 po = gg_cat(pfx, po, tag) 182 po = gg_catn(pfx, po, us) 183 po = gg_cat(pfx, po, "-" as *u8) 184 pfx[po] = 0 as u8 185 return pfx 186} 187 188func main(argc: i64, argv: *i64) -> i64 { 189 gg_p("=== VIZSLA GROUP GATE: find-a-time intersection + poll tally KATs (hand-computed) ===\n" as *u8) 190 let cal: *u8 = "/tmp/nx_vizsla_calendar.sov.elf" as *u8 191 let grp: *u8 = "/tmp/nx_vizsla_group.sov.elf" as *u8 192 gg_ensure(cal, "nx_vizsla_calendar" as *u8) 193 gg_ensure(grp, "nx_vizsla_group" as *u8) 194 195 let us: i64 = sys_now_us() 196 let pfxA: *u8 = gg_mkpfx("/tmp/vzgA" as *u8, us) 197 let pfxB: *u8 = gg_mkpfx("/tmp/vzgB" as *u8, us) 198 let pfxG: *u8 = gg_mkpfx("/tmp/vzgG" as *u8, us) 199 200 gg_write("/tmp/vzg_calA.txt" as *u8, "EVENT a1 2026-07-10 540 60 planning\nEVENT a2 2026-07-10 780 60 lunch\n" as *u8) 201 gg_write("/tmp/vzg_calB.txt" as *u8, "EVENT b1 2026-07-10 600 120 work\nRRULE gym 2026-07-10 900 60 DAILY 1 2 gym\n" as *u8) 202 203 var pass: i64 = 0 204 var r: i64 = 0 205 206 // row 1: member calendars load through the REAL calendar organ 207 let rcA: i64 = gg_runv(cal, gg_args("load" as *u8, "/tmp/vzg_calA.txt" as *u8, pfxA, "6301" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_lA.txt" as *u8) 208 let rcB: i64 = gg_runv(cal, gg_args("load" as *u8, "/tmp/vzg_calB.txt" as *u8, pfxB, "6302" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_lB.txt" as *u8) 209 r = 0 210 if rcA == 0 { if rcB == 0 { 211 if gg_has("/tmp/vzg_lA.txt" as *u8, "VIZSLA-CAL-LOAD scanned=2 new=2" as *u8) == 1 { 212 if gg_has("/tmp/vzg_lB.txt" as *u8, "VIZSLA-CAL-LOAD scanned=2 new=2" as *u8) == 1 { r = 1 } 213 } 214 } } 215 pass = pass + gg_row("fixture-cal-loads" as *u8, r) 216 217 // group file (dynamic: carries the real member cal prefixes) 218 let gf: *u8 = sys_mmap(4096) 219 var go2: i64 = 0 220 go2 = gg_cat(gf, go2, "MEMBER g1 alice " as *u8) 221 go2 = gg_cat(gf, go2, pfxA) 222 go2 = gg_cat(gf, go2, "\nMEMBER g1 bob " as *u8) 223 go2 = gg_cat(gf, go2, pfxB) 224 go2 = gg_cat(gf, go2, "\nMEMBER g2 carol /tmp/vzg-none-" as *u8) 225 go2 = gg_cat(gf, go2, "\nSLOT p1 s1 2026-07-10 960 90\nSLOT p1 s2 2026-07-11 480 90\nVOTE p1 s1 alice yes 2026-07-08\nVOTE p1 s1 bob yes 2026-07-08\nVOTE p1 s2 alice yes 2026-07-08\nVOTE p1 s2 bob yes 2026-07-08\n" as *u8) 226 gf[go2] = 0 as u8 227 gg_write("/tmp/vzg_grp.txt" as *u8, gf) 228 229 // row 2: group load 230 let rc2: i64 = gg_runv(grp, gg_args("load" as *u8, "/tmp/vzg_grp.txt" as *u8, pfxG, "6303" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_r2.txt" as *u8) 231 r = 0 232 if rc2 == 0 { 233 if gg_has("/tmp/vzg_r2.txt" as *u8, "VIZSLA-GRP-LOAD scanned=9 new=9 dup_infile=0 dup_instore=0 segment=seg-6303" as *u8) == 1 { r = 1 } 234 } 235 pass = pass + gg_row("group-load" as *u8, r) 236 237 // row 3: idempotent reload 238 let rc3: i64 = gg_runv(grp, gg_args("load" as *u8, "/tmp/vzg_grp.txt" as *u8, pfxG, "6304" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_r3.txt" as *u8) 239 r = 0 240 if rc3 == 0 { 241 if gg_has("/tmp/vzg_r3.txt" as *u8, "VIZSLA-GRP-LOAD scanned=9 new=0 dup_infile=0 dup_instore=9 segment=none" as *u8) == 1 { r = 1 } 242 } 243 pass = pass + gg_row("idempotent-reload" as *u8, r) 244 245 // row 4: findtime members + candidate count (dur=60, 07-10, bounds 08:00-22:00) 246 let rc4: i64 = gg_runv(grp, gg_args("findtime" as *u8, pfxG, "g1" as *u8, "2026-07-10" as *u8, "2026-07-10" as *u8, "60" as *u8, "480" as *u8, "1320" as *u8), "/tmp/vzg_r4.txt" as *u8) 247 r = 0 248 if rc4 == 0 { 249 if gg_has("/tmp/vzg_r4.txt" as *u8, "VIZSLA-GRP-FIND-VERDICT gid=g1 members=2 days=1 dur=60 candidates=4" as *u8) == 1 { r = 1 } 250 } 251 pass = pass + gg_row("findtime-members" as *u8, r) 252 253 // row 5: morning window before everything 254 r = gg_has("/tmp/vzg_r4.txt" as *u8, "VIZSLA-GRP-SLOT gid=g1 date=2026-07-10 start=08:00 end=09:00 fits=1" as *u8) 255 pass = pass + gg_row("findtime-morning-slot" as *u8, r) 256 257 // row 6: the between-meetings gap 258 r = gg_has("/tmp/vzg_r4.txt" as *u8, "VIZSLA-GRP-SLOT gid=g1 date=2026-07-10 start=12:00 end=13:00 fits=1" as *u8) 259 pass = pass + gg_row("findtime-gap-slot" as *u8, r) 260 261 // row 7: evening window 262 r = gg_has("/tmp/vzg_r4.txt" as *u8, "VIZSLA-GRP-SLOT gid=g1 date=2026-07-10 start=16:00 end=22:00 fits=6" as *u8) 263 pass = pass + gg_row("findtime-evening-slot" as *u8, r) 264 265 // row 8: dur=90 across two days -> short windows drop, candidates=3 266 let rc8: i64 = gg_runv(grp, gg_args("findtime" as *u8, pfxG, "g1" as *u8, "2026-07-10" as *u8, "2026-07-11" as *u8, "90" as *u8, "480" as *u8, "1320" as *u8), "/tmp/vzg_r8.txt" as *u8) 267 r = 0 268 if rc8 == 0 { 269 if gg_has("/tmp/vzg_r8.txt" as *u8, "VIZSLA-GRP-FIND-VERDICT gid=g1 members=2 days=2 dur=90 candidates=3" as *u8) == 1 { r = 1 } 270 } 271 pass = pass + gg_row("findtime-dur90" as *u8, r) 272 273 // row 9: recurring gym occurrence bounds the 07-11 free window at 15:00 274 let rc9: i64 = gg_runv(grp, gg_args("findtime" as *u8, pfxG, "g1" as *u8, "2026-07-11" as *u8, "2026-07-11" as *u8, "60" as *u8, "480" as *u8, "1320" as *u8), "/tmp/vzg_r9.txt" as *u8) 275 r = 0 276 if rc9 == 0 { 277 if gg_has("/tmp/vzg_r9.txt" as *u8, "VIZSLA-GRP-SLOT gid=g1 date=2026-07-11 start=08:00 end=15:00 fits=7" as *u8) == 1 { r = 1 } 278 } 279 pass = pass + gg_row("recurring-blocks" as *u8, r) 280 281 // row 10: tally on the 2-2 tie -> lexicographic winner s1 282 let rc10: i64 = gg_runv(grp, gg_args("tally" as *u8, pfxG, "p1" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_r10.txt" as *u8) 283 r = 0 284 if rc10 == 0 { 285 if gg_has("/tmp/vzg_r10.txt" as *u8, "VIZSLA-GRP-TALLY-VERDICT pid=p1 slots=2 votes=4 winner=s1 yes=2" as *u8) == 1 { r = 1 } 286 } 287 pass = pass + gg_row("tally-tie-lexicographic" as *u8, r) 288 289 // row 11: bob flips s1 to no on a LATER date -> latest-wins, winner s2 290 gg_write("/tmp/vzg_chg.txt" as *u8, "VOTE p1 s1 bob no 2026-07-09\n" as *u8) 291 gg_runv(grp, gg_args("load" as *u8, "/tmp/vzg_chg.txt" as *u8, pfxG, "6305" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_l11.txt" as *u8) 292 let rc11: i64 = gg_runv(grp, gg_args("tally" as *u8, pfxG, "p1" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_r11.txt" as *u8) 293 r = 0 294 if rc11 == 0 { 295 if gg_has("/tmp/vzg_r11.txt" as *u8, "VIZSLA-GRP-TALLY pid=p1 slot=s1 date=2026-07-10 start=16:00 yes=1 no=1" as *u8) == 1 { 296 if gg_has("/tmp/vzg_r11.txt" as *u8, "VIZSLA-GRP-TALLY-VERDICT pid=p1 slots=2 votes=4 winner=s2 yes=2" as *u8) == 1 { r = 1 } 297 } 298 } 299 pass = pass + gg_row("tally-latest-wins" as *u8, r) 300 301 // row 12: determinism 302 gg_runv(grp, gg_args("findtime" as *u8, pfxG, "g1" as *u8, "2026-07-10" as *u8, "2026-07-10" as *u8, "60" as *u8, "480" as *u8, "1320" as *u8), "/tmp/vzg_r12.txt" as *u8) 303 r = gg_fileeq("/tmp/vzg_r4.txt" as *u8, "/tmp/vzg_r12.txt" as *u8) 304 pass = pass + gg_row("findtime-determinism" as *u8, r) 305 306 // row 13: unknown gid (negative control) 307 let rc13: i64 = gg_runv(grp, gg_args("findtime" as *u8, pfxG, "ghost" as *u8, "2026-07-10" as *u8, "2026-07-10" as *u8, "60" as *u8, "480" as *u8, "1320" as *u8), "/tmp/vzg_r13.txt" as *u8) 308 r = 0 309 if rc13 == 1 { r = 1 } 310 pass = pass + gg_row("loud-fail-unknown-gid" as *u8, r) 311 312 // row 14: bad date (negative control) 313 let rc14: i64 = gg_runv(grp, gg_args("findtime" as *u8, pfxG, "g1" as *u8, "2026-13-99" as *u8, "2026-07-10" as *u8, "60" as *u8, "480" as *u8, "1320" as *u8), "/tmp/vzg_r14.txt" as *u8) 314 r = 0 315 if rc14 == 1 { r = 1 } 316 pass = pass + gg_row("loud-fail-bad-date" as *u8, r) 317 318 // row 15: bad vote value (negative control) 319 gg_write("/tmp/vzg_badv.txt" as *u8, "VOTE p1 s1 alice maybe 2026-07-08\n" as *u8) 320 let rc15: i64 = gg_runv(grp, gg_args("load" as *u8, "/tmp/vzg_badv.txt" as *u8, pfxG, "6306" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vzg_r15.txt" as *u8) 321 r = 0 322 if rc15 == 1 { r = 1 } 323 pass = pass + gg_row("loud-fail-bad-vote" as *u8, r) 324 325 let permil: i64 = (pass * 1000) / 15 326 let logfd: i64 = sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4) 327 var fdi: i64 = 0 328 while fdi < 2 { 329 var fd: i64 = 1 330 if fdi == 1 { fd = logfd } 331 if fd > 0 { 332 let line: *u8 = sys_mmap(256) 333 var o: i64 = 0 334 o = gg_cat(line, o, "VIZSLA-GRP-GATE epoch=" as *u8) 335 o = gg_catn(line, o, sys_now_realtime_sec()) 336 o = gg_cat(line, o, " rows=15 pass=" as *u8) 337 o = gg_catn(line, o, pass) 338 o = gg_cat(line, o, " permil=" as *u8) 339 o = gg_catn(line, o, permil) 340 if pass == 15 { 341 o = gg_cat(line, o, " verdict=GREEN\n" as *u8) 342 } else { 343 o = gg_cat(line, o, " verdict=RED\n" as *u8) 344 } 345 sys_write(fd, line, o) 346 } 347 fdi = fdi + 1 348 } 349 if logfd > 0 { sys_close(logfd) } 350 if pass == 15 { return 0 } 351 return 1 352}