code wiki / _hdl_build / nx_vizsla_profile.nx
nx_vizsla_profile.nx source
↩ module page · 455 lines · 15859 B
1// nx_vizsla_profile.nx -- NISHI VIZSLA V0: the archetype gap profiler.
2// The operator's three-archetype theory (architect/author/editor; a household
3// usually covers two; the missing one is THE structural gap) as a measured,
4// re-runnable instrument. The MODEL IS DATA: archetypes, trait weights,
5// domains and fill capabilities all come from knowledge/vizsla/archetype_matrix.txt
6// (the engine reads N archetypes from the file -- "three" is matrix content,
7// never a constant here). Household answers come from knowledge/vizsla/household.txt.
8// Output rows (stdout deterministic; epoch header -> log only):
9// VIZSLA-MEMBER name=<m> primary=<arch> <arch>=<permil>...
10// VIZSLA-COVERAGE archetypes=<n> covered=<k> gaps=<g> threshold=<thr>
11// VIZSLA-GAP archetype=<a> nearest=<member> nearest_permil=<p>
12// VIZSLA-FILL domain=<d> gap=<a> capability=<cap> partner=<member>
13// VIZSLA-VERDICT coverage=FULL | coverage=GAPPED gaps=<g>
14// argv overrides (gate fixture isolation, site-gate pattern):
15// argv[1]=matrix path argv[2]=household path argv[3]=log path
16// Loud-fail law: missing/empty inputs, unknown archetype/member references = exit 1.
17// spec: knowledge/specs/2026-06-10-nishi-vizsla-ladder.md license_tier: ORIGINAL
18import "nx_syscalls.nx"
19const K_MAGIC_65536: i64 = 65536
20
21func vz_slen(s: *u8) -> i64 {
22 var n: i64 = 0
23 while s[n] != (0 as u8) { n = n + 1 }
24 return n
25}
26
27func vz_p(s: *u8) -> i64 {
28 sys_write(1, s, vz_slen(s))
29 return 0
30}
31
32func vz_eq(a: *u8, b: *u8) -> i64 {
33 var i: i64 = 0
34 var go: i64 = 1
35 while go == 1 {
36 if a[i] != b[i] { return 0 }
37 if a[i] == (0 as u8) { return 1 }
38 i = i + 1
39 }
40 return 0
41}
42
43func vz_dup(s: *u8) -> *u8 {
44 let n: i64 = vz_slen(s)
45 let d: *u8 = sys_mmap(n + 2)
46 var i: i64 = 0
47 while i <= n { d[i] = s[i]; i = i + 1 }
48 return d
49}
50
51func vz_atoi(s: *u8) -> i64 {
52 var v: i64 = 0
53 var i: i64 = 0
54 while s[i] != (0 as u8) {
55 let d: i64 = (s[i] as i64) - 48
56 if d >= 0 { if d <= 9 { v = v * 10 + d } }
57 i = i + 1
58 }
59 return v
60}
61
62func vz_isws(c: i64) -> i64 {
63 if c == 32 { return 1 }
64 if c == 13 { return 1 }
65 if c == 9 { return 1 }
66 return 0
67}
68
69// next whitespace-delimited token from b[off..lend) -> dst (NUL-terminated);
70// returns offset after the token; dst[0]=0 means no token left on the line
71func vz_tok(b: *u8, off: i64, lend: i64, dst: *u8, cap: i64) -> i64 {
72 var p: i64 = off
73 var go: i64 = 1
74 while go == 1 {
75 if p >= lend { go = 0 } else {
76 if vz_isws(b[p] as i64) == 1 { p = p + 1 } else { go = 0 }
77 }
78 }
79 var t: i64 = 0
80 go = 1
81 while go == 1 {
82 if p >= lend { go = 0 } else {
83 if vz_isws(b[p] as i64) == 1 { go = 0 } else {
84 if t < cap - 1 { dst[t] = b[p]; t = t + 1 }
85 p = p + 1
86 }
87 }
88 }
89 dst[t] = 0 as u8
90 return p
91}
92
93func vz_readall(path: *u8, szout: *i64) -> *u8 {
94 let fd: i64 = sys_openat_rd(path)
95 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 }
96 let sz: i64 = sys_lseek(fd, 0, 2)
97 sys_lseek(fd, 0, 0)
98 let buf: *u8 = sys_mmap(sz + 64)
99 var got: i64 = 0
100 var n: i64 = 1
101 while n > 0 {
102 n = sys_read(fd, (buf as i64 + got) as *u8, K_MAGIC_65536)
103 if n > 0 { got = got + n }
104 }
105 sys_close(fd)
106 szout[0] = got
107 return buf
108}
109
110func vz_find(list: *i64, n: i64, s: *u8) -> i64 {
111 var i: i64 = 0
112 while i < n {
113 if vz_eq(list[i] as *u8, s) == 1 { return i }
114 i = i + 1
115 }
116 return 0 - 1
117}
118
119func vz_cat(dst: *u8, off: i64, s: *u8) -> i64 {
120 var i: i64 = 0
121 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
122 return off + i
123}
124
125func vz_catn(dst: *u8, off: i64, v: i64) -> i64 {
126 var o: i64 = off
127 var m: i64 = v
128 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
129 let t: *u8 = sys_mmap(28)
130 var k: i64 = 0
131 if m == 0 { t[0] = 48 as u8; k = 1 }
132 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
133 var i: i64 = 0
134 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
135 return o + k
136}
137
138// answered value (0/1) for member mi on trait key (last write wins, scan)
139func vz_ans(a_mem: *i64, a_key: *i64, a_val: *i64, nans: i64, mi: i64, key: *u8) -> i64 {
140 var v: i64 = 0
141 var qi: i64 = 0
142 while qi < nans {
143 if a_mem[qi] == mi {
144 if vz_eq(a_key[qi] as *u8, key) == 1 { v = a_val[qi] }
145 }
146 qi = qi + 1
147 }
148 return v
149}
150
151func main(argc: i64, argv: *i64) -> i64 {
152 var mpath: *u8 = "knowledge/vizsla/archetype_matrix.txt" as *u8
153 var hpath: *u8 = "knowledge/vizsla/household.txt" as *u8
154 var lpath: *u8 = "knowledge/status/vizsla_profile.log" as *u8
155 if argc > 1 { mpath = argv[1] as *u8 }
156 if argc > 2 { hpath = argv[2] as *u8 }
157 if argc > 3 { lpath = argv[3] as *u8 }
158
159 let szp: *i64 = sys_mmap(16) as *i64
160 let mb: *u8 = vz_readall(mpath, szp)
161 let msz: i64 = szp[0]
162 if msz <= 0 { vz_p("VIZSLA-PROFILE matrix MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
163 let hb: *u8 = vz_readall(hpath, szp)
164 let hsz: i64 = szp[0]
165 if hsz <= 0 { vz_p("VIZSLA-PROFILE household MISSING/EMPTY -- fail loud\n" as *u8); return 1 }
166
167 // model tables (all FROM DATA; capacities are buffer sizes, not model shape)
168 let archs: *i64 = sys_mmap(8 * 8) as *i64
169 let totw: *i64 = sys_mmap(8 * 8) as *i64
170 var narch: i64 = 0
171 let t_arch: *i64 = sys_mmap(8 * 64) as *i64
172 let t_w: *i64 = sys_mmap(8 * 64) as *i64
173 let t_key: *i64 = sys_mmap(8 * 64) as *i64
174 var ntrait: i64 = 0
175 let doms: *i64 = sys_mmap(8 * 16) as *i64
176 var ndom: i64 = 0
177 let n_dom: *i64 = sys_mmap(8 * 96) as *i64
178 let n_arch: *i64 = sys_mmap(8 * 96) as *i64
179 let n_cap: *i64 = sys_mmap(8 * 96) as *i64
180 var nneed: i64 = 0
181 var thr: i64 = 500
182
183 let t0: *u8 = sys_mmap(128)
184 let t1: *u8 = sys_mmap(128)
185 let t2: *u8 = sys_mmap(128)
186 let t3: *u8 = sys_mmap(128)
187
188 // ---- parse matrix ----
189 var i: i64 = 0
190 while i < msz {
191 var e: i64 = i
192 var go: i64 = 1
193 while go == 1 {
194 if e >= msz { go = 0 } else {
195 if mb[e] == (10 as u8) { go = 0 } else { e = e + 1 }
196 }
197 }
198 var p: i64 = vz_tok(mb, i, e, t0, 128)
199 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
200 if t0[0] != (0 as u8) {
201 if vz_eq(t0, "CONF" as *u8) == 1 {
202 p = vz_tok(mb, p, e, t1, 128)
203 p = vz_tok(mb, p, e, t2, 128)
204 if vz_eq(t1, "threshold_permil" as *u8) == 1 { thr = vz_atoi(t2) }
205 }
206 if vz_eq(t0, "ARCH" as *u8) == 1 {
207 p = vz_tok(mb, p, e, t1, 128)
208 if narch < 8 { archs[narch] = vz_dup(t1) as i64; totw[narch] = 0; narch = narch + 1 }
209 }
210 if vz_eq(t0, "TRAIT" as *u8) == 1 {
211 p = vz_tok(mb, p, e, t1, 128)
212 p = vz_tok(mb, p, e, t2, 128)
213 p = vz_tok(mb, p, e, t3, 128)
214 let ai: i64 = vz_find(archs, narch, t1)
215 if ai < 0 { vz_p("VIZSLA-PROFILE TRAIT references unknown archetype -- fail loud\n" as *u8); return 1 }
216 if ntrait < 64 {
217 t_arch[ntrait] = ai
218 t_w[ntrait] = vz_atoi(t2)
219 t_key[ntrait] = vz_dup(t3) as i64
220 totw[ai] = totw[ai] + t_w[ntrait]
221 ntrait = ntrait + 1
222 }
223 }
224 if vz_eq(t0, "DOMAIN" as *u8) == 1 {
225 p = vz_tok(mb, p, e, t1, 128)
226 if ndom < 16 { doms[ndom] = vz_dup(t1) as i64; ndom = ndom + 1 }
227 }
228 if vz_eq(t0, "NEED" as *u8) == 1 {
229 p = vz_tok(mb, p, e, t1, 128)
230 p = vz_tok(mb, p, e, t2, 128)
231 p = vz_tok(mb, p, e, t3, 128)
232 let di: i64 = vz_find(doms, ndom, t1)
233 if di < 0 { vz_p("VIZSLA-PROFILE NEED references unknown domain -- fail loud\n" as *u8); return 1 }
234 let na: i64 = vz_find(archs, narch, t2)
235 if na < 0 { vz_p("VIZSLA-PROFILE NEED references unknown archetype -- fail loud\n" as *u8); return 1 }
236 if nneed < 96 {
237 n_dom[nneed] = di
238 n_arch[nneed] = na
239 n_cap[nneed] = vz_dup(t3) as i64
240 nneed = nneed + 1
241 }
242 }
243 }
244 i = e + 1
245 }
246
247 // ---- parse household ----
248 let mems: *i64 = sys_mmap(8 * 16) as *i64
249 var nmem: i64 = 0
250 let a_mem: *i64 = sys_mmap(8 * 512) as *i64
251 let a_key: *i64 = sys_mmap(8 * 512) as *i64
252 let a_val: *i64 = sys_mmap(8 * 512) as *i64
253 var nans: i64 = 0
254
255 i = 0
256 while i < hsz {
257 var e2: i64 = i
258 var go2: i64 = 1
259 while go2 == 1 {
260 if e2 >= hsz { go2 = 0 } else {
261 if hb[e2] == (10 as u8) { go2 = 0 } else { e2 = e2 + 1 }
262 }
263 }
264 var p2: i64 = vz_tok(hb, i, e2, t0, 128)
265 if t0[0] == (35 as u8) { t0[0] = 0 as u8 }
266 if t0[0] != (0 as u8) {
267 if vz_eq(t0, "MEMBER" as *u8) == 1 {
268 p2 = vz_tok(hb, p2, e2, t1, 128)
269 if nmem < 16 { mems[nmem] = vz_dup(t1) as i64; nmem = nmem + 1 }
270 }
271 if vz_eq(t0, "ANS" as *u8) == 1 {
272 p2 = vz_tok(hb, p2, e2, t1, 128)
273 p2 = vz_tok(hb, p2, e2, t2, 128)
274 p2 = vz_tok(hb, p2, e2, t3, 128)
275 let mi0: i64 = vz_find(mems, nmem, t1)
276 if mi0 < 0 { vz_p("VIZSLA-PROFILE ANS references unknown member -- fail loud\n" as *u8); return 1 }
277 if nans < 512 {
278 a_mem[nans] = mi0
279 a_key[nans] = vz_dup(t2) as i64
280 a_val[nans] = vz_atoi(t3)
281 nans = nans + 1
282 }
283 }
284 }
285 i = e2 + 1
286 }
287
288 if narch < 1 { vz_p("VIZSLA-PROFILE no archetypes in matrix -- fail loud\n" as *u8); return 1 }
289 if ntrait < 1 { vz_p("VIZSLA-PROFILE no traits in matrix -- fail loud\n" as *u8); return 1 }
290 if nmem < 1 { vz_p("VIZSLA-PROFILE no members in household -- fail loud\n" as *u8); return 1 }
291
292 // ---- score: member x archetype permil ----
293 let permil: *i64 = sys_mmap(8 * 16 * 8) as *i64
294 var mi: i64 = 0
295 while mi < nmem {
296 var ai2: i64 = 0
297 while ai2 < narch {
298 var sum: i64 = 0
299 var ti: i64 = 0
300 while ti < ntrait {
301 if t_arch[ti] == ai2 {
302 if vz_ans(a_mem, a_key, a_val, nans, mi, t_key[ti] as *u8) == 1 { sum = sum + t_w[ti] }
303 }
304 ti = ti + 1
305 }
306 var pm: i64 = 0
307 if totw[ai2] > 0 { pm = (sum * 1000) / totw[ai2] }
308 permil[mi * 8 + ai2] = pm
309 ai2 = ai2 + 1
310 }
311 mi = mi + 1
312 }
313
314 // ---- primary per member (argmax, file order breaks ties; none if all 0) ----
315 let prim: *i64 = sys_mmap(8 * 16) as *i64
316 mi = 0
317 while mi < nmem {
318 var best: i64 = 0
319 var bi: i64 = 0 - 1
320 var ai3: i64 = 0
321 while ai3 < narch {
322 if permil[mi * 8 + ai3] > best { best = permil[mi * 8 + ai3]; bi = ai3 }
323 ai3 = ai3 + 1
324 }
325 prim[mi] = bi
326 mi = mi + 1
327 }
328
329 // ---- coverage: someone's primary OR anyone >= threshold ----
330 let cov: *i64 = sys_mmap(8 * 8) as *i64
331 var ai4: i64 = 0
332 while ai4 < narch { cov[ai4] = 0; ai4 = ai4 + 1 }
333 mi = 0
334 while mi < nmem {
335 if prim[mi] >= 0 { cov[prim[mi]] = 1 }
336 var ai5: i64 = 0
337 while ai5 < narch {
338 if permil[mi * 8 + ai5] >= thr { cov[ai5] = 1 }
339 ai5 = ai5 + 1
340 }
341 mi = mi + 1
342 }
343 var covered: i64 = 0
344 var ai6: i64 = 0
345 while ai6 < narch {
346 if cov[ai6] == 1 { covered = covered + 1 }
347 ai6 = ai6 + 1
348 }
349 let gaps: i64 = narch - covered
350
351 // ---- compose the report (stdout-deterministic; epoch goes to log only) ----
352 let rep: *u8 = sys_mmap(K_MAGIC_65536)
353 var o: i64 = 0
354 mi = 0
355 while mi < nmem {
356 o = vz_cat(rep, o, "VIZSLA-MEMBER name=" as *u8)
357 o = vz_cat(rep, o, mems[mi] as *u8)
358 o = vz_cat(rep, o, " primary=" as *u8)
359 if prim[mi] >= 0 { o = vz_cat(rep, o, archs[prim[mi]] as *u8) } else { o = vz_cat(rep, o, "none" as *u8) }
360 var ai7: i64 = 0
361 while ai7 < narch {
362 o = vz_cat(rep, o, " " as *u8)
363 o = vz_cat(rep, o, archs[ai7] as *u8)
364 o = vz_cat(rep, o, "=" as *u8)
365 o = vz_catn(rep, o, permil[mi * 8 + ai7])
366 ai7 = ai7 + 1
367 }
368 o = vz_cat(rep, o, "\n" as *u8)
369 mi = mi + 1
370 }
371 o = vz_cat(rep, o, "VIZSLA-COVERAGE archetypes=" as *u8)
372 o = vz_catn(rep, o, narch)
373 o = vz_cat(rep, o, " covered=" as *u8)
374 o = vz_catn(rep, o, covered)
375 o = vz_cat(rep, o, " gaps=" as *u8)
376 o = vz_catn(rep, o, gaps)
377 o = vz_cat(rep, o, " threshold=" as *u8)
378 o = vz_catn(rep, o, thr)
379 o = vz_cat(rep, o, "\n" as *u8)
380
381 // gap rows: nearest member = highest permil in the gap archetype (partnership)
382 var ag: i64 = 0
383 while ag < narch {
384 if cov[ag] == 0 {
385 var nbest: i64 = 0 - 1
386 var nbp: i64 = 0 - 1
387 var mj: i64 = 0
388 while mj < nmem {
389 if permil[mj * 8 + ag] > nbp { nbp = permil[mj * 8 + ag]; nbest = mj }
390 mj = mj + 1
391 }
392 if nbest < 0 { nbest = 0; nbp = 0 }
393 o = vz_cat(rep, o, "VIZSLA-GAP archetype=" as *u8)
394 o = vz_cat(rep, o, archs[ag] as *u8)
395 o = vz_cat(rep, o, " nearest=" as *u8)
396 o = vz_cat(rep, o, mems[nbest] as *u8)
397 o = vz_cat(rep, o, " nearest_permil=" as *u8)
398 o = vz_catn(rep, o, nbp)
399 o = vz_cat(rep, o, "\n" as *u8)
400 }
401 ag = ag + 1
402 }
403
404 // fill plan: every NEED row whose archetype is a gap (needs-file order)
405 var ni: i64 = 0
406 while ni < nneed {
407 if cov[n_arch[ni]] == 0 {
408 var pbest: i64 = 0
409 var pbp: i64 = 0 - 1
410 var mk: i64 = 0
411 while mk < nmem {
412 if permil[mk * 8 + n_arch[ni]] > pbp { pbp = permil[mk * 8 + n_arch[ni]]; pbest = mk }
413 mk = mk + 1
414 }
415 o = vz_cat(rep, o, "VIZSLA-FILL domain=" as *u8)
416 o = vz_cat(rep, o, doms[n_dom[ni]] as *u8)
417 o = vz_cat(rep, o, " gap=" as *u8)
418 o = vz_cat(rep, o, archs[n_arch[ni]] as *u8)
419 o = vz_cat(rep, o, " capability=" as *u8)
420 o = vz_cat(rep, o, n_cap[ni] as *u8)
421 o = vz_cat(rep, o, " partner=" as *u8)
422 o = vz_cat(rep, o, mems[pbest] as *u8)
423 o = vz_cat(rep, o, "\n" as *u8)
424 }
425 ni = ni + 1
426 }
427
428 if gaps == 0 {
429 o = vz_cat(rep, o, "VIZSLA-VERDICT coverage=FULL\n" as *u8)
430 } else {
431 o = vz_cat(rep, o, "VIZSLA-VERDICT coverage=GAPPED gaps=" as *u8)
432 o = vz_catn(rep, o, gaps)
433 o = vz_cat(rep, o, "\n" as *u8)
434 }
435
436 sys_write(1, rep, o)
437
438 // log: epoch header + the same report (append-only, additive law)
439 let logfd: i64 = sys_openat_append(lpath, 0x1a4)
440 if logfd > 0 {
441 let hdr: *u8 = sys_mmap(512)
442 var ho: i64 = 0
443 ho = vz_cat(hdr, ho, "VIZSLA-PROFILE epoch=" as *u8)
444 ho = vz_catn(hdr, ho, sys_now_realtime_sec())
445 ho = vz_cat(hdr, ho, " matrix=" as *u8)
446 ho = vz_cat(hdr, ho, mpath)
447 ho = vz_cat(hdr, ho, " household=" as *u8)
448 ho = vz_cat(hdr, ho, hpath)
449 ho = vz_cat(hdr, ho, "\n" as *u8)
450 sys_write(logfd, hdr, ho)
451 sys_write(logfd, rep, o)
452 sys_close(logfd)
453 }
454 return 0
455}