code wiki / (root) / nx_diag_voice_gate.nx

nx_diag_voice_gate.nx source

↩ module page · 272 lines · 15899 B

1// nx_diag_voice_gate.nx -- LN27 (lang.plan, 2026-09-02): EVERY DIAGNOSTIC TEACHES IN ONE VOICE. 2// The operator named the first LN24 messages as output that does not help a programmer grow: a 3// location and a fact, no why, no fix. The parser's teaching sites already carry the shape (nx_diag_at, 4// nx_diag_caret, then "why the build stopped:" and "fix:"); this gate walks EVERY diagnostic emission 5// site in the toolchain sources and refuses a BARE site -- a location or a refusal printed without a 6// why line and a fix line within its window -- as a RATCHET: the bare count per file may never RISE 7// above knowledge/status/diag_voice_ratchet.conf, it self-tightens on every fall, and it never rewrites 8// its baseline on a rise (a ratchet that launders itself green is a threshold wearing a ratchet's name). 9// It prints the worklist (BARE file:line) so the count is actionable, never a bare number. 10// 11// SITE RULE (mechanical, declared, bite-proven below): a source line is an emission site when it is 12// not a comment line and, before any `//`, contains one of 13// nx_diag_at( nx_diag_organ_at( "error: nxcx_log("nx_compile_x86: "nxasm: FATAL "error at function 14// and is not a `func ` definition line. It is VOICED when, within the next DV_WINDOW lines and before 15// the next site, one line carries a why ("why the build stopped" or a call to nx_diag_why_) and one 16// carries a fix ("fix:" or a did-you-mean nx_dym_note). Everything else is BARE. 17// The classifier is a pure function over a buffer so the fixtures below are assembled at RUNTIME -- 18// a detector that scans source would otherwise find its own test fixture in this very file. 19// 20// nx_diag_voice_gate -- census + ratchet + controls, verdict in the exit code (gv_verdict) 21// license_tier: ORIGINAL layer: lang module: nishi-core.lang.diag_voice_gate 22import "nx_syscalls.nx" 23import "nx_gate_verdict.nx" 24 25const DV_WINDOW: i64 = 60 // lines after a site in which why and fix must appear (the exhaustiveness site lists every missing variant first: 48 lines) 26const DV_LINECAP: i64 = 4096 // longest source line examined (longer lines are cut, never skipped) 27const DV_NFILES: i64 = 8 28const DV_PATHCAP: i64 = 256 29const DV_CONFCAP: i64 = 4096 30const DV_RATCHET: *u8 = "knowledge/status/diag_voice_ratchet.conf\x00" as *u8 31 32func dv_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 33func dv_w(s: *u8) -> i64 { sys_write(1, s, dv_slen(s)); return 0 } 34func dv_n(v: i64) -> i64 { 35 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 36 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 37 let t: *u8 = sys_mmap(24); var k: i64 = 0 38 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 39 let o: *u8 = sys_mmap(24); var w: i64 = 0; var q: i64 = k - 1 40 while q >= 0 { o[w] = t[q]; w = w + 1; q = q - 1 } 41 sys_write(1, o, w); return 0 42} 43func dv_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64 = off; var i: i64 = 0; while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } dst[o] = 0 as u8; return o } 44 45// first index of pat in line[0..n), or -1. 46func dv_find(line: *u8, n: i64, pat: *u8) -> i64 { 47 let pl: i64 = dv_slen(pat) 48 if pl <= 0 { return 0 - 1 } 49 var i: i64 = 0 50 while i + pl <= n { 51 var j: i64 = 0; var ok: i64 = 1 52 while j < pl { if line[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } } 53 if ok == 1 { return i } 54 i = i + 1 55 } 56 return 0 - 1 57} 58// index of the first non-space byte. 59func dv_lead(line: *u8, n: i64) -> i64 { 60 var i: i64 = 0 61 while i < n { if line[i] == (32 as u8) { i = i + 1 } else { if line[i] == (9 as u8) { i = i + 1 } else { return i } } } 62 return n 63} 64// a pattern counts only when it sits BEFORE any line comment. 65func dv_has_code(line: *u8, n: i64, pat: *u8) -> i64 { 66 let p: i64 = dv_find(line, n, pat) 67 if p < 0 { return 0 } 68 let c: i64 = dv_find(line, n, "//" as *u8) 69 if c >= 0 { if c < p { return 0 } } 70 return 1 71} 72func dv_is_site(line: *u8, n: i64) -> i64 { 73 let l: i64 = dv_lead(line, n) 74 if l + 1 < n { if line[l] == (47 as u8) { if line[l + 1] == (47 as u8) { return 0 } } } // comment line 75 if dv_find(line, n, "func " as *u8) == l { return 0 } // a definition, not a site 76 if dv_has_code(line, n, "nx_diag_at(" as *u8) == 1 { return 1 } 77 if dv_has_code(line, n, "nx_diag_organ_at(" as *u8) == 1 { return 1 } 78 if dv_has_code(line, n, "\"error: " as *u8) == 1 { return 1 } 79 if dv_has_code(line, n, "nxcx_log(\"nx_compile_x86: " as *u8) == 1 { return 1 } 80 if dv_has_code(line, n, "\"nxasm: FATAL" as *u8) == 1 { return 1 } 81 if dv_has_code(line, n, "\"error at function" as *u8) == 1 { return 1 } 82 return 0 83} 84func dv_is_why(line: *u8, n: i64) -> i64 { 85 if dv_find(line, n, "why the build stopped" as *u8) >= 0 { return 1 } 86 if dv_find(line, n, "why this matters" as *u8) >= 0 { return 1 } // the non-fatal form: a warning still teaches 87 if dv_has_code(line, n, "nx_diag_why_" as *u8) == 1 { return 1 } 88 return 0 89} 90func dv_is_fix(line: *u8, n: i64) -> i64 { 91 if dv_find(line, n, "fix:" as *u8) >= 0 { return 1 } 92 if dv_has_code(line, n, "nx_dym_note" as *u8) == 1 { return 1 } 93 return 0 94} 95 96// THE CENSUS over one buffer. out[0]=sites out[1]=bare out[2]=voiced. list=1 prints BARE <fname>:<line>. 97// Lines are indexed into ls[] once, then every site looks ahead through the window. 98func dv_census(buf: *u8, n: i64, fname: *u8, out: *i64, list: i64) -> i64 { 99 var nl: i64 = 1; var i: i64 = 0 100 while i < n { if buf[i] == (10 as u8) { nl = nl + 1 } i = i + 1 } 101 let ls: *i64 = sys_mmap((nl + 2) * 8) as *i64 102 let ll: *i64 = sys_mmap((nl + 2) * 8) as *i64 103 var cnt: i64 = 0; var st: i64 = 0; i = 0 104 while i <= n { 105 var eol: i64 = 0 106 if i == n { eol = 1 } else { if buf[i] == (10 as u8) { eol = 1 } } 107 if eol == 1 { ls[cnt] = st; var w: i64 = i - st; if w > DV_LINECAP { w = DV_LINECAP } ll[cnt] = w; cnt = cnt + 1; st = i + 1 } 108 i = i + 1 109 } 110 let issite: *i64 = sys_mmap((cnt + 2) * 8) as *i64 111 var k: i64 = 0 112 while k < cnt { issite[k] = dv_is_site((buf as i64 + ls[k]) as *u8, ll[k]); k = k + 1 } 113 var sites: i64 = 0; var bare: i64 = 0; var voiced: i64 = 0 114 k = 0 115 while k < cnt { 116 if issite[k] == 1 { 117 sites = sites + 1 118 var why: i64 = 0; var fix: i64 = 0 119 var j: i64 = k + 1; var go: i64 = 1 120 while go == 1 { 121 if j >= cnt { go = 0 } else { 122 if j - k > DV_WINDOW { go = 0 } else { 123 if issite[j] == 1 { go = 0 } else { 124 let lp: *u8 = (buf as i64 + ls[j]) as *u8 125 if dv_is_why(lp, ll[j]) == 1 { why = 1 } 126 if dv_is_fix(lp, ll[j]) == 1 { fix = 1 } 127 j = j + 1 128 } 129 } 130 } 131 } 132 if (why == 1) & (fix == 1) { voiced = voiced + 1 } else { 133 bare = bare + 1 134 if list == 1 { dv_w(" BARE " as *u8); dv_w(fname); dv_w(":" as *u8); dv_n(k + 1); if why == 0 { dv_w(" no-why" as *u8) } if fix == 0 { dv_w(" no-fix" as *u8) } dv_w("\n" as *u8) } 135 } 136 } 137 k = k + 1 138 } 139 out[0] = sites; out[1] = bare; out[2] = voiced 140 return sites 141} 142 143// read <root>/<fname> with a two-root probe: buildroot/runtime/ (NAS gate CWD) then runtime/ (laptop CWD). 144func dv_read_src(fname: *u8, lenp: *i64) -> *u8 { 145 let p: *u8 = sys_mmap(DV_PATHCAP) 146 var o: i64 = dv_cat(p, 0, "buildroot/runtime/" as *u8); o = dv_cat(p, o, fname) 147 lenp[0] = 0 148 var b: *u8 = sys_read_file(p, lenp) 149 if lenp[0] > 0 { return b } 150 o = dv_cat(p, 0, "runtime/" as *u8); o = dv_cat(p, o, fname) 151 lenp[0] = 0 152 b = sys_read_file(p, lenp) 153 return b 154} 155// baseline row "<fname>=<n>" -> n, or -1 when absent. 156func dv_baseline(conf: *u8, cn: i64, fname: *u8) -> i64 { 157 if cn <= 0 { return 0 - 1 } 158 let key: *u8 = sys_mmap(DV_PATHCAP) 159 var o: i64 = dv_cat(key, 0, fname); o = dv_cat(key, o, "=" as *u8) 160 let p: i64 = dv_find(conf, cn, key) 161 if p < 0 { return 0 - 1 } 162 var i: i64 = p + o; var v: i64 = 0; var any: i64 = 0 163 while i < cn { let c: i64 = conf[i] as i64; if (c >= 48) & (c <= 57) { v = v * 10 + (c - 48); any = 1; i = i + 1 } else { i = cn } } 164 if any == 0 { return 0 - 1 } 165 return v 166} 167func dv_write_conf(names: *i64, bares: *i64, nf: i64) -> i64 { 168 let b: *u8 = sys_mmap(DV_CONFCAP) 169 var o: i64 = dv_cat(b, 0, "# diag_voice_ratchet.conf -- BARE diagnostic sites per toolchain source (LN27). Written by nx_diag_voice_gate on every FALL; a RISE is RED and never rewrites this file.\n" as *u8) 170 var i: i64 = 0 171 while i < nf { 172 o = dv_cat(b, o, names[i] as *u8); o = dv_cat(b, o, "=" as *u8) 173 let t: *u8 = sys_mmap(24); var m: i64 = bares[i]; var k: i64 = 0 174 if m == 0 { t[0] = 48 as u8; k = 1 } 175 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 176 var q: i64 = k - 1 177 while q >= 0 { b[o] = t[q]; o = o + 1; q = q - 1 } 178 b[o] = 10 as u8; o = o + 1; b[o] = 0 as u8 179 i = i + 1 180 } 181 let fd: i64 = sys_openat_wr(DV_RATCHET, 420) 182 if fd < 0 { return 0 - 1 } 183 sys_write(fd, b, o); sys_close(fd) 184 return o 185} 186 187// THE SYMBOL THE lang.matrix WATCH MEASURES (diag_voice_gate): the whole census + ratchet as one call. 188// Returns the total BARE count over the toolchain, or -1 when a source could not be read. 189func diag_voice_gate(c: *i64) -> i64 { 190 let names: *i64 = sys_mmap(DV_NFILES * 8) as *i64 191 names[0] = "nx_tokenizer.nx" as *u8 as i64; names[1] = "nx_parse.nx" as *u8 as i64 192 names[2] = "nx_ir.nx" as *u8 as i64; names[3] = "nx_compile_x86.nx" as *u8 as i64 193 names[4] = "nxasm_x86_main.nx" as *u8 as i64; names[5] = "nx_x86_64_ctx.nx" as *u8 as i64 194 names[6] = "nx_opt.nx" as *u8 as i64; names[7] = "nx_x86_regalloc.nx" as *u8 as i64 195 let bares: *i64 = sys_mmap(DV_NFILES * 8) as *i64 196 let lenp: *i64 = sys_mmap(16) as *i64 197 let out: *i64 = sys_mmap(32) as *i64 198 let cl: *i64 = sys_mmap(16) as *i64 199 cl[0] = 0 200 let conf: *u8 = sys_read_file(DV_RATCHET, cl) 201 var readok: i64 = 0; var sites: i64 = 0; var bare: i64 = 0; var voiced: i64 = 0 202 var rises: i64 = 0; var falls: i64 = 0; var firsts: i64 = 0 203 var i: i64 = 0 204 while i < DV_NFILES { 205 let fname: *u8 = names[i] as *u8 206 let b: *u8 = dv_read_src(fname, lenp) 207 if lenp[0] > 0 { 208 readok = readok + 1 209 dv_census(b, lenp[0], fname, out, 1) 210 sites = sites + out[0]; bare = bare + out[1]; voiced = voiced + out[2] 211 bares[i] = out[1] 212 let base: i64 = dv_baseline(conf, cl[0], fname) 213 dv_w(" FILE " as *u8); dv_w(fname); dv_w(" sites=" as *u8); dv_n(out[0]); dv_w(" voiced=" as *u8); dv_n(out[2]); dv_w(" bare=" as *u8); dv_n(out[1]); dv_w(" baseline=" as *u8); dv_n(base) 214 if base < 0 { firsts = firsts + 1; dv_w(" FIRST-SIGHT" as *u8) } else { 215 if out[1] > base { rises = rises + 1; dv_w(" RISE" as *u8) } 216 if out[1] < base { falls = falls + 1; dv_w(" FALL" as *u8) } 217 } 218 dv_w("\n" as *u8) 219 } else { bares[i] = 0 - 1; dv_w(" FILE " as *u8); dv_w(fname); dv_w(" UNREADABLE\n" as *u8) } 220 i = i + 1 221 } 222 dv_w("DIAG-VOICE files=" as *u8); dv_n(readok); dv_w("/" as *u8); dv_n(DV_NFILES); dv_w(" sites=" as *u8); dv_n(sites); dv_w(" voiced=" as *u8); dv_n(voiced); dv_w(" bare=" as *u8); dv_n(bare) 223 dv_w(" rises=" as *u8); dv_n(rises); dv_w(" falls=" as *u8); dv_n(falls); dv_w(" first_sight=" as *u8); dv_n(firsts); dv_w(" (voiced+bare=sites per file; a BARE row above names the site)\n" as *u8) 224 gv_check("toolchain-sources-all-readable" as *u8, readok == DV_NFILES, c) 225 gv_check("emission-sites-found-not-vacuous" as *u8, sites > 0, c) 226 gv_check("positive-control-existing-teaching-sites-are-voiced" as *u8, voiced > 0, c) 227 gv_check("partition-voiced-plus-bare-equals-sites" as *u8, voiced + bare == sites, c) 228 gv_check("ratchet-no-file-rises-above-its-baseline" as *u8, rises == 0, c) 229 // TIGHTEN on a fall or a first sight; NEVER on a rise (a rise stays RED against the old baseline). 230 var wrote: i64 = 0 231 if rises == 0 { if (falls > 0) | (firsts > 0) { wrote = dv_write_conf(names, bares, DV_NFILES) } } 232 if wrote > 0 { 233 let cl2: *i64 = sys_mmap(16) as *i64; cl2[0] = 0 234 let conf2: *u8 = sys_read_file(DV_RATCHET, cl2) 235 var agree: i64 = 1; i = 0 236 while i < DV_NFILES { if dv_baseline(conf2, cl2[0], names[i] as *u8) != bares[i] { agree = 0 } i = i + 1 } 237 gv_check("ratchet-tightened-and-reread-matches-by-content" as *u8, agree == 1, c) 238 dv_w(" RATCHET written " as *u8); dv_w(DV_RATCHET); dv_w(" bytes=" as *u8); dv_n(wrote); dv_w("\n" as *u8) 239 } 240 if readok < DV_NFILES { return 0 - 1 } 241 return bare 242} 243 244func main() -> i64 { 245 let c: *i64 = gv_ctr() 246 // ---- NEGATIVE / POSITIVE CONTROLS on runtime-assembled fixtures (never files the census scans) ---- 247 let out: *i64 = sys_mmap(32) as *i64 248 let fx: *u8 = sys_mmap(4096) 249 var o: i64 = dv_cat(fx, 0, "func f(P: *Parser) -> i64 {\n nx_diag_at(t.line)\n nx_diag_puts(\": this name is used before it is declared\\n\" as *u8)\n return 1\n}\n" as *u8) 250 dv_census(fx, o, "fx_bare" as *u8, out, 0) 251 gv_check("neg-control-planted-bare-site-reads-BARE" as *u8, (out[0] == 1) & (out[1] == 1), c) 252 o = dv_cat(fx, 0, "func f(P: *Parser) -> i64 {\n nx_diag_at(t.line)\n nx_diag_puts(\": this name is used before it is declared\\n\" as *u8)\n nx_diag_puts(\" why the build stopped: a use before a declaration has nothing to bind to\\n\" as *u8)\n nx_diag_puts(\" fix: move the declaration above this line\\n\" as *u8)\n return 1\n}\n" as *u8) 253 dv_census(fx, o, "fx_voiced" as *u8, out, 0) 254 gv_check("control-voiced-site-reads-VOICED" as *u8, (out[0] == 1) & (out[2] == 1) & (out[1] == 0), c) 255 o = dv_cat(fx, 0, "func f() -> i64 {\n // the parser calls nx_diag_at( here in prose only\n let x: i64 = 1 // nx_diag_organ_at( in a trailing comment\n return x\n}\n" as *u8) 256 dv_census(fx, o, "fx_comment" as *u8, out, 0) 257 gv_check("control-comment-mentions-are-not-sites" as *u8, out[0] == 0, c) 258 o = dv_cat(fx, 0, "func nx_diag_at(line: i64) -> i64 {\n nx_diag_puts(\"error at \" as *u8)\n return nx_diag_loc(line)\n}\n" as *u8) 259 dv_census(fx, o, "fx_def" as *u8, out, 0) 260 gv_check("control-the-voice-helper-definition-is-not-a-site" as *u8, out[0] == 0, c) 261 o = dv_cat(fx, 0, "func g() -> i64 {\n nx_diag_at(t.line)\n nx_diag_puts(\": x\\n\" as *u8)\n nx_diag_why_undefined()\n nx_dym_note2(P, nm, nl)\n return 1\n}\n" as *u8) 262 dv_census(fx, o, "fx_helpers" as *u8, out, 0) 263 gv_check("control-why-and-fix-helpers-count-as-voice" as *u8, (out[0] == 1) & (out[2] == 1), c) 264 o = dv_cat(fx, 0, "func h() -> i64 {\n nx_diag_at(t.line)\n nx_diag_puts(\" why the build stopped: only why, no fix\\n\" as *u8)\n nx_diag_at(u.line)\n nx_diag_puts(\" fix: the fix belongs to the SECOND site, not the first\\n\" as *u8)\n return 1\n}\n" as *u8) 265 dv_census(fx, o, "fx_window" as *u8, out, 0) 266 gv_check("neg-control-a-fix-after-the-next-site-does-not-voice-the-first" as *u8, (out[0] == 2) & (out[1] == 2), c) 267 268 // ---- THE CENSUS over the toolchain sources ---- 269 let bare: i64 = diag_voice_gate(c) 270 gv_check("census-ran-over-the-toolchain" as *u8, bare >= 0, c) 271 return gv_verdict("DIAG-VOICE-GATE" as *u8, c, "LN27: every diagnostic emission site in the toolchain carries where, why and fix -- bare sites ratchet down, never up" as *u8) 272}