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}