code wiki / (root) / nx_compare_growth_lib_20260910.nx

nx_compare_growth_lib_20260910.nx source

↩ module page · 263 lines · 10868 B

1// Additive .plan capability-growth projection. Authored stages never become evidence verdicts. 2// Input is borrowed for model lifetime. No store writes, execution, publication or stage advancement. 3// growthpath|1|id|rung|entry|target|research_refs|learned_model|questions 4// growthexercise|1|id|path|deps|contract|tool_ref|workload_ref|resource_ref|acceptance_ref|failure_next 5// growthassessment|1|id|path|scope|stage|evidence_refs|unix|assessor_ref|supersedes 6// "-" denotes no list or optional link. References remain unresolved until their authoritative owners verify them. 7import "nx_measurement_binding_lib.nx" 8const CG_ROW_WORDS: i64=3 9const CG_MODEL_WORDS: i64=10 10const CG_PATH: i64=1 11const CG_EXERCISE: i64=2 12const CG_ASSESSMENT: i64=3 13const CG_E_INPUT: i64=0-1 14const CG_E_CAPACITY: i64=0-2 15const CG_E_SHAPE: i64=0-3 16const CG_E_ID: i64=0-4 17const CG_E_DUPLICATE: i64=0-5 18const CG_E_LINK: i64=0-6 19const CG_E_CYCLE: i64=0-7 20const CG_E_TIME: i64=0-8 21struct CgModel { 22 plan: *u8, 23 n: i64, 24 rows: *i64, 25 count: i64, 26 capacity: i64, 27 error: i64, 28 error_row: i64, 29 paths: i64, 30 exercises: i64, 31 assessments: i64 32} 33func cg_kind(b: *u8,p: i64,e: i64) -> i64 { 34 if bf_line_starts(b,p,e,"growthpath|" as *u8)==1 { return CG_PATH } 35 if bf_line_starts(b,p,e,"growthexercise|" as *u8)==1 { return CG_EXERCISE } 36 if bf_line_starts(b,p,e,"growthassessment|" as *u8)==1 { return CG_ASSESSMENT } 37 return 0 38} 39func cg_error(m: *CgModel,code: i64,row: i64) -> i64 { 40 if m.error==0 { m.error=code; m.error_row=row } 41 return code 42} 43func cg_field(m: *CgModel,row: i64,col: i64,off: *i64) -> i64 { 44 return bf_field(m.plan,m.rows[row*CG_ROW_WORDS+1],m.rows[row*CG_ROW_WORDS+2],col,off) 45} 46func cg_is(m: *CgModel,row: i64,col: i64,s: *u8) -> i64 { 47 var off: i64=0; let n: i64=cg_field(m,row,col,&off) 48 return pb_equal(m.plan,off,n,s,0,bf_slen(s)) 49} 50func cg_same(m: *CgModel,a: i64,ac: i64,b: i64,bc: i64) -> i64 { 51 var ao: i64=0; var bo: i64=0 52 let an: i64=cg_field(m,a,ac,&ao); let bn: i64=cg_field(m,b,bc,&bo) 53 return pb_equal(m.plan,ao,an,m.plan,bo,bn) 54} 55func cg_ident(b: *u8,o: i64,n: i64) -> i64 { 56 if n<=0 { return 0 } 57 var i: i64=0 58 while i<n { 59 let c: i64=b[o+i] as i64 60 var ok: i64=0 61 if c>=65 { if c<=90 { ok=1 } } 62 if c>=97 { if c<=122 { ok=1 } } 63 if c>=48 { if c<=57 { ok=1 } } 64 if c==45 { ok=1 }; if c==95 { ok=1 }; if c==46 { ok=1 } 65 if ok==0 { return 0 } 66 i=i+1 67 } 68 if n==1 { if b[o]==(45 as u8) { return 0 } } 69 return 1 70} 71func cg_idfield(m: *CgModel,row: i64,col: i64) -> i64 { 72 var o: i64=0; let n: i64=cg_field(m,row,col,&o) 73 return cg_ident(m.plan,o,n) 74} 75func cg_decimal(m: *CgModel,row: i64,col: i64) -> i64 { 76 var o: i64=0; let n: i64=cg_field(m,row,col,&o) 77 if n<=0 { return CG_E_TIME } 78 var i: i64=0; var v: i64=0 79 while i<n { 80 let d: i64=(m.plan[o+i] as i64)-48 81 if d<0 { return CG_E_TIME }; if d>9 { return CG_E_TIME } 82 if v>(PB_I64_MAX-d)/10 { return CG_E_TIME } 83 v=v*10+d; i=i+1 84 } 85 if v<=0 { return CG_E_TIME } 86 return v 87} 88func cg_find(m: *CgModel,kind: i64,o: i64,n: i64) -> i64 { 89 var i: i64=0 90 while i<m.count { 91 if m.rows[i*CG_ROW_WORDS]==kind { 92 var io: i64=0; let ni: i64=cg_field(m,i,2,&io) 93 if pb_equal(m.plan,io,ni,m.plan,o,n)==1 { return i } 94 } 95 i=i+1 96 } 97 return 0-1 98} 99func cg_link(m: *CgModel,row: i64,col: i64,kind: i64) -> i64 { 100 var o: i64=0; let n: i64=cg_field(m,row,col,&o) 101 return cg_find(m,kind,o,n) 102} 103func cg_existing(m: *CgModel,row: i64,col: i64,tag: *u8) -> i64 { 104 var o: i64=0; let n: i64=cg_field(m,row,col,&o) 105 var p: i64=0; var count: i64=0 106 while p<m.n { 107 let raw: i64=bf_line_end(m.plan,m.n,p); let e: i64=pb_trim_cr(m.plan,p,raw) 108 if bf_line_starts(m.plan,p,e,tag)==1 { 109 var eo: i64=0; let en: i64=bf_field(m.plan,p,e,1,&eo) 110 if pb_equal(m.plan,o,n,m.plan,eo,en)==1 { count=count+1 } 111 } 112 p=raw+1 113 } 114 return count 115} 116// A dependency list is ordered authored data. Duplicate, missing and cross-path edges are refused. 117func cg_deps(m: *CgModel,row: i64,target: i64) -> i64 { 118 if cg_is(m,row,4,"-" as *u8)==1 { return 0 } 119 var o: i64=0; let n: i64=cg_field(m,row,4,&o) 120 var p: i64=o; let end: i64=o+n; var count: i64=0 121 while p<=end { 122 var e: i64=p 123 while e<end { if m.plan[e]==(44 as u8) { break }; e=e+1 } 124 if cg_ident(m.plan,p,e-p)==0 { return cg_error(m,CG_E_ID,row) } 125 let dep: i64=cg_find(m,CG_EXERCISE,p,e-p) 126 if dep<0 { return cg_error(m,CG_E_LINK,row) } 127 if dep==row { return cg_error(m,CG_E_CYCLE,row) } 128 if cg_same(m,row,3,dep,3)==0 { return cg_error(m,CG_E_LINK,row) } 129 var earlier: i64=o 130 while earlier<p { 131 var ee: i64=earlier 132 while ee<end { if m.plan[ee]==(44 as u8) { break }; ee=ee+1 } 133 if pb_equal(m.plan,p,e-p,m.plan,earlier,ee-earlier)==1 { return cg_error(m,CG_E_DUPLICATE,row) } 134 earlier=ee+1 135 } 136 if target<0 { count=count+1 } else { if dep==target { count=count+1 } } 137 if e==end { break }; p=e+1 138 } 139 return count 140} 141func cg_graph(m: *CgModel) -> i64 { 142 if m.count>PB_I64_MAX/8 { return cg_error(m,CG_E_CAPACITY,0-1) } 143 let bytes: i64=(m.count+1)*8 144 let deg: *i64=sys_mmap(bytes) as *i64 145 let seen: *i64=sys_mmap(bytes) as *i64 146 if (deg as i64)<=0 { return cg_error(m,CG_E_CAPACITY,0-1) } 147 if (seen as i64)<=0 { sys_munmap(deg as *u8,bytes); return cg_error(m,CG_E_CAPACITY,0-1) } 148 var i: i64=0 149 while i<m.count { 150 if m.rows[i*CG_ROW_WORDS]==CG_EXERCISE { deg[i]=cg_deps(m,i,0-1) } 151 i=i+1 152 } 153 var removed: i64=0; var changed: i64=1 154 while changed==1 { 155 changed=0; i=0 156 while i<m.count { 157 if m.rows[i*CG_ROW_WORDS]==CG_EXERCISE { 158 if seen[i]==0 { if deg[i]==0 { 159 seen[i]=1; removed=removed+1; changed=1 160 var j: i64=0 161 while j<m.count { 162 if m.rows[j*CG_ROW_WORDS]==CG_EXERCISE { if seen[j]==0 { deg[j]=deg[j]-cg_deps(m,j,i) } } 163 j=j+1 164 } 165 } } 166 } 167 i=i+1 168 } 169 } 170 sys_munmap(deg as *u8,bytes); sys_munmap(seen as *u8,bytes) 171 if m.error!=0 { return m.error } 172 if removed!=m.exercises { return cg_error(m,CG_E_CYCLE,0-1) } 173 return 0 174} 175func cg_validate(m: *CgModel) -> i64 { 176 var i: i64=0 177 while i<m.count { 178 let kind: i64=m.rows[i*CG_ROW_WORDS] 179 if cg_is(m,i,1,"1" as *u8)==0 { return cg_error(m,CG_E_SHAPE,i) } 180 if cg_idfield(m,i,2)==0 { return cg_error(m,CG_E_ID,i) } 181 var j: i64=0 182 while j<i { 183 if m.rows[j*CG_ROW_WORDS]==kind { if cg_same(m,i,2,j,2)==1 { return cg_error(m,CG_E_DUPLICATE,i) } } 184 j=j+1 185 } 186 if kind==CG_PATH { 187 if cg_existing(m,i,3,LD_RUNG_TAG)!=1 { return cg_error(m,CG_E_LINK,i) } 188 if cg_existing(m,i,5,LD_TARGET_TAG)!=1 { return cg_error(m,CG_E_LINK,i) } 189 let entry: i64=cg_is(m,i,4,"proactive_research" as *u8)+cg_is(m,i,4,"observed_failure" as *u8)+cg_is(m,i,4,"operator_target" as *u8) 190 if entry!=1 { return cg_error(m,CG_E_SHAPE,i) } 191 } else { 192 if cg_link(m,i,3,CG_PATH)<0 { return cg_error(m,CG_E_LINK,i) } 193 if kind==CG_EXERCISE { 194 if cg_deps(m,i,0-1)<0 { return m.error } 195 if cg_is(m,i,10,"@research" as *u8)+cg_is(m,i,10,"@learning" as *u8)==0 { 196 let next: i64=cg_link(m,i,10,CG_EXERCISE) 197 if next<0 { return cg_error(m,CG_E_LINK,i) } 198 if cg_same(m,i,3,next,3)==0 { return cg_error(m,CG_E_LINK,i) } 199 } 200 } else { 201 let stage: i64=cg_is(m,i,5,"research" as *u8)+cg_is(m,i,5,"learning" as *u8)+cg_is(m,i,5,"identified" as *u8)+cg_is(m,i,5,"practice" as *u8)+cg_is(m,i,5,"mastery" as *u8)+cg_is(m,i,5,"innovation" as *u8) 202 if stage!=1 { return cg_error(m,CG_E_SHAPE,i) } 203 let epoch: i64=cg_decimal(m,i,7) 204 if epoch<0 { return cg_error(m,CG_E_TIME,i) } 205 if cg_is(m,i,9,"-" as *u8)==0 { 206 let prev: i64=cg_link(m,i,9,CG_ASSESSMENT) 207 if prev<0 { return cg_error(m,CG_E_LINK,i) } 208 if cg_same(m,i,3,prev,3)==0 { return cg_error(m,CG_E_LINK,i) } 209 if cg_same(m,i,4,prev,4)==0 { return cg_error(m,CG_E_LINK,i) } 210 let prior: i64=cg_decimal(m,prev,7) 211 if prior<0 { return cg_error(m,CG_E_TIME,i) } 212 if prior>=epoch { return cg_error(m,CG_E_TIME,i) } 213 } 214 } 215 } 216 i=i+1 217 } 218 return cg_graph(m) 219} 220func cg_parse(b: *u8,n: i64) -> *CgModel { 221 let m: *CgModel=sys_mmap(CG_MODEL_WORDS*8) as *CgModel 222 if (m as i64)<=0 { return 0 as *CgModel } 223 m.plan=b; m.n=n; m.error_row=0-1 224 if n<0 { cg_error(m,CG_E_INPUT,0-1); return m } 225 if n==0 { return m } 226 if (b as i64)<=0 { cg_error(m,CG_E_INPUT,0-1); return m } 227 if pb_input_ok(b,n)==0 { cg_error(m,CG_E_INPUT,0-1); return m } 228 var p: i64=0 229 while p<n { 230 let e: i64=bf_line_end(b,n,p) 231 if cg_kind(b,p,e)>0 { m.capacity=m.capacity+1 } 232 p=e+1 233 } 234 if m.capacity==0 { return m } 235 if m.capacity>PB_I64_MAX/(CG_ROW_WORDS*8) { cg_error(m,CG_E_CAPACITY,0-1); return m } 236 m.rows=sys_mmap(m.capacity*CG_ROW_WORDS*8) as *i64 237 if (m.rows as i64)<=0 { cg_error(m,CG_E_CAPACITY,0-1); return m } 238 p=0 239 while p<n { 240 let raw: i64=bf_line_end(b,n,p); let e: i64=pb_trim_cr(b,p,raw); let kind: i64=cg_kind(b,p,e) 241 if kind>0 { 242 var scratch: i64=0 243 let fields: i64=pb_field_count(b,p,e,&scratch) 244 var expected: i64=9 245 if kind==CG_EXERCISE { expected=11 }; if kind==CG_ASSESSMENT { expected=10 } 246 if fields!=expected { cg_error(m,CG_E_SHAPE,m.count); return m } 247 var f: i64=1 248 while f<fields { 249 if bf_field(b,p,e,f,&scratch)<=0 { cg_error(m,CG_E_SHAPE,m.count); return m }; f=f+1 250 } 251 m.rows[m.count*CG_ROW_WORDS]=kind; m.rows[m.count*CG_ROW_WORDS+1]=p; m.rows[m.count*CG_ROW_WORDS+2]=e 252 m.count=m.count+1 253 if kind==CG_PATH { m.paths=m.paths+1 }; if kind==CG_EXERCISE { m.exercises=m.exercises+1 }; if kind==CG_ASSESSMENT { m.assessments=m.assessments+1 } 254 } 255 p=raw+1 256 } 257 cg_validate(m); return m 258} 259func cg_free(m: *CgModel) -> i64 { 260 if (m as i64)<=0 { return 0 } 261 if (m.rows as i64)>0 { sys_munmap(m.rows as *u8,m.capacity*CG_ROW_WORDS*8) } 262 sys_munmap(m as *u8,CG_MODEL_WORDS*8); return 0 263}