code wiki / _hdl_build / nx_eco_graph_card.nx
nx_eco_graph_card.nx source
↩ module page · 632 lines · 34879 B
1// nx_eco_graph_card.nx -- the FAMILY-TREE CARD for organs (operator 2026-07-16: "like family tree... cards
2// ...see how intertwined they are" + "its supposed to be COMPREHENSIVE"). EVERY organ gets a card -- not a
3// hub sample. One card = one organ's person-page: identity + generation, PARENTS (imports), CHILDREN
4// (importers), PARTNERS (co-parents of its children), SIBLINGS-per-parent, lineage. Zero-JS HTML; cards
5// link card-to-card; per-letter DIRECTORY pages make all ~16k discoverable.
6// Usage: nx_eco_graph_card <store> <seed> <out.html> one card (explicit)
7// nx_eco_graph_card <seed> one card (MCP mode: pinned paths)
8// nx_eco_graph_card <store> --all <outdir> [hubfile] EVERY card + directory (comprehensive)
9// license_tier: ORIGINAL expect_exit:0
10import "nx_syscalls.nx"
11import "nx_eco_graph.nx"
12
13func cslen(s: *u8) -> i64 { var n:i64=0; while s[n]!=(0 as u8){n=n+1} return n }
14func cw(fd: i64, s: *u8) -> i64 { sys_write(fd, s, cslen(s)); return 0 }
15func cn(fd: i64, v: i64) -> i64 { let b:*u8=sys_mmap(24); var m:i64=v; if m<0{sys_write(fd,"-" as *u8,1);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(fd,b,k); return 0 }
16func cname(fd: i64, g: *EcoGraph, idx: i64) -> i64 {
17 let off: i64 = g.node_off[idx]
18 var n: i64 = 0
19 while g.arena[off+n] != (0 as u8) { n = n + 1 }
20 sys_write(fd, ((g.arena as i64)+off) as *u8, n)
21 return 0
22}
23func cshort(fd: i64, g: *EcoGraph, idx: i64) -> i64 {
24 let off: i64 = g.node_off[idx]
25 var n: i64 = 0
26 while g.arena[off+n] != (0 as u8) { n = n + 1 }
27 var e: i64 = n
28 if n > 3 { if g.arena[off+n-3]==(46 as u8) { if g.arena[off+n-2]==(110 as u8) { if g.arena[off+n-1]==(120 as u8) { e = n - 3 } } } }
29 sys_write(fd, ((g.arena as i64)+off) as *u8, e)
30 return 0
31}
32func cchip(fd: i64, g: *EcoGraph, idx: i64) -> i64 {
33 cw(fd, "<a class=chip href=\"/compare/atlas/card/" as *u8); cname(fd, g, idx); cw(fd, ".html\">" as *u8)
34 cshort(fd, g, idx)
35 cw(fd, "</a>" as *u8)
36 return 0
37}
38// ---- INTELLIGENCE: separate the REAL TREE from validation paperwork and one-off orphans ----
39// does node's name end with the given suffix?
40func nends(g: *EcoGraph, idx: i64, suf: *u8) -> i64 {
41 let off: i64 = g.node_off[idx]
42 var n: i64 = 0
43 while g.arena[off+n] != (0 as u8) { n = n + 1 }
44 let sl: i64 = cslen(suf)
45 if sl > n { return 0 }
46 var i: i64 = 0
47 while i < sl { if g.arena[off+n-sl+i] != suf[i] { return 0 } i = i + 1 }
48 return 1
49}
50// validation artifact (test/gate/bench/demo/probe/smoke) -- paperwork, not a child
51func is_test(g: *EcoGraph, idx: i64) -> i64 {
52 if nends(g, idx, "_test.nx\x00" as *u8) == 1 { return 1 }
53 if nends(g, idx, "_gate.nx\x00" as *u8) == 1 { return 1 }
54 if nends(g, idx, "_bench.nx\x00" as *u8) == 1 { return 1 }
55 if nends(g, idx, "_demo.nx\x00" as *u8) == 1 { return 1 }
56 if nends(g, idx, "_probe.nx\x00" as *u8) == 1 { return 1 }
57 if nends(g, idx, "_smoke.nx\x00" as *u8) == 1 { return 1 }
58 return 0
59}
60// status codes: 0=TRUNK (real children build on it) 1=SHIPPED LEAF (installed elf) 2=VALIDATION (is a test)
61// 3=TESTED-ONLY (only test children, not installed) 4=ORPHAN (nothing builds on it, not installed)
62func nstatus(g: *EcoGraph, idx: i64, inst: *u8) -> i64 {
63 if is_test(g, idx) == 1 { return 2 }
64 var rc: i64 = 0
65 var tc: i64 = 0
66 var p: i64 = g.in_head[idx]
67 while p < g.in_head[idx+1] {
68 if is_test(g, g.in_list[p]) == 1 { tc = tc + 1 } else { rc = rc + 1 }
69 p = p + 1
70 }
71 if rc > 0 { return 0 }
72 if inst[idx] == (1 as u8) { return 1 }
73 if tc > 0 { return 3 }
74 return 4
75}
76func wstatus(fd: i64, st: i64) -> i64 {
77 if st == 0 { cw(fd, "<span style=\"background:#2a3f1e;color:#a5e07a;border:1px solid #4a6a2e;border-radius:8px;padding:3px 10px;font-size:.8rem\">TRUNK — part of the living tree</span>" as *u8) }
78 if st == 1 { cw(fd, "<span style=\"background:#1e3346;color:#7fd1ff;border:1px solid #2e5a7a;border-radius:8px;padding:3px 10px;font-size:.8rem\">SHIPPED LEAF — installed product, nothing builds on it yet</span>" as *u8) }
79 if st == 2 { cw(fd, "<span style=\"background:#26304a;color:#8a97ad;border:1px solid #3a4a6a;border-radius:8px;padding:3px 10px;font-size:.8rem\">VALIDATION — a test/gate, paperwork for its subject</span>" as *u8) }
80 if st == 3 { cw(fd, "<span style=\"background:#3a3320;color:#e6c86a;border:1px solid #6a5a2e;border-radius:8px;padding:3px 10px;font-size:.8rem\">TESTED-ONLY — has validation but nothing builds on it and it is not installed</span>" as *u8) }
81 if st == 4 { cw(fd, "<span style=\"background:#40222a;color:#e08a9a;border:1px solid #6a2e3a;border-radius:8px;padding:3px 10px;font-size:.8rem\">ORPHAN — one-off: no children, no install, no tests</span>" as *u8) }
82 return 0
83}
84// BFS generations from true roots (shortest import-hops; cycle-safe). Returns maxgen.
85func card_gens(g: *EcoGraph, gen: *i64) -> i64 {
86 let n: i64 = g.node_count
87 let work: *i64 = sys_mmap((n+2)*8) as *i64
88 var i: i64 = 0
89 while i < n { gen[i] = 0 - 1; i = i + 1 }
90 var wt: i64 = 0
91 i = 0
92 while i < n {
93 if g.out_head[i] == g.out_head[i+1] { gen[i] = 0; work[wt] = i; wt = wt + 1 }
94 i = i + 1
95 }
96 var wh: i64 = 0
97 while wh < wt {
98 let v: i64 = work[wh]
99 var p: i64 = g.in_head[v]; let e: i64 = g.in_head[v+1]
100 while p < e {
101 let u: i64 = g.in_list[p]
102 if gen[u] < 0 { gen[u] = gen[v] + 1; work[wt] = u; wt = wt + 1 }
103 p = p + 1
104 }
105 wh = wh + 1
106 }
107 var mx: i64 = 0
108 i = 0
109 while i < n { if gen[i] < 0 { gen[i] = 0 } if gen[i] > mx { mx = gen[i] } i = i + 1 }
110 return mx
111}
112
113// ---- emit ONE card to fd. seen = scratch byte map (n bytes, cleared inside). hasimg: lineage img vs MCP note. ----
114func card_emit(g: *EcoGraph, gen: *i64, maxgen: i64, me: i64, fd: i64, seen: *u8, hasimg: i64, inst: *u8) -> i64 {
115 let n: i64 = g.node_count
116 let st: i64 = nstatus(g, me, inst)
117 cw(fd, "<!doctype html><html lang=en><head><meta charset=utf-8><meta name=viewport content=\"width=device-width,initial-scale=1\"><title>" as *u8)
118 cshort(fd, g, me)
119 cw(fd, " — organ card</title><style>body{margin:0;background:#0b0e16;color:#e8ecf6;font:15px/1.6 -apple-system,Segoe UI,system-ui,sans-serif}.wrap{max-width:980px;margin:0 auto;padding:24px 18px 70px}.crumb{font-size:.8rem;color:#8a97ad;margin-bottom:10px}a{color:#c9a0ff;text-decoration:none}a:hover{text-decoration:underline}h1{font-size:26px;margin:0 0 4px}.sub{color:#8a97ad;margin:0 0 16px}h2{font-size:12px;letter-spacing:.13em;text-transform:uppercase;color:#c9a0ff;margin:24px 0 10px;border-bottom:1px solid #222c44;padding-bottom:6px}.stats{display:flex;gap:12px;flex-wrap:wrap;margin:14px 0}.st{background:#141a26;border:1px solid #26304a;border-radius:12px;padding:10px 16px}.st b{font-size:22px;display:block;color:#e8ecf6}.st span{color:#8a97ad;font-size:.78rem}.chip{display:inline-block;background:#141a26;border:1px solid #26304a;border-radius:9px;padding:5px 11px;margin:3px 5px 3px 0;color:#cdd6e6;font-size:.88rem}.chip:hover{border-color:#c9a0ff}.note{color:#8a97ad;font-size:.85rem}.imgwrap{background:#0d1220;border:1px solid #222c44;border-radius:14px;overflow-x:auto;margin-top:8px}</style></head><body><div class=wrap>" as *u8)
120 cw(fd, "<p class=crumb><a href=/>Nishi Family</a> › <a href=/compare/atlas>Atlas</a> › <a href=/compare/atlas/tree>Family Tree</a> › <a href=/compare/atlas/card/index.html>Directory</a> › Card</p>" as *u8)
121 cw(fd, "<h1>" as *u8); cshort(fd, g, me); cw(fd, "</h1>" as *u8)
122 cw(fd, "<p style=\"margin:2px 0 10px\">" as *u8); wstatus(fd, st); cw(fd, "</p>" as *u8)
123 cw(fd, "<p class=sub>Organ card — parents it builds on, children built on it, and how intertwined it is with the rest of the ecosystem.</p>" as *u8)
124 let np: i64 = g.out_head[me+1] - g.out_head[me]
125 let nc: i64 = g.in_head[me+1] - g.in_head[me]
126 var nrc: i64 = 0
127 var ntc: i64 = 0
128 var p0: i64 = g.in_head[me]
129 while p0 < g.in_head[me+1] {
130 if is_test(g, g.in_list[p0]) == 1 { ntc = ntc + 1 } else { nrc = nrc + 1 }
131 p0 = p0 + 1
132 }
133 cw(fd, "<div class=stats>" as *u8)
134 cw(fd, "<div class=st><b>gen " as *u8); cn(fd, gen[me]); cw(fd, "</b><span>import-hops from god (of " as *u8); cn(fd, maxgen); cw(fd, ")</span></div>" as *u8)
135 cw(fd, "<div class=st><b>" as *u8); cn(fd, np); cw(fd, "</b><span>parents (imports)</span></div>" as *u8)
136 cw(fd, "<div class=st><b>" as *u8); cn(fd, nc); cw(fd, "</b><span>children (importers)</span></div>" as *u8)
137 cw(fd, "<div class=st><b>" as *u8); cn(fd, eg_ca(g, me)); cw(fd, "</b><span>total descendants reach (Ca)</span></div>" as *u8)
138 cw(fd, "</div>" as *u8)
139 cw(fd, "<h2>Parents — what it builds on</h2><div>" as *u8)
140 var p: i64 = g.out_head[me]
141 while p < g.out_head[me+1] { cchip(fd, g, g.out_list[p]); p = p + 1 }
142 if np == 0 { cw(fd, "<span class=note>none — a true ROOT (gen 0, god-tier primitive)</span>" as *u8) }
143 cw(fd, "</div>" as *u8)
144 // COMPLETE, never truncated (operator law): every child, every test -- the page scrolls.
145 cw(fd, "<h2>Real children — organs built on it (" as *u8); cn(fd, nrc); cw(fd, ", complete)</h2><div>" as *u8)
146 p = g.in_head[me]
147 while p < g.in_head[me+1] {
148 if is_test(g, g.in_list[p]) == 0 { cchip(fd, g, g.in_list[p]) }
149 p = p + 1
150 }
151 if nrc == 0 { cw(fd, "<span class=note>none — nothing builds on it (leaf)</span>" as *u8) }
152 cw(fd, "</div>" as *u8)
153 cw(fd, "<h2>Validation — its tests/gates (" as *u8); cn(fd, ntc); cw(fd, ", complete)</h2><div>" as *u8)
154 p = g.in_head[me]
155 while p < g.in_head[me+1] {
156 if is_test(g, g.in_list[p]) == 1 { cchip(fd, g, g.in_list[p]) }
157 p = p + 1
158 }
159 if ntc == 0 { cw(fd, "<span class=note>none — no test/gate imports this organ</span>" as *u8) }
160 cw(fd, "</div>" as *u8)
161 // partners: co-parents of my children
162 var i: i64 = 0
163 while i < n { seen[i] = 0 as u8; i = i + 1 }
164 seen[me] = 1 as u8
165 var partners: i64 = 0
166 cw(fd, "<h2>Partners — co-parents of its children (complete)</h2><div>" as *u8)
167 p = g.in_head[me]
168 while p < g.in_head[me+1] {
169 let ch: i64 = g.in_list[p]
170 var q: i64 = g.out_head[ch]
171 while q < g.out_head[ch+1] {
172 let op: i64 = g.out_list[q]
173 if seen[op] == (0 as u8) {
174 seen[op] = 1 as u8
175 cchip(fd, g, op)
176 partners = partners + 1
177 }
178 q = q + 1
179 }
180 p = p + 1
181 }
182 if partners == 0 { cw(fd, "<span class=note>none — its children depend on it alone</span>" as *u8) }
183 cw(fd, "</div><p class=note>" as *u8); cn(fd, partners); cw(fd, " distinct organs co-parent its children — the intertwining measure.</p>" as *u8)
184 cw(fd, "<h2>Siblings — per parent</h2><div>" as *u8)
185 p = g.out_head[me]
186 var srows: i64 = 0
187 while p < g.out_head[me+1] {
188 let par: i64 = g.out_list[p]
189 let sibs: i64 = g.in_head[par+1] - g.in_head[par] - 1
190 cw(fd, "<span class=chip>via " as *u8); cshort(fd, g, par); cw(fd, ": " as *u8); cn(fd, sibs); cw(fd, " siblings</span>" as *u8)
191 srows = srows + 1
192 p = p + 1
193 }
194 if srows == 0 { cw(fd, "<span class=note>root — no parents, no siblings</span>" as *u8) }
195 cw(fd, "</div>" as *u8)
196 cw(fd, "<h2>Lineage — roots to god</h2>" as *u8)
197 if hasimg == 1 {
198 cw(fd, "<div class=imgwrap><img src=\"/compare/atlas/tree/lineage_" as *u8); cname(fd, g, me); cw(fd, ".png\" alt=\"lineage family tree of " as *u8); cshort(fd, g, me); cw(fd, "\" style=\"display:block;max-width:100%;height:auto\"></div>" as *u8)
199 } else {
200 cw(fd, "<p class=note>Lineage image renders on demand — one MCP call: <code>nx_eco_graph_png [\"" as *u8); cname(fd, g, me); cw(fd, "\"]</code> → it appears here. Or read the parents chain above card-by-card.</p>" as *u8)
201 }
202 cw(fd, "<p class=sub style=\"margin-top:26px\"><a href=\"/compare/atlas/explore/#" as *u8); cname(fd, g, me); cw(fd, "\" style=\"background:#1a2136;border:1px solid #c9a0ff;border-radius:9px;padding:6px 12px\">✥ open in the TREE EXPLORER</a> · <a href=/compare/atlas/tree>← the family tree</a> · <a href=/compare/atlas/card/index.html>directory</a> · <a href=/compare/atlas>Atlas home</a></p>" as *u8)
203 cw(fd, "</div></body></html>" as *u8)
204 return partners
205}
206
207// path join outdir + "/" + name + suffix into buf
208func mkpath(buf: *u8, outdir: *u8, g: *EcoGraph, idx: i64, suffix: *u8) -> i64 {
209 var o: i64 = 0
210 var i: i64 = 0
211 while outdir[i] != (0 as u8) { buf[o] = outdir[i]; o = o + 1; i = i + 1 }
212 buf[o] = 47 as u8; o = o + 1
213 let off: i64 = g.node_off[idx]
214 i = 0
215 while g.arena[off+i] != (0 as u8) { buf[o] = g.arena[off+i]; o = o + 1; i = i + 1 }
216 i = 0
217 while suffix[i] != (0 as u8) { buf[o] = suffix[i]; o = o + 1; i = i + 1 }
218 buf[o] = 0 as u8
219 return o
220}
221// directory bucket for a node: first letter after an "nx_" prefix (else first char); a-z -> 0..25, other -> 26
222func dbucket(g: *EcoGraph, idx: i64) -> i64 {
223 let off: i64 = g.node_off[idx]
224 var c: i64 = g.arena[off] as i64
225 if c == 110 { if (g.arena[off+1] as i64) == 120 { if (g.arena[off+2] as i64) == 95 { c = g.arena[off+3] as i64 } } }
226 if c >= 65 { if c <= 90 { c = c + 32 } }
227 if c >= 97 { if c <= 122 { return c - 97 } }
228 return 26
229}
230// name compare for sort (arena strings)
231func ncmp(g: *EcoGraph, a: i64, b: i64) -> i64 {
232 let oa: i64 = g.node_off[a]
233 let ob: i64 = g.node_off[b]
234 var i: i64 = 0
235 while 1 == 1 {
236 let ca: i64 = g.arena[oa+i] as i64
237 let cb: i64 = g.arena[ob+i] as i64
238 if ca < cb { return 0 - 1 }
239 if ca > cb { return 1 }
240 if ca == 0 { return 0 }
241 i = i + 1
242 }
243 return 0
244}
245
246func s_eq(a: *u8, b: *u8) -> i64 {
247 var i: i64 = 0
248 while 1 == 1 {
249 if a[i] != b[i] { return 0 }
250 if a[i] == (0 as u8) { return 1 }
251 i = i + 1
252 }
253 return 0
254}
255
256func main(argc: i64, argv: *i64) -> i64 {
257 // ---------- COMPREHENSIVE MODES ----------
258 // <store> --all <outdir> [hubfile] [instfile] explicit (local pipelines)
259 // --all-live THE SOVEREIGN ONE-CALL REGEN (MCP, CWD=nishihost):
260 // pinned store + docroot outdir, per-node lineage-PNG
261 // stat (docroot is local), installed evidence from
262 // knowledge/status/installed_twins.txt. No WSL, no tar,
263 // no ssh -- the whole atlas regenerates in one tools/call.
264 var allmode: i64 = 0
265 var astore: *u8 = 0 as *u8
266 var aout: *u8 = 0 as *u8
267 var ahub: *u8 = 0 as *u8
268 var ainst: *u8 = 0 as *u8
269 if argc >= 4 {
270 let a2: *u8 = argv[2] as *u8
271 if a2[0] == (45 as u8) { if a2[1] == (45 as u8) { allmode = 1 } }
272 if allmode == 1 {
273 astore = argv[1] as *u8
274 aout = argv[3] as *u8
275 if argc >= 5 { ahub = argv[4] as *u8 }
276 if argc >= 6 { ainst = argv[5] as *u8 }
277 }
278 }
279 if argc >= 2 {
280 if s_eq(argv[1] as *u8, "--all-live\x00" as *u8) == 1 {
281 allmode = 2
282 astore = "knowledge/store/ecograph_full\x00" as *u8
283 aout = "sites/nishifamily/compare/atlas/card\x00" as *u8
284 ainst = "knowledge/status/installed_twins.txt\x00" as *u8
285 }
286 }
287 if allmode >= 1 {
288 let g: *EcoGraph = eg_load(astore)
289 if (g as i64) == 0 { cw(1, "ERROR store not found\n" as *u8); return 3 }
290 let n: i64 = g.node_count
291 let gen: *i64 = sys_mmap((n+2)*8) as *i64
292 let maxgen: i64 = card_gens(g, gen)
293 let seen: *u8 = sys_mmap(n + 2)
294 // installed set (argv[5] = file of .nx names with an installed elf twin): SHIPPED-LEAF evidence
295 let inst: *u8 = sys_mmap(n + 2)
296 var ii: i64 = 0
297 while ii < n { inst[ii] = 0 as u8; ii = ii + 1 }
298 if (ainst as i64) != 0 {
299 let ilen: *i64 = sys_mmap(16) as *i64
300 let ibuf: *u8 = sys_read_file(ainst, ilen)
301 if ilen[0] > 0 {
302 var s0: i64 = 0
303 var q0: i64 = 0
304 while q0 <= ilen[0] {
305 var iend: i64 = 0
306 if q0 == ilen[0] { iend = 1 } else { if ibuf[q0] == (10 as u8) { iend = 1 } }
307 if iend == 1 {
308 var e0: i64 = q0
309 if e0 > s0 { if ibuf[e0-1] == (13 as u8) { e0 = e0 - 1 } }
310 if e0 > s0 {
311 let ix0: i64 = eg_find(g, ((ibuf as i64)+s0) as *u8, e0 - s0)
312 if ix0 >= 0 { inst[ix0] = 1 as u8 }
313 }
314 s0 = q0 + 1
315 }
316 q0 = q0 + 1
317 }
318 }
319 }
320 // hub set (pre-rendered lineage PNGs): mark nodes named in hubfile
321 let hub: *u8 = sys_mmap(n + 2)
322 var hi: i64 = 0
323 while hi < n { hub[hi] = 0 as u8; hi = hi + 1 }
324 if (ahub as i64) != 0 {
325 let hlen: *i64 = sys_mmap(16) as *i64
326 let hbuf: *u8 = sys_read_file(ahub, hlen)
327 if hlen[0] > 0 {
328 var s: i64 = 0
329 var q: i64 = 0
330 while q <= hlen[0] {
331 var isend: i64 = 0
332 if q == hlen[0] { isend = 1 } else { if hbuf[q] == (10 as u8) { isend = 1 } }
333 if isend == 1 {
334 var e: i64 = q
335 if e > s { if hbuf[e-1] == (13 as u8) { e = e - 1 } }
336 if e > s {
337 let idx: i64 = eg_find(g, ((hbuf as i64)+s) as *u8, e - s)
338 if idx >= 0 { hub[idx] = 1 as u8 }
339 }
340 s = q + 1
341 }
342 q = q + 1
343 }
344 }
345 }
346 let outdir: *u8 = aout
347 let pbuf: *u8 = sys_mmap(512)
348 let statbuf: *u8 = sys_mmap(400)
349 let statlen: *i64 = sys_mmap(16) as *i64
350 var made: i64 = 0
351 var me: i64 = 0
352 while me < n {
353 // hasimg: hubfile mark (explicit mode) OR live docroot stat (--all-live: the PNGs are LOCAL)
354 var him: i64 = hub[me] as i64
355 if allmode == 2 {
356 var so: i64 = 0
357 let spre: *u8 = "sites/nishifamily/compare/atlas/tree/lineage_\x00" as *u8
358 var sk: i64 = 0
359 while spre[sk] != (0 as u8) { statbuf[so] = spre[sk]; so = so + 1; sk = sk + 1 }
360 let soff: i64 = g.node_off[me]
361 sk = 0
362 while g.arena[soff+sk] != (0 as u8) { statbuf[so] = g.arena[soff+sk]; so = so + 1; sk = sk + 1 }
363 let ssuf: *u8 = ".png\x00" as *u8
364 sk = 0
365 while ssuf[sk] != (0 as u8) { statbuf[so] = ssuf[sk]; so = so + 1; sk = sk + 1 }
366 statbuf[so] = 0 as u8
367 statlen[0] = 0
368 sys_read_file(statbuf, statlen)
369 him = 0
370 if statlen[0] > 0 { him = 1 }
371 }
372 mkpath(pbuf, outdir, g, me, ".html\x00" as *u8)
373 let fd: i64 = sys_openat_wr(pbuf, 0x1a4)
374 if fd >= 0 {
375 card_emit(g, gen, maxgen, me, fd, seen, him, inst)
376 sys_close(fd)
377 made = made + 1
378 }
379 // ---- the card's UNIT-FACE: fam_<name>.json for the interactive explorer (parents + top
380 // children by Ca + class/gen/ca) -- data sovereign-generated, interaction JS is last-mile ----
381 var fo: i64 = 0
382 var fi: i64 = 0
383 while outdir[fi] != (0 as u8) { pbuf[fo] = outdir[fi]; fo = fo + 1; fi = fi + 1 }
384 let fpre: *u8 = "/fam_\x00" as *u8
385 fi = 0
386 while fpre[fi] != (0 as u8) { pbuf[fo] = fpre[fi]; fo = fo + 1; fi = fi + 1 }
387 let foff: i64 = g.node_off[me]
388 fi = 0
389 while g.arena[foff+fi] != (0 as u8) { pbuf[fo] = g.arena[foff+fi]; fo = fo + 1; fi = fi + 1 }
390 let fsuf: *u8 = ".json\x00" as *u8
391 fi = 0
392 while fsuf[fi] != (0 as u8) { pbuf[fo] = fsuf[fi]; fo = fo + 1; fi = fi + 1 }
393 pbuf[fo] = 0 as u8
394 let jd: i64 = sys_openat_wr(pbuf, 0x1a4)
395 if jd >= 0 {
396 cw(jd, "{\"name\":\"" as *u8); cname(jd, g, me)
397 cw(jd, "\",\"status\":" as *u8); cn(jd, nstatus(g, me, inst))
398 cw(jd, ",\"gen\":" as *u8); cn(jd, gen[me])
399 cw(jd, ",\"ca\":" as *u8); cn(jd, eg_ca(g, me))
400 // parents (all, with class)
401 cw(jd, ",\"parents\":[" as *u8)
402 var jp: i64 = g.out_head[me]
403 var first: i64 = 1
404 while jp < g.out_head[me+1] {
405 if first == 0 { cw(jd, "," as *u8) }
406 first = 0
407 cw(jd, "{\"n\":\"" as *u8); cname(jd, g, g.out_list[jp])
408 cw(jd, "\",\"s\":" as *u8); cn(jd, nstatus(g, g.out_list[jp], inst))
409 cw(jd, ",\"ca\":" as *u8); cn(jd, eg_ca(g, g.out_list[jp])); cw(jd, "}" as *u8)
410 jp = jp + 1
411 }
412 cw(jd, "]" as *u8)
413 // COMPLETE children + COMPLETE tests (operator law: no truncation -- the client sorts/filters)
414 var creal: i64 = 0
415 var ctst: i64 = 0
416 jp = g.in_head[me]
417 while jp < g.in_head[me+1] {
418 if is_test(g, g.in_list[jp]) == 1 { ctst = ctst + 1 } else { creal = creal + 1 }
419 jp = jp + 1
420 }
421 cw(jd, ",\"children_total\":" as *u8); cn(jd, creal)
422 cw(jd, ",\"tests_total\":" as *u8); cn(jd, ctst)
423 cw(jd, ",\"children\":[" as *u8)
424 first = 1
425 jp = g.in_head[me]
426 while jp < g.in_head[me+1] {
427 let ch: i64 = g.in_list[jp]
428 if is_test(g, ch) == 0 {
429 if first == 0 { cw(jd, "," as *u8) }
430 first = 0
431 cw(jd, "{\"n\":\"" as *u8); cname(jd, g, ch)
432 cw(jd, "\",\"s\":" as *u8); cn(jd, nstatus(g, ch, inst))
433 cw(jd, ",\"ca\":" as *u8); cn(jd, eg_ca(g, ch)); cw(jd, "}" as *u8)
434 }
435 jp = jp + 1
436 }
437 cw(jd, "],\"tests\":[" as *u8)
438 first = 1
439 jp = g.in_head[me]
440 while jp < g.in_head[me+1] {
441 let ch: i64 = g.in_list[jp]
442 if is_test(g, ch) == 1 {
443 if first == 0 { cw(jd, "," as *u8) }
444 first = 0
445 cw(jd, "{\"n\":\"" as *u8); cname(jd, g, ch)
446 cw(jd, "\",\"ca\":" as *u8); cn(jd, eg_ca(g, ch)); cw(jd, "}" as *u8)
447 }
448 jp = jp + 1
449 }
450 cw(jd, "]}" as *u8)
451 sys_close(jd)
452 }
453 me = me + 1
454 }
455 // ---- directory: 27 bucket pages + index ----
456 let bcnt: *i64 = sys_mmap(28*8) as *i64
457 var b: i64 = 0
458 while b < 27 { bcnt[b] = 0; b = b + 1 }
459 var i: i64 = 0
460 while i < n { bcnt[dbucket(g, i)] = bcnt[dbucket(g, i)] + 1; i = i + 1 }
461 let scratch: *i64 = sys_mmap((n+2)*8) as *i64
462 b = 0
463 while b < 27 {
464 // collect bucket members
465 var m: i64 = 0
466 i = 0
467 while i < n { if dbucket(g, i) == b { scratch[m] = i; m = m + 1 } i = i + 1 }
468 // insertion sort by name
469 var s2: i64 = 1
470 while s2 < m {
471 let key: i64 = scratch[s2]
472 var j: i64 = s2 - 1
473 var moving: i64 = 1
474 while moving == 1 {
475 if j < 0 { moving = 0 } else {
476 if ncmp(g, scratch[j], key) > 0 { scratch[j+1] = scratch[j]; j = j - 1 } else { moving = 0 }
477 }
478 }
479 scratch[j+1] = key
480 s2 = s2 + 1
481 }
482 // write dir page
483 var dp: i64 = 0
484 var o: i64 = 0
485 while outdir[o] != (0 as u8) { pbuf[o] = outdir[o]; o = o + 1 }
486 let dn: *u8 = "/dir_\x00" as *u8
487 var k: i64 = 0
488 while dn[k] != (0 as u8) { pbuf[o] = dn[k]; o = o + 1; k = k + 1 }
489 var bc: i64 = 97 + b
490 if b == 26 { bc = 48 }
491 pbuf[o] = bc as u8; o = o + 1
492 let sfx: *u8 = ".html\x00" as *u8
493 k = 0
494 while sfx[k] != (0 as u8) { pbuf[o] = sfx[k]; o = o + 1; k = k + 1 }
495 pbuf[o] = 0 as u8
496 let dfd: i64 = sys_openat_wr(pbuf, 0x1a4)
497 if dfd >= 0 {
498 cw(dfd, "<!doctype html><html lang=en><head><meta charset=utf-8><meta name=viewport content=\"width=device-width,initial-scale=1\"><title>Directory — organ cards</title><style>body{margin:0;background:#0b0e16;color:#e8ecf6;font:15px/1.6 -apple-system,Segoe UI,system-ui,sans-serif}.wrap{max-width:1080px;margin:0 auto;padding:24px 18px 70px}a{color:#c9a0ff;text-decoration:none}a:hover{text-decoration:underline}h1{font-size:24px}.chip{display:inline-block;background:#141a26;border:1px solid #26304a;border-radius:9px;padding:4px 10px;margin:3px 5px 3px 0;color:#cdd6e6;font-size:.85rem}.crumb{font-size:.8rem;color:#8a97ad}</style></head><body><div class=wrap><p class=crumb><a href=/compare/atlas>Atlas</a> › <a href=/compare/atlas/card/index.html>Directory</a> › bucket</p><h1>Cards — " as *u8)
499 cn(dfd, m); cw(dfd, " organs</h1><div>" as *u8)
500 var w: i64 = 0
501 while w < m {
502 cw(dfd, "<a class=chip href=\"/compare/atlas/card/" as *u8); cname(dfd, g, scratch[w]); cw(dfd, ".html\">" as *u8); cshort(dfd, g, scratch[w]); cw(dfd, "</a>" as *u8)
503 w = w + 1
504 }
505 cw(dfd, "</div><p class=crumb style=\"margin-top:20px\"><a href=/compare/atlas/card/index.html>← directory index</a></p></div></body></html>" as *u8)
506 sys_close(dfd)
507 }
508 b = b + 1
509 }
510 // index page
511 var o2: i64 = 0
512 while outdir[o2] != (0 as u8) { pbuf[o2] = outdir[o2]; o2 = o2 + 1 }
513 let ix: *u8 = "/index.html\x00" as *u8
514 var k2: i64 = 0
515 while ix[k2] != (0 as u8) { pbuf[o2] = ix[k2]; o2 = o2 + 1; k2 = k2 + 1 }
516 pbuf[o2] = 0 as u8
517 let xfd: i64 = sys_openat_wr(pbuf, 0x1a4)
518 if xfd >= 0 {
519 cw(xfd, "<!doctype html><html lang=en><head><meta charset=utf-8><meta name=viewport content=\"width=device-width,initial-scale=1\"><title>Organ Card Directory — search every organ</title><style>body{margin:0;background:#0b0e16;color:#e8ecf6;font:15px/1.6 -apple-system,Segoe UI,system-ui,sans-serif}.wrap{max-width:980px;margin:0 auto;padding:24px 18px 70px}a{color:#c9a0ff;text-decoration:none}h1{font-size:26px}.bk{display:inline-block;background:#141a26;border:1px solid #26304a;border-radius:12px;padding:12px 18px;margin:5px;color:#e8ecf6;font-size:1.05rem}.bk b{color:#ffd479}.crumb{font-size:.8rem;color:#8a97ad}#q{width:100%;box-sizing:border-box;background:#141a26;border:1px solid #3a4a6a;border-radius:12px;color:#e8ecf6;font-size:1.1rem;padding:12px 16px;margin:14px 0 10px;outline:none}#q:focus{border-color:#c9a0ff}.chip{display:inline-block;background:#141a26;border:1px solid #26304a;border-radius:9px;padding:4px 10px;margin:3px 5px 3px 0;color:#cdd6e6;font-size:.86rem}.s0{border-color:#4a6a2e}.s1{border-color:#2e5a7a}.s2{opacity:.55}.s3{border-color:#6a5a2e}.s4{border-color:#6a2e3a}.leg{font-size:.78rem;color:#8a97ad;margin:4px 0 14px}.leg i{display:inline-block;width:10px;height:10px;border-radius:3px;margin:0 4px 0 10px;vertical-align:middle}</style></head><body><div class=wrap><p class=crumb><a href=/compare/atlas>Atlas</a> › <a href=/compare/atlas/tree>Family Tree</a> › Directory</p><h1>Every organ has a card — " as *u8)
520 cn(xfd, made)
521 cw(xfd, " cards</h1>" as *u8)
522 // ---- SEARCH (family-tree table stakes): sovereign-generated index, ~30-line vanilla-JS filter = the last mile ----
523 cw(xfd, "<input id=q type=text placeholder=\"search any organ… (2+ letters; status-colored results)\" autofocus><div class=leg><i style=\"background:#4a6a2e\"></i>trunk <i style=\"background:#2e5a7a\"></i>shipped <i style=\"background:#3a4a6a;opacity:.55\"></i>validation <i style=\"background:#6a5a2e\"></i>tested-only <i style=\"background:#6a2e3a\"></i>orphan</div><div id=r></div>" as *u8)
524 cw(xfd, "<p class=crumb>Or browse by first letter (nx_ prefix ignored):</p><div>" as *u8)
525 let cb: *u8 = sys_mmap(4)
526 b = 0
527 while b < 27 {
528 var bc2: i64 = 97 + b
529 if b == 26 { bc2 = 48 }
530 cb[0] = bc2 as u8
531 cw(xfd, "<a class=bk href=\"/compare/atlas/card/dir_" as *u8)
532 sys_write(xfd, cb, 1)
533 cw(xfd, ".html\"><b>" as *u8)
534 sys_write(xfd, cb, 1)
535 cw(xfd, "</b> · " as *u8); cn(xfd, bcnt[b]); cw(xfd, "</a>" as *u8)
536 b = b + 1
537 }
538 cw(xfd, "</div>" as *u8)
539 // the embedded index: one entry per organ "name|status|gen|Ca"
540 cw(xfd, "<script>var I=[" as *u8)
541 i = 0
542 while i < n {
543 cw(xfd, "\"" as *u8)
544 cname(xfd, g, i)
545 cw(xfd, "|" as *u8); cn(xfd, nstatus(g, i, inst))
546 cw(xfd, "|" as *u8); cn(xfd, gen[i])
547 cw(xfd, "|" as *u8); cn(xfd, eg_ca(g, i))
548 cw(xfd, "\"," as *u8)
549 i = i + 1
550 }
551 cw(xfd, "];var q=document.getElementById('q'),r=document.getElementById('r');q.addEventListener('input',function(){var v=q.value.toLowerCase(),o='',c=0;if(v.length<2){r.innerHTML='';return}for(var i=0;i<I.length&&c<200;i++){var p=I[i].split('|');if(p[0].toLowerCase().indexOf(v)>=0){o+='<a class=\"chip s'+p[1]+'\" href=\"/compare/atlas/card/'+p[0]+'.html\">'+p[0].replace(/\\.nx$/,'')+' · gen'+p[2]+' · Ca '+p[3]+'</a>';c++}}r.innerHTML=o||'<span class=crumb>no match</span>';});</script>" as *u8)
552 cw(xfd, "</div></body></html>" as *u8)
553 sys_close(xfd)
554 }
555 cw(1, "ALL-CARDS made=" as *u8); cn(1, made); cw(1, " of " as *u8); cn(1, n); cw(1, " maxgen=" as *u8); cn(1, maxgen); cw(1, "\n" as *u8)
556 return 0
557 }
558
559 // ---------- SINGLE-CARD MODES (explicit + MCP) ----------
560 var storep: *u8 = 0 as *u8
561 var seedp: *u8 = 0 as *u8
562 var outp: *u8 = 0 as *u8
563 if argc >= 4 { storep = argv[1] as *u8; seedp = argv[2] as *u8; outp = argv[3] as *u8 }
564 if argc == 2 {
565 seedp = argv[1] as *u8
566 let sl: i64 = cslen(seedp)
567 if sl < 1 { cw(1, "ERROR empty seed\n" as *u8); return 5 }
568 if sl > 100 { cw(1, "ERROR seed too long\n" as *u8); return 5 }
569 if seedp[0] == (46 as u8) { cw(1, "ERROR leading dot\n" as *u8); return 5 }
570 var si: i64 = 0
571 while si < sl {
572 let c: i64 = seedp[si] as i64
573 var ok: i64 = 0
574 if c >= 97 { if c <= 122 { ok = 1 } }
575 if c >= 65 { if c <= 90 { ok = 1 } }
576 if c >= 48 { if c <= 57 { ok = 1 } }
577 if c == 95 { ok = 1 }
578 if c == 46 { ok = 1 }
579 if ok == 0 { cw(1, "ERROR bad seed char\n" as *u8); return 5 }
580 si = si + 1
581 }
582 storep = "knowledge/store/ecograph_full\x00" as *u8
583 let ob: *u8 = sys_mmap(256)
584 var oo: i64 = 0
585 let pre: *u8 = "sites/nishifamily/compare/atlas/card/\x00" as *u8
586 var pi: i64 = 0
587 while pre[pi] != (0 as u8) { ob[oo] = pre[pi]; oo = oo + 1; pi = pi + 1 }
588 si = 0
589 while si < sl { ob[oo] = seedp[si]; oo = oo + 1; si = si + 1 }
590 let suf: *u8 = ".html\x00" as *u8
591 pi = 0
592 while suf[pi] != (0 as u8) { ob[oo] = suf[pi]; oo = oo + 1; pi = pi + 1 }
593 ob[oo] = 0 as u8
594 outp = ob
595 }
596 if (seedp as i64) == 0 { cw(1, "usage: nx_eco_graph_card <store> <seed> <out.html> | <seed> | <store> --all <outdir> [hubfile]\n" as *u8); return 2 }
597 let g: *EcoGraph = eg_load(storep)
598 if (g as i64) == 0 { cw(1, "ERROR store not found\n" as *u8); return 3 }
599 let me: i64 = eg_find(g, seedp, cslen(seedp))
600 if me < 0 { cw(1, "ERROR seed not in graph\n" as *u8); return 4 }
601 let n: i64 = g.node_count
602 let gen: *i64 = sys_mmap((n+2)*8) as *i64
603 let maxgen: i64 = card_gens(g, gen)
604 let seen: *u8 = sys_mmap(n + 2)
605 let fd: i64 = sys_openat_wr(outp, 0x1a4)
606 if fd < 0 { cw(1, "ERROR cannot open out\n" as *u8); return 6 }
607 let inst1: *u8 = sys_mmap(n + 2)
608 // BY CONSTRUCTION: only reference the lineage PNG if it actually exists on disk (CWD-relative,
609 // works on the NAS where MCP mode runs). A card must never point at a 404-fallback -- that class
610 // was caught LIVE by nx_page_verify (nx_u256 card RED, 2026-07-16). Missing -> the MCP-call note.
611 var hasimg: i64 = 0
612 let ipath: *u8 = sys_mmap(300)
613 var io: i64 = 0
614 let ipre: *u8 = "sites/nishifamily/compare/atlas/tree/lineage_\x00" as *u8
615 var ik: i64 = 0
616 while ipre[ik] != (0 as u8) { ipath[io] = ipre[ik]; io = io + 1; ik = ik + 1 }
617 ik = 0
618 while seedp[ik] != (0 as u8) { ipath[io] = seedp[ik]; io = io + 1; ik = ik + 1 }
619 let isuf: *u8 = ".png\x00" as *u8
620 ik = 0
621 while isuf[ik] != (0 as u8) { ipath[io] = isuf[ik]; io = io + 1; ik = ik + 1 }
622 ipath[io] = 0 as u8
623 let plen: *i64 = sys_mmap(16) as *i64
624 plen[0] = 0
625 sys_read_file(ipath, plen)
626 if plen[0] > 0 { hasimg = 1 }
627 let partners: i64 = card_emit(g, gen, maxgen, me, fd, seen, hasimg, inst1)
628 sys_close(fd)
629 cw(1, "wrote card " as *u8); cw(1, outp); cw(1, " partners=" as *u8); cn(1, partners); cw(1, "\n" as *u8)
630 if argc == 2 { cw(1, "URL https://nishifamily.com/compare/atlas/card/" as *u8); cw(1, seedp); cw(1, ".html\n" as *u8) }
631 return 0
632}