code wiki / _hdl_build / nx_atlas_graphrec_gate.nx
nx_atlas_graphrec_gate.nx source
↩ module page · 201 lines · 9248 B
1// nx_atlas_graphrec_gate.nx -- proves the RECOMBINATION SCORING, not merely that the organ runs.
2//
3// WHY IT EXISTS: I shipped nx_atlas_graphrec LIVE (built, promoted, registered, called over /mcp,
4// committing to the discovery-graph- plane) WITHOUT a gate -- a rule-9 violation of this
5// ecosystem's own standard, self-caught. Worse, the scoring was inline in main(), so the only way
6// to exercise it was to run the whole organ against a real 17k-node graph; any gate over that
7// would have been vacuous. gr_propose was extracted first so these teeth bite the actual decision
8// logic against SYNTHETIC graphs where the right answer is known by construction.
9//
10// Each tooth isolates ONE rule, and the two hub rules are separate because they failed
11// separately: the FIRST live run put nx_syscalls (Ca=14084) into 6 of the top 20 because hubs
12// were suppressed as WITNESS but not as ENDPOINT. T4 and T5 exist so that cannot come back.
13// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
14import "nx_atlas_graphrec_lib.nx"
15import "nx_gate.nx"
16
17const GG_NODES: i64 = 2048
18const GG_EDGES: i64 = 8192
19const GG_ARENA: i64 = 262144
20const GG_HASH: i64 = 4096
21// FIXTURE SIZES ARE LITERALS, NOT DERIVED FROM THE CONSTANTS UNDER TEST. Self-caught: T5 first
22// sized its hub as GR_ENDPOINT_THR + 8, so the mutation run (thr -> 999999999) tried to build a
23// billion nodes and was killed instead of FAILING. A fixture that scales with the value being
24// mutated cannot witness that mutation. These exceed the real thresholds (24 / 512) by design.
25const GG_WITNESS_DEG: i64 = 28
26const GG_ENDPOINT_DEG: i64 = 520
27
28// build "n<i>" into buf, return length (unique synthetic node names)
29func gg_name(buf: *u8, i: i64) -> i64 {
30 buf[0] = 110 as u8
31 if i == 0 { buf[1] = 48 as u8; return 2 }
32 let tmp: *u8 = sys_mmap(32)
33 var k: i64 = 0
34 var x: i64 = i
35 while x > 0 { tmp[k] = ((x % 10) + 48) as u8; x = x / 10; k = k + 1 }
36 var o: i64 = 1
37 while k > 0 { k = k - 1; buf[o] = tmp[k]; o = o + 1 }
38 return o
39}
40
41func gg_new() -> *EcoGraph { return eg_new(GG_NODES, GG_EDGES, GG_ARENA, GG_HASH) }
42
43// nx_gate.nx has gw (string) but no number writer -- print counts without a second dependency.
44func gg_num(v: i64) -> i64 {
45 let b: *u8 = sys_mmap(32)
46 if v == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 }
47 let t: *u8 = sys_mmap(32)
48 var n: i64 = 0
49 var x: i64 = v
50 while x > 0 { t[n] = ((x % 10) + 48) as u8; x = x / 10; n = n + 1 }
51 var o: i64 = 0
52 while n > 0 { n = n - 1; b[o] = t[n]; o = o + 1 }
53 sys_write(1, b, o)
54 return 0
55}
56
57// is pair (a,b) present in the first `have` results, in either order?
58func gg_has_pair(ta: *i64, tb: *i64, have: i64, a: i64, b: i64) -> i64 {
59 var i: i64 = 0
60 while i < have {
61 if ta[i] == a { if tb[i] == b { return 1 } }
62 if ta[i] == b { if tb[i] == a { return 1 } }
63 i = i + 1
64 }
65 return 0
66}
67
68func main() -> i64 {
69 gw("=== nx_atlas_graphrec_gate: graph-adjacency recombination scoring ===\n" as *u8)
70 var pass: i64 = 0
71 var tot: i64 = 0
72 let ta: *i64 = sys_mmap(1024) as *i64
73 let tb: *i64 = sys_mmap(1024) as *i64
74 let ts: *i64 = sys_mmap(1024) as *i64
75 let st: *i64 = sys_mmap(64) as *i64
76 let nm: *u8 = sys_mmap(64)
77
78 // ---- T1: three shared neighbours + NO direct edge -> proposed with cn=3 -------------------
79 let g1: *EcoGraph = gg_new()
80 let a1: i64 = eg_intern(g1, "A" as *u8, 1)
81 let b1: i64 = eg_intern(g1, "B" as *u8, 1)
82 let c1: i64 = eg_intern(g1, "C" as *u8, 1)
83 let w1: i64 = eg_intern(g1, "W1" as *u8, 2)
84 let w2: i64 = eg_intern(g1, "W2" as *u8, 2)
85 let w3: i64 = eg_intern(g1, "W3" as *u8, 2)
86 eg_add_edge(g1, w1, a1); eg_add_edge(g1, w1, b1); eg_add_edge(g1, w1, c1)
87 eg_add_edge(g1, w2, a1); eg_add_edge(g1, w2, b1); eg_add_edge(g1, w2, c1)
88 eg_add_edge(g1, w3, a1); eg_add_edge(g1, w3, b1)
89 let h1: i64 = gr_propose(g1, 3, 10, ta, tb, ts, st)
90 tot = tot + 1
91 var t1: i64 = 0
92 if h1 >= 1 { if gg_has_pair(ta, tb, h1, a1, b1) == 1 { if ts[0] == 3 { t1 = 1 } } }
93 if t1 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
94 gw("T1 unlinked pair with 3 shared neighbours is proposed, score = common-neighbour count\n" as *u8)
95
96 // ---- T2 NEG: the SAME pair, now DIRECTLY linked -> never proposed (already composed) ------
97 let g2: *EcoGraph = gg_new()
98 let a2: i64 = eg_intern(g2, "A" as *u8, 1)
99 let b2: i64 = eg_intern(g2, "B" as *u8, 1)
100 let x1: i64 = eg_intern(g2, "W1" as *u8, 2)
101 let x2: i64 = eg_intern(g2, "W2" as *u8, 2)
102 let x3: i64 = eg_intern(g2, "W3" as *u8, 2)
103 eg_add_edge(g2, x1, a2); eg_add_edge(g2, x1, b2)
104 eg_add_edge(g2, x2, a2); eg_add_edge(g2, x2, b2)
105 eg_add_edge(g2, x3, a2); eg_add_edge(g2, x3, b2)
106 eg_add_edge(g2, a2, b2)
107 let h2: i64 = gr_propose(g2, 3, 10, ta, tb, ts, st)
108 tot = tot + 1
109 var t2: i64 = 0
110 if gg_has_pair(ta, tb, h2, a2, b2) == 0 { t2 = 1 }
111 if t2 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
112 gw("T2 NEG: an ALREADY-LINKED pair is never proposed (recombination, not rediscovery)\n" as *u8)
113
114 // ---- T3: minscore is a real floor --------------------------------------------------------
115 let h3: i64 = gr_propose(g1, 4, 10, ta, tb, ts, st)
116 tot = tot + 1
117 var t3: i64 = 0
118 if gg_has_pair(ta, tb, h3, a1, b1) == 0 { t3 = 1 }
119 if t3 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
120 gw("T3 minscore floor: cn=3 is withheld when minscore=4 (threshold is honoured)\n" as *u8)
121
122 // ---- T4: a HUB WITNESS contributes nothing (deg > GR_HUB_THR) ----------------------------
123 // H imports P and Q plus enough others to exceed the witness threshold. If hub suppression
124 // were removed, P and Q would gain a shared neighbour from H and become a proposal.
125 let g4: *EcoGraph = gg_new()
126 let p4: i64 = eg_intern(g4, "P" as *u8, 1)
127 let q4: i64 = eg_intern(g4, "Q" as *u8, 1)
128 let hb: i64 = eg_intern(g4, "HUB" as *u8, 3)
129 eg_add_edge(g4, hb, p4); eg_add_edge(g4, hb, q4)
130 var f: i64 = 0
131 while f < GG_WITNESS_DEG {
132 let ln: i64 = gg_name(nm, 100 + f)
133 let fx: i64 = eg_intern(g4, nm, ln)
134 eg_add_edge(g4, hb, fx)
135 f = f + 1
136 }
137 let h4: i64 = gr_propose(g4, 1, 10, ta, tb, ts, st)
138 tot = tot + 1
139 var t4: i64 = 0
140 if gg_has_pair(ta, tb, h4, p4, q4) == 0 { if st[1] >= 1 { t4 = 1 } }
141 if t4 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
142 gw("T4 hub WITNESS suppressed: a universal importer is evidence of nothing (hubs_skipped>=1)\n" as *u8)
143
144 // ---- T5: a HUB ENDPOINT is never a candidate (deg > GR_ENDPOINT_THR) ---------------------
145 // THE REGRESSION THAT ACTUALLY HAPPENED: the first live run filled 6 of the top 20 with
146 // nx_syscalls (Ca=14084) because only WITNESS hubs were suppressed. R is a hub endpoint here.
147 let g5: *EcoGraph = gg_new()
148 let r5: i64 = eg_intern(g5, "R" as *u8, 1)
149 let s5: i64 = eg_intern(g5, "S" as *u8, 1)
150 let w5: i64 = eg_intern(g5, "W" as *u8, 1)
151 eg_add_edge(g5, w5, r5); eg_add_edge(g5, w5, s5)
152 var e5: i64 = 0
153 while e5 < GG_ENDPOINT_DEG {
154 let ln2: i64 = gg_name(nm, 1000 + e5)
155 let nx5: i64 = eg_intern(g5, nm, ln2)
156 eg_add_edge(g5, nx5, r5)
157 e5 = e5 + 1
158 }
159 let h5: i64 = gr_propose(g5, 1, 10, ta, tb, ts, st)
160 tot = tot + 1
161 var t5: i64 = 0
162 if gg_has_pair(ta, tb, h5, r5, s5) == 0 { if st[4] >= 1 { t5 = 1 } }
163 if t5 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
164 gw("T5 hub ENDPOINT suppressed: infrastructure everyone imports is not a candidate (>=1 suppressed)\n" as *u8)
165
166 // ---- T6: results are DESCENDING by score -------------------------------------------------
167 // A-B share 3 witnesses, A-C share 2 -> A-B must outrank A-C.
168 let h6: i64 = gr_propose(g1, 2, 10, ta, tb, ts, st)
169 tot = tot + 1
170 var t6: i64 = 0
171 if h6 >= 2 {
172 var ord: i64 = 1
173 var i6: i64 = 1
174 while i6 < h6 { if ts[i6 - 1] < ts[i6] { ord = 0 } i6 = i6 + 1 }
175 if ord == 1 { if ts[0] == 3 { t6 = 1 } }
176 }
177 if t6 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
178 gw("T6 ranking: proposals come back DESCENDING by shared-neighbour count, strongest first\n" as *u8)
179
180 // ---- T7: a degenerate graph yields nothing (main turns this into REFUSE exit 2) -----------
181 let g7: *EcoGraph = gg_new()
182 eg_intern(g7, "only" as *u8, 4)
183 let h7: i64 = gr_propose(g7, 1, 10, ta, tb, ts, st)
184 tot = tot + 1
185 var t7: i64 = 0
186 if h7 == 0 { t7 = 1 }
187 if t7 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
188 gw("T7 degenerate graph (1 node, 0 edges) proposes NOTHING -- never invents an opportunity\n" as *u8)
189
190 gw("\n=== nx_atlas_graphrec_gate " as *u8)
191 gg_num(pass)
192 gw("/" as *u8)
193 gg_num(tot)
194 gw(" ===\n" as *u8)
195 if pass == tot {
196 gw("GRAPHREC GREEN -- scoring proven on synthetic graphs (linked-pair NEG + both hub rules)\n" as *u8)
197 return 0
198 }
199 gw("GRAPHREC RED\n" as *u8)
200 return 1
201}