code wiki / (root) / nx_jslogic_census.nx

nx_jslogic_census.nx source

↩ module page · 413 lines · 18868 B

1// nx_jslogic_census.nx -- THE RULER for the JS/HTML-INTEROP-ONLY law (operator standing order 2// 2026-08-12: "we shouldnt be building into the js strings -- nishi os from the first bit up, js 3// and html only as an interop layer for 3rd-party systems"). It measures the AUTHORED JavaScript 4// living inside the page emitter's string literals so the migration into the wasm engine has a 5// number that can only go DOWN (the nx_sov_guard2 / nx_magicratchet ratchet shape). 6// 7// MECHANISM (comments are SKIPPED -- a scanner that reads comments measures the documentation): 8// tokenize the NishiLang source into CODE / //-COMMENT / STRING states (backslash escapes inside 9// strings; REAL newlines inside literals are legal and stay in-string). Literal bytes count only 10// between the literal containing <script> and the literal containing </script> (inclusive), so 11// HTML/CSS chrome outside the script region is never charged. The base64 wasm payload and 12// gpe_num-emitted values are BUFFER emissions, not literals -- data crossing the boundary is 13// lawful and is not counted. DECLARED IMPRECISION: the two boundary literals carry a few bytes 14// of enclosing HTML, so totals are a small UPPER bound on authored JS. 15// 16// CLASSES from knowledge/jslogic_class.conf rows `<fnv64-decimal> <CLASS>` where CLASS is 17// INTEROP (shim: decode/instantiate/blit/input/context plumbing) | LOGIC (game/engine behavior 18// that belongs in the wasm) | SHADER (GLSL display path -- judged separately). A literal whose 19// hash is not in the conf lands in UNKNOWN -- ITS OWN BUCKET, never silently merged; editing a 20// classified literal changes its hash and forces re-classification by construction. 21// 22// usage: nx_jslogic_census check [srcpath] -> census + ratchet vs knowledge/status/jslogic.baseline 23// nx_jslogic_census snapshot [srcpath] -> census + deliberately re-record the baseline 24// nx_jslogic_census rows [srcpath] -> per-literal rows (hash, bytes, class, head) for conf work 25// exit: 0 GREEN (logic+unknown <= baseline) | 1 RED rose vs baseline | 2 usage | 3 unreadable-src 26// Journals every run: knowledge/status/jslogic.jrnl (epoch TAB totals). license_tier: ORIGINAL 27// No hw writes (Rule 26). 28import "nx_syscalls.nx" 29const JC_MAGIC_1024: i64 = 1024 30 31const JC_SRC_DEF: *u8 = "buildroot/runtime/nx_game_page_emit.nx" 32const JC_CONF: *u8 = "knowledge/jslogic_class.conf" 33const JC_BASE: *u8 = "knowledge/status/jslogic.baseline" 34const JC_JRNL: *u8 = "knowledge/status/jslogic.jrnl" 35const JC_MAXLIT: i64 = 4096 36 37func jc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 38func jc_puts(s: *u8) -> i64 { sys_write(1, s, jc_slen(s)); return 0 } 39func jc_pn(v: i64) -> i64 { 40 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 41 var m: i64 = v 42 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 43 let t: *u8 = sys_mmap(32) 44 var k: i64 = 0 45 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 46 let o: *u8 = sys_mmap(32) 47 var i: i64 = 0 48 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 49 sys_write(1, o, k) 50 return 0 51} 52func jc_find(hay: *u8, off: i64, n: i64, needle: *u8) -> i64 { 53 let nl: i64 = jc_slen(needle) 54 if nl == 0 { return 1 } 55 var i: i64 = off 56 while i + nl <= n { 57 var j: i64 = 0 58 var hit: i64 = 1 59 while j < nl { if hay[i + j] != needle[j] { hit = 0; j = nl } else { j = j + 1 } } 60 if hit == 1 { return 1 } 61 i = i + 1 62 } 63 return 0 64} 65// FNV-1a 64 over [off, off+len) 66func jc_fnv(b: *u8, off: i64, len: i64) -> i64 { 67 var h: i64 = 0xcbf29ce484222325 68 var i: i64 = 0 69 while i < len { 70 h = h ^ (b[off + i] as i64) 71 h = h * 0x100000001b3 72 i = i + 1 73 } 74 if h < 0 { h = 0 - h } 75 return h 76} 77// read a decimal integer at s[pos..], skipping leading spaces; advances pos 78func jc_rdint(s: *u8, pos: *i64, n: i64) -> i64 { 79 var i: i64 = pos[0] 80 var go: i64 = 1 81 while go == 1 { if i >= n { go = 0 } else { if s[i] == (32 as u8) { i = i + 1 } else { go = 0 } } } 82 var v: i64 = 0 83 var any: i64 = 0 84 var g2: i64 = 1 85 while g2 == 1 { 86 if i >= n { g2 = 0 } else { 87 let c: i64 = s[i] as i64 88 if c >= 48 { if c <= 57 { v = v*10 + (c-48); any = 1; i = i + 1 } else { g2 = 0 } } else { g2 = 0 } 89 } 90 } 91 pos[0] = i 92 if any == 0 { return 0 - 1 } 93 return v 94} 95 96func main(argc: i64, argv: *i64) -> i64 { 97 var vk: i64 = 0 - 1 98 if argc < 2 { vk = 0 } // no-arg contract = check (beat/clock rosters fork with no args) 99 if argc >= 2 { 100 let verb: *u8 = argv[1] as *u8 101 if jc_find(verb, 0, jc_slen(verb), "check" as *u8) == 1 { if jc_slen(verb) == 5 { vk = 0 } } 102 if jc_find(verb, 0, jc_slen(verb), "snapshot" as *u8) == 1 { vk = 1 } 103 if jc_find(verb, 0, jc_slen(verb), "rows" as *u8) == 1 { if jc_slen(verb) == 4 { vk = 2 } } 104 } 105 if vk < 0 { jc_puts("usage: nx_jslogic_census check|snapshot|rows [srcpath]\n" as *u8); return 2 } 106 var src: *u8 = JC_SRC_DEF 107 if argc > 2 { src = argv[2] as *u8 } 108 109 let ln: *i64 = sys_mmap(16) as *i64 110 let b: *u8 = sys_read_file(src, ln) 111 if (b as i64) == 0 { jc_puts("JSLOGIC-CENSUS FAIL: unreadable src\n" as *u8); return 3 } 112 let n: i64 = ln[0] 113 114 // conf: hash -> class (0 INTEROP, 1 LOGIC, 2 SHADER) 115 let CH: *i64 = sys_mmap(JC_MAGIC_1024*8) as *i64 116 let CC: *i64 = sys_mmap(JC_MAGIC_1024*8) as *i64 117 var nc: i64 = 0 118 let cl: *i64 = sys_mmap(16) as *i64 119 let cb: *u8 = sys_read_file(JC_CONF, cl) 120 if (cb as i64) != 0 { 121 var ci: i64 = 0 122 while ci < cl[0] { 123 // line 124 var ce: i64 = ci 125 var cs: i64 = 1 126 while cs == 1 { if ce >= cl[0] { cs = 0 } else { if cb[ce] == (10 as u8) { cs = 0 } else { ce = ce + 1 } } } 127 if ce > ci { if cb[ci] != (35 as u8) { 128 let pp: *i64 = sys_mmap(16) as *i64 129 pp[0] = ci 130 let hv: i64 = jc_rdint(cb, pp, ce) 131 if hv >= 0 { 132 var cls: i64 = 0 - 1 133 if jc_find(cb, pp[0], ce, "INTEROP" as *u8) == 1 { cls = 0 } 134 if jc_find(cb, pp[0], ce, "LOGIC" as *u8) == 1 { cls = 1 } 135 if jc_find(cb, pp[0], ce, "SHADER" as *u8) == 1 { cls = 2 } 136 if cls >= 0 { if nc < JC_MAGIC_1024 { CH[nc] = hv; CC[nc] = cls; nc = nc + 1 } } 137 } 138 } } 139 ci = ce + 1 140 } 141 } 142 143 // ---- tokenize: CODE / COMMENT / STRING; collect literal spans ---- 144 let LS: *i64 = sys_mmap(JC_MAXLIT*8) as *i64 145 let LE: *i64 = sys_mmap(JC_MAXLIT*8) as *i64 146 var nl2: i64 = 0 147 var i: i64 = 0 148 var st: i64 = 0 // 0 code, 1 comment, 2 string 149 var lit0: i64 = 0 150 var esc: i64 = 0 151 var over: i64 = 0 152 while i < n { 153 let c: i64 = b[i] as i64 154 if st == 0 { 155 if c == 47 { if i + 1 < n { if (b[i+1] as i64) == 47 { st = 1; i = i + 1 } } } 156 if st == 0 { if c == 34 { st = 2; lit0 = i + 1; esc = 0 } } 157 } else { if st == 1 { 158 if c == 10 { st = 0 } 159 } else { 160 if esc == 1 { esc = 0 } else { 161 if c == 92 { esc = 1 } 162 if c == 34 { 163 if nl2 < JC_MAXLIT { LS[nl2] = lit0; LE[nl2] = i; nl2 = nl2 + 1 } else { over = 1 } 164 st = 0 165 } 166 } 167 } } 168 i = i + 1 169 } 170 if over == 1 { jc_puts("JSLOGIC-CENSUS FAIL: literal cap JC_MAXLIT exceeded -- REFUSING a partial census\n" as *u8); return 3 } 171 172 // ---- script region: count literals from the one containing <script> through </script> ---- 173 var injs: i64 = 0 174 var regions: i64 = 0 175 var openk: i64 = 0 - 1 // index of the literal that OPENS the script region (see the uncharged pass) 176 var tI: i64 = 0 177 var tL: i64 = 0 178 var tS: i64 = 0 179 var tU: i64 = 0 180 var njs: i64 = 0 181 var k: i64 = 0 182 while k < nl2 { 183 let s0: i64 = LS[k] 184 let e0: i64 = LE[k] 185 var opened: i64 = 0 186 if injs == 0 { 187 // an opener literal may OPEN and CLOSE in the same literal; handle open first 188 var has: i64 = 0 189 var p2: i64 = s0 190 while p2 + 8 <= e0 { if b[p2]==(60 as u8) { if b[p2+1]==(115 as u8) { if b[p2+2]==(99 as u8) { if b[p2+3]==(114 as u8) { if b[p2+4]==(105 as u8) { if b[p2+5]==(112 as u8) { if b[p2+6]==(116 as u8) { if b[p2+7]==(62 as u8) { has = 1; p2 = e0 } } } } } } } } p2 = p2 + 1 } 191 if has == 1 { injs = 1; regions = regions + 1; opened = 1; if openk < 0 { openk = k } } 192 } 193 if injs == 1 { 194 let len: i64 = e0 - s0 195 let hv: i64 = jc_fnv(b, s0, len) 196 var cls: i64 = 0 - 1 197 var q: i64 = 0 198 while q < nc { if CH[q] == hv { cls = CC[q]; q = nc } else { q = q + 1 } } 199 if cls == 0 { tI = tI + len } 200 if cls == 1 { tL = tL + len } 201 if cls == 2 { tS = tS + len } 202 if cls < 0 { tU = tU + len } 203 njs = njs + 1 204 if vk == 2 { 205 jc_puts("LIT hash=" as *u8); jc_pn(hv) 206 jc_puts(" bytes=" as *u8); jc_pn(len) 207 jc_puts(" class=" as *u8) 208 if cls == 0 { jc_puts("INTEROP" as *u8) } 209 if cls == 1 { jc_puts("LOGIC" as *u8) } 210 if cls == 2 { jc_puts("SHADER" as *u8) } 211 if cls < 0 { jc_puts("UNKNOWN" as *u8) } 212 jc_puts(" head=" as *u8) 213 var hshow: i64 = 40 214 if len < hshow { hshow = len } 215 var h2: i64 = 0 216 while h2 < hshow { 217 var cc2: i64 = b[s0+h2] as i64 218 if cc2 < 32 { cc2 = 46 } 219 if cc2 > 126 { cc2 = 46 } 220 let ob: *u8 = sys_mmap(4) 221 ob[0] = cc2 as u8 222 sys_write(1, ob, 1) 223 h2 = h2 + 1 224 } 225 jc_puts("\n" as *u8) 226 } 227 // close AFTER counting the closer literal 228 var has2: i64 = 0 229 var p3: i64 = s0 230 while p3 + 9 <= e0 { if b[p3]==(60 as u8) { if b[p3+1]==(47 as u8) { if b[p3+2]==(115 as u8) { if b[p3+3]==(99 as u8) { if b[p3+4]==(114 as u8) { if b[p3+5]==(105 as u8) { if b[p3+6]==(112 as u8) { if b[p3+7]==(116 as u8) { if b[p3+8]==(62 as u8) { has2 = 1; p3 = e0 } } } } } } } } } p3 = p3 + 1 } 231 if has2 == 1 { if opened == 0 { injs = 0 } } 232 } 233 k = k + 1 234 } 235 236 // ---- UNCHARGED EMITTED JS -- the coverage axis the region rule structurally cannot reach ---- 237 // The region walk above is SOURCE-ORDER: it charges only literals lying between the literal that 238 // carries the script opener and the one that carries the closer, AS THEY APPEAR IN THE FILE. A 239 // page emitter that defines its JS-emitting helper functions ABOVE that opener emits those bytes 240 // into the SAME page and the walk never reaches them, so they are charged to NOTHING and the 241 // ratchet is blind to them. MEASURED 2026-09-01 on nx_game_page_emit.nx: 66 literals / 37,061 B 242 // uncharged, containing the entire hair solver, the entire cloth solver and the whole WebGPU 243 // tier -- i.e. exactly the code the interop-only law exists to find. 244 // THE EMITTER HELPER IS DERIVED FROM THE ARTIFACT, NEVER CHOSEN: walk back from the opener 245 // literal's own quote to the paren that opens its call and take the identifier before it. A 246 // hard-coded name would make this ruler subject-specific and would rot at the next emitter. 247 // DELIBERATELY NOT FOLDED INTO logic_unknown: the baseline was banked without these bytes, so 248 // folding would move the bar and the number in the same step and no reading would be comparable 249 // -- and this population is not all JS (a few HTML chrome literals ride the same helper). This 250 // axis ANNOUNCES and COUNTS and hands over a worklist; it never changes an existing verdict. 251 var uchl: i64 = 0 252 var uchb: i64 = 0 253 var openline: i64 = 0 254 let hname: *u8 = sys_mmap(160) 255 var hlen: i64 = 0 256 if openk >= 0 { 257 var q: i64 = LS[openk] - 2 258 var g3: i64 = 1 259 while g3 == 1 { if q < 0 { g3 = 0 } else { if b[q] == (40 as u8) { g3 = 0 } else { q = q - 1 } } } 260 if q > 0 { 261 let e3: i64 = q - 1 262 var s3: i64 = e3 263 var g4: i64 = 1 264 while g4 == 1 { 265 if s3 < 0 { g4 = 0 } else { 266 let cc: i64 = b[s3] as i64 267 var okc: i64 = 0 268 if cc >= 97 { if cc <= 122 { okc = 1 } } 269 if cc >= 65 { if cc <= 90 { okc = 1 } } 270 if cc >= 48 { if cc <= 57 { okc = 1 } } 271 if cc == 95 { okc = 1 } 272 if okc == 1 { s3 = s3 - 1 } else { g4 = 0 } 273 } 274 } 275 s3 = s3 + 1 276 var w3: i64 = s3 277 while w3 <= e3 { if hlen < 150 { hname[hlen] = b[w3]; hlen = hlen + 1 } w3 = w3 + 1 } 278 hname[hlen] = 0 as u8 279 } 280 var z: i64 = 0 281 while z < LS[openk] { if b[z] == (10 as u8) { openline = openline + 1 } z = z + 1 } 282 openline = openline + 1 283 } 284 if hlen > 0 { 285 var lncur: i64 = 1 286 var lnpos: i64 = 0 287 var k2: i64 = 0 288 while k2 < openk { 289 while lnpos < LS[k2] { if b[lnpos] == (10 as u8) { lncur = lncur + 1 } lnpos = lnpos + 1 } 290 var ls2: i64 = LS[k2] 291 var gg: i64 = 1 292 while gg == 1 { if ls2 == 0 { gg = 0 } else { if b[ls2-1] == (10 as u8) { gg = 0 } else { ls2 = ls2 - 1 } } } 293 var le2: i64 = LS[k2] 294 var gh: i64 = 1 295 while gh == 1 { if le2 >= n { gh = 0 } else { if b[le2] == (10 as u8) { gh = 0 } else { le2 = le2 + 1 } } } 296 if jc_find(b, ls2, le2, hname) == 1 { 297 let ulen: i64 = LE[k2] - LS[k2] 298 uchl = uchl + 1 299 uchb = uchb + ulen 300 if vk == 2 { 301 jc_puts("UNCHARGED bytes=" as *u8); jc_pn(ulen) 302 jc_puts(" line=" as *u8); jc_pn(lncur) 303 jc_puts(" head=" as *u8) 304 var uh: i64 = 40 305 if ulen < uh { uh = ulen } 306 var h3: i64 = 0 307 while h3 < uh { 308 var c3: i64 = b[LS[k2]+h3] as i64 309 if c3 < 32 { c3 = 46 } 310 if c3 > 126 { c3 = 46 } 311 let ob3: *u8 = sys_mmap(4) 312 ob3[0] = c3 as u8 313 sys_write(1, ob3, 1) 314 h3 = h3 + 1 315 } 316 jc_puts("\n" as *u8) 317 } 318 } 319 k2 = k2 + 1 320 } 321 } 322 323 let logic_unknown: i64 = tL + tU 324 jc_puts("JSLOGIC-CENSUS src-literals=" as *u8); jc_pn(nl2) 325 jc_puts(" js-literals=" as *u8); jc_pn(njs) 326 jc_puts(" regions=" as *u8); jc_pn(regions) 327 jc_puts(" interop=" as *u8); jc_pn(tI) 328 jc_puts(" logic=" as *u8); jc_pn(tL) 329 jc_puts(" shader=" as *u8); jc_pn(tS) 330 jc_puts(" unknown=" as *u8); jc_pn(tU) 331 jc_puts(" logic_unknown=" as *u8); jc_pn(logic_unknown) 332 jc_puts(" uncharged_lits=" as *u8); jc_pn(uchl) 333 jc_puts(" uncharged_bytes=" as *u8); jc_pn(uchb) 334 jc_puts("\n" as *u8) 335 if uchb > 0 { 336 jc_puts("JSLOGIC-CENSUS UNCHARGED-JS lits=" as *u8); jc_pn(uchl) 337 jc_puts(" bytes=" as *u8); jc_pn(uchb) 338 jc_puts(" helper=" as *u8); jc_puts(hname) 339 jc_puts(" opener_src_line=" as *u8); jc_pn(openline) 340 jc_puts(" -- emitted by helpers DEFINED ABOVE the opener, so the source-order region rule cannot reach them. NOT in logic_unknown (the baseline was banked without them). Worklist: the rows verb prints one UNCHARGED line each.\n" as *u8) 341 } 342 343 // journal (epoch TAB totals) -- evidence on success AND failure 344 let jb: *u8 = sys_mmap(256) 345 var jo: i64 = 0 346 var ep: i64 = sys_now_realtime_sec() 347 var m2: i64 = ep 348 let td: *u8 = sys_mmap(32) 349 var tk: i64 = 0 350 if m2 == 0 { jb[jo] = 48 as u8; jo = jo + 1 } 351 while m2 > 0 { td[tk] = (48 + (m2 % 10)) as u8; m2 = m2 / 10; tk = tk + 1 } 352 while tk > 0 { tk = tk - 1; jb[jo] = td[tk]; jo = jo + 1 } 353 let jrest: *u8 = "\tjslogic\t" as *u8 354 var jr: i64 = 0 355 while jrest[jr] != (0 as u8) { jb[jo] = jrest[jr]; jo = jo + 1; jr = jr + 1 } 356 var vals: *i64 = sys_mmap(6*8) as *i64 357 vals[0] = tI 358 vals[1] = tL 359 vals[2] = tS 360 vals[3] = tU 361 var vi: i64 = 0 362 while vi < 4 { 363 var vv: i64 = vals[vi] 364 if vv == 0 { jb[jo] = 48 as u8; jo = jo + 1 } 365 var vt: i64 = 0 366 while vv > 0 { td[vt] = (48 + (vv % 10)) as u8; vv = vv / 10; vt = vt + 1 } 367 while vt > 0 { vt = vt - 1; jb[jo] = td[vt]; jo = jo + 1 } 368 if vi < 3 { jb[jo] = 9 as u8; jo = jo + 1 } 369 vi = vi + 1 370 } 371 jb[jo] = 10 as u8 372 jo = jo + 1 373 let jfd: i64 = sys_openat_append(JC_JRNL, 0x1a4) 374 if jfd >= 0 { sys_write(jfd, jb, jo); sys_fsync(jfd); sys_close(jfd) } 375 376 if vk == 2 { return 0 } 377 if vk == 1 { 378 let sb: *u8 = sys_mmap(64) 379 var so: i64 = 0 380 var sv: i64 = logic_unknown 381 if sv == 0 { sb[so] = 48 as u8; so = so + 1 } 382 var st2: i64 = 0 383 while sv > 0 { td[st2] = (48 + (sv % 10)) as u8; sv = sv / 10; st2 = st2 + 1 } 384 while st2 > 0 { st2 = st2 - 1; sb[so] = td[st2]; so = so + 1 } 385 sb[so] = 10 as u8 386 so = so + 1 387 let bfd: i64 = sys_openat_wr(JC_BASE, 0x1a4) 388 if bfd < 0 { jc_puts("JSLOGIC-CENSUS FAIL: cannot write baseline\n" as *u8); return 3 } 389 sys_write(bfd, sb, so) 390 sys_fsync(bfd) 391 sys_close(bfd) 392 jc_puts("JSLOGIC-CENSUS SNAPSHOT baseline logic_unknown=" as *u8); jc_pn(logic_unknown); jc_puts("\n" as *u8) 393 return 0 394 } 395 // check: ratchet vs baseline (absent baseline = UNPROVEN, refuse loudly rather than pass) 396 let bl: *i64 = sys_mmap(16) as *i64 397 let bb: *u8 = sys_read_file(JC_BASE, bl) 398 if (bb as i64) == 0 { jc_puts("JSLOGIC-CENSUS RED: no baseline banked -- run snapshot deliberately first\n" as *u8); return 1 } 399 let bp: *i64 = sys_mmap(16) as *i64 400 bp[0] = 0 401 let base: i64 = jc_rdint(bb, bp, bl[0]) 402 if base < 0 { jc_puts("JSLOGIC-CENSUS RED: baseline unparsable\n" as *u8); return 1 } 403 if logic_unknown > base { 404 jc_puts("JSLOGIC-CENSUS RED: logic_unknown " as *u8); jc_pn(logic_unknown) 405 jc_puts(" ROSE vs baseline " as *u8); jc_pn(base) 406 jc_puts(" -- new JS-authored logic is refused by the interop-only law\n" as *u8) 407 return 1 408 } 409 jc_puts("JSLOGIC-CENSUS GREEN logic_unknown=" as *u8); jc_pn(logic_unknown) 410 jc_puts(" <= baseline " as *u8); jc_pn(base) 411 jc_puts("\n" as *u8) 412 return 0 413}