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