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}