code wiki / (root) / nx_ctlbyte_repair.nx

nx_ctlbyte_repair.nx source

↩ module page · 359 lines · 16899 B

1// nx_ctlbyte_repair.nx -- FIND AND REPAIR CONTROL-BYTE CORRUPTION IN NishiLang SOURCES. 2// 3// WHAT HAPPENED, MEASURED 2026-09-03. A whole-population compiler census (nx_langcensus) found 314 of the 4// tree's 13,721 top-level programs refused with "a control byte (decimal 14) sits in the source here" -- the 5// single largest refusal class in the estate, larger than the next nineteen combined. Every one carries ONE 6// contiguous run of EXACTLY 119 bytes of 0x0E, and in every case that run sits inside an integer-print 7// helper, between the digit loop and its `return 0`. The corruption is present on BOTH trees, so it cannot 8// be recovered from a twin, and the run length is a fixed filler that does not equal the length of the text 9// it replaced -- so it cannot be recovered from the pattern either. It CAN be recovered from the CONTRACT: 10// the enclosing function has already handled zero and sign and has built the digits into d[0..k) in reverse, 11// so the only thing the lost bytes can have done is reverse them and write them. 12// ★★★★★★A LOST REGION IS RECOVERABLE WHEN THE CODE AROUND IT PINS ITS CONTRACT -- AND THE ONLY HONEST REPAIR 13// IS THE ONE THE SURROUNDING CODE FORCES, NEVER THE ONE THAT MERELY LOOKS PLAUSIBLE. 14// 15// 13 of the affected sources are on the gate roster, so their binaries RUN while their sources cannot 16// rebuild them: the AHEAD class, where the served artifact carries code no source can reproduce. 17// 18// TWO SHAPES, ONE DECIDABLE RULE. Between the digit loop and the corrupt run: 19// - no `sys_write(` yet -> the reversal AND the write were destroyed -> INSERT the tail, drop the run. 20// - a `sys_write(` already -> only trailing cleanup was destroyed -> DROP the run, insert nothing. 21// Anything else -> UNKNOWN, and this organ REFUSES to touch it. ★A REPAIRER THAT GUESSES IS A CORRUPTER WITH 22// GOOD INTENTIONS: the unknown shapes are NAMED for a human, never silently rewritten. 23// 24// Usage: nx_ctlbyte_repair [--apply] [root ...] 25// Default is a DRY census: every file, its class, and the partition -- nothing is written. `--apply` 26// performs only the repairs whose class is decided, and re-reads each file afterwards to prove the byte 27// is gone. 28// ROOTS ARE ARGUMENTS, AND THE ORGAN PRINTS THE ONES IT WALKED. Measured 2026-09-03: with the roots 29// hard-coded as `runtime/`, running this on the NAS (CWD = the serving root, where `runtime/` holds 17 30// files) reported `files=17 ... verdict=CLEAN` over a tree whose sources live in `buildroot/runtime/`. 31// ★★★★★A SCANNER POINTED AT THE WRONG ROOT PRODUCES A CONFIDENT, COMPLETE-LOOKING FALSE NEGATIVE -- and a 32// bare relative path is not a tree name, it is an expression whose meaning is the caller's CWD. 33// Defaults (runtime, runtime/_hdl_build) apply only when no root is named, and are printed either way. 34// Exit: 0 CLEAN (no corruption found) - 1 CORRUPTION PRESENT (dry run, or unknown shapes remain) 35// 2 usage - 3 UNPROVEN (a walk cap filled, or a write-back could not be verified). 36// 37// RESOURCE ENVELOPE: one read and at most one write per affected file, sequential; buffers sized from the 38// file and reused; nothing outside the named source files is written. 39// 40// license_tier: ORIGINAL No hw writes (Rule 26). 41 42import "nx_syscalls.nx" 43 44// ---- bounds, named and derived (Rule 11) ----------------------------------- 45// The tree holds ~19,400 .nx files; the table is sized above that and REFUSES rather than truncating. 46const CB_MAX_FILES: i64 = 32768 47const CB_PATH_MAX: i64 = 4096 48const CB_DIRBUF: i64 = 65536 49// The largest source in the tree is ~420 KB; 4 MiB is an order above it and the read is sized from the file 50// anyway (sys_read_file cannot short-read), so this only bounds the repaired copy we build. 51const CB_FILEBUF: i64 = 4194304 52// The corrupt byte and the observed filler length. The length is NOT used to reconstruct anything -- it is 53// reported so a run of a different length is visible as a different defect rather than folded into this one. 54const CB_BYTE: i64 = 14 55const CB_OBSERVED_RUN: i64 = 119 56// How far back from the run we look for the digit loop that pins the contract. The helper prologue is four 57// short lines; 400 bytes covers it with room and bounds the scan. 58const CB_LOOKBACK: i64 = 400 59 60const CB_CLASS_INSERT: i64 = 0 61const CB_CLASS_DROP: i64 = 1 62const CB_CLASS_UNKNOWN: i64 = 2 63 64const CB_EXIT_CLEAN: i64 = 0 65const CB_EXIT_PRESENT: i64 = 1 66const CB_EXIT_USAGE: i64 = 2 67const CB_EXIT_UNPROVEN: i64 = 3 68const CB_MODE_0644: i64 = 0x1a4 69 70// ---- string helpers (no allocation) ---------------------------------------- 71func cb_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 72func cb_eq_n(a: *u8, b: *u8, n: i64) -> i64 { 73 var i: i64 = 0 74 while i < n { if a[i] != b[i] { return 0 } i = i + 1 } 75 return 1 76} 77func cb_ends_with(s: *u8, sfx: *u8) -> i64 { 78 let n: i64 = cb_len(s) 79 let m: i64 = cb_len(sfx) 80 if m > n { return 0 } 81 return cb_eq_n(((s as i64) + n - m) as *u8, sfx, m) 82} 83// 1 iff buf[from..to) contains needle. 84func cb_region_has(buf: *u8, from: i64, to: i64, needle: *u8) -> i64 { 85 let m: i64 = cb_len(needle) 86 if m <= 0 { return 0 } 87 var i: i64 = from 88 if i < 0 { i = 0 } 89 while i + m <= to { 90 if cb_eq_n(((buf as i64) + i) as *u8, needle, m) == 1 { return 1 } 91 i = i + 1 92 } 93 return 0 94} 95func cb_cat(dst: *u8, at: i64, s: *u8, cap: i64) -> i64 { 96 var i: i64 = 0 97 var o: i64 = at 98 while s[i] != (0 as u8) { 99 if o >= cap - 1 { return o } 100 dst[o] = s[i] 101 o = o + 1 102 i = i + 1 103 } 104 dst[o] = 0 as u8 105 return o 106} 107func cb_puts(s: *u8) -> i64 { sys_write(1, s, cb_len(s)) return 0 } 108func cb_putn(v: i64) -> i64 { 109 if v == 0 { sys_write(1, "0" as *u8, 1) return 0 } 110 var m: i64 = v 111 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 112 let d: *u8 = sys_mmap(24) 113 var k: i64 = 0 114 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 115 let o: *u8 = sys_mmap(24) 116 var i: i64 = 0 117 while i < k { o[i] = d[k - 1 - i]; i = i + 1 } 118 sys_write(1, o, k) 119 return 0 120} 121 122// THE RECOVERED TAIL. Deliberately uses names that cannot collide with the helper's own locals (every 123// affected prologue declares exactly v/n, m, d, k), so the repair can never shadow a live variable. 124func cb_fix_text() -> *u8 { 125 return " let cb_o: *u8 = sys_mmap(24)\n var cb_i: i64 = 0\n while cb_i < k { cb_o[cb_i] = d[k - 1 - cb_i]; cb_i = cb_i + 1 }\n sys_write(1, cb_o, k)\x00" as *u8 126} 127 128// ---- the walk (loop until getdents returns <= 0; a filled table is announced, never silent) ------------- 129func cb_walk(dir: *u8, tab: *i64, cap: i64, n_in: i64, full: *i64) -> i64 { 130 var n: i64 = n_in 131 let fd: i64 = sys_openat_rd(dir) 132 if fd < 0 { return n } 133 let dbuf: *u8 = sys_mmap(CB_DIRBUF) 134 var go: i64 = 1 135 while go == 1 { 136 let nr: i64 = sys_getdents64(fd, dbuf, CB_DIRBUF) 137 if nr <= 0 { go = 0 } else { 138 var off: i64 = 0 139 while off < nr { 140 let rec: *u8 = ((dbuf as i64) + off) as *u8 141 let nm: *u8 = dirent_name(rec) 142 if cb_ends_with(nm, ".nx" as *u8) == 1 { 143 if n >= cap { full[0] = 1 } else { 144 let p: *u8 = sys_mmap(CB_PATH_MAX) 145 var o: i64 = cb_cat(p, 0, dir, CB_PATH_MAX) 146 o = cb_cat(p, o, "/" as *u8, CB_PATH_MAX) 147 o = cb_cat(p, o, nm, CB_PATH_MAX) 148 tab[n] = p as i64 149 n = n + 1 150 } 151 } 152 let rl: i64 = dirent_reclen(rec) 153 if rl <= 0 { off = nr } else { off = off + rl } 154 } 155 } 156 } 157 sys_close(fd) 158 return n 159} 160 161func cb_class_name(c: i64) -> *u8 { 162 if c == CB_CLASS_INSERT { return "INSERT-TAIL" as *u8 } 163 if c == CB_CLASS_DROP { return "DROP-RUN" as *u8 } 164 return "UNKNOWN-SHAPE" as *u8 165} 166 167func main(argc: i64, argv: *i64) -> i64 { 168 var apply: i64 = 0 169 var i: i64 = 1 170 while i < argc { 171 let a: *u8 = argv[i] as *u8 172 if cb_eq_n(a, "--apply" as *u8, 7) == 1 { if cb_len(a) == 7 { apply = 1 } } 173 i = i + 1 174 } 175 176 let full: *i64 = sys_mmap(8) as *i64 177 full[0] = 0 178 let tab: *i64 = sys_mmap(CB_MAX_FILES * 8) as *i64 179 var nf: i64 = 0 180 var nroots: i64 = 0 181 cb_puts("CTLBYTE roots=" as *u8) 182 var ai: i64 = 1 183 while ai < argc { 184 let a2: *u8 = argv[ai] as *u8 185 var isflag: i64 = 0 186 if cb_eq_n(a2, "--" as *u8, 2) == 1 { isflag = 1 } 187 if isflag == 0 { 188 cb_puts(a2); cb_puts(" " as *u8) 189 nf = cb_walk(a2, tab, CB_MAX_FILES, nf, full) 190 nroots = nroots + 1 191 } 192 ai = ai + 1 193 } 194 if nroots == 0 { 195 cb_puts("runtime runtime/_hdl_build (DEFAULT -- name roots explicitly when the CWD is not the source tree) " as *u8) 196 nf = cb_walk("runtime" as *u8, tab, CB_MAX_FILES, nf, full) 197 nf = cb_walk("runtime/_hdl_build" as *u8, tab, CB_MAX_FILES, nf, full) 198 } 199 cb_puts("\n" as *u8) 200 // A root that matched NOTHING is almost always a wrong path, and a zero-file walk that reports CLEAN is 201 // the false negative this organ exists to avoid publishing. 202 if nf == 0 { 203 cb_puts("CTLBYTE verdict=UNPROVEN -- the named roots contain no .nx files; a zero-file walk cannot say CLEAN\n" as *u8) 204 sys_exit(CB_EXIT_UNPROVEN) 205 } 206 if full[0] == 1 { 207 cb_puts("CTLBYTE verdict=UNPROVEN -- the file table filled at " as *u8) 208 cb_putn(CB_MAX_FILES) 209 cb_puts(" entries; a prefix of a population is not a population.\n" as *u8) 210 sys_exit(CB_EXIT_UNPROVEN) 211 } 212 213 cb_puts("CTLBYTE files=" as *u8); cb_putn(nf) 214 cb_puts(" byte=" as *u8); cb_putn(CB_BYTE) 215 if apply == 1 { cb_puts(" mode=APPLY\n" as *u8) } else { cb_puts(" mode=DRY (nothing is written; pass --apply to repair)\n" as *u8) } 216 217 let out: *u8 = sys_mmap(CB_FILEBUF) 218 let lp: *i64 = sys_mmap(8) as *i64 219 var n_hit: i64 = 0 220 var n_ins: i64 = 0 221 var n_drop: i64 = 0 222 var n_unk: i64 = 0 223 var n_fixed: i64 = 0 224 var n_verifyfail: i64 = 0 225 var n_oddlen: i64 = 0 226 var n_multirun: i64 = 0 227 228 var f: i64 = 0 229 while f < nf { 230 let p: *u8 = tab[f] as *u8 231 lp[0] = 0 232 let b: *u8 = sys_read_file(p, lp) 233 if (b as i64) != 0 { 234 let n: i64 = lp[0] 235 // locate the FIRST run of the corrupt byte 236 var s: i64 = 0 - 1 237 var j: i64 = 0 238 while j < n { 239 if (b[j] as i64) == CB_BYTE { s = j; j = n } else { j = j + 1 } 240 } 241 if s >= 0 { 242 n_hit = n_hit + 1 243 var e: i64 = s 244 while e < n { if (b[e] as i64) == CB_BYTE { e = e + 1 } else { e = n + 1 } } 245 if e > n { e = e - 1 } 246 // e is now one past the run 247 var e2: i64 = s 248 while e2 < n { 249 if (b[e2] as i64) == CB_BYTE { e2 = e2 + 1 } else { e2 = n } 250 } 251 // recompute cleanly: walk forward while the byte matches 252 var re: i64 = s 253 var walking: i64 = 1 254 while walking == 1 { 255 if re >= n { walking = 0 } else { 256 if (b[re] as i64) == CB_BYTE { re = re + 1 } else { walking = 0 } 257 } 258 } 259 let runlen: i64 = re - s 260 if runlen != CB_OBSERVED_RUN { n_oddlen = n_oddlen + 1 } 261 // a SECOND run anywhere after this one is a different defect: never touch it 262 var more: i64 = 0 263 var t: i64 = re 264 while t < n { if (b[t] as i64) == CB_BYTE { more = 1; t = n } else { t = t + 1 } } 265 if more == 1 { n_multirun = n_multirun + 1 } 266 267 // classify by the CONTRACT pinned in the lookback window 268 var from: i64 = s - CB_LOOKBACK 269 if from < 0 { from = 0 } 270 var cls: i64 = CB_CLASS_UNKNOWN 271 if more == 0 { 272 if cb_region_has(b, from, s, "m = m / 10" as *u8) == 1 { 273 // where does the digit loop line end? everything after it, before the run, decides. 274 var dl: i64 = from 275 var last: i64 = 0 - 1 276 while dl + 10 <= s { 277 if cb_eq_n(((b as i64) + dl) as *u8, "m = m / 10" as *u8, 10) == 1 { last = dl } 278 dl = dl + 1 279 } 280 if last >= 0 { 281 if cb_region_has(b, last, s, "sys_write(" as *u8) == 1 { cls = CB_CLASS_DROP } else { cls = CB_CLASS_INSERT } 282 } 283 } 284 } 285 if cls == CB_CLASS_INSERT { n_ins = n_ins + 1 } 286 if cls == CB_CLASS_DROP { n_drop = n_drop + 1 } 287 if cls == CB_CLASS_UNKNOWN { n_unk = n_unk + 1 } 288 289 cb_puts(cb_class_name(cls)); cb_puts(" runlen="); cb_putn(runlen) 290 cb_puts(" "); cb_puts(p); cb_puts("\n" as *u8) 291 292 if apply == 1 { 293 if cls != CB_CLASS_UNKNOWN { 294 var o: i64 = 0 295 var c: i64 = 0 296 while c < s { if o < CB_FILEBUF { out[o] = b[c]; o = o + 1 } c = c + 1 } 297 if cls == CB_CLASS_INSERT { 298 let fx: *u8 = cb_fix_text() 299 var z: i64 = 0 300 while fx[z] != (0 as u8) { if o < CB_FILEBUF { out[o] = fx[z]; o = o + 1 } z = z + 1 } 301 } 302 var c2: i64 = re 303 while c2 < n { if o < CB_FILEBUF { out[o] = b[c2]; o = o + 1 } c2 = c2 + 1 } 304 let fd: i64 = sys_openat_wr(p, CB_MODE_0644) 305 if fd >= 0 { 306 let wn: i64 = sys_write(fd, out, o) 307 sys_close(fd) 308 if wn == o { 309 // PROVE IT: re-read and confirm the byte is gone. A repair that reports success 310 // without re-reading is a claim, not a measurement. 311 lp[0] = 0 312 let vb: *u8 = sys_read_file(p, lp) 313 var still: i64 = 0 314 if (vb as i64) != 0 { 315 var q: i64 = 0 316 while q < lp[0] { if (vb[q] as i64) == CB_BYTE { still = 1; q = lp[0] } else { q = q + 1 } } 317 } else { still = 1 } 318 if still == 0 { n_fixed = n_fixed + 1 } else { n_verifyfail = n_verifyfail + 1 } 319 } else { n_verifyfail = n_verifyfail + 1 } 320 } else { n_verifyfail = n_verifyfail + 1 } 321 } 322 } 323 } 324 } 325 f = f + 1 326 } 327 328 // THE PARTITION IS A CLAIM: print it and check it sums. 329 let sum: i64 = n_ins + n_drop + n_unk 330 cb_puts("CTLBYTE affected=" as *u8); cb_putn(n_hit) 331 cb_puts(" insert=" as *u8); cb_putn(n_ins) 332 cb_puts(" drop=" as *u8); cb_putn(n_drop) 333 cb_puts(" unknown=" as *u8); cb_putn(n_unk) 334 cb_puts(" sum=" as *u8); cb_putn(sum) 335 if sum == n_hit { cb_puts(" RECONCILES" as *u8) } else { cb_puts(" LEAK -- the partition does not sum" as *u8) } 336 cb_puts("\n" as *u8) 337 if n_oddlen > 0 { cb_puts("CTLBYTE run-length differs from the observed filler on " as *u8); cb_putn(n_oddlen); cb_puts(" file(s) -- a DIFFERENT defect, not this one\n" as *u8) } 338 if n_multirun > 0 { cb_puts("CTLBYTE more than one run on " as *u8); cb_putn(n_multirun); cb_puts(" file(s) -- left untouched by design\n" as *u8) } 339 if apply == 1 { 340 cb_puts("CTLBYTE repaired_and_verified=" as *u8); cb_putn(n_fixed) 341 cb_puts(" write_or_verify_failed=" as *u8); cb_putn(n_verifyfail) 342 cb_puts("\n" as *u8) 343 } 344 345 var verdict: i64 = CB_EXIT_CLEAN 346 if sum != n_hit { verdict = CB_EXIT_UNPROVEN } 347 if n_verifyfail > 0 { verdict = CB_EXIT_UNPROVEN } 348 if verdict == CB_EXIT_CLEAN { 349 if apply == 1 { 350 if n_unk > 0 { verdict = CB_EXIT_PRESENT } 351 } 352 if apply == 0 { if n_hit > 0 { verdict = CB_EXIT_PRESENT } } 353 } 354 if verdict == CB_EXIT_CLEAN { cb_puts("CTLBYTE verdict=CLEAN\n" as *u8) } 355 if verdict == CB_EXIT_PRESENT { cb_puts("CTLBYTE verdict=CORRUPTION-PRESENT -- every file and its class is named above\n" as *u8) } 356 if verdict == CB_EXIT_UNPROVEN { cb_puts("CTLBYTE verdict=UNPROVEN\n" as *u8) } 357 sys_exit(verdict) 358 return verdict 359}