nx_5wh_log.nx source
↩ module page · 402 lines · 14964 B
1// nx_5wh_log.nx -- unified 5W+H+GLP ledger.
2//
3// The bridge between top-down measurement (nx_monte_carlo,
4// nx_multivariate, nx_patch_attribution, nx_knn, nx_closed_loop,
5// nx_quality_grade) and bottom-up attribution (nx_attribution,
6// nx_activation_steer). Both axes emit Nx5whRecord into ONE
7// queryable causal DAG.
8//
9// Schema (canonical 9-field tuple per COMPETITIVE_POSITION.md:60):
10// who -- actor id (caller / tensor / weight)
11// what -- sealed enum: MEASUREMENT / VERDICT / ATTRIBUTION ...
12// when -- monotonic step counter
13// where -- sealed where-kind + 3 indices (layer/head/pos)
14// why_parent -- record_id of the record this one was caused by
15// (or -1 for root); forms the causal DAG
16// how -- algorithm tag (FNV-1a of algo name)
17// genealogy -- research-paper id hash (Welford 1962 etc.)
18// lineage -- data-checkpoint id hash (W matrix hash etc.)
19// performance -- one numeric: latency_us | err_bound | share_q10
20// (interpretation depends on what_kind)
21//
22// JPL Power of 10 Rule 2: bounded capacity; ring overflow drops
23// oldest with NX_5WH_DROPPED verdict returned on emit.
24//
25// genealogy_id: substrate_5wh_log_v1
26// lineage_id: competitive_position_md_line_60
27
28import "nx_syscalls.nx"
29import "nx_runtime.nx"
30import "nx_tier.nx"
31
32// ===== sealed enum: what_kind =====================================
33
34const NX_5WH_WHAT_MEASUREMENT: nx_int = 0
35const NX_5WH_WHAT_VERDICT: nx_int = 1
36const NX_5WH_WHAT_ATTRIBUTION: nx_int = 2
37const NX_5WH_WHAT_CONTRIBUTION: nx_int = 3
38const NX_5WH_WHAT_OP_BEGIN: nx_int = 4
39const NX_5WH_WHAT_OP_END: nx_int = 5
40const NX_5WH_WHAT_ALLOC: nx_int = 6
41const NX_5WH_WHAT_STEER: nx_int = 7
42const NX_5WH_WHAT_ADJUST: nx_int = 8
43const NX_5WH_WHAT_REROLL: nx_int = 9
44const NX_5WH_WHAT_GATE: nx_int = 10
45const NX_5WH_WHAT_N_KINDS: nx_int = 11
46
47func nx_5wh_what_is_valid(k: nx_int) -> nx_int {
48 if k < 0 { return 0 }
49 if k >= NX_5WH_WHAT_N_KINDS { return 0 }
50 return 1
51}
52
53// ===== sealed enum: where_kind ====================================
54
55const NX_5WH_WHERE_NONE: nx_int = 0
56const NX_5WH_WHERE_TRANSFORMER_LAYER: nx_int = 1
57const NX_5WH_WHERE_ATTN_HEAD: nx_int = 2
58const NX_5WH_WHERE_MLP_BLOCK: nx_int = 3
59const NX_5WH_WHERE_EMBED: nx_int = 4
60const NX_5WH_WHERE_UNEMBED: nx_int = 5
61const NX_5WH_WHERE_UNET_BLOCK: nx_int = 6
62const NX_5WH_WHERE_VAE_BLOCK: nx_int = 7
63const NX_5WH_WHERE_SAMPLER: nx_int = 8
64const NX_5WH_WHERE_DECODER: nx_int = 9
65const NX_5WH_WHERE_RASTER: nx_int = 10
66const NX_5WH_WHERE_MESH: nx_int = 11
67const NX_5WH_WHERE_HARDWARE: nx_int = 12
68const NX_5WH_WHERE_EXTERNAL: nx_int = 13
69const NX_5WH_WHERE_N_KINDS: nx_int = 14
70
71func nx_5wh_where_is_valid(k: nx_int) -> nx_int {
72 if k < 0 { return 0 }
73 if k >= NX_5WH_WHERE_N_KINDS { return 0 }
74 return 1
75}
76
77// ===== emit verdict =================================================
78
79const NX_5WH_OK: nx_int = 0
80const NX_5WH_DROPPED: nx_int = 1
81const NX_5WH_INVALID: nx_int = 2
82
83// ===== sentinel root for why_parent ================================
84
85const NX_5WH_NO_PARENT: nx_int = -1
86
87// ===== record struct ===============================================
88
89struct Nx5whRecord {
90 who: nx_int,
91 what: nx_int,
92 when_step: nx_int,
93 where_kind: nx_int,
94 where_idx_a: nx_int,
95 where_idx_b: nx_int,
96 where_idx_c: nx_int,
97 why_parent_id: nx_int,
98 how: nx_int,
99 genealogy: nx_int,
100 lineage: nx_int,
101 performance: nx_int,
102}
103
104const NX_5WH_RECORD_BYTES: nx_size = 96 // 12 fields x 8 bytes
105
106// ===== ledger struct ===============================================
107
108struct Nx5whLedger {
109 records: *Nx5whRecord,
110 capacity: nx_int,
111 head: nx_int, // next slot to write
112 n_emitted: nx_int, // total emits since alloc (monotone)
113 n_dropped: nx_int, // total dropped due to overflow
114 step: nx_int, // when-counter
115}
116
117const NX_5WH_LEDGER_BYTES: nx_size = 48
118const NX_5WH_DEFAULT_CAP: nx_int = 4096
119const NX_5WH_MAX_CAP: nx_int = 1048576
120
121// ===== alloc =======================================================
122
123func nx_5wh_log_alloc(capacity: nx_int) -> *Nx5whLedger {
124 var cap: nx_int = capacity
125 if cap <= 0 { cap = NX_5WH_DEFAULT_CAP }
126 if cap > NX_5WH_MAX_CAP { cap = NX_5WH_MAX_CAP }
127 let bytes_records: nx_size = (cap as nx_size) * NX_5WH_RECORD_BYTES
128 let recs_ptr: *u8 = sys_mmap(bytes_records)
129 let ledger_ptr: *u8 = sys_mmap(NX_5WH_LEDGER_BYTES)
130 let ledger: *Nx5whLedger = ledger_ptr as *Nx5whLedger
131 ledger.records = recs_ptr as *Nx5whRecord
132 ledger.capacity = cap
133 ledger.head = 0
134 ledger.n_emitted = 0
135 ledger.n_dropped = 0
136 ledger.step = 0
137 return ledger
138}
139
140// ===== bounded ring-buffer slot picker ============================
141
142func _5wh_advance(ledger: *Nx5whLedger) -> nx_int {
143 let slot: nx_int = ledger.head
144 ledger.head = ledger.head + 1
145 if ledger.head >= ledger.capacity {
146 ledger.head = 0
147 ledger.n_dropped = ledger.n_dropped + 1
148 }
149 return slot
150}
151
152// ===== emit ========================================================
153
154func nx_5wh_emit(ledger: *Nx5whLedger,
155 who: nx_int, what: nx_int,
156 where_kind: nx_int,
157 where_idx_a: nx_int, where_idx_b: nx_int, where_idx_c: nx_int,
158 why_parent_id: nx_int,
159 how: nx_int, genealogy: nx_int, lineage: nx_int,
160 performance: nx_int) -> nx_int {
161 if nx_5wh_what_is_valid(what) == 0 { return 0 - 1 }
162 if nx_5wh_where_is_valid(where_kind) == 0 { return 0 - 1 }
163 let slot: nx_int = _5wh_advance(ledger)
164 let rec: *Nx5whRecord = (ledger.records as *u8 + (slot as nx_size) * NX_5WH_RECORD_BYTES) as *Nx5whRecord
165 rec.who = who
166 rec.what = what
167 rec.when_step = ledger.step
168 rec.where_kind = where_kind
169 rec.where_idx_a = where_idx_a
170 rec.where_idx_b = where_idx_b
171 rec.where_idx_c = where_idx_c
172 rec.why_parent_id = why_parent_id
173 rec.how = how
174 rec.genealogy = genealogy
175 rec.lineage = lineage
176 rec.performance = performance
177 ledger.step = ledger.step + 1
178 ledger.n_emitted = ledger.n_emitted + 1
179 return slot
180}
181
182// ===== record fetch ================================================
183
184func nx_5wh_record_at(ledger: *Nx5whLedger, slot: nx_int) -> *Nx5whRecord {
185 if slot < 0 { return 0 as *Nx5whRecord }
186 if slot >= ledger.capacity { return 0 as *Nx5whRecord }
187 return (ledger.records as *u8 + (slot as nx_size) * NX_5WH_RECORD_BYTES) as *Nx5whRecord
188}
189
190// ===== query: filterable scan ======================================
191//
192// what_kind_mask: bitmask -- bit i set means "include records where
193// what==i". Pass -1 (all bits) to match all. Pass 0 to skip filter.
194// where_kind_mask: same shape over where_kind values.
195// min_step / max_step: when-window; pass -1 to disable bound.
196// out_ids[]: caller-provided output array; out_cap entries.
197// Returns number of matching records written (clamped to out_cap).
198
199func _5wh_bit_test(mask: nx_int, bit: nx_int) -> nx_int {
200 if mask == 0 - 1 { return 1 }
201 if mask == 0 { return 1 }
202 if bit < 0 { return 0 }
203 if bit >= 64 { return 0 }
204 let shifted: nx_int = mask >> bit
205 let lsb: nx_int = shifted & 1
206 return lsb
207}
208
209func nx_5wh_query(ledger: *Nx5whLedger,
210 what_mask: nx_int, where_mask: nx_int,
211 min_step: nx_int, max_step: nx_int,
212 out_ids: *nx_int, out_cap: nx_int) -> nx_int {
213 var count: nx_int = 0
214 var i: nx_int = 0
215 let cap: nx_int = ledger.capacity
216 let emitted: nx_int = ledger.n_emitted
217 var scan_n: nx_int = emitted
218 if scan_n > cap { scan_n = cap }
219 while i < scan_n {
220 if count >= out_cap { return count }
221 let rec: *Nx5whRecord = nx_5wh_record_at(ledger, i)
222 let what_hit: nx_int = _5wh_bit_test(what_mask, rec.what)
223 let where_hit: nx_int = _5wh_bit_test(where_mask, rec.where_kind)
224 var ok: nx_int = 1
225 if what_hit == 0 { ok = 0 }
226 if where_hit == 0 { ok = 0 }
227 if min_step >= 0 {
228 if rec.when_step < min_step { ok = 0 }
229 }
230 if max_step >= 0 {
231 if rec.when_step > max_step { ok = 0 }
232 }
233 if ok == 1 {
234 out_ids[count] = i
235 count = count + 1
236 }
237 i = i + 1
238 }
239 return count
240}
241
242// ===== lineage walk: follow why_parent_id back to root =============
243//
244// Returns recorded chain in out_ids[] from the seed record back
245// toward root (NX_5WH_NO_PARENT). Bounded by out_cap and
246// JPL Rule 2 max-depth NX_5WH_MAX_WALK to refuse cycles.
247
248const NX_5WH_MAX_WALK: nx_int = 1024
249
250func nx_5wh_walk_lineage(ledger: *Nx5whLedger, seed_id: nx_int,
251 out_ids: *nx_int, out_cap: nx_int) -> nx_int {
252 var count: nx_int = 0
253 var cur: nx_int = seed_id
254 var safety: nx_int = 0
255 while safety < NX_5WH_MAX_WALK {
256 if cur < 0 { return count }
257 if count >= out_cap { return count }
258 let rec: *Nx5whRecord = nx_5wh_record_at(ledger, cur)
259 if rec == (0 as *Nx5whRecord) { return count }
260 out_ids[count] = cur
261 count = count + 1
262 cur = rec.why_parent_id
263 safety = safety + 1
264 }
265 return count
266}
267
268// ===== summary counts ==============================================
269
270func nx_5wh_count_by_what(ledger: *Nx5whLedger, what: nx_int) -> nx_int {
271 if nx_5wh_what_is_valid(what) == 0 { return 0 - 1 }
272 var count: nx_int = 0
273 var i: nx_int = 0
274 let cap: nx_int = ledger.capacity
275 let emitted: nx_int = ledger.n_emitted
276 var scan_n: nx_int = emitted
277 if scan_n > cap { scan_n = cap }
278 while i < scan_n {
279 let rec: *Nx5whRecord = nx_5wh_record_at(ledger, i)
280 if rec.what == what { count = count + 1 }
281 i = i + 1
282 }
283 return count
284}
285
286func nx_5wh_n_emitted(ledger: *Nx5whLedger) -> nx_int {
287 return ledger.n_emitted
288}
289
290func nx_5wh_n_dropped(ledger: *Nx5whLedger) -> nx_int {
291 return ledger.n_dropped
292}
293
294// ===== self-test ====================================================
295//
296// Verifies:
297// - emit returns ascending slot ids
298// - record fetch returns identical fields
299// - query filters work (what_mask + where_mask + step range)
300// - lineage walk follows why_parent back to root
301// - bounded ring drops oldest correctly
302// - sealed-enum validators refuse out-of-range
303
304func main() -> nx_int {
305 let ledger: *Nx5whLedger = nx_5wh_log_alloc(8)
306 if ledger.capacity != 8 { return 1 }
307 if ledger.n_emitted != 0 { return 2 }
308
309 // Emit a chain: MEASUREMENT (root) -> VERDICT (caused by m0)
310 // -> ATTRIBUTION (caused by v0).
311 let m0: nx_int = nx_5wh_emit(ledger,
312 100, NX_5WH_WHAT_MEASUREMENT,
313 NX_5WH_WHERE_SAMPLER, 0, 0, 0,
314 NX_5WH_NO_PARENT,
315 200, 300, 400, 950)
316 if m0 != 0 { return 3 }
317 let v0: nx_int = nx_5wh_emit(ledger,
318 101, NX_5WH_WHAT_VERDICT,
319 NX_5WH_WHERE_SAMPLER, 0, 0, 0,
320 m0,
321 201, 301, 401, 1)
322 if v0 != 1 { return 4 }
323 let a0: nx_int = nx_5wh_emit(ledger,
324 102, NX_5WH_WHAT_ATTRIBUTION,
325 NX_5WH_WHERE_TRANSFORMER_LAYER, 5, 2, 128,
326 v0,
327 202, 302, 402, 768)
328 if a0 != 2 { return 5 }
329
330 // Fetch + verify fields.
331 let rec_m0: *Nx5whRecord = nx_5wh_record_at(ledger, m0)
332 if rec_m0.who != 100 { return 10 }
333 if rec_m0.what != NX_5WH_WHAT_MEASUREMENT { return 11 }
334 if rec_m0.why_parent_id != NX_5WH_NO_PARENT { return 12 }
335 if rec_m0.performance != 950 { return 13 }
336
337 let rec_a0: *Nx5whRecord = nx_5wh_record_at(ledger, a0)
338 if rec_a0.where_kind != NX_5WH_WHERE_TRANSFORMER_LAYER { return 20 }
339 if rec_a0.where_idx_a != 5 { return 21 }
340 if rec_a0.where_idx_b != 2 { return 22 }
341 if rec_a0.where_idx_c != 128 { return 23 }
342 if rec_a0.why_parent_id != v0 { return 24 }
343
344 // Query: all VERDICTs anywhere -> should find exactly v0.
345 let q_buf: *nx_int = (sys_mmap(64)) as *nx_int
346 let verdict_mask: nx_int = 1 << NX_5WH_WHAT_VERDICT
347 let n_v: nx_int = nx_5wh_query(ledger, verdict_mask, 0, -1, -1, q_buf, 8)
348 if n_v != 1 { return 30 }
349 if q_buf[0] != v0 { return 31 }
350
351 // Query: all records at TRANSFORMER_LAYER -> should find a0.
352 let xform_mask: nx_int = 1 << NX_5WH_WHERE_TRANSFORMER_LAYER
353 let n_x: nx_int = nx_5wh_query(ledger, 0, xform_mask, -1, -1, q_buf, 8)
354 if n_x != 1 { return 32 }
355 if q_buf[0] != a0 { return 33 }
356
357 // Query: step-window 1..2 -> v0 + a0.
358 let n_win: nx_int = nx_5wh_query(ledger, 0, 0, 1, 2, q_buf, 8)
359 if n_win != 2 { return 34 }
360 if q_buf[0] != v0 { return 35 }
361 if q_buf[1] != a0 { return 36 }
362
363 // Lineage walk from a0 -> a0, v0, m0.
364 let walk_buf: *nx_int = (sys_mmap(64)) as *nx_int
365 let n_walk: nx_int = nx_5wh_walk_lineage(ledger, a0, walk_buf, 8)
366 if n_walk != 3 { return 40 }
367 if walk_buf[0] != a0 { return 41 }
368 if walk_buf[1] != v0 { return 42 }
369 if walk_buf[2] != m0 { return 43 }
370
371 // Counts.
372 if nx_5wh_count_by_what(ledger, NX_5WH_WHAT_MEASUREMENT) != 1 { return 50 }
373 if nx_5wh_count_by_what(ledger, NX_5WH_WHAT_VERDICT) != 1 { return 51 }
374 if nx_5wh_count_by_what(ledger, NX_5WH_WHAT_ATTRIBUTION) != 1 { return 52 }
375 if nx_5wh_count_by_what(ledger, NX_5WH_WHAT_OP_BEGIN) != 0 { return 53 }
376
377 // Sealed-enum validators refuse out-of-range.
378 if nx_5wh_what_is_valid(0 - 1) != 0 { return 60 }
379 if nx_5wh_what_is_valid(NX_5WH_WHAT_N_KINDS) != 0 { return 61 }
380 if nx_5wh_where_is_valid(0 - 1) != 0 { return 62 }
381 if nx_5wh_where_is_valid(NX_5WH_WHERE_N_KINDS) != 0 { return 63 }
382
383 // Invalid emit refused.
384 let bad: nx_int = nx_5wh_emit(ledger,
385 0, 999, NX_5WH_WHERE_NONE, 0, 0, 0,
386 NX_5WH_NO_PARENT, 0, 0, 0, 0)
387 if bad != 0 - 1 { return 64 }
388
389 // Ring overflow: fill cap=8 more emits, head should wrap.
390 var k: nx_int = 0
391 while k < 10 {
392 nx_5wh_emit(ledger,
393 500 + k, NX_5WH_WHAT_OP_BEGIN,
394 NX_5WH_WHERE_HARDWARE, 0, 0, 0,
395 NX_5WH_NO_PARENT,
396 600 + k, 700 + k, 800 + k, k)
397 k = k + 1
398 }
399 if ledger.n_dropped < 1 { return 70 }
400
401 return 0
402}