nx_idea_coverage.nx source
↩ module page · 231 lines · 9696 B
1// nx_idea_coverage.nx -- the ATTRIBUTION COVERAGE census for the idea genealogy.
2//
3// AUTHOR=ORGAN, MEASURED (no self-assert): joins the TOP-DOWN idea_genealogy.tsv against the
4// BOTTOM-UP node universe (lineage.tsv child ids + math_genealogy.tsv foundation ids) and reports,
5// from real files only:
6// - total_bu = number of bottom-up nodes (the attributable universe)
7// - attributed_nodes = distinct bottom-up nodes that a SOURCED/credited idea row bridges to
8// - coverage_permil = attributed_nodes / total_bu * 1000
9// - resolved_bridges = idea-row realized_in tokens that resolve into the bottom-up tree
10// - pending_bridges = idea-row realized_in tokens that DON'T resolve yet = the no-orphans worklist
11// (credit given now; each needs a lineage.tsv row authored to go live)
12// Emits one IDEACOV-PENDING line per pending bridge (the claimable action) + a summary, to stdout
13// and append-only to knowledge/status/idea_coverage.log. This is the genealogist spec's
14// "actionable-coverage" rung made mechanical: the TREE's state IS the worklist. Sovereign syscalls
15// only.
16//
17// module: nishi-core.genealogy.idea_coverage
18// depends: nishi-core.genealogy.idea_genealogist
19// capability: GENEALOGY
20// license_tier: ORIGINAL
21import "nx_syscalls.nx"
22import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
23const IC_MAGIC_1048576: i64 = 1048576
24const IC_MAGIC_1048575: i64 = 1048575
25const IC_MAGIC_2048: i64 = 2048
26
27const IC_IDEA: *u8 = "knowledge/registry/idea_genealogy.tsv"
28const IC_LIN: *u8 = "knowledge/registry/lineage.tsv"
29const IC_MATHG: *u8 = "knowledge/registry/math_genealogy.tsv"
30const IC_LOG: *u8 = "knowledge/status/idea_coverage.log"
31const IC_IDCAP: i64 = 64
32
33func ic_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
34// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
35// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
36// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
37// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
38func ic_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
39
40func ic_streq(a: *u8, b: *u8) -> i64 {
41 var i: i64 = 0
42 while i < IC_IDCAP { if a[i] != b[i] { return 0 } if a[i] == (0 as u8) { return 1 } i = i + 1 }
43 return 1
44}
45func ic_in_set(arena: i64, cnt: i64, idcap: i64, name: *u8) -> i64 {
46 var i: i64 = 0
47 while i < cnt { if ic_streq((arena + i * idcap) as *u8, name) == 1 { return 1 } i = i + 1 }
48 return 0
49}
50
51// extract TAB field `fidx` of the line starting at ls (until NL) into out (NUL-terminated).
52func ic_field_tab(buf: *u8, ls: i64, n: i64, fidx: i64, out: *u8, outcap: i64) -> i64 {
53 var p: i64 = ls
54 var f: i64 = 0
55 var bad: i64 = 0
56 while f < fidx {
57 if p >= n { bad = 1; f = fidx } else {
58 if buf[p] == (10 as u8) { bad = 1; f = fidx } else {
59 if buf[p] == (9 as u8) { f = f + 1 }
60 p = p + 1
61 }
62 }
63 }
64 if bad == 1 { out[0] = 0 as u8; return 0 }
65 var k: i64 = 0
66 var go: i64 = 1
67 while go == 1 {
68 if p >= n { go = 0 } else {
69 if buf[p] == (9 as u8) { go = 0 } else { if buf[p] == (10 as u8) { go = 0 } else {
70 if k < outcap - 1 { out[k] = buf[p]; k = k + 1 }
71 p = p + 1
72 } }
73 }
74 }
75 out[k] = 0 as u8
76 return k
77}
78
79// load TAB-field `fidx` of every non-comment row into arena (appended at base); returns new count.
80func ic_load_field(path: *u8, fidx: i64, arena: i64, base: i64, idcap: i64, maxc: i64) -> i64 {
81 let buf: *u8 = sys_mmap(IC_MAGIC_1048576)
82 let fd: i64 = sys_openat_rd(path)
83 if fd < 0 { return base }
84 var n: i64 = 0
85 var r: i64 = sys_read(fd, buf, IC_MAGIC_1048575)
86 while r > 0 { n = n + r; r = sys_read(fd, buf + n, IC_MAGIC_1048575 - n) }
87 sys_close(fd)
88 var cnt: i64 = base
89 var i: i64 = 0
90 while i < n {
91 if buf[i] == (35 as u8) {
92 var sk: i64 = 1
93 while sk == 1 { if i >= n { sk = 0 } else { if buf[i] == (10 as u8) { sk = 0 } i = i + 1 } }
94 } else {
95 if cnt < maxc {
96 ic_field_tab(buf, i, n, fidx, (arena + cnt * idcap) as *u8, idcap)
97 let dst: *u8 = (arena + cnt * idcap) as *u8
98 if dst[0] != (0 as u8) { cnt = cnt + 1 }
99 }
100 var le: i64 = i
101 var s2: i64 = 1
102 while s2 == 1 { if le >= n { s2 = 0 } else { if buf[le] == (10 as u8) { s2 = 0 } else { le = le + 1 } } }
103 i = le + 1
104 }
105 }
106 return cnt
107}
108
109// load (field0, field8) pairs of idea_genealogy.tsv in lockstep; returns row count.
110func ic_load_pairs(path: *u8, a0: i64, a8: i64, idcap: i64, maxc: i64) -> i64 {
111 let buf: *u8 = sys_mmap(IC_MAGIC_1048576)
112 let fd: i64 = sys_openat_rd(path)
113 if fd < 0 { return 0 }
114 var n: i64 = 0
115 var r: i64 = sys_read(fd, buf, IC_MAGIC_1048575)
116 while r > 0 { n = n + r; r = sys_read(fd, buf + n, IC_MAGIC_1048575 - n) }
117 sys_close(fd)
118 var cnt: i64 = 0
119 var i: i64 = 0
120 while i < n {
121 if buf[i] == (35 as u8) {
122 var sk: i64 = 1
123 while sk == 1 { if i >= n { sk = 0 } else { if buf[i] == (10 as u8) { sk = 0 } i = i + 1 } }
124 } else {
125 if cnt < maxc {
126 ic_field_tab(buf, i, n, 0, (a0 + cnt * idcap) as *u8, idcap)
127 ic_field_tab(buf, i, n, 8, (a8 + cnt * idcap) as *u8, idcap)
128 let d0: *u8 = (a0 + cnt * idcap) as *u8
129 if d0[0] != (0 as u8) { cnt = cnt + 1 }
130 }
131 var le: i64 = i
132 var s2: i64 = 1
133 while s2 == 1 { if le >= n { s2 = 0 } else { if buf[le] == (10 as u8) { s2 = 0 } else { le = le + 1 } } }
134 i = le + 1
135 }
136 }
137 return cnt
138}
139
140func ic_pending(fd: i64, idea: *u8, tok: *u8) -> i64 {
141 ic_w(fd, "IDEACOV-PENDING idea=" as *u8); ic_w(fd, idea)
142 ic_w(fd, " awaits_lineage_row_for=" as *u8); ic_w(fd, tok)
143 ic_w(fd, " action=AUTHOR-LINEAGE-ROW\n" as *u8)
144 return 0
145}
146func ic_summary(fd: i64, total_bu: i64, attributed: i64, permil: i64, ideas: i64, resolved: i64, pending: i64, epoch: i64, ok: i64) -> i64 {
147 ic_w(fd, "IDEACOV authored=organ total_bu=" as *u8); ic_wn(fd, total_bu)
148 ic_w(fd, " attributed_nodes=" as *u8); ic_wn(fd, attributed)
149 ic_w(fd, " coverage_permil=" as *u8); ic_wn(fd, permil)
150 ic_w(fd, " ideas=" as *u8); ic_wn(fd, ideas)
151 ic_w(fd, " resolved_bridges=" as *u8); ic_wn(fd, resolved)
152 ic_w(fd, " pending_bridges=" as *u8); ic_wn(fd, pending)
153 ic_w(fd, " epoch=" as *u8); ic_wn(fd, epoch)
154 if ok == 1 { ic_w(fd, " verdict=GREEN\n" as *u8) } else { ic_w(fd, " verdict=RED\n" as *u8) }
155 return 0
156}
157
158func main() -> i64 {
159 // bottom-up node universe = lineage child ids + math_genealogy foundation ids
160 let bu: i64 = sys_mmap(IC_MAGIC_2048 * IC_IDCAP) as i64
161 var brc: i64 = ic_load_field(IC_LIN, 0, bu, 0, IC_IDCAP, IC_MAGIC_2048)
162 brc = ic_load_field(IC_MATHG, 1, bu, brc, IC_IDCAP, IC_MAGIC_2048)
163
164 // idea rows (idea_id, realized_in)
165 let ai: i64 = sys_mmap(512 * IC_IDCAP) as i64
166 let ar: i64 = sys_mmap(512 * IC_IDCAP) as i64
167 let cnt: i64 = ic_load_pairs(IC_IDEA, ai, ar, IC_IDCAP, 512)
168
169 let glog: i64 = sys_openat_append(IC_LOG, 420)
170
171 let covered: i64 = sys_mmap(512 * IC_IDCAP) as i64
172 var ccnt: i64 = 0
173 var resolved: i64 = 0
174 var pending: i64 = 0
175 let tok: *u8 = sys_mmap(IC_IDCAP)
176
177 var i: i64 = 0
178 while i < cnt {
179 let rf: *u8 = (ar + i * IC_IDCAP) as *u8
180 let idf: *u8 = (ai + i * IC_IDCAP) as *u8
181 var p: i64 = 0
182 var k: i64 = 0
183 var go: i64 = 1
184 while go == 1 {
185 let ch: i64 = rf[p] as i64
186 var fin: i64 = 0
187 if ch == 0 { fin = 1 }
188 if ch == 44 { fin = 1 }
189 if fin == 1 {
190 if k > 0 {
191 tok[k] = 0 as u8
192 var isdash: i64 = 0
193 if tok[0] == (45 as u8) { if tok[1] == (0 as u8) { isdash = 1 } }
194 if isdash == 0 {
195 if ic_in_set(bu, brc, IC_IDCAP, tok) == 1 {
196 resolved = resolved + 1
197 if ic_in_set(covered, ccnt, IC_IDCAP, tok) == 0 {
198 let d: *u8 = (covered + ccnt * IC_IDCAP) as *u8
199 var z: i64 = 0
200 while tok[z] != (0 as u8) { d[z] = tok[z]; z = z + 1 }
201 d[z] = 0 as u8
202 ccnt = ccnt + 1
203 }
204 } else {
205 pending = pending + 1
206 ic_pending(1, idf, tok)
207 if glog >= 0 { ic_pending(glog, idf, tok) }
208 }
209 }
210 k = 0
211 }
212 if ch == 0 { go = 0 }
213 } else { if k < IC_IDCAP - 1 { tok[k] = ch as u8; k = k + 1 } }
214 p = p + 1
215 }
216 i = i + 1
217 }
218
219 var permil: i64 = 0
220 if brc > 0 { permil = ccnt * 1000 / brc }
221 let epoch: i64 = sys_now_realtime_sec()
222 var ok: i64 = 1
223 if cnt == 0 { ok = 0 }
224 if brc == 0 { ok = 0 }
225
226 ic_summary(1, brc, ccnt, permil, cnt, resolved, pending, epoch, ok)
227 if glog >= 0 { ic_summary(glog, brc, ccnt, permil, cnt, resolved, pending, epoch, ok); sys_close(glog) }
228
229 if ok == 1 { sys_exit(0); return 0 }
230 sys_exit(1); return 1
231}