code wiki / _hdl_build / nx_capgraph_edges_lib.nx

nx_capgraph_edges_lib.nx source

↩ module page · 591 lines · 19611 B

1// nx_capgraph_edges_lib.nx -- pure core for nx_capgraph_edges: ownership, resolution, closure walk. 2// 3// SPLIT OUT 2026-07-31 so the measuring organ can be GATED. By this ecosystem's own ladder (L5) a 4// capability with no non-vacuous gate is at most level 2 (WORKS), never 3 (GATED) -- and it would have 5// been dishonest for the organ that MEASURES capability levels to claim a level it had not earned. The 6// helpers below were unreachable from a gate while they sat beside a main(), so they moved here. 7// license_tier: ORIGINAL No hw writes (Rule 26). 8import "nx_capgraph_lib.nx" 9import "nx_tool_run.nx" 10 11const CE_CAP: i64 = 262144 12const CE_HEAD: i64 = 32768 13const CE_MAXDOM: i64 = 128 14const CE_MAXOWN: i64 = 2048 15const CE_MAXSRC: i64 = 2048 16const CE_MAXE: i64 = 1024 17const CE_NAMEW: i64 = 64 18const CE_PATHW: i64 = 160 19const CE_MAXQ: i64 = 512 20// NOT a code constant (rule 11). The transitive depth is read from CE_CFG at run time and its value is 21// JUSTIFIED BY A MEASURED CURVE (`--depthscan` prints edges-found per depth, so the cut is chosen where 22// the curve plateaus, not by taste). CE_DEPTH_FALLBACK applies only when the config row is absent, and 23// the emitted envelope says which of the two was used -- an unconfigured run must never look configured. 24const CE_DEPTH_FALLBACK: i64 = 3 25const CE_DEPTH_SCANMAX: i64 = 8 26const CE_CFG: *u8 = "knowledge/status/capgraph.conf" as *u8 27const CE_DEPTH_KEY_LEN: i64 = 17 28const CE_SHARED: i64 = 0 - 2 29const CE_SOTA: *u8 = "/volume1/homes/elderwesto/nishihost/nx_sota_status.elf" as *u8 30const CE_OUTDEF: *u8 = "knowledge/status/capgraph_edges.conf" as *u8 31 32static ce_dom: *u8 33static ce_ndom: i64 34static ce_ownname: *u8 35static ce_ownd: *i64 36static ce_nown: i64 37static ce_srcd: *i64 38static ce_srcp: *u8 39static ce_nsrc: i64 40static ce_ef: *i64 41static ce_et: *i64 42static ce_ne: i64 43static ce_if: *i64 44static ce_it: *i64 45static ce_nie: i64 46static ce_buf: *u8 47static ce_scr: *u8 48static ce_scr2: *u8 49static ce_path: *u8 50static ce_fd: i64 51static ce_missing: i64 52static ce_ambig: i64 53static ce_scanned: i64 54static ce_nonnx: i64 55static ce_altres: i64 56static ce_res_bld: i64 57static ce_res_srv: i64 58static ce_res_base: i64 59static ce_trans: i64 60static ce_q: *u8 61static ce_qd: *i64 62static ce_qh: i64 63static ce_qt: i64 64static ce_seen: *u8 65static ce_nseen: i64 66static ce_imp: *u8 67static ce_transedges: i64 68static ce_maxdepth: i64 69static ce_depthsrc: i64 70static ce_depthscan: i64 71static ce_enc: *u8 72static ce_encown: *i64 73static ce_enccnt: *i64 74static ce_encdom: *i64 75static ce_nenc: i64 76 77func ce_init() { 78 ce_ndom = 0 79 ce_nown = 0 80 ce_nsrc = 0 81 ce_ne = 0 82 ce_missing = 0 83 ce_ambig = 0 84 ce_scanned = 0 85 ce_nonnx = 0 86 ce_altres = 0 87 ce_res_bld = 0 88 ce_res_srv = 0 89 ce_res_base = 0 90 // TRANSITIVE IS THE DEFAULT. A domain can depend on another THROUGH shared infrastructure, and that 91 // build dependency is exactly as real as a direct import -- measured: it finds 7 more domain edges 92 // (13 -> 20) via 69 infra-mediated attributions, still sparse (20 of 756 possible) and deterministic. 93 // Defaulting to it is also the CONSERVATIVE choice: L4 edges only ever LOWER an effective level, so 94 // a found edge can never flatter, while a MISSING edge lets a dependent read healthier than the 95 // layer it stands on. `--direct` restores the strict one-hop subset. 96 ce_trans = 1 97 ce_transedges = 0 98 ce_qh = 0 99 ce_qt = 0 100 ce_nseen = 0 101 ce_q = sys_mmap(CE_MAXQ * CE_NAMEW + 64) as *u8 102 ce_qd = sys_mmap(CE_MAXQ * 8 + 64) as *i64 103 ce_seen = sys_mmap(CE_MAXQ * CE_NAMEW + 64) as *u8 104 ce_imp = sys_mmap(CE_NAMEW + 64) as *u8 105 ce_enc = sys_mmap(CE_MAXOWN * CE_NAMEW + 64) as *u8 106 ce_encown = sys_mmap(CE_MAXOWN * 8 + 64) as *i64 107 ce_enccnt = sys_mmap(CE_MAXOWN * 8 + 64) as *i64 108 ce_encdom = sys_mmap(CE_MAXOWN * 8 + 64) as *i64 109 ce_nenc = 0 110 ce_fd = 0 - 1 111 ce_dom = sys_mmap(CE_MAXDOM * CE_NAMEW + 64) as *u8 112 ce_ownname = sys_mmap(CE_MAXOWN * CE_NAMEW + 64) as *u8 113 ce_ownd = sys_mmap(CE_MAXOWN * 8 + 64) as *i64 114 ce_srcd = sys_mmap(CE_MAXSRC * 8 + 64) as *i64 115 ce_srcp = sys_mmap(CE_MAXSRC * CE_PATHW + 64) as *u8 116 ce_ef = sys_mmap(CE_MAXE * 8 + 64) as *i64 117 ce_et = sys_mmap(CE_MAXE * 8 + 64) as *i64 118 ce_if = sys_mmap(CE_MAXE * 8 + 64) as *i64 119 ce_it = sys_mmap(CE_MAXE * 8 + 64) as *i64 120 ce_nie = 0 121 ce_buf = sys_mmap(CE_CAP + 64) as *u8 122 ce_scr = sys_mmap(CE_PATHW + 64) as *u8 123 ce_scr2 = sys_mmap(CE_PATHW + 64) as *u8 124 ce_path = sys_mmap(CE_PATHW + 64) as *u8 125} 126 127func ce_cpy(dst: *u8, src: *u8, cap: i64) -> i64 { 128 var w: i64 = 0 129 var done: i64 = 0 130 while done == 0 { 131 let c: i64 = src[w] as i64 132 if c == 0 { done = 1 } 133 else { 134 if w >= cap - 1 { done = 1 } 135 else { 136 dst[w] = src[w] 137 w = w + 1 138 } 139 } 140 } 141 dst[w] = 0 as u8 142 return w 143} 144 145func ce_dom_add(nm: *u8) -> i64 { 146 if ce_ndom >= CE_MAXDOM { return 0 - 1 } 147 let id: i64 = ce_ndom 148 ce_cpy(((ce_dom as i64) + id * CE_NAMEW) as *u8, nm, CE_NAMEW) 149 ce_ndom = ce_ndom + 1 150 return id 151} 152 153func ce_dom_name(i: i64) -> *u8 { 154 return ((ce_dom as i64) + i * CE_NAMEW) as *u8 155} 156 157func ce_own_find(base: *u8) -> i64 { 158 var i: i64 = 0 159 var hit: i64 = 0 - 1 160 while i < ce_nown { 161 if cg_streq(((ce_ownname as i64) + i * CE_NAMEW) as *u8, base) == 1 { 162 hit = ce_ownd[i] 163 i = ce_nown 164 } else { i = i + 1 } 165 } 166 return hit 167} 168 169func ce_own_idx(base: *u8) -> i64 { 170 var i: i64 = 0 171 var hit: i64 = 0 - 1 172 while i < ce_nown { 173 if cg_streq(((ce_ownname as i64) + i * CE_NAMEW) as *u8, base) == 1 { 174 hit = i 175 i = ce_nown 176 } else { i = i + 1 } 177 } 178 return hit 179} 180 181// A module claimed by MORE THAN ONE domain is SHARED INFRASTRUCTURE, not owned -- importing it 182// establishes no DIRECTIONAL dependency. First-wins ownership was measured to make the majority of 183// edges ORDER-DEPENDENT (144 of 252 modules ambiguous; llm>modelwright and modelwright>llm both 184// derivable from the same corpus depending only on iteration order). Marking shared modules CE_SHARED 185// and excluding them makes the result DETERMINISTIC, and honours the banked law that a wrong answer is 186// worse than an absent one. Fewer sound edges beat more order-dependent ones. 187func ce_own_add(base: *u8, d: i64) { 188 if ce_nown >= CE_MAXOWN { return } 189 let at: i64 = ce_own_idx(base) 190 if at >= 0 { 191 if ce_ownd[at] != d { 192 if ce_ownd[at] != CE_SHARED { 193 ce_ownd[at] = CE_SHARED 194 ce_ambig = ce_ambig + 1 195 } 196 } 197 return 198 } 199 ce_cpy(((ce_ownname as i64) + ce_nown * CE_NAMEW) as *u8, base, CE_NAMEW) 200 ce_ownd[ce_nown] = d 201 ce_nown = ce_nown + 1 202} 203 204func ce_src_add(d: i64, path: *u8) { 205 if ce_nsrc >= CE_MAXSRC { return } 206 ce_srcd[ce_nsrc] = d 207 ce_cpy(((ce_srcp as i64) + ce_nsrc * CE_PATHW) as *u8, path, CE_PATHW) 208 ce_nsrc = ce_nsrc + 1 209} 210 211func ce_edge_add(a: i64, b: i64) { 212 if a < 0 { return } 213 if b < 0 { return } 214 if a == b { return } 215 if ce_ne >= CE_MAXE { return } 216 var i: i64 = 0 217 var dup: i64 = 0 218 while i < ce_ne { 219 if ce_ef[i] == a { 220 if ce_et[i] == b { dup = 1 } 221 } 222 i = i + 1 223 } 224 if dup == 1 { return } 225 ce_ef[ce_ne] = a 226 ce_et[ce_ne] = b 227 ce_ne = ce_ne + 1 228} 229 230// A SHARED module is not noise to be discarded -- it is INFRASTRUCTURE, and the domains importing it 231// all stand on it. Recording (module -> importing domain) keeps that dependency instead of throwing it 232// away, and makes the chokepoint visible: a module N domains import is exactly the lib worth migrating 233// first. Direction is unambiguous here because the module is the prerequisite in every case. 234func ce_infra_add(modidx: i64, d: i64) { 235 if modidx < 0 { return } 236 if d < 0 { return } 237 if ce_nie >= CE_MAXE { return } 238 var i: i64 = 0 239 var dup: i64 = 0 240 while i < ce_nie { 241 if ce_if[i] == modidx { 242 if ce_it[i] == d { dup = 1 } 243 } 244 i = i + 1 245 } 246 if dup == 1 { return } 247 ce_if[ce_nie] = modidx 248 ce_it[ce_nie] = d 249 ce_nie = ce_nie + 1 250} 251 252func ce_basename(src: *u8) { 253 var last: i64 = 0 - 1 254 var i: i64 = 0 255 while src[i] != (0 as u8) { 256 if src[i] == (47 as u8) { last = i } 257 i = i + 1 258 } 259 ce_cpy(ce_scr2, ((src as i64) + last + 1) as *u8, CE_PATHW) 260} 261 262func ce_join(pfx: *u8, sfx: *u8) { 263 var w: i64 = 0 264 var i: i64 = 0 265 while pfx[i] != (0 as u8) { 266 if w < CE_PATHW - 1 { 267 ce_path[w] = pfx[i] 268 w = w + 1 269 } 270 i = i + 1 271 } 272 var j: i64 = 0 273 while sfx[j] != (0 as u8) { 274 if w < CE_PATHW - 1 { 275 ce_path[w] = sfx[j] 276 w = w + 1 277 } 278 j = j + 1 279 } 280 ce_path[w] = 0 as u8 281} 282 283// A matrix row may cite a NON-SOURCE artifact (.js/.tsv/.md/.html/.spec). Those carry no NishiLang 284// imports and can never yield an edge -- counting them as "missing" conflated a FILE THAT IS ABSENT 285// with a FILE THAT IS NOT A SOURCE, which made the envelope dishonest in the direction that flatters. 286func ce_is_nx(p: *u8) -> i64 { 287 var n: i64 = 0 288 while p[n] != (0 as u8) { n = n + 1 } 289 if n < 3 { return 0 } 290 if p[n - 3] != (46 as u8) { return 0 } 291 if p[n - 2] != (110 as u8) { return 0 } 292 if p[n - 1] != (120 as u8) { return 0 } 293 return 1 294} 295 296// Extract pipe-delimited field `idx` from ce_buf[ls..le) into ce_scr. 297func ce_field(ls: i64, le: i64, idx: i64) -> i64 { 298 var f: i64 = 0 299 var w: i64 = 0 300 var i: i64 = ls 301 var done: i64 = 0 302 while done == 0 { 303 if i >= le { done = 1 } 304 else { 305 let c: i64 = ce_buf[i] as i64 306 if c == 124 { 307 f = f + 1 308 if f > idx { done = 1 } 309 else { i = i + 1 } 310 } else { 311 if f == idx { 312 if w < CE_PATHW - 1 { 313 ce_scr[w] = ce_buf[i] 314 w = w + 1 315 } 316 } 317 i = i + 1 318 } 319 } 320 } 321 ce_scr[w] = 0 as u8 322 return w 323} 324 325func ce_read_into_buf(path: *u8, cap: i64) -> i64 { 326 let fd: i64 = sys_openat_rd(path) 327 if fd < 0 { return 0 - 1 } 328 var total: i64 = 0 329 var done: i64 = 0 330 while done == 0 { 331 let want: i64 = cap - total 332 if want <= 0 { done = 1 } 333 else { 334 let got: i64 = sys_read(fd, ((ce_buf as i64) + total) as *u8, want) 335 if got <= 0 { done = 1 } 336 else { total = total + got } 337 } 338 } 339 sys_close(fd) 340 ce_buf[total] = 0 as u8 341 return total 342} 343 344func ce_w(s: *u8) { 345 var n: i64 = 0 346 while s[n] != (0 as u8) { n = n + 1 } 347 sys_write(ce_fd, s, n) 348} 349 350func ce_wi(x: i64) { 351 let b: *u8 = sys_mmap(64) as *u8 352 var v: i64 = x 353 var neg: i64 = 0 354 if v < 0 { 355 neg = 1 356 v = 0 - v 357 } 358 var i: i64 = 40 359 if v == 0 { 360 i = i - 1 361 b[i] = 48 as u8 362 } 363 while v > 0 { 364 let d: i64 = v - (v / 10) * 10 365 i = i - 1 366 b[i] = (d + 48) as u8 367 v = v / 10 368 } 369 if neg == 1 { 370 i = i - 1 371 b[i] = 45 as u8 372 } 373 sys_write(ce_fd, ((b as i64) + i) as *u8, 40 - i) 374} 375 376// OWNERSHIP COVERAGE, measured rather than asserted. Every module the closure actually touches is 377// recorded once, flagged by whether ANY domain owns it. An UNOWNED module is exactly where dependency 378// information dies: the closure walks through it but can attribute nothing on the far side. Reporting 379// owned/seen turns "coverage is bounded by the matrices" from a hand-wave into a number that updates 380// itself as the matrices grow. 381// ⚠RAW IMPORT COUNT RANKS THE WRONG THING -- measured, and nearly shipped. Sorting unowned modules by 382// hits puts nx_syscalls.nx (2129), nx_tier.nx (591), nx_sha256/nx_tls13/... on top: UNIVERSAL SUBSTRATE, 383// which must NEVER be domain-owned. Claiming one would fabricate edges from its "owner" to every domain. 384// The discriminator needs no new threshold, because the design already has a natural one: track how many 385// DISTINCT DOMAINS import each module. Imported by exactly ONE domain => unambiguously that domain's to 386// claim. Imported by many => substrate, and the right answer is to leave it unowned. 387func ce_enc_add(base: *u8, sd: i64) { 388 var i: i64 = 0 389 while i < ce_nenc { 390 if cg_streq(((ce_enc as i64) + i * CE_NAMEW) as *u8, base) == 1 { 391 ce_enccnt[i] = ce_enccnt[i] + 1 392 if ce_encdom[i] >= 0 { 393 if ce_encdom[i] != sd { ce_encdom[i] = CE_SHARED } 394 } 395 return 396 } 397 i = i + 1 398 } 399 if ce_nenc >= CE_MAXOWN { return } 400 ce_cpy(((ce_enc as i64) + ce_nenc * CE_NAMEW) as *u8, base, CE_NAMEW) 401 var owned: i64 = 0 402 if ce_own_idx(base) >= 0 { owned = 1 } 403 ce_encown[ce_nenc] = owned 404 ce_enccnt[ce_nenc] = 1 405 ce_encdom[ce_nenc] = sd 406 ce_nenc = ce_nenc + 1 407} 408 409func ce_enc_owned() -> i64 { 410 var c: i64 = 0 411 var i: i64 = 0 412 while i < ce_nenc { 413 if ce_encown[i] == 1 { c = c + 1 } 414 i = i + 1 415 } 416 return c 417} 418 419func ce_seen_has(base: *u8) -> i64 { 420 var i: i64 = 0 421 var hit: i64 = 0 422 while i < ce_nseen { 423 if cg_streq(((ce_seen as i64) + i * CE_NAMEW) as *u8, base) == 1 { 424 hit = 1 425 i = ce_nseen 426 } else { i = i + 1 } 427 } 428 return hit 429} 430 431func ce_qpush(base: *u8, depth: i64) { 432 if depth > ce_maxdepth { return } 433 if ce_qt >= CE_MAXQ { return } 434 if ce_nseen >= CE_MAXQ { return } 435 if ce_seen_has(base) == 1 { return } 436 ce_cpy(((ce_seen as i64) + ce_nseen * CE_NAMEW) as *u8, base, CE_NAMEW) 437 ce_nseen = ce_nseen + 1 438 ce_cpy(((ce_q as i64) + ce_qt * CE_NAMEW) as *u8, base, CE_NAMEW) 439 ce_qd[ce_qt] = depth 440 ce_qt = ce_qt + 1 441} 442 443// Resolve a bare module basename to a file and read it into ce_buf. Imports name a module, not a path, 444// so the two source dirs are the only places it can live. 445func ce_resolve_base(base: *u8) -> i64 { 446 ce_join("buildroot/runtime/" as *u8, base) 447 var n: i64 = ce_read_into_buf(ce_path, CE_HEAD) 448 if n < 0 { 449 ce_join("buildroot/runtime/_hdl_build/" as *u8, base) 450 n = ce_read_into_buf(ce_path, CE_HEAD) 451 } 452 return n 453} 454 455// Scan the CURRENT ce_buf for `import "<mod>"` lines and attribute each one to source-domain sd. 456// An OWNED module yields an edge immediately and is NOT followed -- the dependency is already 457// attributed. A SHARED or UNOWNED module is followed (when --transitive) because a domain can depend 458// on another THROUGH infrastructure, and that dependency is just as real as a direct one. 459// Names are copied into the queue before any further read, so the single shared buffer is safe. 460func ce_scan_buf_imports(sd: i64, depth: i64, n: i64) { 461 var fls: i64 = 0 462 var f: i64 = 0 463 while f <= n { 464 var fe: i64 = 0 465 if f == n { fe = 1 } 466 else { if ce_buf[f] == (10 as u8) { fe = 1 } } 467 if fe == 1 { 468 var isimp: i64 = 0 469 if fls + 8 < f { 470 if ce_buf[fls] == (105 as u8) { 471 if ce_buf[fls + 1] == (109 as u8) { 472 if ce_buf[fls + 2] == (112 as u8) { 473 if ce_buf[fls + 3] == (111 as u8) { 474 if ce_buf[fls + 4] == (114 as u8) { 475 if ce_buf[fls + 5] == (116 as u8) { isimp = 1 } 476 } 477 } 478 } 479 } 480 } 481 } 482 if isimp == 1 { 483 var q1: i64 = 0 - 1 484 var z: i64 = fls 485 while z < f { 486 if ce_buf[z] == (34 as u8) { 487 if q1 < 0 { q1 = z } 488 } 489 z = z + 1 490 } 491 if q1 > 0 { 492 var w2: i64 = 0 493 var y: i64 = q1 + 1 494 var dd: i64 = 0 495 while dd == 0 { 496 if y >= f { dd = 1 } 497 else { 498 if ce_buf[y] == (34 as u8) { dd = 1 } 499 else { 500 if w2 < CE_NAMEW - 1 { 501 ce_imp[w2] = ce_buf[y] 502 w2 = w2 + 1 503 } 504 y = y + 1 505 } 506 } 507 } 508 ce_imp[w2] = 0 as u8 509 if w2 > 0 { 510 ce_enc_add(ce_imp, sd) 511 let midx: i64 = ce_own_idx(ce_imp) 512 if midx >= 0 { 513 let owner: i64 = ce_ownd[midx] 514 if owner >= 0 { 515 if owner != sd { 516 if depth > 1 { ce_transedges = ce_transedges + 1 } 517 } 518 ce_edge_add(owner, sd) 519 } 520 if owner == CE_SHARED { 521 ce_infra_add(midx, sd) 522 if ce_trans == 1 { ce_qpush(ce_imp, depth + 1) } 523 } 524 } else { 525 if ce_trans == 1 { ce_qpush(ce_imp, depth + 1) } 526 } 527 } 528 } 529 } 530 fls = f + 1 531 } 532 f = f + 1 533 } 534} 535 536// Depth comes from a CONFIG ROW, never a code constant (rule 11). An absent config yields the declared 537// fallback AND records that fact in ce_depthsrc, so the emitted envelope can never claim "configured" 538// when nothing configured it -- a silently-defaulted knob is indistinguishable from a chosen one. 539func ce_load_depth() { 540 ce_maxdepth = CE_DEPTH_FALLBACK 541 ce_depthsrc = 0 542 let cl: *i64 = sys_mmap(16) as *i64 543 let cb: *u8 = sys_read_file(CE_CFG, cl) 544 let n: i64 = cl[0] 545 if n <= 0 { return } 546 let key: *u8 = "transitive_depth=" as *u8 547 var i: i64 = 0 548 var done: i64 = 0 549 while done == 0 { 550 if i + CE_DEPTH_KEY_LEN >= n { done = 1 } 551 else { 552 var k: i64 = 0 553 var ok: i64 = 1 554 while k < CE_DEPTH_KEY_LEN { 555 if cb[i + k] != key[k] { ok = 0 } 556 k = k + 1 557 } 558 if ok == 1 { 559 var v: i64 = 0 560 var any: i64 = 0 561 var j: i64 = i + CE_DEPTH_KEY_LEN 562 var d2: i64 = 0 563 while d2 == 0 { 564 if j >= n { d2 = 1 } 565 else { 566 let c: i64 = cb[j] as i64 567 if c < 48 { d2 = 1 } 568 else { 569 if c > 57 { d2 = 1 } 570 else { 571 v = v * 10 + (c - 48) 572 any = 1 573 j = j + 1 574 } 575 } 576 } 577 } 578 if any == 1 { 579 if v >= 1 { 580 if v <= CE_DEPTH_SCANMAX { 581 ce_maxdepth = v 582 ce_depthsrc = 1 583 } 584 } 585 } 586 done = 1 587 } else { i = i + 1 } 588 } 589 } 590} 591