code wiki / (root) / nx_bprov_chain.nx

nx_bprov_chain.nx source

↩ module page · 100 lines · 3524 B

1// nx_bprov_chain.nx -- ergonomic wrappers over nx_bit_provenance. 2// 3// Cardinal: feedback-bit-provenance-systemic-auto-injection. 4// 5// The bit-provenance ledger primitive (nx_bit_provenance.nx) exposes 6// alloc / emit / emit3 / join. Used directly, each producer site 7// needs 2-3 lines of boilerplate: 8// 9// let id: i64 = nx_bprov_alloc() 10// nx_bprov_emit(id, src_a, src_b, layer, tag) 11// 12// This wrapper collapses that into a single chain-call: 13// 14// let id: i64 = nx_bprov_chain2(layer, tag, src_a, src_b) 15// 16// Or for 3 sources: 17// let id: i64 = nx_bprov_chain3(layer, tag, src_a, src_b, src_c) 18// 19// Or 0 sources (silicon-born input): 20// let id: i64 = nx_bprov_chain0(layer, tag) 21// 22// These are the "born into what we build" half of the systemic 23// answer. New substrate primitives use these in their main paths. 24// The other half (retroactive injection on existing primitives) is 25// the self-host IR pass per docs/NISHI_BPROV_AUTO_INJECTION_DESIGN.md. 26 27import "nx_bit_provenance.nx" 28 29// Silicon-born / no upstream: just allocate + record. 30func nx_bprov_chain0(layer: i64, tag: i64) -> i64 { 31 let id: i64 = nx_bprov_alloc() 32 nx_bprov_emit(id, 0, 0, layer, tag) 33 return id 34} 35 36// One upstream source. 37func nx_bprov_chain1(layer: i64, tag: i64, src_a: i64) -> i64 { 38 let id: i64 = nx_bprov_alloc() 39 nx_bprov_emit(id, src_a, 0, layer, tag) 40 return id 41} 42 43// Two upstream sources (most common). 44func nx_bprov_chain2(layer: i64, tag: i64, src_a: i64, src_b: i64) -> i64 { 45 let id: i64 = nx_bprov_alloc() 46 nx_bprov_emit(id, src_a, src_b, layer, tag) 47 return id 48} 49 50// Three upstream sources (matmul-cell-class). 51func nx_bprov_chain3(layer: i64, tag: i64, 52 src_a: i64, src_b: i64, src_c: i64) -> i64 { 53 let id: i64 = nx_bprov_alloc() 54 nx_bprov_emit3(id, src_a, src_b, src_c, layer, tag) 55 return id 56} 57 58// Consumer-side helper -- alias for nx_bprov_join with a friendlier 59// name in caller context. 60func nx_bprov_consume(in_bit_id: i64, layer: i64, tag: i64) -> i64 { 61 return nx_bprov_join(in_bit_id, layer, tag) 62} 63 64// ---- self-test --------------------------------------------------- 65// expect_exit: 0 66 67func main() -> i64 { 68 if nx_bprov_init() != 0 { return 1 } 69 70 // Birth 2 silicon bits. 71 let b_a: i64 = nx_bprov_chain0(NX_BPROV_L_NEG_1, 0xC0DE0001) 72 let b_b: i64 = nx_bprov_chain0(NX_BPROV_L_NEG_1, 0xC0DE0002) 73 74 // Compose at L3. 75 let b_x: i64 = nx_bprov_chain2(NX_BPROV_L_3, 0xC0DE0003, b_a, b_b) 76 77 // Compose at L3.5 with 3 sources (last is silicon-immutable 0). 78 let b_y: i64 = nx_bprov_chain3(NX_BPROV_L_35, 0xC0DE0004, b_a, b_b, b_x) 79 80 // Single-source chain at L4. 81 let b_z: i64 = nx_bprov_chain1(NX_BPROV_L_4, 0xC0DE0005, b_y) 82 83 // Pre-consume audit: 5 zombies (b_a/b_b/b_x/b_y/b_z all unjoined). 84 if nx_bprov_audit_zombies() != 5 { return 10 } 85 86 // Consume the leaf at L7 (browser death). 87 if nx_bprov_consume(b_z, NX_BPROV_L_7, 0xC0DE0006) != 0 { return 20 } 88 89 // Join intermediates at their actual consumer layers. 90 if nx_bprov_consume(b_a, NX_BPROV_L_3, 0xC0DE0003) != 0 { return 21 } 91 if nx_bprov_consume(b_b, NX_BPROV_L_3, 0xC0DE0003) != 0 { return 22 } 92 if nx_bprov_consume(b_x, NX_BPROV_L_35, 0xC0DE0004) != 0 { return 23 } 93 if nx_bprov_consume(b_y, NX_BPROV_L_4, 0xC0DE0005) != 0 { return 24 } 94 95 // Final audit: zombies=0, all 5 bits silicon-to-death traced. 96 if nx_bprov_audit_zombies() != 0 { return 30 } 97 if nx_bprov_n_records() != 5 { return 40 } 98 99 return 0 100}