code wiki / _hdl_build / nx_schema_backfill.nx

nx_schema_backfill.nx source

↩ module page · 322 lines · 16274 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_toolsafety_lib.nx" 12import "nx_syscalls.nx" 13 14// sized: allowlist read matches md_allow_has_name's 256KiB envelope; refuse-on-full keeps the census honest 15const SB_ALCAP: i64 = 1 << 18 16// sized: only the FIRST source line is read; header docs are one-liners 17const SB_HDRCAP: i64 = 4096 18// sized: schema titles are one-line prose; hard cap keeps rows lean 19const SB_TITLECAP: i64 = 300 20// derived: shortest honest capability description in curated rows is ~20 bytes; below = not a title, skip 21const SB_MINDESC: i64 = 20 22// sized: tool names are sanitized [a-zA-Z0-9_] <= 120 by the register API 23const SB_NAMECAP: i64 = 128 24// sized: elf paths in the allowlist are absolute NAS paths well under this 25const SB_PATHCAP: i64 = 512 26 27func sbw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 28 29func sb_ends(s: *u8, sl: i64, suf: *u8, fl: i64) -> i64 { 30 if sl < fl { return 0 } 31 var i: i64 = 0 32 while i < fl { if s[sl-fl+i] != suf[i] { return 0 } i = i + 1 } 33 return 1 34} 35 36// ---- SAFETY FLAGS: DERIVED, NOT ASSERTED (2026-08-06) ---------------------------------------- 37// MEASURED BEFORE CHANGING ANYTHING: of the 389 rows this organ has auto-derived into 38// tool_schemas.conf, **389 carry the identical quad `0 1 0 1`** -- zero exceptions. Against ~852 39// total rows that is ~46% of the registry's safety metadata being ONE HARDCODED CONSTANT that was 40// never looked up. nx_prim_query serves it downstream as `safety:{read_only,destructive, 41// idempotent,open_world}`, so a consumer cannot tell a measured 0 from a constant 0. 42// ★★A CONSTANT WEARING THE SHAPE OF A MEASUREMENT IS WORSE THAN A BLANK: a blank invites a 43// lookup, a fabricated value ends the enquiry. This organ's own header says "blank beats bad" and 44// it honours that for the DESCRIPTION -- then guessed the most security-relevant field. 45// (In fairness the old constant erred CONSERVATIVE -- claiming destructive+open_world over-warns 46// rather than under-warns -- so this was an INFORMATION defect, not an unsafe one.) 47// 48// WHAT IS AND IS NOT DERIVABLE. read_only / destructive / open_world fall out of a static scan of 49// the organ's own source for the syscalls it actually reaches for. `idempotent` does NOT -- nothing 50// in the source declares it -- so it stays 0, the conservative direction (a caller will not blindly 51// re-run something marked non-idempotent). ★DERIVE WHAT IS DERIVABLE, DECLARE THE REST UNDECLARED, 52// AND SAY WHICH IS WHICH IN THE ROW ITSELF. 53// SB_SRCCAP and the private sb_has substring scanner were DELETED 2026-08-25, not merely bypassed: 54// a dead copy of a ruler beside the shared one is the duplicate-ruler defect waiting to be re-called. 55 56func sb_wflag(fd: i64, v: i64) -> i64 { 57 if v == 1 { ma_write_str(fd, "1" as *u8) } else { ma_write_str(fd, "0" as *u8) } 58 return 0 59} 60 61// box[0]=read_only box[1]=destructive box[2]=idempotent box[3]=open_world box[4]=derived(1/0) 62func sb_derive_flags(path: *u8, box: *i64) -> i64 { 63 box[0] = 0 64 box[1] = 1 65 box[2] = 0 66 box[3] = 1 67 box[4] = 0 68 // COMPOSED, NOT RE-IMPLEMENTED (2026-08-25). The single-file scan that used to live here is gone. 69 // It was not wrong about what it looked at -- it was looking at the wrong SUBJECT. An organ that 70 // writes through an imported helper reaches the write syscall in the LIB, so scanning only the 71 // organ's own source published readOnly=1 for a writer: wrong in the UNSAFE direction, and stamped 72 // with a provenance note confident enough that nx_tools_api's overlay deliberately left it alone. 73 // MEASURED by nx_schemadrift over the whole population this organ had already written. 74 // A MEASUREMENT OF THE WRONG SUBJECT IS STILL A MEASUREMENT, AND THAT IS EXACTLY WHY NOTHING 75 // DOWNSTREAM COULD TELL IT FROM A GOOD ONE. 76 // ts_quad is the ONE ruler now (nx_toolsafety_lib), shared with nx_toolflags and the drift control, 77 // so the three cannot disagree: there is only one of it. It also removes the 256 KiB source cap -- 78 // the old scan returned NOT-DERIVED for any source past it -- because sys_read_file sizes from the 79 // file and cannot short-read. 80 let quad: *i64 = sys_mmap(64) as *i64 81 let deep: *i64 = sys_mmap(64) as *i64 82 let own: *i64 = sys_mmap(64) as *i64 83 // ABSTAIN, DO NOT ASSERT. An inconclusive walk (unreadable subject, unreadable marker table, or a 84 // budget hit) leaves the CAUTIOUS DEFAULT set above and box[4]=0, which makes sb_append stamp the 85 // row NOT DERIVABLE. A DERIVER THAT FAILS TOWARD PERMISSIVE IS WORSE THAN ONE THAT DECLINES. 86 if ts_quad(path, quad, deep, own) == 0 { return 0 } 87 box[0] = quad[0] 88 box[1] = quad[1] 89 box[2] = quad[2] 90 box[3] = quad[3] 91 box[4] = 1 92 return 1 93} 94 95// append one schema row -- SAME invariants as the API path (trailing-nl self-heal; caller scrubbed title) 96func sb_append(nm: *u8, ti: *u8, box: *i64) -> i64 { 97 let sf: i64 = sys_openat_append("knowledge/tool_schemas.conf" as *u8, 420) 98 if sf < 0 { return 0 } 99 ma_ensure_trailing_nl("knowledge/tool_schemas.conf" as *u8, sf) 100 ma_write_str(sf, nm) 101 ma_write_str(sf, "\t" as *u8) 102 ma_write_str(sf, ti) 103 ma_write_str(sf, "\t" as *u8) 104 sb_wflag(sf, box[0]) 105 ma_write_str(sf, "\t" as *u8) 106 sb_wflag(sf, box[1]) 107 ma_write_str(sf, "\t" as *u8) 108 sb_wflag(sf, box[2]) 109 ma_write_str(sf, "\t" as *u8) 110 sb_wflag(sf, box[3]) 111 ma_write_str(sf, "\t" as *u8) 112 ma_write_str(sf, nm) 113 if box[4] == 1 { 114 ma_write_str(sf, " output (auto-derived by nx_schema_backfill; safety flags DERIVED FROM THE TRANSITIVE IMPORT CLOSURE by nx_toolsafety_lib -- a write reached through an imported helper counts, idempotent UNDECLARED)\n" as *u8) 115 } else { 116 ma_write_str(sf, " output (auto-derived by nx_schema_backfill; safety flags NOT DERIVABLE -- conservative default, treat as UNKNOWN)\n" as *u8) 117 } 118 sys_close(sf) 119 return 1 120} 121 122// read the FIRST line of path; copy the text after the first `-- ` into ti (scrubbed, trimmed, capped). 123// returns title length; 0 = header convention absent or desc too short; -1 = file unreadable. 124func sb_title_from_header(path: *u8, ti: *u8) -> i64 { 125 let fd: i64 = sys_openat_rd(path) 126 if fd < 0 { return 0 - 1 } 127 let hb: *u8 = sys_mmap(SB_HDRCAP) 128 let hn: i64 = sys_read(fd, hb, SB_HDRCAP - 1) 129 sys_close(fd) 130 if hn <= 2 { return 0 } 131 // The header is NOT always line 1: many organs open with their `import` lines and put the 132 // `// <stem>.nx -- <desc>` block AFTER them (measured: nx_gamebench_gate, nx_media_extract_gate 133 // were reported as UNDOCUMENTED purely because this parser only looked at line 1 -- the organs were 134 // documented all along). Scan the header window for the FIRST `//` line carrying `-- `; that is the 135 // convention's actual shape. Declared limitation: a `//` line containing `-- ` above the real header 136 // would win, so the rule is first-match and the emitted title is always verbatim source text. 137 var ls: i64 = 0 138 var ds: i64 = 0 139 var le: i64 = 0 140 var scan: i64 = 1 141 while scan == 1 { 142 if ls >= hn { scan = 0 } else { 143 le = ls 144 var sc: i64 = 1 145 while sc == 1 { if le >= hn { sc = 0 } else { if hb[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 146 var iscmt: i64 = 0 147 if le - ls >= 8 { if hb[ls] == (47 as u8) { if hb[ls+1] == (47 as u8) { iscmt = 1 } } } 148 if iscmt == 1 { 149 var p: i64 = ls + 2 150 var s2: i64 = 1 151 while s2 == 1 { 152 if p + 3 > le { s2 = 0 } else { 153 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 } } } 154 if ds == 0 { p = p + 1 } 155 } 156 } 157 } 158 if ds > 0 { scan = 0 } else { ls = le + 1 } 159 } 160 } 161 if ds == 0 { return 0 } 162 var o: i64 = 0 163 var q: i64 = ds 164 while q < le { 165 var c: i64 = hb[q] as i64 166 if c < 32 { c = 32 } 167 if c == 9 { c = 32 } 168 if o < SB_TITLECAP - 1 { ti[o] = c as u8; o = o + 1 } 169 q = q + 1 170 } 171 var tc: i64 = 1 172 while tc == 1 { if o > 0 { if ti[o-1] == (32 as u8) { o = o - 1 } else { tc = 0 } } else { tc = 0 } } 173 ti[o] = 0 as u8 174 if o < SB_MINDESC { return 0 } 175 return o 176} 177 178func main() -> i64 { 179 let al: *u8 = sys_mmap(SB_ALCAP) 180 let fd: i64 = sys_openat_rd("tool_allowlist.conf" as *u8) 181 if fd < 0 { sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"tool_allowlist.conf unreadable\"}\n" as *u8); sys_exit(2); return 2 } 182 let n: i64 = sys_read(fd, al, SB_ALCAP - 1) 183 sys_close(fd) 184 if n <= 0 { sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"tool_allowlist.conf empty\"}\n" as *u8); sys_exit(2); return 2 } 185 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 } 186 al[n] = 0 as u8 187 var scanned: i64 = 0 188 var had: i64 = 0 189 var filled: i64 = 0 190 var nosrc: i64 = 0 191 var nohdr: i64 = 0 192 var derived: i64 = 0 193 let nm: *u8 = sys_mmap(SB_NAMECAP) 194 let elf: *u8 = sys_mmap(SB_PATHCAP) 195 let ti: *u8 = sys_mmap(SB_TITLECAP) 196 let pth: *u8 = sys_mmap(SB_PATHCAP) 197 let fbox: *i64 = sys_mmap(64) as *i64 198 var i: i64 = 0 199 while i < n { 200 var le: i64 = i 201 var sc: i64 = 1 202 while sc == 1 { if le >= n { sc = 0 } else { if al[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 203 var ok: i64 = 1 204 if le <= i { ok = 0 } 205 if ok == 1 { if al[i] == (35 as u8) { ok = 0 } } 206 if ok == 1 { 207 var nmn: i64 = 0 208 var p: i64 = i 209 var s2: i64 = 1 210 while s2 == 1 { 211 if p >= le { s2 = 0; ok = 0 } else { 212 if al[p] == (9 as u8) { s2 = 0 } else { 213 if nmn < SB_NAMECAP - 1 { nm[nmn] = al[p]; nmn = nmn + 1 } 214 p = p + 1 215 } 216 } 217 } 218 nm[nmn] = 0 as u8 219 var en: i64 = 0 220 if ok == 1 { 221 p = p + 1 222 var s3: i64 = 1 223 while s3 == 1 { 224 if p >= le { s3 = 0 } else { 225 if al[p] == (9 as u8) { s3 = 0 } else { 226 if en < SB_PATHCAP - 1 { elf[en] = al[p]; en = en + 1 } 227 p = p + 1 228 } 229 } 230 } 231 } 232 elf[en] = 0 as u8 233 if nmn == 0 { ok = 0 } 234 if en == 0 { ok = 0 } 235 if ok == 1 { 236 scanned = scanned + 1 237 let hs: i64 = ma_schema_has_name(nm) 238 if hs == 1 { had = had + 1 } 239 if hs < 0 { 240 sbw("{\"organ\":\"nx_schema_backfill\",\"refused\":\"tool_schemas.conf unreadable or possibly truncated -- refusing to append blind\"}\n" as *u8) 241 sys_exit(3) 242 return 3 243 } 244 if hs == 0 { 245 var bs: i64 = 0 246 var k: i64 = 0 247 while elf[k] != (0 as u8) { if elf[k] == (47 as u8) { bs = k + 1 } k = k + 1 } 248 var stl: i64 = k - bs 249 let base: *u8 = ((elf as i64) + bs) as *u8 250 if sb_ends(base, stl, ".sov.elf.new" as *u8, 12) == 1 { stl = stl - 12 } else { 251 if sb_ends(base, stl, ".elf.new" as *u8, 8) == 1 { stl = stl - 8 } else { 252 if sb_ends(base, stl, ".sov.elf" as *u8, 8) == 1 { stl = stl - 8 } else { 253 if sb_ends(base, stl, ".elf" as *u8, 4) == 1 { stl = stl - 4 } else { 254 if sb_ends(base, stl, ".new" as *u8, 4) == 1 { stl = stl - 4 } 255 } 256 } 257 } 258 } 259 var r1: i64 = 0 - 1 260 var r2: i64 = 0 - 1 261 var tin: i64 = 0 262 if stl > 0 { 263 var o2: i64 = sd_cat(pth, 0, "buildroot/runtime/_hdl_build/" as *u8) 264 var c2: i64 = 0 265 while c2 < stl { pth[o2] = base[c2]; o2 = o2 + 1; c2 = c2 + 1 } 266 o2 = sd_cat(pth, o2, ".nx" as *u8) 267 pth[o2] = 0 as u8 268 r1 = sb_title_from_header(pth, ti) 269 if r1 > 0 { tin = r1 } else { 270 o2 = sd_cat(pth, 0, "buildroot/runtime/" as *u8) 271 c2 = 0 272 while c2 < stl { pth[o2] = base[c2]; o2 = o2 + 1; c2 = c2 + 1 } 273 o2 = sd_cat(pth, o2, ".nx" as *u8) 274 pth[o2] = 0 as u8 275 r2 = sb_title_from_header(pth, ti) 276 if r2 > 0 { tin = r2 } 277 } 278 } 279 if tin > 0 { 280 // pth still holds the source path that actually yielded the title, so the 281 // flags are derived from the SAME file the description came from. 282 sb_derive_flags(pth, fbox) 283 if sb_append(nm, ti, fbox) == 1 { 284 filled = filled + 1 285 if fbox[4] == 1 { derived = derived + 1 } 286 } 287 } else { 288 var nof: i64 = 1 289 if r1 >= 0 { nof = 0 } 290 if r2 >= 0 { nof = 0 } 291 // a COUNT is not a work item: name every skip on stderr so the residual is 292 // actionable (write the header, re-run, watch the number fall) instead of 293 // being an unfalsifiable "2 left" that nobody can pick up. 294 sys_write(2, "SKIP " as *u8, 5) 295 if nof == 1 { sys_write(2, "no-source " as *u8, 12) } else { sys_write(2, "no-header " as *u8, 12) } 296 sys_write(2, nm, nmn) 297 sys_write(2, "\n" as *u8, 1) 298 if nof == 1 { nosrc = nosrc + 1 } else { nohdr = nohdr + 1 } 299 } 300 } 301 } 302 } 303 i = le + 1 304 } 305 let out: *u8 = sys_mmap(SB_HDRCAP) 306 var o3: i64 = sd_cat(out, 0, "{\"organ\":\"nx_schema_backfill\",\"scanned\":" as *u8) 307 o3 = sd_catn(out, o3, scanned) 308 o3 = sd_cat(out, o3, ",\"had_schema\":" as *u8) 309 o3 = sd_catn(out, o3, had) 310 o3 = sd_cat(out, o3, ",\"flags_static_derived\":" as *u8) 311 o3 = sd_catn(out, o3, derived) 312 o3 = sd_cat(out, o3, ",\"filled\":" as *u8) 313 o3 = sd_catn(out, o3, filled) 314 o3 = sd_cat(out, o3, ",\"skipped_no_source\":" as *u8) 315 o3 = sd_catn(out, o3, nosrc) 316 o3 = sd_cat(out, o3, ",\"skipped_no_header\":" as *u8) 317 o3 = sd_catn(out, o3, nohdr) 318 o3 = sd_cat(out, o3, ",\"note\":\"idempotent; re-run after maker-beat header writes; run nx_toolreg_reconcile to publish\"}\n" as *u8) 319 out[o3] = 0 as u8 320 sbw(out) 321 return 0 322}