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}