code wiki / (root) / nx_raci_sov.nx

nx_raci_sov.nx source

↩ module page · 215 lines · 11367 B

1// nx_raci_sov.nx -- get the conductor's RACI OFF the TSV into the SOVEREIGN seg_store (operator: "get us off 2// tsv and all the other third party bullshit"). The conductor (nx_harmony_conduct) + the pulse governance 3// read role accountability from knowledge/registry/nishi_raci.tsv -- a third-party flat TSV. This migrates 4// those rows into knowledge/store/raci (sovereign seg_store) via the PROVEN nx_role_store_migrate pattern 5// (read -> seed -> byte-verify every row), and answers `raci_is_accountable(role)` FROM THE STORE -- no TSV. 6// It also FIXES a latent bug: the hardcoded owner list said {engineer,doctor,researcher,adversarial,pm} but 7// the real contract's Accountable roles are {researcher,workstream,doctor,engineer,publisher,supervisor,pm, 8// warden} -- "adversarial" is NOT a RACI role, and workstream/publisher/supervisor/warden were missing. 9// Sovereign. license_tier: ORIGINAL 10import "nx_seg_store.nx" 11import "nx_syscalls.nx" 12 13const RACI_TSV: *u8 = "knowledge/registry/nishi_raci.tsv" 14const RACI_STORE: *u8 = "knowledge/store/raci" 15 16// key "raci:row:K" -> out 17func rsv_key(k: i64, out: *u8) -> i64 { 18 var o: i64=0; let p: *u8="raci:row:" as *u8; var i: i64=0 19 while p[i]!=(0 as u8){ out[o]=p[i]; o=o+1; i=i+1 } 20 // ★★★THE CHOKEPOINT, AND THE REASON THE FIRST FIX WAS NOT ENOUGH. This built its digits in a 21 // sys_mmap(24) scratch buffer -- and rsv_key is called ONCE PER ROW by every scan in this file. So even 22 // after hoisting the callers' own per-row mmap, each iteration STILL burned a page here: 2 allocations 23 // per row became 1, and nx_orchestrate_gate went from 2 PASS lines to 4 and then timed out again. 24 // MIGRATE THE CHOKEPOINT, NOT THE LEAF -- one allocation-free key builder fixes every caller at once. 25 // Digits are counted first and written in place, which needs no scratch and is exactly equivalent. 26 if k==0 { out[o]=48 as u8; o=o+1 } else { 27 var nd: i64=0; var m: i64=k 28 while m>0 { nd=nd+1; m=m/10 } 29 m=k 30 var j: i64=nd-1 31 while j>=0 { out[o+j]=(48+(m%10)) as u8; m=m/10; j=j-1 } 32 o=o+nd 33 } 34 out[o]=0 as u8; return 0 35} 36 37// MIGRATE the RACI rows into the store (skip '#' comments + empty), then byte-verify each row reads back. 38// Re-migrates each run (the RACI is the static coordination contract until the TSV is retired). Returns 39// verified-row-count via verp[0]; total source rows via totp[0]. GREEN when verp==totp. 40func raci_migrate(totp: *i64, verp: *i64) -> i64 { 41 let szp: *i64 = sys_mmap(16) as *i64 42 let buf: *u8 = ss_readall(RACI_TSV, szp) 43 let sz: i64 = szp[0] 44 if sz <= 0 { totp[0]=0; verp[0]=0; return 0 } 45 let lp: *i64 = sys_mmap(8*512) as *i64; let ll: *i64 = sys_mmap(8*512) as *i64 46 var k: i64 = 0; var i: i64 = 0; var ls: i64 = 0 47 while i <= sz { 48 var nl: i64 = 0; if i>=sz { nl=1 } else { if buf[i]==(10 as u8) { nl=1 } } 49 if nl==1 { 50 let len: i64 = i - ls 51 if len>0 { if (buf[ls] as i64) != 35 { if k<512 { lp[k]=(buf as i64)+ls; ll[k]=len; k=k+1 } } } // skip '#' 52 ls = i+1 53 } 54 i=i+1 55 } 56 totp[0]=k 57 // seed every data row keyed by index, in one commit 58 let w: *i64 = ss_begin() 59 var j: i64 = 0 60 while j<k { let rk: *u8=sys_mmap(64); rsv_key(j, rk); ss_add(w, 1, rk, lp[j] as *u8, ll[j]); j=j+1 } 61 ss_commit(RACI_STORE, w, sys_now_realtime_sec()) 62 // verify each row reads back byte-exact from the store 63 let h: *i64 = ss_open(RACI_STORE) 64 let pq: *i64=sys_mmap(16) as *i64; let lq: *i64=sys_mmap(16) as *i64 65 var ver: i64 = 0; var j2: i64 = 0 66 while j2<k { 67 let rk: *u8=sys_mmap(64); rsv_key(j2, rk) 68 if ss_hget(h, rk, pq, lq)==1 { if lq[0]==ll[j2] { let a: *u8=pq[0] as *u8; let b: *u8=lp[j2] as *u8; var eq: i64=1; var x: i64=0; while x<lq[0] { if a[x]!=b[x] { eq=0 } x=x+1 } if eq==1 { ver=ver+1 } } } 69 j2=j2+1 70 } 71 verp[0]=ver 72 return ver 73} 74 75func rsv_field(line: *u8, len: i64, idx: i64, out: *u8) -> i64 { 76 var f: i64=0; var i: i64=0; var w: i64=0 77 while i<len { let c: i64=line[i] as i64 78 if c==9 { if f==idx { out[w]=0 as u8; return 1 } f=f+1 } else { if f==idx { out[w]=line[i]; w=w+1 } } 79 i=i+1 } 80 if f==idx { out[w]=0 as u8; return 1 } 81 return 0 82} 83func rsv_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 } 84func rsv_has(s: *u8, ch: i64) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ if (s[i] as i64)==ch {return 1} i=i+1 } return 0 } 85 86// SOVEREIGN ownership: is `role` Accountable ('A') for ANY activity? reads the STORE, not the TSV. Iterates 87// raci:row:0.. until a gap. The grounded replacement for the hardcoded owner list. 88func raci_is_accountable(role: *u8) -> i64 { 89 let h: *i64 = ss_open(RACI_STORE) 90 if (h as i64)==0 { return 0 } 91 let pq: *i64=sys_mmap(16) as *i64; let lq: *i64=sys_mmap(16) as *i64 92 let rolef: *u8=sys_mmap(64); let letf: *u8=sys_mmap(64) 93 var k: i64=0; var go: i64=1 94 let rk: *u8=sys_mmap(64) // hoisted: same per-row page burn as raci_accountable_for had 95 while go==1 { 96 rsv_key(k, rk) 97 if ss_hget(h, rk, pq, lq)==1 { 98 let line: *u8=pq[0] as *u8; let ln: i64=lq[0] 99 rsv_field(line, ln, 0, rolef); rsv_field(line, ln, 2, letf) 100 if rsv_streq(rolef, role)==1 { if rsv_has(letf, 65)==1 { ss_close(h); return 1 } } // 'A' = Accountable 101 k=k+1 102 } else { go=0 } 103 } 104 ss_close(h) 105 return 0 106} 107 108// PUBLIC row accessor (reader-flip export, 2026-07-16): row k's bytes into out (NUL-terminated, 109// capped), from the STORE. Returns len, or -1 when k is past the last row (the iteration sentinel). 110// ---- seq1789: THE HANDLE IS HOISTED, AND EVERY OPEN IS CLOSED ------------------------------------- 111// THE DEFECT (measured 2026-07-30): raci_row opened the seg-store ON EVERY ROW and never closed it, and 112// raci_read_all called raci_row once per row -- so ONE full-contract read cost N opens, each mapping every 113// live segment, none released. nx_orchestrate_gate calls it 5+ times and HUNG; that hang propagated up 114// through nx_swcompare_evidence (which forks domain gates with no deadline) until the whole `librarian` 115// domain was unmeasurable and the symptom presented as an MCP transport error. 116// ss_close's own header predicted this exactly: the leak parks a process in uninterruptible sleep, so it 117// "presents as a HANG, not as an OOM". This file was one of the ~133 openers with no matching closer. 118// LAW: AN UNCLOSED RESOURCE INSIDE A LOOP IS NOT A LEAK, IT IS A CLOCK -- it fails at a size, not at a 119// line, so it looks like a hang in whoever calls you rather than a bug where it is written. 120// SHAPE OF THE FIX (the reason there are now two functions): the handle-taking core does the work, the 121// convenience wrapper owns the lifetime. Any caller that needs MANY rows takes the handle once instead of 122// paying an open per row -- which is the difference between O(1) and O(N) mappings for the same answer. 123 124// CORE: row k's bytes into out (NUL-terminated, capped) from an ALREADY-OPEN store. Opens nothing and 125// closes nothing -- the caller owns the handle. Returns len, or -1 when k is past the last row. 126func raci_row_h(h: *i64, k: i64, out: *u8, cap: i64) -> i64 { 127 if (h as i64)==0 { return 0 - 1 } 128 let pq: *i64=sys_mmap(16) as *i64 129 let lq: *i64=sys_mmap(16) as *i64 130 let rk: *u8=sys_mmap(64) 131 rsv_key(k, rk) 132 if ss_hget(h, rk, pq, lq)!=1 { return 0 - 1 } 133 var n: i64 = lq[0] 134 if n > cap - 1 { n = cap - 1 } 135 let src: *u8 = pq[0] as *u8 136 var i: i64=0 137 while i<n { out[i]=src[i]; i=i+1 } 138 out[n]=0 as u8 139 return n 140} 141 142// PUBLIC row accessor (reader-flip export, 2026-07-16): unchanged contract for single-row callers -- 143// same arguments, same return, same sentinel -- but it now RELEASES what it maps. Callers wanting more 144// than one row should open once and use raci_row_h. 145func raci_row(k: i64, out: *u8, cap: i64) -> i64 { 146 let h: *i64 = ss_open(RACI_STORE) 147 if (h as i64)==0 { return 0 - 1 } 148 let n: i64 = raci_row_h(h, k, out, cap) 149 ss_close(h) 150 return n 151} 152 153// PM/routing export (reader-flip, 2026-07-16): the Accountable role for `activity`, FROM THE STORE 154// (single-A invariant validated by nx_raci_gate, so the first 'A' match is THE owner). 1 = found 155// (out_role NUL-terminated), 0 = no accountable row. Replaces every TSV activity-lookup. 156func raci_accountable_for(activity: *u8, out_role: *u8) -> i64 { 157 let h: *i64 = ss_open(RACI_STORE) 158 if (h as i64)==0 { return 0 } 159 let pq: *i64=sys_mmap(16) as *i64 160 let lq: *i64=sys_mmap(16) as *i64 161 let actf: *u8=sys_mmap(64) 162 let letf: *u8=sys_mmap(64) 163 var k: i64=0 164 var go: i64=1 165 // ★MEASURED 2026-07-30: this mmap was INSIDE the loop -- one fresh 64-byte mapping PER ROW. mmap is 166 // page-granular, so every iteration burned a whole 4KiB page plus a syscall, and nothing ever unmapped 167 // them. A lookup that MISSES walks the entire plane, so the cost is O(rows) pages for a single failed 168 // question. LIVE EFFECT: nx_orchestrate_gate printed 2 PASS lines and then TIMED OUT at the 12s deadline 169 // on its THIRD lookup -- the first two matched early rows, the third scanned to the end -- which made the 170 // whole `librarian` domain read RED in nx_sota_status, which is the single BLOCK in nx_deploy_ready. 171 // ★★★ONE ALLOCATION IN A HOT LOOP IS A SCALE BUG WEARING A CORRECTNESS COSTUME: it is invisible on a 172 // small plane, it never returns a wrong answer, and it takes down a domain's evidence once the data grows. 173 // rsv_key overwrites the buffer every pass, so a single hoisted allocation is exactly equivalent. 174 let rk: *u8=sys_mmap(64) 175 while go==1 { 176 rsv_key(k, rk) 177 if ss_hget(h, rk, pq, lq)==1 { 178 let line: *u8=pq[0] as *u8 179 let ln: i64=lq[0] 180 rsv_field(line, ln, 1, actf) 181 rsv_field(line, ln, 2, letf) 182 if rsv_streq(actf, activity)==1 { if rsv_has(letf, 65)==1 { rsv_field(line, ln, 0, out_role); ss_close(h); return 1 } } 183 k=k+1 184 } else { go=0 } 185 } 186 ss_close(h) 187 return 0 188} 189 190// FULL-CONTRACT reader (reader-flip export, 2026-07-16): every row from the STORE, newline-joined, 191// byte-compatible with the old TSV data rows -- so full-matrix consumers (dashboard/harmony/roster) 192// flip with a ONE-LINE swap of their file-read call. Returns total bytes (0 if store empty). 193func raci_read_all(out: *u8, cap: i64) -> i64 { 194 // ONE open for the whole contract (seq1789). This used to reach the store through raci_row, which 195 // opened it PER ROW and never released it -- same answer, N mappings, and the process eventually 196 // parked in uninterruptible sleep. Behaviour on a missing store is preserved exactly: empty, 0. 197 let h: *i64 = ss_open(RACI_STORE) 198 if (h as i64) == 0 { out[0] = 0 as u8; return 0 } 199 var o: i64 = 0 200 var k: i64 = 0 201 var go: i64 = 1 202 while go == 1 { 203 let n: i64 = raci_row_h(h, k, ((out as i64) + o) as *u8, cap - o - 1) 204 if n < 0 { go = 0 } else { 205 o = o + n 206 out[o] = 10 as u8 207 o = o + 1 208 k = k + 1 209 if o >= cap - 2 { go = 0 } 210 } 211 } 212 out[o] = 0 as u8 213 ss_close(h) 214 return o 215}