code wiki / _hdl_build / nx_magic.nx

nx_magic.nx source

↩ module page · 465 lines · 19113 B

1// nx_magic.nx -- the MISSING FIXER for law L001 (CLAUDE rule 11, debt seq274 sev8). 2// nx_law_warden DETECTS the breach (2348 inline literals over 600 organs) and cap-autonomy FILES it, 3// but nothing turned a breach into a one-step SAFE edit -- so the operator kept watching workstreams 4// "hit these as bugs and just give them a NEW NUMBER". This organ closes that half. 5// nx_magic map <file.nx> [threshold] -> JSON: every offending line+col+value+context, UNCAPPED 6// nx_magic propose <file.nx> [threshold] -> JSON: the const block + per-value site counts 7// nx_magic apply <file.nx> [threshold] -> ATOMIC rewrite: hoist each distinct value to a named 8// const inserted AFTER the last import and BEFORE the 9// first func (the forward-ref law: a const must be 10// declared above every reader), then replace the sites. 11// SEMANTIC-NEUTRALITY IS PROVABLE, NOT ASSERTED: hoisting a literal to a const must compile to the 12// SAME code, so the caller's proof is a BYTE-IDENTICAL elf on rebuild. Not identical => the transform 13// is NOT neutral => revert. (nx_magic never builds; it stays a pure, reviewable text transform.) 14// SKIPPED BY CONSTRUCTION (false-positive control): comment lines, const/static DECLARATION lines, 15// bytes inside string literals, digits that are part of an identifier (x2048), and any value below 16// the threshold. Decimal only -- hex is DECLARED out of envelope (nearly all hex here is < 1024). 17// IDEMPOTENT: a value whose const already exists is not re-hoisted, so a second apply is a no-op. 18// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 19import "nx_syscalls.nx" 20const MG_MAGIC_1024: i64 = 1024 21const MG_MAGIC_4096: i64 = 4096 22 23const MG_CAP: i64 = 1048576 24const MG_OUT: i64 = 1048576 25const MG_NL: i64 = 10 26const MG_QU: i64 = 34 27const MG_BSL: i64 = 92 28const MG_SLASH: i64 = 47 29const MG_US: i64 = 95 30const MG_COMMA: i64 = 44 31const MG_COLON: i64 = 58 32const MG_LB: i64 = 123 33const MG_RB: i64 = 125 34const MG_LSQ: i64 = 91 35const MG_RSQ: i64 = 93 36const MG_SP: i64 = 32 37const MG_TAB: i64 = 9 38const MG_DEF_THRESHOLD: i64 = 1024 39const MG_MAXVALS: i64 = 256 40const MG_MAXSITES: i64 = 4096 41const MG_STDERR: i64 = 2 42const MG_EXIT_USAGE: i64 = 2 43const MG_EXIT_ABSENT: i64 = 4 44const MG_FMODE: i64 = 420 45const MG_CTX: i64 = 60 46 47func mg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 48func mg_werr(s: *u8) -> i64 { sys_write(MG_STDERR, s, mg_slen(s)); return 0 } 49func mg_eqs(a: *u8, b: *u8) -> i64 { 50 var i: i64 = 0 51 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 52 if b[i] != (0 as u8) { return 0 } 53 return 1 54} 55func mg_b(d: *u8, o: i64, c: i64) -> i64 { d[o] = c as u8; return o + 1 } 56func mg_cat(d: *u8, o: i64, s: *u8) -> i64 { 57 var oo: i64 = o 58 var i: i64 = 0 59 while s[i] != (0 as u8) { d[oo] = s[i]; oo = oo + 1; i = i + 1 } 60 return oo 61} 62func mg_catn(d: *u8, o: i64, v: i64) -> i64 { 63 let t: *u8 = sys_mmap(32) 64 var m: i64 = v 65 var k: i64 = 0 66 if m < 0 { m = 0 } 67 if m == 0 { t[0] = 48 as u8; k = 1 } 68 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 69 var oo: i64 = o 70 var i: i64 = 0 71 while i < k { d[oo] = t[k-1-i]; oo = oo + 1; i = i + 1 } 72 return oo 73} 74func mg_atoi(s: *u8) -> i64 { 75 var v: i64 = 0 76 var i: i64 = 0 77 while s[i] != (0 as u8) { 78 let c: i64 = s[i] as i64 79 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } 80 i = i + 1 81 } 82 return v 83} 84func mg_is_ident(c: i64) -> i64 { 85 if c >= 48 { if c <= 57 { return 1 } } 86 if c >= 65 { if c <= 90 { return 1 } } 87 if c >= 97 { if c <= 122 { return 1 } } 88 if c == MG_US { return 1 } 89 return 0 90} 91func mg_is_digit(c: i64) -> i64 { if c >= 48 { if c <= 57 { return 1 } } return 0 } 92// first non-space index of line [ls,le) 93func mg_first_ns(q: *u8, ls: i64, le: i64) -> i64 { 94 var i: i64 = ls 95 var go: i64 = 1 96 while go == 1 { 97 go = 0 98 if i < le { if q[i] == (MG_SP as u8) { i = i + 1; go = 1 } else { if q[i] == (MG_TAB as u8) { i = i + 1; go = 1 } } } 99 } 100 return i 101} 102// does line [ls,le) start (after indent) with the c-string lit? 103func mg_starts(q: *u8, ls: i64, le: i64, lit: *u8) -> i64 { 104 let s: i64 = mg_first_ns(q, ls, le) 105 let n: i64 = mg_slen(lit) 106 if s + n > le { return 0 } 107 var i: i64 = 0 108 while i < n { if q[s+i] != lit[i] { return 0 } i = i + 1 } 109 return 1 110} 111// a line we must NOT touch: comment, or a const/static DECLARATION (its literal is already named) 112func mg_skip_line(q: *u8, ls: i64, le: i64) -> i64 { 113 if mg_starts(q, ls, le, "//" as *u8) == 1 { return 1 } 114 if mg_starts(q, ls, le, "const " as *u8) == 1 { return 1 } 115 if mg_starts(q, ls, le, "static " as *u8) == 1 { return 1 } 116 return 0 117} 118func mg_read(path: *u8, b: *u8, cap: i64) -> i64 { 119 let fd: i64 = sys_openat_rd(path) 120 if fd < 0 { return 0 - 1 } 121 var n: i64 = 0 122 var go: i64 = 1 123 while go == 1 { 124 let r: i64 = sys_read(fd, (b as i64 + n) as *u8, cap - n) 125 if r > 0 { n = n + r } else { go = 0 } 126 if n >= cap { go = 0 } 127 } 128 sys_close(fd) 129 return n 130} 131// Detect the file's dominant const PREFIX (chars before the first '_' of a const name) so generated 132// names stay idiomatic to the organ instead of importing a foreign convention. Falls back to "K". 133func mg_detect_prefix(q: *u8, n: i64, out: *u8) -> i64 { 134 var i: i64 = 0 135 var done: i64 = 0 136 while i < n { 137 var le: i64 = i 138 var s: i64 = 1 139 while s == 1 { if le >= n { s = 0 } else { if q[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 140 if done == 0 { 141 if mg_starts(q, i, le, "const " as *u8) == 1 { 142 let st: i64 = mg_first_ns(q, i, le) + 6 143 var p: i64 = st 144 var go2: i64 = 1 145 while go2 == 1 { 146 go2 = 0 147 if p < le { if q[p] != (MG_US as u8) { if mg_is_ident(q[p] as i64) == 1 { p = p + 1; go2 = 1 } } } 148 } 149 if p > st { if p < le { if q[p] == (MG_US as u8) { 150 var k: i64 = 0 151 while k < p - st { out[k] = q[st+k]; k = k + 1 } 152 out[p-st] = 0 as u8 153 done = 1 154 } } } 155 } 156 } 157 i = le + 1 158 } 159 if done == 0 { out[0] = 75 as u8; out[1] = 0 as u8 } 160 return 0 161} 162// build the generated const name for a value into out: <PFX>_MAGIC_<value> 163func mg_name_for(pfx: *u8, v: i64, out: *u8) -> i64 { 164 var o: i64 = mg_cat(out, 0, pfx) 165 o = mg_cat(out, o, "_MAGIC_" as *u8) 166 o = mg_catn(out, o, v) 167 out[o] = 0 as u8 168 return o 169} 170// does the file already contain "const <name>" (idempotency + collision guard)? 171func mg_has_const(q: *u8, n: i64, name: *u8) -> i64 { 172 let nl: i64 = mg_slen(name) 173 var i: i64 = 0 174 while i < n { 175 var le: i64 = i 176 var s: i64 = 1 177 while s == 1 { if le >= n { s = 0 } else { if q[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 178 if mg_starts(q, i, le, "const " as *u8) == 1 { 179 let st: i64 = mg_first_ns(q, i, le) + 6 180 if st + nl <= le { 181 var k: i64 = 0 182 var ok: i64 = 1 183 while k < nl { if q[st+k] != name[k] { ok = 0; k = nl } else { k = k + 1 } } 184 if ok == 1 { if st + nl < le { if mg_is_ident(q[st+nl] as i64) == 0 { return 1 } } else { return 1 } } 185 } 186 } 187 i = le + 1 188 } 189 return 0 190} 191// json-safe slice copy (context snippets can carry quotes/backslashes) 192func mg_cat_json(d: *u8, o: i64, q: *u8, a: i64, b: i64) -> i64 { 193 var oo: i64 = o 194 var i: i64 = a 195 while i < b { 196 var c: i64 = q[i] as i64 197 if c == MG_QU { c = 39 } 198 if c == MG_BSL { c = MG_SLASH } 199 if c < 32 { c = MG_SP } 200 d[oo] = c as u8 201 oo = oo + 1 202 i = i + 1 203 } 204 return oo 205} 206 207// THE SCANNER. Walks the file once and records every offending literal site into the parallel 208// arrays (line, col, len, value). Returns the site count. Honest about its own bound: stops at 209// MG_MAXSITES and the caller DECLARES truncation rather than silently under-reporting. 210func mg_scan(q: *u8, n: i64, thr: i64, sline: *i64, scol: *i64, slen: *i64, sval: *i64, sls: *i64, sle: *i64) -> i64 { 211 var sites: i64 = 0 212 var lineno: i64 = 1 213 var i: i64 = 0 214 while i < n { 215 var le: i64 = i 216 var s: i64 = 1 217 while s == 1 { if le >= n { s = 0 } else { if q[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 218 if mg_skip_line(q, i, le) == 0 { 219 var instr: i64 = 0 220 var p: i64 = i 221 while p < le { 222 let c: i64 = q[p] as i64 223 if instr == 1 { 224 if c == MG_BSL { p = p + 1 } else { if c == MG_QU { instr = 0 } } 225 p = p + 1 226 } else { 227 if c == MG_QU { instr = 1; p = p + 1 } else { 228 if mg_is_digit(c) == 1 { 229 // a digit run only counts if it does NOT continue an identifier 230 var prev_ident: i64 = 0 231 if p > i { if mg_is_ident(q[p-1] as i64) == 1 { prev_ident = 1 } } 232 var e: i64 = p 233 var g2: i64 = 1 234 while g2 == 1 { g2 = 0; if e < le { if mg_is_digit(q[e] as i64) == 1 { e = e + 1; g2 = 1 } } } 235 var trail_ident: i64 = 0 236 if e < le { if mg_is_ident(q[e] as i64) == 1 { trail_ident = 1 } } 237 if prev_ident == 0 { if trail_ident == 0 { 238 var v: i64 = 0 239 var k: i64 = p 240 while k < e { v = v * 10 + ((q[k] as i64) - 48); k = k + 1 } 241 if v >= thr { if sites < MG_MAXSITES { 242 sline[sites] = lineno 243 scol[sites] = p - i 244 slen[sites] = e - p 245 sval[sites] = v 246 sls[sites] = i 247 sle[sites] = le 248 sites = sites + 1 249 } } 250 } } 251 p = e 252 } else { p = p + 1 } 253 } 254 } 255 } 256 } 257 lineno = lineno + 1 258 i = le + 1 259 } 260 return sites 261} 262 263func main(argc: i64, argv: *i64) -> i64 { 264 if argc < 3 { mg_werr("usage: nx_magic map|propose|apply <file.nx> [threshold]\n" as *u8); sys_exit(MG_EXIT_USAGE); return MG_EXIT_USAGE } 265 let verb: *u8 = argv[1] as *u8 266 let path: *u8 = argv[2] as *u8 267 var thr: i64 = MG_DEF_THRESHOLD 268 if argc > 3 { thr = mg_atoi(argv[3] as *u8) } 269 if thr < 1 { thr = MG_DEF_THRESHOLD } 270 271 let q: *u8 = sys_mmap(MG_CAP) 272 let n: i64 = mg_read(path, q, MG_CAP - 1) 273 if n <= 0 { mg_werr("SOURCE ABSENT/EMPTY (fail-closed): " as *u8); mg_werr(path); mg_werr("\n" as *u8); sys_exit(MG_EXIT_ABSENT); return MG_EXIT_ABSENT } 274 275 let sline: *i64 = sys_mmap(MG_MAXSITES * 8) as *i64 276 let scol: *i64 = sys_mmap(MG_MAXSITES * 8) as *i64 277 let slen: *i64 = sys_mmap(MG_MAXSITES * 8) as *i64 278 let sval: *i64 = sys_mmap(MG_MAXSITES * 8) as *i64 279 let sls: *i64 = sys_mmap(MG_MAXSITES * 8) as *i64 280 let sle: *i64 = sys_mmap(MG_MAXSITES * 8) as *i64 281 let sites: i64 = mg_scan(q, n, thr, sline, scol, slen, sval, sls, sle) 282 283 // distinct values (insertion-ordered) 284 let dval: *i64 = sys_mmap(MG_MAXVALS * 8) as *i64 285 let dcnt: *i64 = sys_mmap(MG_MAXVALS * 8) as *i64 286 var nd: i64 = 0 287 var i2: i64 = 0 288 while i2 < sites { 289 var found: i64 = 0 290 var j: i64 = 0 291 while j < nd { if dval[j] == sval[i2] { dcnt[j] = dcnt[j] + 1; found = 1; j = nd } else { j = j + 1 } } 292 if found == 0 { if nd < MG_MAXVALS { dval[nd] = sval[i2]; dcnt[nd] = 1; nd = nd + 1 } } 293 i2 = i2 + 1 294 } 295 296 let pfx: *u8 = sys_mmap(256) 297 mg_detect_prefix(q, n, pfx) 298 let nm: *u8 = sys_mmap(256) 299 let out: *u8 = sys_mmap(MG_OUT) 300 301 if mg_eqs("map" as *u8, verb) == 1 { 302 var o: i64 = mg_b(out, 0, MG_LB) 303 o = mg_cat(out, o, "\"tool\":\"nx_magic\",\"verb\":\"map\",\"file\":\"" as *u8) 304 o = mg_cat(out, o, path) 305 o = mg_cat(out, o, "\",\"threshold\":" as *u8) 306 o = mg_catn(out, o, thr) 307 o = mg_cat(out, o, ",\"sites\":" as *u8) 308 o = mg_catn(out, o, sites) 309 o = mg_cat(out, o, ",\"distinct_values\":" as *u8) 310 o = mg_catn(out, o, nd) 311 o = mg_cat(out, o, ",\"const_prefix\":\"" as *u8) 312 o = mg_cat(out, o, pfx) 313 o = mg_cat(out, o, "\",\"rows\":[" as *u8) 314 var k2: i64 = 0 315 while k2 < sites { 316 if k2 > 0 { o = mg_b(out, o, MG_COMMA) } 317 o = mg_cat(out, o, "{\"line\":" as *u8) 318 o = mg_catn(out, o, sline[k2]) 319 o = mg_cat(out, o, ",\"col\":" as *u8) 320 o = mg_catn(out, o, scol[k2]) 321 o = mg_cat(out, o, ",\"value\":" as *u8) 322 o = mg_catn(out, o, sval[k2]) 323 o = mg_cat(out, o, ",\"proposed_const\":\"" as *u8) 324 mg_name_for(pfx, sval[k2], nm) 325 o = mg_cat(out, o, nm) 326 o = mg_cat(out, o, "\",\"context\":\"" as *u8) 327 var ce: i64 = sle[k2] 328 if ce - sls[k2] > MG_CTX { ce = sls[k2] + MG_CTX } 329 o = mg_cat_json(out, o, q, sls[k2], ce) 330 o = mg_cat(out, o, "\"}" as *u8) 331 k2 = k2 + 1 332 } 333 o = mg_cat(out, o, "],\"envelope\":{\"decimal_only\":1,\"hex_out_of_envelope\":1,\"site_cap\":" as *u8) 334 o = mg_catn(out, o, MG_MAXSITES) 335 o = mg_cat(out, o, ",\"truncated\":" as *u8) 336 var tr: i64 = 0 337 if sites >= MG_MAXSITES { tr = 1 } 338 o = mg_catn(out, o, tr) 339 o = mg_cat(out, o, ",\"skipped\":\"comment+const/static-decl+in-string+identifier-digits\"}" as *u8) 340 o = mg_b(out, o, MG_RB) 341 o = mg_b(out, o, MG_NL) 342 sys_write(1, out, o) 343 sys_exit(0) 344 return 0 345 } 346 347 if mg_eqs("propose" as *u8, verb) == 1 { 348 var o: i64 = mg_b(out, 0, MG_LB) 349 o = mg_cat(out, o, "\"tool\":\"nx_magic\",\"verb\":\"propose\",\"file\":\"" as *u8) 350 o = mg_cat(out, o, path) 351 o = mg_cat(out, o, "\",\"sites\":" as *u8) 352 o = mg_catn(out, o, sites) 353 o = mg_cat(out, o, ",\"consts\":[" as *u8) 354 var k3: i64 = 0 355 while k3 < nd { 356 if k3 > 0 { o = mg_b(out, o, MG_COMMA) } 357 mg_name_for(pfx, dval[k3], nm) 358 o = mg_cat(out, o, "{\"name\":\"" as *u8) 359 o = mg_cat(out, o, nm) 360 o = mg_cat(out, o, "\",\"value\":" as *u8) 361 o = mg_catn(out, o, dval[k3]) 362 o = mg_cat(out, o, ",\"sites\":" as *u8) 363 o = mg_catn(out, o, dcnt[k3]) 364 o = mg_cat(out, o, ",\"already_declared\":" as *u8) 365 o = mg_catn(out, o, mg_has_const(q, n, nm)) 366 o = mg_b(out, o, MG_RB) 367 k3 = k3 + 1 368 } 369 o = mg_cat(out, o, "],\"note\":\"generated names are MECHANICAL and collision-free; renaming each to a meaningful domain term (or moving it to a config row) is the remaining OWNER judgment rule-11 asks for\"" as *u8) 370 o = mg_b(out, o, MG_RB) 371 o = mg_b(out, o, MG_NL) 372 sys_write(1, out, o) 373 sys_exit(0) 374 return 0 375 } 376 377 if mg_eqs("apply" as *u8, verb) == 1 { 378 if sites == 0 { 379 mg_werr("NO-OP no sites at or above threshold\n" as *u8) 380 sys_exit(0) 381 return 0 382 } 383 // insertion point = end of the LAST import line (consts must precede every reader) 384 var ins: i64 = 0 385 var li: i64 = 0 386 while li < n { 387 var le: i64 = li 388 var s: i64 = 1 389 while s == 1 { if le >= n { s = 0 } else { if q[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 390 if mg_starts(q, li, le, "import " as *u8) == 1 { ins = le + 1 } 391 li = le + 1 392 } 393 let nb: *u8 = sys_mmap(MG_OUT) 394 var o: i64 = 0 395 var c1: i64 = 0 396 while c1 < ins { nb[o] = q[c1]; o = o + 1; c1 = c1 + 1 } 397 // const block (skip any value already declared -> idempotent) 398 var added: i64 = 0 399 var k4: i64 = 0 400 while k4 < nd { 401 mg_name_for(pfx, dval[k4], nm) 402 if mg_has_const(q, n, nm) == 0 { 403 o = mg_cat(nb, o, "const " as *u8) 404 o = mg_cat(nb, o, nm) 405 o = mg_cat(nb, o, ": i64 = " as *u8) 406 o = mg_catn(nb, o, dval[k4]) 407 o = mg_b(nb, o, MG_NL) 408 added = added + 1 409 } 410 k4 = k4 + 1 411 } 412 // body with each site replaced by its const name 413 var si: i64 = 0 414 var p2: i64 = ins 415 // skip any site lying before the insertion point (import lines carry no literals, but the 416 // scan is whole-file, so the site cursor must start aligned with the copy cursor) 417 var guard: i64 = 1 418 while guard == 1 { 419 guard = 0 420 if si < sites { if sls[si] + scol[si] < ins { si = si + 1; guard = 1 } } 421 } 422 while p2 < n { 423 var isite: i64 = 0 424 if si < sites { if sls[si] + scol[si] == p2 { isite = 1 } } 425 if isite == 1 { 426 mg_name_for(pfx, sval[si], nm) 427 o = mg_cat(nb, o, nm) 428 p2 = p2 + slen[si] 429 si = si + 1 430 } else { 431 nb[o] = q[p2] 432 o = o + 1 433 p2 = p2 + 1 434 } 435 } 436 // atomic: tmp + fsync + rename (a reader never sees a torn source) 437 let tmpp: *u8 = sys_mmap(MG_MAGIC_1024) 438 var to: i64 = mg_cat(tmpp, 0, path) 439 to = mg_cat(tmpp, to, ".mgtmp" as *u8) 440 tmpp[to] = 0 as u8 441 let fd: i64 = sys_openat_wr(tmpp, MG_FMODE) 442 if fd < 0 { mg_werr("apply: cannot open tmp\n" as *u8); sys_exit(1); return 1 } 443 sys_write(fd, nb, o) 444 sys_fsync(fd) 445 sys_close(fd) 446 sys_renameat(tmpp, path) 447 let m: *u8 = sys_mmap(MG_MAGIC_4096) 448 var mo: i64 = mg_cat(m, 0, "MAGIC-APPLIED file=" as *u8) 449 mo = mg_cat(m, mo, path) 450 mo = mg_cat(m, mo, " consts_added=" as *u8) 451 mo = mg_catn(m, mo, added) 452 mo = mg_cat(m, mo, " sites_replaced=" as *u8) 453 mo = mg_catn(m, mo, sites) 454 mo = mg_cat(m, mo, " bytes=" as *u8) 455 mo = mg_catn(m, mo, o) 456 mo = mg_cat(m, mo, " -- NEUTRALITY IS UNPROVEN UNTIL YOU REBUILD AND BYTE-COMPARE THE ELF\n" as *u8) 457 sys_write(1, m, mo) 458 sys_exit(0) 459 return 0 460 } 461 462 mg_werr("usage: nx_magic map|propose|apply <file.nx> [threshold]\n" as *u8) 463 sys_exit(MG_EXIT_USAGE) 464 return MG_EXIT_USAGE 465}