code wiki / _hdl_build / nx_eco_graph_card.nx
nx_eco_graph_card.nx source
↩ module page · 633 lines · 34940 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 if nends(g, idx, "_kat.nx\x00" as *u8) == 1 { return 1 }
59 return 0
60}
61// status codes: 0=TRUNK (real children build on it) 1=SHIPPED LEAF (installed elf) 2=VALIDATION (is a test)
62// 3=TESTED-ONLY (only test children, not installed) 4=ORPHAN (nothing builds on it, not installed)
63func nstatus(g: *EcoGraph, idx: i64, inst: *u8) -> i64 {
64 if is_test(g, idx) == 1 { return 2 }
65 var rc: i64 = 0
66 var tc: i64 = 0
67 var p: i64 = g.in_head[idx]
68 while p < g.in_head[idx+1] {
69 if is_test(g, g.in_list[p]) == 1 { tc = tc + 1 } else { rc = rc + 1 }
70 p = p + 1
71 }
72 if rc > 0 { return 0 }
73 if inst[idx] == (1 as u8) { return 1 }
74 if tc > 0 { return 3 }
75 return 4
76}
77func wstatus(fd: i64, st: i64) -> i64 {
78 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) }
79 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) }
80 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) }
81 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) }
82 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) }
83 return 0
84}
85// BFS generations from true roots (shortest import-hops; cycle-safe). Returns maxgen.
86func card_gens(g: *EcoGraph, gen: *i64) -> i64 {
87 let n: i64 = g.node_count
88 let work: *i64 = sys_mmap((n+2)*8) as *i64
89 var i: i64 = 0
90 while i < n { gen[i] = 0 - 1; i = i + 1 }
91 var wt: i64 = 0
92 i = 0
93 while i < n {
94 if g.out_head[i] == g.out_head[i+1] { gen[i] = 0; work[wt] = i; wt = wt + 1 }
95 i = i + 1
96 }
97 var wh: i64 = 0
98 while wh < wt {
99 let v: i64 = work[wh]
100 var p: i64 = g.in_head[v]; let e: i64 = g.in_head[v+1]
101 while p < e {
102 let u: i64 = g.in_list[p]
103 if gen[u] < 0 { gen[u] = gen[v] + 1; work[wt] = u; wt = wt + 1 }
104 p = p + 1
105 }
106 wh = wh + 1
107 }
108 var mx: i64 = 0
109 i = 0
110 while i < n { if gen[i] < 0 { gen[i] = 0 } if gen[i] > mx { mx = gen[i] } i = i + 1 }
111 return mx
112}
113
114// ---- emit ONE card to fd. seen = scratch byte map (n bytes, cleared inside). hasimg: lineage img vs MCP note. ----
115func card_emit(g: *EcoGraph, gen: *i64, maxgen: i64, me: i64, fd: i64, seen: *u8, hasimg: i64, inst: *u8) -> i64 {
116 let n: i64 = g.node_count
117 let st: i64 = nstatus(g, me, inst)
118 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)
119 cshort(fd, g, me)
120 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)
121 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)
122 cw(fd, "<h1>" as *u8); cshort(fd, g, me); cw(fd, "</h1>" as *u8)
123 cw(fd, "<p style=\"margin:2px 0 10px\">" as *u8); wstatus(fd, st); cw(fd, "</p>" as *u8)
124 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)
125 let np: i64 = g.out_head[me+1] - g.out_head[me]
126 let nc: i64 = g.in_head[me+1] - g.in_head[me]
127 var nrc: i64 = 0
128 var ntc: i64 = 0
129 var p0: i64 = g.in_head[me]
130 while p0 < g.in_head[me+1] {
131 if is_test(g, g.in_list[p0]) == 1 { ntc = ntc + 1 } else { nrc = nrc + 1 }
132 p0 = p0 + 1
133 }
134 cw(fd, "<div class=stats>" as *u8)
135 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)
136 cw(fd, "<div class=st><b>" as *u8); cn(fd, np); cw(fd, "</b><span>parents (imports)</span></div>" as *u8)
137 cw(fd, "<div class=st><b>" as *u8); cn(fd, nc); cw(fd, "</b><span>children (importers)</span></div>" as *u8)
138 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)
139 cw(fd, "</div>" as *u8)
140 cw(fd, "<h2>Parents — what it builds on</h2><div>" as *u8)
141 var p: i64 = g.out_head[me]
142 while p < g.out_head[me+1] { cchip(fd, g, g.out_list[p]); p = p + 1 }
143 if np == 0 { cw(fd, "<span class=note>none — a true ROOT (gen 0, god-tier primitive)</span>" as *u8) }
144 cw(fd, "</div>" as *u8)
145 // COMPLETE, never truncated (operator law): every child, every test -- the page scrolls.
146 cw(fd, "<h2>Real children — organs built on it (" as *u8); cn(fd, nrc); cw(fd, ", complete)</h2><div>" as *u8)
147 p = g.in_head[me]
148 while p < g.in_head[me+1] {
149 if is_test(g, g.in_list[p]) == 0 { cchip(fd, g, g.in_list[p]) }
150 p = p + 1
151 }
152 if nrc == 0 { cw(fd, "<span class=note>none — nothing builds on it (leaf)</span>" as *u8) }
153 cw(fd, "</div>" as *u8)
154 cw(fd, "<h2>Validation — its tests/gates (" as *u8); cn(fd, ntc); cw(fd, ", complete)</h2><div>" as *u8)
155 p = g.in_head[me]
156 while p < g.in_head[me+1] {
157 if is_test(g, g.in_list[p]) == 1 { cchip(fd, g, g.in_list[p]) }
158 p = p + 1
159 }
160 if ntc == 0 { cw(fd, "<span class=note>none — no test/gate imports this organ</span>" as *u8) }
161 cw(fd, "</div>" as *u8)
162 // partners: co-parents of my children
163 var i: i64 = 0
164 while i < n { seen[i] = 0 as u8; i = i + 1 }
165 seen[me] = 1 as u8
166 var partners: i64 = 0
167 cw(fd, "<h2>Partners — co-parents of its children (complete)</h2><div>" as *u8)
168 p = g.in_head[me]
169 while p < g.in_head[me+1] {
170 let ch: i64 = g.in_list[p]
171 var q: i64 = g.out_head[ch]
172 while q < g.out_head[ch+1] {
173 let op: i64 = g.out_list[q]
174 if seen[op] == (0 as u8) {
175 seen[op] = 1 as u8
176 cchip(fd, g, op)
177 partners = partners + 1
178 }
179 q = q + 1
180 }
181 p = p + 1
182 }
183 if partners == 0 { cw(fd, "<span class=note>none — its children depend on it alone</span>" as *u8) }
184 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)
185 cw(fd, "<h2>Siblings — per parent</h2><div>" as *u8)
186 p = g.out_head[me]
187 var srows: i64 = 0
188 while p < g.out_head[me+1] {
189 let par: i64 = g.out_list[p]
190 let sibs: i64 = g.in_head[par+1] - g.in_head[par] - 1
191 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)
192 srows = srows + 1
193 p = p + 1
194 }
195 if srows == 0 { cw(fd, "<span class=note>root — no parents, no siblings</span>" as *u8) }
196 cw(fd, "</div>" as *u8)
197 cw(fd, "<h2>Lineage — roots to god</h2>" as *u8)
198 if hasimg == 1 {
199 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)
200 } else {
201 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)
202 }
203 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)
204 cw(fd, "</div></body></html>" as *u8)
205 return partners
206}
207
208// path join outdir + "/" + name + suffix into buf
209func mkpath(buf: *u8, outdir: *u8, g: *EcoGraph, idx: i64, suffix: *u8) -> i64 {
210 var o: i64 = 0
211 var i: i64 = 0
212 while outdir[i] != (0 as u8) { buf[o] = outdir[i]; o = o + 1; i = i + 1 }
213 buf[o] = 47 as u8; o = o + 1
214 let off: i64 = g.node_off[idx]
215 i = 0
216 while g.arena[off+i] != (0 as u8) { buf[o] = g.arena[off+i]; o = o + 1; i = i + 1 }
217 i = 0
218 while suffix[i] != (0 as u8) { buf[o] = suffix[i]; o = o + 1; i = i + 1 }
219 buf[o] = 0 as u8
220 return o
221}
222// directory bucket for a node: first letter after an "nx_" prefix (else first char); a-z -> 0..25, other -> 26
223func dbucket(g: *EcoGraph, idx: i64) -> i64 {
224 let off: i64 = g.node_off[idx]
225 var c: i64 = g.arena[off] as i64
226 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 } } }
227 if c >= 65 { if c <= 90 { c = c + 32 } }
228 if c >= 97 { if c <= 122 { return c - 97 } }
229 return 26
230}
231// name compare for sort (arena strings)
232func ncmp(g: *EcoGraph, a: i64, b: i64) -> i64 {
233 let oa: i64 = g.node_off[a]
234 let ob: i64 = g.node_off[b]
235 var i: i64 = 0
236 while 1 == 1 {
237 let ca: i64 = g.arena[oa+i] as i64
238 let cb: i64 = g.arena[ob+i] as i64
239 if ca < cb { return 0 - 1 }
240 if ca > cb { return 1 }
241 if ca == 0 { return 0 }
242 i = i + 1
243 }
244 return 0
245}
246
247func s_eq(a: *u8, b: *u8) -> i64 {
248 var i: i64 = 0
249 while 1 == 1 {
250 if a[i] != b[i] { return 0 }
251 if a[i] == (0 as u8) { return 1 }
252 i = i + 1
253 }
254 return 0
255}
256
257func main(argc: i64, argv: *i64) -> i64 {
258 // ---------- COMPREHENSIVE MODES ----------
259 // <store> --all <outdir> [hubfile] [instfile] explicit (local pipelines)
260 // --all-live THE SOVEREIGN ONE-CALL REGEN (MCP, CWD=nishihost):
261 // pinned store + docroot outdir, per-node lineage-PNG
262 // stat (docroot is local), installed evidence from
263 // knowledge/status/installed_twins.txt. No WSL, no tar,
264 // no ssh -- the whole atlas regenerates in one tools/call.
265 var allmode: i64 = 0
266 var astore: *u8 = 0 as *u8
267 var aout: *u8 = 0 as *u8
268 var ahub: *u8 = 0 as *u8
269 var ainst: *u8 = 0 as *u8
270 if argc >= 4 {
271 let a2: *u8 = argv[2] as *u8
272 if a2[0] == (45 as u8) { if a2[1] == (45 as u8) { allmode = 1 } }
273 if allmode == 1 {
274 astore = argv[1] as *u8
275 aout = argv[3] as *u8
276 if argc >= 5 { ahub = argv[4] as *u8 }
277 if argc >= 6 { ainst = argv[5] as *u8 }
278 }
279 }
280 if argc >= 2 {
281 if s_eq(argv[1] as *u8, "--all-live\x00" as *u8) == 1 {
282 allmode = 2
283 astore = "knowledge/store/ecograph_full\x00" as *u8
284 aout = "sites/nishifamily/compare/atlas/card\x00" as *u8
285 ainst = "knowledge/status/installed_twins.txt\x00" as *u8
286 }
287 }
288 if allmode >= 1 {
289 let g: *EcoGraph = eg_load(astore)
290 if (g as i64) == 0 { cw(1, "ERROR store not found\n" as *u8); return 3 }
291 let n: i64 = g.node_count
292 let gen: *i64 = sys_mmap((n+2)*8) as *i64
293 let maxgen: i64 = card_gens(g, gen)
294 let seen: *u8 = sys_mmap(n + 2)
295 // installed set (argv[5] = file of .nx names with an installed elf twin): SHIPPED-LEAF evidence
296 let inst: *u8 = sys_mmap(n + 2)
297 var ii: i64 = 0
298 while ii < n { inst[ii] = 0 as u8; ii = ii + 1 }
299 if (ainst as i64) != 0 {
300 let ilen: *i64 = sys_mmap(16) as *i64
301 let ibuf: *u8 = sys_read_file(ainst, ilen)
302 if ilen[0] > 0 {
303 var s0: i64 = 0
304 var q0: i64 = 0
305 while q0 <= ilen[0] {
306 var iend: i64 = 0
307 if q0 == ilen[0] { iend = 1 } else { if ibuf[q0] == (10 as u8) { iend = 1 } }
308 if iend == 1 {
309 var e0: i64 = q0
310 if e0 > s0 { if ibuf[e0-1] == (13 as u8) { e0 = e0 - 1 } }
311 if e0 > s0 {
312 let ix0: i64 = eg_find(g, ((ibuf as i64)+s0) as *u8, e0 - s0)
313 if ix0 >= 0 { inst[ix0] = 1 as u8 }
314 }
315 s0 = q0 + 1
316 }
317 q0 = q0 + 1
318 }
319 }
320 }
321 // hub set (pre-rendered lineage PNGs): mark nodes named in hubfile
322 let hub: *u8 = sys_mmap(n + 2)
323 var hi: i64 = 0
324 while hi < n { hub[hi] = 0 as u8; hi = hi + 1 }
325 if (ahub as i64) != 0 {
326 let hlen: *i64 = sys_mmap(16) as *i64
327 let hbuf: *u8 = sys_read_file(ahub, hlen)
328 if hlen[0] > 0 {
329 var s: i64 = 0
330 var q: i64 = 0
331 while q <= hlen[0] {
332 var isend: i64 = 0
333 if q == hlen[0] { isend = 1 } else { if hbuf[q] == (10 as u8) { isend = 1 } }
334 if isend == 1 {
335 var e: i64 = q
336 if e > s { if hbuf[e-1] == (13 as u8) { e = e - 1 } }
337 if e > s {
338 let idx: i64 = eg_find(g, ((hbuf as i64)+s) as *u8, e - s)
339 if idx >= 0 { hub[idx] = 1 as u8 }
340 }
341 s = q + 1
342 }
343 q = q + 1
344 }
345 }
346 }
347 let outdir: *u8 = aout
348 let pbuf: *u8 = sys_mmap(512)
349 let statbuf: *u8 = sys_mmap(400)
350 let statlen: *i64 = sys_mmap(16) as *i64
351 var made: i64 = 0
352 var me: i64 = 0
353 while me < n {
354 // hasimg: hubfile mark (explicit mode) OR live docroot stat (--all-live: the PNGs are LOCAL)
355 var him: i64 = hub[me] as i64
356 if allmode == 2 {
357 var so: i64 = 0
358 let spre: *u8 = "sites/nishifamily/compare/atlas/tree/lineage_\x00" as *u8
359 var sk: i64 = 0
360 while spre[sk] != (0 as u8) { statbuf[so] = spre[sk]; so = so + 1; sk = sk + 1 }
361 let soff: i64 = g.node_off[me]
362 sk = 0
363 while g.arena[soff+sk] != (0 as u8) { statbuf[so] = g.arena[soff+sk]; so = so + 1; sk = sk + 1 }
364 let ssuf: *u8 = ".png\x00" as *u8
365 sk = 0
366 while ssuf[sk] != (0 as u8) { statbuf[so] = ssuf[sk]; so = so + 1; sk = sk + 1 }
367 statbuf[so] = 0 as u8
368 statlen[0] = 0
369 sys_read_file(statbuf, statlen)
370 him = 0
371 if statlen[0] > 0 { him = 1 }
372 }
373 mkpath(pbuf, outdir, g, me, ".html\x00" as *u8)
374 let fd: i64 = sys_openat_wr(pbuf, 0x1a4)
375 if fd >= 0 {
376 card_emit(g, gen, maxgen, me, fd, seen, him, inst)
377 sys_close(fd)
378 made = made + 1
379 }
380 // ---- the card's UNIT-FACE: fam_<name>.json for the interactive explorer (parents + top
381 // children by Ca + class/gen/ca) -- data sovereign-generated, interaction JS is last-mile ----
382 var fo: i64 = 0
383 var fi: i64 = 0
384 while outdir[fi] != (0 as u8) { pbuf[fo] = outdir[fi]; fo = fo + 1; fi = fi + 1 }
385 let fpre: *u8 = "/fam_\x00" as *u8
386 fi = 0
387 while fpre[fi] != (0 as u8) { pbuf[fo] = fpre[fi]; fo = fo + 1; fi = fi + 1 }
388 let foff: i64 = g.node_off[me]
389 fi = 0
390 while g.arena[foff+fi] != (0 as u8) { pbuf[fo] = g.arena[foff+fi]; fo = fo + 1; fi = fi + 1 }
391 let fsuf: *u8 = ".json\x00" as *u8
392 fi = 0
393 while fsuf[fi] != (0 as u8) { pbuf[fo] = fsuf[fi]; fo = fo + 1; fi = fi + 1 }
394 pbuf[fo] = 0 as u8
395 let jd: i64 = sys_openat_wr(pbuf, 0x1a4)
396 if jd >= 0 {
397 cw(jd, "{\"name\":\"" as *u8); cname(jd, g, me)
398 cw(jd, "\",\"status\":" as *u8); cn(jd, nstatus(g, me, inst))
399 cw(jd, ",\"gen\":" as *u8); cn(jd, gen[me])
400 cw(jd, ",\"ca\":" as *u8); cn(jd, eg_ca(g, me))
401 // parents (all, with class)
402 cw(jd, ",\"parents\":[" as *u8)
403 var jp: i64 = g.out_head[me]
404 var first: i64 = 1
405 while jp < g.out_head[me+1] {
406 if first == 0 { cw(jd, "," as *u8) }
407 first = 0
408 cw(jd, "{\"n\":\"" as *u8); cname(jd, g, g.out_list[jp])
409 cw(jd, "\",\"s\":" as *u8); cn(jd, nstatus(g, g.out_list[jp], inst))
410 cw(jd, ",\"ca\":" as *u8); cn(jd, eg_ca(g, g.out_list[jp])); cw(jd, "}" as *u8)
411 jp = jp + 1
412 }
413 cw(jd, "]" as *u8)
414 // COMPLETE children + COMPLETE tests (operator law: no truncation -- the client sorts/filters)
415 var creal: i64 = 0
416 var ctst: i64 = 0
417 jp = g.in_head[me]
418 while jp < g.in_head[me+1] {
419 if is_test(g, g.in_list[jp]) == 1 { ctst = ctst + 1 } else { creal = creal + 1 }
420 jp = jp + 1
421 }
422 cw(jd, ",\"children_total\":" as *u8); cn(jd, creal)
423 cw(jd, ",\"tests_total\":" as *u8); cn(jd, ctst)
424 cw(jd, ",\"children\":[" as *u8)
425 first = 1
426 jp = g.in_head[me]
427 while jp < g.in_head[me+1] {
428 let ch: i64 = g.in_list[jp]
429 if is_test(g, ch) == 0 {
430 if first == 0 { cw(jd, "," as *u8) }
431 first = 0
432 cw(jd, "{\"n\":\"" as *u8); cname(jd, g, ch)
433 cw(jd, "\",\"s\":" as *u8); cn(jd, nstatus(g, ch, inst))
434 cw(jd, ",\"ca\":" as *u8); cn(jd, eg_ca(g, ch)); cw(jd, "}" as *u8)
435 }
436 jp = jp + 1
437 }
438 cw(jd, "],\"tests\":[" as *u8)
439 first = 1
440 jp = g.in_head[me]
441 while jp < g.in_head[me+1] {
442 let ch: i64 = g.in_list[jp]
443 if is_test(g, ch) == 1 {
444 if first == 0 { cw(jd, "," as *u8) }
445 first = 0
446 cw(jd, "{\"n\":\"" as *u8); cname(jd, g, ch)
447 cw(jd, "\",\"ca\":" as *u8); cn(jd, eg_ca(g, ch)); cw(jd, "}" as *u8)
448 }
449 jp = jp + 1
450 }
451 cw(jd, "]}" as *u8)
452 sys_close(jd)
453 }
454 me = me + 1
455 }
456 // ---- directory: 27 bucket pages + index ----
457 let bcnt: *i64 = sys_mmap(28*8) as *i64
458 var b: i64 = 0
459 while b < 27 { bcnt[b] = 0; b = b + 1 }
460 var i: i64 = 0
461 while i < n { bcnt[dbucket(g, i)] = bcnt[dbucket(g, i)] + 1; i = i + 1 }
462 let scratch: *i64 = sys_mmap((n+2)*8) as *i64
463 b = 0
464 while b < 27 {
465 // collect bucket members
466 var m: i64 = 0
467 i = 0
468 while i < n { if dbucket(g, i) == b { scratch[m] = i; m = m + 1 } i = i + 1 }
469 // insertion sort by name
470 var s2: i64 = 1
471 while s2 < m {
472 let key: i64 = scratch[s2]
473 var j: i64 = s2 - 1
474 var moving: i64 = 1
475 while moving == 1 {
476 if j < 0 { moving = 0 } else {
477 if ncmp(g, scratch[j], key) > 0 { scratch[j+1] = scratch[j]; j = j - 1 } else { moving = 0 }
478 }
479 }
480 scratch[j+1] = key
481 s2 = s2 + 1
482 }
483 // write dir page
484 var dp: i64 = 0
485 var o: i64 = 0
486 while outdir[o] != (0 as u8) { pbuf[o] = outdir[o]; o = o + 1 }
487 let dn: *u8 = "/dir_\x00" as *u8
488 var k: i64 = 0
489 while dn[k] != (0 as u8) { pbuf[o] = dn[k]; o = o + 1; k = k + 1 }
490 var bc: i64 = 97 + b
491 if b == 26 { bc = 48 }
492 pbuf[o] = bc as u8; o = o + 1
493 let sfx: *u8 = ".html\x00" as *u8
494 k = 0
495 while sfx[k] != (0 as u8) { pbuf[o] = sfx[k]; o = o + 1; k = k + 1 }
496 pbuf[o] = 0 as u8
497 let dfd: i64 = sys_openat_wr(pbuf, 0x1a4)
498 if dfd >= 0 {
499 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)
500 cn(dfd, m); cw(dfd, " organs</h1><div>" as *u8)
501 var w: i64 = 0
502 while w < m {
503 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)
504 w = w + 1
505 }
506 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)
507 sys_close(dfd)
508 }
509 b = b + 1
510 }
511 // index page
512 var o2: i64 = 0
513 while outdir[o2] != (0 as u8) { pbuf[o2] = outdir[o2]; o2 = o2 + 1 }
514 let ix: *u8 = "/index.html\x00" as *u8
515 var k2: i64 = 0
516 while ix[k2] != (0 as u8) { pbuf[o2] = ix[k2]; o2 = o2 + 1; k2 = k2 + 1 }
517 pbuf[o2] = 0 as u8
518 let xfd: i64 = sys_openat_wr(pbuf, 0x1a4)
519 if xfd >= 0 {
520 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)
521 cn(xfd, made)
522 cw(xfd, " cards</h1>" as *u8)
523 // ---- SEARCH (family-tree table stakes): sovereign-generated index, ~30-line vanilla-JS filter = the last mile ----
524 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)
525 cw(xfd, "<p class=crumb>Or browse by first letter (nx_ prefix ignored):</p><div>" as *u8)
526 let cb: *u8 = sys_mmap(4)
527 b = 0
528 while b < 27 {
529 var bc2: i64 = 97 + b
530 if b == 26 { bc2 = 48 }
531 cb[0] = bc2 as u8
532 cw(xfd, "<a class=bk href=\"/compare/atlas/card/dir_" as *u8)
533 sys_write(xfd, cb, 1)
534 cw(xfd, ".html\"><b>" as *u8)
535 sys_write(xfd, cb, 1)
536 cw(xfd, "</b> · " as *u8); cn(xfd, bcnt[b]); cw(xfd, "</a>" as *u8)
537 b = b + 1
538 }
539 cw(xfd, "</div>" as *u8)
540 // the embedded index: one entry per organ "name|status|gen|Ca"
541 cw(xfd, "<script>var I=[" as *u8)
542 i = 0
543 while i < n {
544 cw(xfd, "\"" as *u8)
545 cname(xfd, g, i)
546 cw(xfd, "|" as *u8); cn(xfd, nstatus(g, i, inst))
547 cw(xfd, "|" as *u8); cn(xfd, gen[i])
548 cw(xfd, "|" as *u8); cn(xfd, eg_ca(g, i))
549 cw(xfd, "\"," as *u8)
550 i = i + 1
551 }
552 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)
553 cw(xfd, "</div></body></html>" as *u8)
554 sys_close(xfd)
555 }
556 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)
557 return 0
558 }
559
560 // ---------- SINGLE-CARD MODES (explicit + MCP) ----------
561 var storep: *u8 = 0 as *u8
562 var seedp: *u8 = 0 as *u8
563 var outp: *u8 = 0 as *u8
564 if argc >= 4 { storep = argv[1] as *u8; seedp = argv[2] as *u8; outp = argv[3] as *u8 }
565 if argc == 2 {
566 seedp = argv[1] as *u8
567 let sl: i64 = cslen(seedp)
568 if sl < 1 { cw(1, "ERROR empty seed\n" as *u8); return 5 }
569 if sl > 100 { cw(1, "ERROR seed too long\n" as *u8); return 5 }
570 if seedp[0] == (46 as u8) { cw(1, "ERROR leading dot\n" as *u8); return 5 }
571 var si: i64 = 0
572 while si < sl {
573 let c: i64 = seedp[si] as i64
574 var ok: i64 = 0
575 if c >= 97 { if c <= 122 { ok = 1 } }
576 if c >= 65 { if c <= 90 { ok = 1 } }
577 if c >= 48 { if c <= 57 { ok = 1 } }
578 if c == 95 { ok = 1 }
579 if c == 46 { ok = 1 }
580 if ok == 0 { cw(1, "ERROR bad seed char\n" as *u8); return 5 }
581 si = si + 1
582 }
583 storep = "knowledge/store/ecograph_full\x00" as *u8
584 let ob: *u8 = sys_mmap(256)
585 var oo: i64 = 0
586 let pre: *u8 = "sites/nishifamily/compare/atlas/card/\x00" as *u8
587 var pi: i64 = 0
588 while pre[pi] != (0 as u8) { ob[oo] = pre[pi]; oo = oo + 1; pi = pi + 1 }
589 si = 0
590 while si < sl { ob[oo] = seedp[si]; oo = oo + 1; si = si + 1 }
591 let suf: *u8 = ".html\x00" as *u8
592 pi = 0
593 while suf[pi] != (0 as u8) { ob[oo] = suf[pi]; oo = oo + 1; pi = pi + 1 }
594 ob[oo] = 0 as u8
595 outp = ob
596 }
597 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 }
598 let g: *EcoGraph = eg_load(storep)
599 if (g as i64) == 0 { cw(1, "ERROR store not found\n" as *u8); return 3 }
600 let me: i64 = eg_find(g, seedp, cslen(seedp))
601 if me < 0 { cw(1, "ERROR seed not in graph\n" as *u8); return 4 }
602 let n: i64 = g.node_count
603 let gen: *i64 = sys_mmap((n+2)*8) as *i64
604 let maxgen: i64 = card_gens(g, gen)
605 let seen: *u8 = sys_mmap(n + 2)
606 let fd: i64 = sys_openat_wr(outp, 0x1a4)
607 if fd < 0 { cw(1, "ERROR cannot open out\n" as *u8); return 6 }
608 let inst1: *u8 = sys_mmap(n + 2)
609 // BY CONSTRUCTION: only reference the lineage PNG if it actually exists on disk (CWD-relative,
610 // works on the NAS where MCP mode runs). A card must never point at a 404-fallback -- that class
611 // was caught LIVE by nx_page_verify (nx_u256 card RED, 2026-07-16). Missing -> the MCP-call note.
612 var hasimg: i64 = 0
613 let ipath: *u8 = sys_mmap(300)
614 var io: i64 = 0
615 let ipre: *u8 = "sites/nishifamily/compare/atlas/tree/lineage_\x00" as *u8
616 var ik: i64 = 0
617 while ipre[ik] != (0 as u8) { ipath[io] = ipre[ik]; io = io + 1; ik = ik + 1 }
618 ik = 0
619 while seedp[ik] != (0 as u8) { ipath[io] = seedp[ik]; io = io + 1; ik = ik + 1 }
620 let isuf: *u8 = ".png\x00" as *u8
621 ik = 0
622 while isuf[ik] != (0 as u8) { ipath[io] = isuf[ik]; io = io + 1; ik = ik + 1 }
623 ipath[io] = 0 as u8
624 let plen: *i64 = sys_mmap(16) as *i64
625 plen[0] = 0
626 sys_read_file(ipath, plen)
627 if plen[0] > 0 { hasimg = 1 }
628 let partners: i64 = card_emit(g, gen, maxgen, me, fd, seen, hasimg, inst1)
629 sys_close(fd)
630 cw(1, "wrote card " as *u8); cw(1, outp); cw(1, " partners=" as *u8); cn(1, partners); cw(1, "\n" as *u8)
631 if argc == 2 { cw(1, "URL https://nishifamily.com/compare/atlas/card/" as *u8); cw(1, seedp); cw(1, ".html\n" as *u8) }
632 return 0
633}