code wiki / _hdl_build / nx_capgraph_edges.nx

nx_capgraph_edges.nx source

↩ module page · 466 lines · 20924 B

1// nx_capgraph_edges.nx -- DERIVES the capability graph's prerequisite edges FROM THE IMPORT CLOSURE. 2// 3// WHY (debt 1785518444, filed by me 2026-07-31): nx_capgraph_derive shipped reading a HAND-DECLARED 4// edge file. Declared edges are a seed, not a measurement, and a MISSING edge is the dangerous case -- 5// it lets a dependent read healthier than the layer it stands on. This organ replaces the declaration 6// with a measurement. 7// 8// THE MEASUREMENT, end to end, no taste anywhere in it: 9// 1. OWNERSHIP comes from knowledge/compare/<domain>.matrix, which already maps every domain to the 10// real organ SOURCE PATHS backing each of its capabilities (field2), with field3 = the symbol. 11// Rows whose symbol is _ABSENT_ are declared GAPS -- skipped, they own nothing. 12// 2. DEPENDENCY comes from the source itself: every `import "<module>.nx"` in an owned source. 13// 3. EDGE: if a source owned by domain A imports a module owned by domain B (B != A), then B is a 14// PREREQUISITE of A. That is a fact about the build, not an opinion about the architecture. 15// 16// ⚠THE MEASURED GRAPH IS NOT ACYCLIC. Probed 2026-07-31: search>webscraping, browser>webscraping AND 17// webscraping>browser, search>deepresearch AND deepresearch>search, comms>videoops AND videoops>comms. 18// Mutually-importing domains are REAL. This is not a defect in the measurement and must not be 19// "cleaned up" by dropping edges: a cycle is a genuine finding -- it names a CO-DEPENDENT CLUSTER that 20// can only be raised together. The consumer's min-relaxation is a fixpoint iteration bounded by node 21// count, so it converges on a general digraph; the cycle members simply share a floor. 22// 23// HONEST ENVELOPE, emitted into the file itself so no reader has to trust this comment: 24// - coverage is bounded by the matrices, not by this organ: a domain with few matrix rows yields few 25// edges. That is a matrix-completeness gap, and it is REPORTED, never silently treated as "no deps". 26// - matrix rows pointing at sources that do not exist on disk are COUNTED and reported (missing=N). 27// - first-wins ownership when two domains claim the same module; ambiguity is COUNTED and reported. 28// 29// nx_capgraph_edges [outfile] exit 0 ok | 4 capture-fail | 5 write-fail 30// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 31import "nx_capgraph_edges_lib.nx" 32import "nx_matrix_sym_lib.nx" 33 34func main(argc: i64, argv: *i64) -> i64 { 35 ce_init() 36 ce_depthscan = 0 37 ce_load_depth() 38 var outp: *u8 = CE_OUTDEF 39 var ai2: i64 = 1 40 while ai2 < argc { 41 let a: *u8 = argv[ai2] as *u8 42 if cg_streq(a, "--transitive" as *u8) == 1 { ce_trans = 1 } 43 else { 44 if cg_streq(a, "--direct" as *u8) == 1 { ce_trans = 0 } 45 else { 46 if cg_streq(a, "--depthscan" as *u8) == 1 { ce_depthscan = 1 } 47 else { outp = a } 48 } 49 } 50 ai2 = ai2 + 1 51 } 52 53 // ---- domain list, from the live honesty gate (never a hardcoded roster) ---- 54 let sout: *u8 = sys_mmap(CE_CAP + 16) 55 let solen: *i64 = sys_mmap(16) as *i64 56 let rc: i64 = tr_run1(CE_SOTA, 0 as *u8, sout, CE_CAP, solen) 57 let sn: i64 = solen[0] 58 if rc == 127 { return 4 } 59 if sn <= 0 { return 4 } 60 var ls: i64 = 0 61 var i: i64 = 0 62 while i <= sn { 63 var isend: i64 = 0 64 if i == sn { isend = 1 } 65 else { if sout[i] == (10 as u8) { isend = 1 } } 66 if isend == 1 { 67 var covp: i64 = 0 - 1 68 var j: i64 = ls 69 while j < i { 70 if j + 4 <= i { 71 if sout[j] == (99 as u8) { 72 if sout[j + 1] == (111 as u8) { 73 if sout[j + 2] == (118 as u8) { 74 if sout[j + 3] == (61 as u8) { 75 covp = j 76 j = i 77 } 78 } 79 } 80 } 81 } 82 j = j + 1 83 } 84 if covp > 0 { 85 var start: i64 = ls 86 var found: i64 = 0 87 var s: i64 = ls 88 while s < i { 89 if found == 0 { 90 if sout[s] != (32 as u8) { 91 start = s 92 found = 1 93 } 94 } 95 s = s + 1 96 } 97 if found == 1 { 98 var w: i64 = 0 99 var q: i64 = start 100 var d2: i64 = 0 101 while d2 == 0 { 102 if q >= i { d2 = 1 } 103 else { 104 if sout[q] == (32 as u8) { d2 = 1 } 105 else { 106 if w < CE_NAMEW - 1 { 107 ce_scr2[w] = sout[q] 108 w = w + 1 109 } 110 q = q + 1 111 } 112 } 113 } 114 ce_scr2[w] = 0 as u8 115 if w > 0 { ce_dom_add(ce_scr2) } 116 } 117 } 118 ls = i + 1 119 } 120 i = i + 1 121 } 122 123 // ---- PHASE 1: ownership from the matrices ---- 124 var d: i64 = 0 125 while d < ce_ndom { 126 ce_cpy(ce_path, "knowledge/compare/" as *u8, CE_PATHW) 127 var pl: i64 = 0 128 while ce_path[pl] != (0 as u8) { pl = pl + 1 } 129 let dn: *u8 = ce_dom_name(d) 130 var k: i64 = 0 131 while dn[k] != (0 as u8) { 132 if pl < CE_PATHW - 8 { 133 ce_path[pl] = dn[k] 134 pl = pl + 1 135 } 136 k = k + 1 137 } 138 ce_path[pl] = 46 as u8 139 ce_path[pl + 1] = 109 as u8 140 ce_path[pl + 2] = 97 as u8 141 ce_path[pl + 3] = 116 as u8 142 ce_path[pl + 4] = 114 as u8 143 ce_path[pl + 5] = 105 as u8 144 ce_path[pl + 6] = 120 as u8 145 ce_path[pl + 7] = 0 as u8 146 let mn: i64 = ce_read_into_buf(ce_path, CE_CAP) 147 if mn > 0 { 148 var mls: i64 = 0 149 var m: i64 = 0 150 while m <= mn { 151 var me: i64 = 0 152 if m == mn { me = 1 } 153 else { if ce_buf[m] == (10 as u8) { me = 1 } } 154 if me == 1 { 155 var skip: i64 = 0 156 if mls >= m { skip = 1 } 157 else { 158 if ce_buf[mls] == (35 as u8) { skip = 1 } 159 if ce_buf[mls] == (64 as u8) { skip = 1 } 160 } 161 if skip == 0 { 162 let plen: i64 = ce_field(mls, m, 1) 163 if plen > 0 { 164 ce_cpy(ce_path, ce_scr, CE_PATHW) 165 let slen: i64 = ce_field(mls, m, 2) 166 var absent: i64 = 0 167 if slen == 0 { absent = 1 } 168 // ONE reader of the symbol format (nx_matrix_sym_lib). The exact-equality 169 // test that stood here knew only the bare "_ABSENT_", so a WATCH CONTRACT 170 // "_ABSENT_:<future_symbol>" -- a DECLARED GAP that owns nothing -- was 171 // read as a real symbol and given an OWNERSHIP EDGE over its organ. 172 // A DECLARED GAP THAT OWNS A SOURCE FILE POISONS EVERY REACHABILITY 173 // QUESTION ASKED OVER THE GRAPH, because the invented edge is 174 // indistinguishable from a real one at every later hop. 175 if msym_is_declared_gap_z(ce_scr) == 1 { absent = 1 } 176 if absent == 0 { 177 ce_basename(ce_path) 178 ce_own_add(ce_scr2, d) 179 ce_src_add(d, ce_path) 180 } 181 } 182 } 183 mls = m + 1 184 } 185 m = m + 1 186 } 187 } 188 d = d + 1 189 } 190 191 // ---- PHASE 2: edges from the import closure ---- 192 var scan_lo: i64 = ce_maxdepth 193 var scan_hi: i64 = ce_maxdepth 194 if ce_depthscan == 1 { 195 scan_lo = 1 196 scan_hi = CE_DEPTH_SCANMAX 197 cax_puts("=== DEPTH CURVE: edges per transitive depth -- the cut must be MEASURED, not chosen ===\n" as *u8) 198 cax_puts(" depth 1 == the strict one-hop (direct) subset. Pick the depth where the curve FLATTENS.\n\n" as *u8) 199 } 200 var dcur: i64 = scan_lo 201 while dcur <= scan_hi { 202 ce_maxdepth = dcur 203 ce_ne = 0 204 ce_nie = 0 205 ce_transedges = 0 206 ce_scanned = 0 207 ce_nonnx = 0 208 ce_altres = 0 209 ce_missing = 0 210 ce_nenc = 0 211 var si: i64 = 0 212 while si < ce_nsrc { 213 let sd: i64 = ce_srcd[si] 214 let sp: *u8 = ((ce_srcp as i64) + si * CE_PATHW) as *u8 215 // RESOLUTION IS MULTI-ROOT BY MEASUREMENT: matrix paths are relative to buildroot/ for sources 216 // but to the SERVING ROOT for site/knowledge artifacts, and two rows are stale renames that 217 // still exist under the other source dir. A single-prefix probe reported 23 "missing" files 218 // that were mostly PRESENT -- the tool was wrong, not the corpus. 219 var fn2: i64 = 0 - 1 220 if ce_is_nx(sp) == 0 { 221 ce_nonnx = ce_nonnx + 1 222 } else { 223 ce_join("buildroot/" as *u8, sp) 224 fn2 = ce_read_into_buf(ce_path, CE_HEAD) 225 if fn2 >= 0 { ce_res_bld = ce_res_bld + 1 } 226 if fn2 < 0 { 227 ce_join("\x00" as *u8, sp) 228 fn2 = ce_read_into_buf(ce_path, CE_HEAD) 229 if fn2 >= 0 { 230 ce_altres = ce_altres + 1 231 ce_res_srv = ce_res_srv + 1 232 } 233 } 234 if fn2 < 0 { 235 ce_basename(sp) 236 ce_join("buildroot/runtime/" as *u8, ce_scr2) 237 fn2 = ce_read_into_buf(ce_path, CE_HEAD) 238 if fn2 >= 0 { 239 ce_altres = ce_altres + 1 240 ce_res_base = ce_res_base + 1 241 } 242 } 243 if fn2 < 0 { 244 ce_basename(sp) 245 ce_join("buildroot/runtime/_hdl_build/" as *u8, ce_scr2) 246 fn2 = ce_read_into_buf(ce_path, CE_HEAD) 247 if fn2 >= 0 { 248 ce_altres = ce_altres + 1 249 ce_res_base = ce_res_base + 1 250 } 251 } 252 if fn2 < 0 { ce_missing = ce_missing + 1 } 253 } 254 if fn2 >= 0 { 255 ce_scanned = ce_scanned + 1 256 ce_qh = 0 257 ce_qt = 0 258 ce_nseen = 0 259 ce_scan_buf_imports(sd, 1, fn2) 260 while ce_qh < ce_qt { 261 let qi: i64 = ce_qh 262 ce_qh = ce_qh + 1 263 let qdep: i64 = ce_qd[qi] 264 ce_cpy(ce_scr, ((ce_q as i64) + qi * CE_NAMEW) as *u8, CE_NAMEW) 265 let qn: i64 = ce_resolve_base(ce_scr) 266 if qn > 0 { ce_scan_buf_imports(sd, qdep, qn) } 267 } 268 } 269 si = si + 1 270 } 271 if ce_depthscan == 1 { 272 cax_puts(" " as *u8) 273 cax_kv("depth" as *u8, dcur) 274 cax_kv("domain_edges" as *u8, ce_ne) 275 cax_kv("infra_edges" as *u8, ce_nie) 276 cax_kv("via_infra" as *u8, ce_transedges) 277 cax_puts("\n" as *u8) 278 } 279 dcur = dcur + 1 280 } 281 if ce_depthscan == 1 { 282 cax_puts("\nDEPTH-SCAN done -- set transitive_depth=<d> in knowledge/status/capgraph.conf.\n" as *u8) 283 return 0 284 } 285 286 // ---- PHASE 3: emit ---- 287 ce_fd = sys_openat_wr(outp, 0x1A4) 288 if ce_fd < 0 { 289 cax_puts("CAPGRAPH-EDGES verdict=WRITE-FAIL\n" as *u8) 290 return 5 291 } 292 ce_w("# capgraph_edges.conf -- MEASURED prerequisite edges. GENERATED by nx_capgraph_edges.\n" as *u8) 293 ce_w("# DO NOT HAND-EDIT: regenerate instead, or the file stops being a measurement.\n" as *u8) 294 ce_w("#\n# METHOD: ownership from knowledge/compare/<domain>.matrix field2 (source path), rows whose\n" as *u8) 295 ce_w("# field3 symbol is _ABSENT_ skipped as declared gaps; dependency from each owned source's\n" as *u8) 296 ce_w("# `import \"<module>.nx\"` lines; edge B>A when a source owned by A imports a module owned by B.\n" as *u8) 297 ce_w("# That is a fact about the build, not an opinion about the architecture.\n#\n" as *u8) 298 ce_w("# ENVELOPE (read this before trusting the graph):\n" as *u8) 299 ce_w("# domains=" as *u8) 300 ce_wi(ce_ndom) 301 ce_w(" owned_modules=" as *u8) 302 ce_wi(ce_nown) 303 ce_w(" sources_scanned=" as *u8) 304 ce_wi(ce_scanned) 305 ce_w("\n# non_source_rows=" as *u8) 306 ce_wi(ce_nonnx) 307 ce_w(" (rows citing .js/.tsv/.md/.html evidence -- carry no imports, can never yield an edge;\n" as *u8) 308 ce_w("# counted SEPARATELY because 'not a source' is not the same defect as 'absent')\n" as *u8) 309 ce_w("# resolved_via_alt_root=" as *u8) 310 ce_wi(ce_altres) 311 ce_w(" (found at the serving root or under the other source dir, not buildroot/)\n" as *u8) 312 ce_w("# sources_missing=" as *u8) 313 ce_wi(ce_missing) 314 ce_w(" (.nx rows genuinely absent from every root -- a real matrix-quality gap)\n" as *u8) 315 ce_w("# shared_modules_EXCLUDED=" as *u8) 316 ce_wi(ce_ambig) 317 ce_w(" (claimed by >1 domain = SHARED INFRA, not owned: importing one implies\n" as *u8) 318 ce_w("# NO directional dependency, so they derive no edge. Including them made edge DIRECTION\n" as *u8) 319 ce_w("# order-dependent -- both llm>modelwright and modelwright>llm were derivable. Excluding\n" as *u8) 320 ce_w("# them makes this file DETERMINISTIC. Under-counts edges; never fabricates one.)\n" as *u8) 321 ce_w("# OWNERSHIP COVERAGE = " as *u8) 322 ce_wi(ce_enc_owned()) 323 ce_w(" owned of " as *u8) 324 ce_wi(ce_nenc) 325 ce_w(" modules the closure actually touches. THIS IS THE REAL BOUND ON THIS GRAPH:\n" as *u8) 326 ce_w("# an UNOWNED module is where dependency information DIES -- the walk passes through it and\n" as *u8) 327 ce_w("# can attribute nothing on the far side. Every edge below is real; the edge SET is a FLOOR.\n" as *u8) 328 ce_w("# Raising this number is purely a matter of adding matrix rows -- no code change.\n" as *u8) 329 ce_w("# edges=" as *u8) 330 ce_wi(ce_ne) 331 ce_w("\n#\n# COVERAGE IS BOUNDED BY THE MATRICES, not by this organ: a domain with few matrix rows\n" as *u8) 332 ce_w("# yields few edges. A missing edge lets a dependent read healthier than what it stands on.\n" as *u8) 333 ce_w("# ⚠THE MEASURED GRAPH IS NOT ACYCLIC -- mutually-importing domains are real and must NOT be\n" as *u8) 334 ce_w("# pruned: a cycle names a CO-DEPENDENT CLUSTER that can only be raised together.\n\n" as *u8) 335 var e: i64 = 0 336 while e < ce_ne { 337 ce_w(ce_dom_name(ce_ef[e])) 338 ce_w(">" as *u8) 339 ce_w(ce_dom_name(ce_et[e])) 340 ce_w("\n" as *u8) 341 e = e + 1 342 } 343 ce_w("\n# SHARED INFRASTRUCTURE as FIRST-CLASS NODES (infra:<module>). A module claimed by more\n" as *u8) 344 ce_w("# than one domain is a prerequisite of every domain that imports it -- direction is never\n" as *u8) 345 ce_w("# ambiguous here, so nothing is discarded. A node many domains stand on IS the chokepoint.\n" as *u8) 346 ce_w("# These carry NO measured level yet, and UNMEASURED never drags a dependent down (L3).\n" as *u8) 347 var g: i64 = 0 348 while g < ce_nie { 349 ce_w("infra:" as *u8) 350 ce_w(((ce_ownname as i64) + ce_if[g] * CE_NAMEW) as *u8) 351 ce_w(">" as *u8) 352 ce_w(ce_dom_name(ce_it[g])) 353 ce_w("\n" as *u8) 354 g = g + 1 355 } 356 sys_close(ce_fd) 357 ce_fd = 1 358 359 cax_puts("=== CAPGRAPH-EDGES: prerequisite edges MEASURED from the import closure ===\n" as *u8) 360 cax_kv("domains" as *u8, ce_ndom) 361 cax_kv("owned_modules" as *u8, ce_nown) 362 cax_kv("sources_scanned" as *u8, ce_scanned) 363 cax_kv("non_source_rows" as *u8, ce_nonnx) 364 cax_kv("alt_root_resolved" as *u8, ce_altres) 365 cax_puts("\n" as *u8) 366 // A resolver that silently absorbs TWO path conventions makes the corpus drift INVISIBLE -- the 367 // exact "papers over the defect" pattern this arc keeps finding. Robust resolution is right; hiding 368 // WHICH root won is not. Two nonzero buckets = the matrices disagree about how to write a path. 369 cax_kv("resolved_via_buildroot" as *u8, ce_res_bld) 370 cax_kv("resolved_via_serving_root" as *u8, ce_res_srv) 371 cax_kv("resolved_via_basename_search" as *u8, ce_res_base) 372 var conv: i64 = 0 373 if ce_res_bld > 0 { conv = conv + 1 } 374 if ce_res_srv > 0 { conv = conv + 1 } 375 if ce_res_base > 0 { conv = conv + 1 } 376 if conv > 1 { 377 cax_puts("\n ⚠PATH-CONVENTION DRIFT: the matrices do NOT agree on how to write a source path.\n" as *u8) 378 cax_puts(" Resolution succeeds anyway, which is precisely why this must be REPORTED and not\n" as *u8) 379 cax_puts(" absorbed -- a tolerant reader is how a corpus drifts apart without anyone noticing.\n" as *u8) 380 } 381 cax_kv("sources_missing" as *u8, ce_missing) 382 cax_kv("shared_modules" as *u8, ce_ambig) 383 cax_kv("domain_edges" as *u8, ce_ne) 384 cax_kv("infra_edges" as *u8, ce_nie) 385 cax_kv("transitive_mode" as *u8, ce_trans) 386 cax_kv("depth" as *u8, ce_maxdepth) 387 if ce_depthsrc == 1 { cax_puts("(from capgraph.conf) " as *u8) } 388 else { cax_puts("(FALLBACK -- capgraph.conf absent, run --depthscan then set it) " as *u8) } 389 cax_kv("edges_found_via_infra" as *u8, ce_transedges) 390 cax_puts("\n" as *u8) 391 let seen_tot: i64 = ce_nenc 392 let seen_own: i64 = ce_enc_owned() 393 var cov_permil: i64 = 0 394 if seen_tot > 0 { cov_permil = seen_own * 1000 / seen_tot } 395 cax_kv("modules_touched" as *u8, seen_tot) 396 cax_kv("owned_by_a_domain" as *u8, seen_own) 397 cax_kv("ownership_coverage_permil" as *u8, cov_permil) 398 cax_puts("<- THE REAL BOUND: an UNOWNED module is where dependency info dies\n" as *u8) 399 400 // Turn the coverage debt from "add 548 rows" into a RANKED worklist. An unowned module imported many 401 // times is carrying the most invisible dependency; claiming it in a matrix converts the most surface 402 // per row. This is the cheapest possible ordering of a pure-content task, and it is measured. 403 var substrate: i64 = 0 404 var sz: i64 = 0 405 while sz < ce_nenc { 406 if ce_encown[sz] == 0 { 407 if ce_encdom[sz] == CE_SHARED { substrate = substrate + 1 } 408 } 409 sz = sz + 1 410 } 411 cax_kv("unowned_SUBSTRATE" as *u8, substrate) 412 cax_puts("(imported by MANY domains -- leave unowned; claiming one would fabricate edges to all)\n" as *u8) 413 cax_puts("\n-- CLAIM THESE FIRST: unowned modules imported by EXACTLY ONE domain --\n" as *u8) 414 cax_puts(" single-domain => unambiguously that domain's to claim, so a matrix row here is SAFE and\n" as *u8) 415 cax_puts(" converts invisible surface into measurable edges. Ranked by import hits.\n\n" as *u8) 416 let picked: *i64 = sys_mmap(CE_MAXOWN * 8 + 64) as *i64 417 var pz: i64 = 0 418 while pz < ce_nenc { 419 picked[pz] = 0 420 pz = pz + 1 421 } 422 var pshown: i64 = 0 423 while pshown < 15 { 424 var pb: i64 = 0 - 1 425 var pi: i64 = 0 426 while pi < ce_nenc { 427 if picked[pi] == 0 { 428 if ce_encown[pi] == 0 { 429 if ce_encdom[pi] >= 0 { 430 if pb < 0 { pb = pi } 431 else { if ce_enccnt[pi] > ce_enccnt[pb] { pb = pi } } 432 } 433 } 434 } 435 pi = pi + 1 436 } 437 if pb < 0 { pshown = 15 } 438 else { 439 picked[pb] = 1 440 cax_puts(" " as *u8) 441 cax_puts(((ce_enc as i64) + pb * CE_NAMEW) as *u8) 442 cax_puts(" " as *u8) 443 cax_kv("import_hits" as *u8, ce_enccnt[pb]) 444 cax_puts("claim_for=" as *u8) 445 cax_puts(ce_dom_name(ce_encdom[pb])) 446 cax_puts("\n" as *u8) 447 pshown = pshown + 1 448 } 449 } 450 cax_puts("\n" as *u8) 451 var p: i64 = 0 452 while p < ce_ne { 453 cax_puts(" " as *u8) 454 cax_puts(ce_dom_name(ce_ef[p])) 455 cax_puts(" > " as *u8) 456 cax_puts(ce_dom_name(ce_et[p])) 457 cax_puts("\n" as *u8) 458 p = p + 1 459 } 460 cax_puts("\nwrote " as *u8) 461 cax_puts(outp) 462 cax_puts("\nenvelope: ownership=matrix field2 (_ABSENT_ rows skipped) dependency=import lines;\n" as *u8) 463 cax_puts(" modules claimed by >1 domain are SHARED INFRA and derive NO edge (deterministic by\n" as *u8) 464 cax_puts(" construction, under-counts rather than fabricates); coverage bounded by matrix completeness.\n" as *u8) 465 return 0 466}