code wiki / _hdl_build / nx_schema_backfill.nx

nx_schema_backfill.nx source

↩ module page · 240 lines · 11403 B

1// nx_schema_backfill.nx -- CAPABILITY DISCOVERABILITY HARVESTER (seq1282). Every tool_allowlist.conf row 2// lacking a knowledge/tool_schemas.conf row gets one AUTO-DERIVED from its source's own first header line 3// (the tree-wide `// <stem>.nx -- <desc>` convention; the codewiki maker beat writes missing headers daily, 4// so RE-RUNNING harvests newly documented organs). The register API keeps NEW tools discoverable by 5// construction (seq722 fix) -- this organ only drains history. HONEST: no source / no `-- ` header / desc 6// too short => SKIPPED + COUNTED, never guessed (blank beats bad). Append-if-absent via the API's own 7// ma_schema_has_name tri-state (UNKNOWN refuses the WHOLE run -- a truncated read can never duplicate). 8// nx_schema_backfill (JSON report: scanned/had_schema/filled/skipped_no_source/skipped_no_header) 9// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 10import "nx_mgmt_api.nx" 11import "nx_syscalls.nx" 12 13// sized: allowlist read matches md_allow_has_name's 256KiB envelope; refuse-on-full keeps the census honest 14const SB_ALCAP: i64 = 1 << 18 15// sized: only the FIRST source line is read; header docs are one-liners 16const SB_HDRCAP: i64 = 4096 17// sized: schema titles are one-line prose; hard cap keeps rows lean 18const SB_TITLECAP: i64 = 300 19// derived: shortest honest capability description in curated rows is ~20 bytes; below = not a title, skip 20const SB_MINDESC: i64 = 20 21// sized: tool names are sanitized [a-zA-Z0-9_] <= 120 by the register API 22const SB_NAMECAP: i64 = 128 23// sized: elf paths in the allowlist are absolute NAS paths well under this 24const SB_PATHCAP: i64 = 512 25 26func sbw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 27 28func sb_ends(s: *u8, sl: i64, suf: *u8, fl: i64) -> i64 { 29 if sl < fl { return 0 } 30 var i: i64 = 0 31 while i < fl { if s[sl-fl+i] != suf[i] { return 0 } i = i + 1 } 32 return 1 33} 34 35// append one schema row -- SAME invariants as the API path (trailing-nl self-heal; caller scrubbed title) 36func sb_append(nm: *u8, ti: *u8) -> i64 { 37 let sf: i64 = sys_openat_append("knowledge/tool_schemas.conf" as *u8, 420) 38 if sf < 0 { return 0 } 39 ma_ensure_trailing_nl("knowledge/tool_schemas.conf" as *u8, sf) 40 ma_write_str(sf, nm) 41 ma_write_str(sf, "\t" as *u8) 42 ma_write_str(sf, ti) 43 ma_write_str(sf, "\t0\t1\t0\t1\t" as *u8) 44 ma_write_str(sf, nm) 45 ma_write_str(sf, " output (auto-derived from source header by nx_schema_backfill)\n" as *u8) 46 sys_close(sf) 47 return 1 48} 49 50// read the FIRST line of path; copy the text after the first `-- ` into ti (scrubbed, trimmed, capped). 51// returns title length; 0 = header convention absent or desc too short; -1 = file unreadable. 52func sb_title_from_header(path: *u8, ti: *u8) -> i64 { 53 let fd: i64 = sys_openat_rd(path) 54 if fd < 0 { return 0 - 1 } 55 let hb: *u8 = sys_mmap(SB_HDRCAP) 56 let hn: i64 = sys_read(fd, hb, SB_HDRCAP - 1) 57 sys_close(fd) 58 if hn <= 2 { return 0 } 59 // The header is NOT always line 1: many organs open with their `import` lines and put the 60 // `// <stem>.nx -- <desc>` block AFTER them (measured: nx_gamebench_gate, nx_media_extract_gate 61 // were reported as UNDOCUMENTED purely because this parser only looked at line 1 -- the organs were 62 // documented all along). Scan the header window for the FIRST `//` line carrying `-- `; that is the 63 // convention's actual shape. Declared limitation: a `//` line containing `-- ` above the real header 64 // would win, so the rule is first-match and the emitted title is always verbatim source text. 65 var ls: i64 = 0 66 var ds: i64 = 0 67 var le: i64 = 0 68 var scan: i64 = 1 69 while scan == 1 { 70 if ls >= hn { scan = 0 } else { 71 le = ls 72 var sc: i64 = 1 73 while sc == 1 { if le >= hn { sc = 0 } else { if hb[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 74 var iscmt: i64 = 0 75 if le - ls >= 8 { if hb[ls] == (47 as u8) { if hb[ls+1] == (47 as u8) { iscmt = 1 } } } 76 if iscmt == 1 { 77 var p: i64 = ls + 2 78 var s2: i64 = 1 79 while s2 == 1 { 80 if p + 3 > le { s2 = 0 } else { 81 if hb[p] == (45 as u8) { if hb[p+1] == (45 as u8) { if hb[p+2] == (32 as u8) { ds = p + 3; s2 = 0 } } } 82 if ds == 0 { p = p + 1 } 83 } 84 } 85 } 86 if ds > 0 { scan = 0 } else { ls = le + 1 } 87 } 88 } 89 if ds == 0 { return 0 } 90 var o: i64 = 0 91 var q: i64 = ds 92 while q < le { 93 var c: i64 = hb[q] as i64 94 if c < 32 { c = 32 } 95 if c == 9 { c = 32 } 96 if o < SB_TITLECAP - 1 { ti[o] = c as u8; o = o + 1 } 97 q = q + 1 98 } 99 var tc: i64 = 1 100 while tc == 1 { if o > 0 { if ti[o-1] == (32 as u8) { o = o - 1 } else { tc = 0 } } else { tc = 0 } } 101 ti[o] = 0 as u8 102 if o < SB_MINDESC { return 0 } 103 return o 104} 105 106func main() -> i64 { 107 let al: *u8 = sys_mmap(SB_ALCAP) 108 let fd: i64 = sys_openat_rd("tool_allowlist.conf" as *u8) 109 if fd < 0 { sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"tool_allowlist.conf unreadable\"}\n" as *u8); sys_exit(2); return 2 } 110 let n: i64 = sys_read(fd, al, SB_ALCAP - 1) 111 sys_close(fd) 112 if n <= 0 { sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"tool_allowlist.conf empty\"}\n" as *u8); sys_exit(2); return 2 } 113 if n >= SB_ALCAP - 1 { sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"allowlist read filled the buffer (possible truncation) -- refusing a partial census\"}\n" as *u8); sys_exit(2); return 2 } 114 al[n] = 0 as u8 115 var scanned: i64 = 0 116 var had: i64 = 0 117 var filled: i64 = 0 118 var nosrc: i64 = 0 119 var nohdr: i64 = 0 120 let nm: *u8 = sys_mmap(SB_NAMECAP) 121 let elf: *u8 = sys_mmap(SB_PATHCAP) 122 let ti: *u8 = sys_mmap(SB_TITLECAP) 123 let pth: *u8 = sys_mmap(SB_PATHCAP) 124 var i: i64 = 0 125 while i < n { 126 var le: i64 = i 127 var sc: i64 = 1 128 while sc == 1 { if le >= n { sc = 0 } else { if al[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 129 var ok: i64 = 1 130 if le <= i { ok = 0 } 131 if ok == 1 { if al[i] == (35 as u8) { ok = 0 } } 132 if ok == 1 { 133 var nmn: i64 = 0 134 var p: i64 = i 135 var s2: i64 = 1 136 while s2 == 1 { 137 if p >= le { s2 = 0; ok = 0 } else { 138 if al[p] == (9 as u8) { s2 = 0 } else { 139 if nmn < SB_NAMECAP - 1 { nm[nmn] = al[p]; nmn = nmn + 1 } 140 p = p + 1 141 } 142 } 143 } 144 nm[nmn] = 0 as u8 145 var en: i64 = 0 146 if ok == 1 { 147 p = p + 1 148 var s3: i64 = 1 149 while s3 == 1 { 150 if p >= le { s3 = 0 } else { 151 if al[p] == (9 as u8) { s3 = 0 } else { 152 if en < SB_PATHCAP - 1 { elf[en] = al[p]; en = en + 1 } 153 p = p + 1 154 } 155 } 156 } 157 } 158 elf[en] = 0 as u8 159 if nmn == 0 { ok = 0 } 160 if en == 0 { ok = 0 } 161 if ok == 1 { 162 scanned = scanned + 1 163 let hs: i64 = ma_schema_has_name(nm) 164 if hs == 1 { had = had + 1 } 165 if hs < 0 { 166 sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"tool_schemas.conf unreadable or possibly truncated -- refusing to append blind\"}\n" as *u8) 167 sys_exit(3) 168 return 3 169 } 170 if hs == 0 { 171 var bs: i64 = 0 172 var k: i64 = 0 173 while elf[k] != (0 as u8) { if elf[k] == (47 as u8) { bs = k + 1 } k = k + 1 } 174 var stl: i64 = k - bs 175 let base: *u8 = ((elf as i64) + bs) as *u8 176 if sb_ends(base, stl, ".sov.elf.new" as *u8, 12) == 1 { stl = stl - 12 } else { 177 if sb_ends(base, stl, ".elf.new" as *u8, 8) == 1 { stl = stl - 8 } else { 178 if sb_ends(base, stl, ".sov.elf" as *u8, 8) == 1 { stl = stl - 8 } else { 179 if sb_ends(base, stl, ".elf" as *u8, 4) == 1 { stl = stl - 4 } else { 180 if sb_ends(base, stl, ".new" as *u8, 4) == 1 { stl = stl - 4 } 181 } 182 } 183 } 184 } 185 var r1: i64 = 0 - 1 186 var r2: i64 = 0 - 1 187 var tin: i64 = 0 188 if stl > 0 { 189 var o2: i64 = sd_cat(pth, 0, "buildroot/runtime/_hdl_build/" as *u8) 190 var c2: i64 = 0 191 while c2 < stl { pth[o2] = base[c2]; o2 = o2 + 1; c2 = c2 + 1 } 192 o2 = sd_cat(pth, o2, ".nx" as *u8) 193 pth[o2] = 0 as u8 194 r1 = sb_title_from_header(pth, ti) 195 if r1 > 0 { tin = r1 } else { 196 o2 = sd_cat(pth, 0, "buildroot/runtime/" as *u8) 197 c2 = 0 198 while c2 < stl { pth[o2] = base[c2]; o2 = o2 + 1; c2 = c2 + 1 } 199 o2 = sd_cat(pth, o2, ".nx" as *u8) 200 pth[o2] = 0 as u8 201 r2 = sb_title_from_header(pth, ti) 202 if r2 > 0 { tin = r2 } 203 } 204 } 205 if tin > 0 { 206 if sb_append(nm, ti) == 1 { filled = filled + 1 } 207 } else { 208 var nof: i64 = 1 209 if r1 >= 0 { nof = 0 } 210 if r2 >= 0 { nof = 0 } 211 // a COUNT is not a work item: name every skip on stderr so the residual is 212 // actionable (write the header, re-run, watch the number fall) instead of 213 // being an unfalsifiable "2 left" that nobody can pick up. 214 sys_write(2, "SKIP " as *u8, 5) 215 if nof == 1 { sys_write(2, "no-source " as *u8, 12) } else { sys_write(2, "no-header " as *u8, 12) } 216 sys_write(2, nm, nmn) 217 sys_write(2, "\n" as *u8, 1) 218 if nof == 1 { nosrc = nosrc + 1 } else { nohdr = nohdr + 1 } 219 } 220 } 221 } 222 } 223 i = le + 1 224 } 225 let out: *u8 = sys_mmap(SB_HDRCAP) 226 var o3: i64 = sd_cat(out, 0, "{\"organ\":\"nx_schema_backfill\",\"scanned\":" as *u8) 227 o3 = sd_catn(out, o3, scanned) 228 o3 = sd_cat(out, o3, ",\"had_schema\":" as *u8) 229 o3 = sd_catn(out, o3, had) 230 o3 = sd_cat(out, o3, ",\"filled\":" as *u8) 231 o3 = sd_catn(out, o3, filled) 232 o3 = sd_cat(out, o3, ",\"skipped_no_source\":" as *u8) 233 o3 = sd_catn(out, o3, nosrc) 234 o3 = sd_cat(out, o3, ",\"skipped_no_header\":" as *u8) 235 o3 = sd_catn(out, o3, nohdr) 236 o3 = sd_cat(out, o3, ",\"note\":\"idempotent; re-run after maker-beat header writes; run nx_toolreg_reconcile to publish\"}\n" as *u8) 237 out[o3] = 0 as u8 238 sbw(out) 239 return 0 240}