code wiki / _hdl_build / nx_actlog.nx

nx_actlog.nx source

↩ module page · 1750 lines · 85350 B

1// nx_actlog.nx -- ACTION LOG + WORKFLOW SEQUENCE MINER (ws=ws-intel3, 2026-07-20). 2// F217 completion (loop design-of-record R3): every cycle action journaled (ws/tool/verb/ 3// outcome) + the nx_workflow_mine half = n-gram mining over per-workstream action sequences. 4// Recurring tool:verb bigrams/trigrams with support >= minsup are the EMPIRICAL workflow 5// candidates (executed patterns, not combinatorial proposals -- the complement of 6// nx_atlas_discover). The loop: sessions/seats/plans LOG actions -> mine surfaces patterns 7// -> proposals enter nx_pm_intake -> PM/LLM seat triages -> catalog verb. Sequences NEVER 8// cross workstream boundaries (per-ws successor chains). State derived, append-only, 9// conflict-free (O_APPEND; ws_sync lineage). 10// Frame: <ts>\t<ws>\t<tool>\t<verb>\t<outcome>\t<note> 11// SCALE LAW: windowed reads + declared envelope (window_bytes/truncated/bigrams_capped/ 12// trigrams_capped); O(n^3) pair scan honest for journal-window scale, declared. 13// license_tier: ORIGINAL No hw writes (Rule 26). 14// log <journal> <ws> <tool> <verb> <outcome> <note> -> ACTLOG OK 15// mine <journal> [minsup] -> JSON (default minsup 2) 16// freq <journal> [topn] -> JSON per-tool:verb counts, ranked (topn: rows emitted, default 30; distinct is always the whole population) 17// (the fallback-log ranking verb; F872 rung 2) 18// harden <journal> [minsup] [filer] -> every tool:verb recurring >= minsup 19// auto-files a hardening debt via the 20// ALLOWLIST-RESOLVED filer (default nx_debt; 21// count-free canonical desc => idempotent) 22// selftest <scratch-journal> -> gate T1..T9 (caller pre-cleans) 23// steps <journal> [minsup] [conf] [topn] [now] -> ES26 STEPS-TO-SOLVE (2026-09-06): recurring adjacent 24// bigrams/trigrams joined to knowledge/stepsolve.conf and 25// classified ONE-STEP-AVAILABLE / DEPENDENCY / REDUCIBLE / 26// UNDECLARED; support-weighted partition, the reason or the 27// composed verb per ritual, the UNDECLARED worklist most 28// common first; spine knowledge/status/stepsolve.spine + 29// gauge stamp knowledge/status/stepsolve.stamp (gauge_pass) 30import "nx_sovjson_lib.nx" 31import "nx_syscalls.nx" 32import "nx_gate_verdict.nx" 33import "nx_tool_run.nx" 34import "nx_stepsolve_lib.nx" // ES26 (2026-09-06): THE ONE steps-to-solve ruler -- the `steps` verb below joins this miner's n-grams to knowledge/stepsolve.conf 35const AL_MAGIC_5381: i64 = 5381 36const AL_MAGIC_1100: i64 = 1100 37const AL_MAGIC_1101: i64 = 1101 38const AL_MAGIC_1102: i64 = 1102 39const AL_MAGIC_1103: i64 = 1103 40const AL_MAGIC_1104: i64 = 1104 41const AL_MAGIC_1105: i64 = 1105 42const AL_MAGIC_1106: i64 = 1106 43const AL_MAGIC_1107: i64 = 1107 44const AL_MAGIC_1108: i64 = 1108 45const AL_MAGIC_1110: i64 = 1110 46const AL_MAGIC_1111: i64 = 1111 47const AL_MAGIC_1112: i64 = 1112 48const AL_MAGIC_1113: i64 = 1113 49const AL_MAGIC_1114: i64 = 1114 50const AL_MAGIC_1115: i64 = 1115 51const AL_MAGIC_4096: i64 = 4096 52const AL_MAGIC_1500: i64 = 1500 53const AL_MAGIC_1024: i64 = 1024 54const AL_MAGIC_4090: i64 = 4090 55 56const AL_WIN: i64 = 4194304 57const AL_SEEK_SET: i64 = 0 58const AL_SEEK_END: i64 = 2 59const AL_OUT: i64 = 262144 60const AL_SOFT: i64 = 49152 61const AL_NAME_MAX: i64 = 120 62const AL_MINSUP_DEF: i64 = 2 63const AL_BIGRAM_CAP: i64 = 30 64const AL_TRIGRAM_CAP: i64 = 15 65const AL_FREQ_CAP: i64 = 30 66const AL_FREQ_SLOTS: i64 = 256 67const AL_HARDEN_SEV: i64 = 5 68const AL_HARDEN_CAP: i64 = 10 69const AL_ALLOW_BUF: i64 = 131072 70const AL_IX_TVMAX: i64 = 4096 71const AL_IX_HSLOTS: i64 = 8193 72const AL_IX_GMAX: i64 = 16384 73const AL_IX_GHSLOTS: i64 = 32771 74const AL_IX_ARENA: i64 = 1048576 75const AL_IX_HMOD: i64 = 1000003 76const AL_IX_KEYB: i64 = 8192 77const AL_IX_RING: i64 = 9 78const AL_IX_MAXGAP: i64 = 8 79 80// al_cat/al_catn/al_vlen/al_le/al_col DELEGATE to the shared nx_sovjson_lib (sj_*) -- dup logic eaten (TS04-family) 81func al_cat(d: *u8, o: i64, s: *u8) -> i64 { return sj_cat(d, o, s) } 82func al_catn(d: *u8, o: i64, v: i64) -> i64 { return sj_catn(d, o, v) } 83func al_vlen(s: *u8) -> i64 { return sj_vlen(s) } 84func al_atoi_z(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c>=48 { if c<=57 { v=v*10+(c-48) } } i=i+1 } return v } 85// TAIL-ANCHORED (2026-08-20, Lane I). This read filled from offset 0 and stopped at AL_WIN, so once 86// the journal passed 4 MiB every reader kept the OLDEST bytes and dropped the NEWEST. MEASURED at the 87// time of this fix: knowledge/status/actlog.jrnl was 23,221,549 B against a 4,194,304 B window, so 88// mine/freq/harden answered "what do we do repeatedly" from the OLDEST 18.1% of the record -- a 89// recurrence miner blind to recent work proposes hardening for behaviour already superseded. 90// The identical defect was fixed in the siblings on 2026-08-07 (nx_trajscan tj_read, nx_toolatency 91// tl_read_tail, nx_wirecensus) and nx_actlog was MISSED: a fix that lives in one organ and not its 92// sibling is half a fix, and the missing half is invisible until something runs it. Deliberately the 93// SAME shape as tj_read, not a variant -- two spellings of one rule is the duplicate-ruler defect. 94// ANCHORED, not RAISED: a cap that can be crossed in silence will be crossed again. 95// DECLARED IMPRECISION (shared with tj_read, NOT introduced here): a tail read can begin mid-frame, 96// so the first line may be a partial frame -- bounded at <=1 malformed frame per read. Worth eating 97// in ONE place across all four organs rather than diverging here. 98func al_read(path: *u8, buf: *u8, cap: i64) -> i64 { 99 let fd: i64 = sys_openat_rd(path) 100 if fd < 0 { return 0 } 101 let sz: i64 = sys_lseek(fd, 0, AL_SEEK_END) 102 if sz > cap { sys_lseek(fd, sz - cap, AL_SEEK_SET) } else { sys_lseek(fd, 0, AL_SEEK_SET) } 103 var n: i64 = 0 104 var go: i64 = 1 105 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64)+n) as *u8, cap-n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } } 106 sys_close(fd) 107 return n 108} 109func al_append(journal: *u8, ts: i64, ws: *u8, tool: *u8, verb: *u8, outcome: *u8, note: *u8) -> i64 { 110 var t: i64 = ts 111 if t < 0 { t = sys_now_realtime_sec() } 112 let ln: *u8 = sys_mmap(AL_MAGIC_4096) 113 var o: i64 = 0 114 o = al_catn(ln, o, t) 115 ln[o]=9 as u8; o=o+1 116 o = al_cat(ln, o, ws) 117 ln[o]=9 as u8; o=o+1 118 o = al_cat(ln, o, tool) 119 ln[o]=9 as u8; o=o+1 120 o = al_cat(ln, o, verb) 121 ln[o]=9 as u8; o=o+1 122 o = al_cat(ln, o, outcome) 123 ln[o]=9 as u8; o=o+1 124 var i: i64 = 0 125 var used: i64 = 0 126 while note[i]!=(0 as u8) { 127 if used < AL_MAGIC_1500 { 128 let c: i64 = note[i] as i64 129 if c==9 { ln[o]=32 as u8; o=o+1 } else { if c==10 { ln[o]=32 as u8; o=o+1 } else { if c==13 { ln[o]=32 as u8; o=o+1 } else { ln[o]=c as u8; o=o+1 } } } 130 used = used + 1 131 } 132 i = i + 1 133 } 134 ln[o]=10 as u8; o=o+1 135 let fd: i64 = sys_openat_append(journal, 0x1a4) 136 if fd < 0 { return -1 } 137 sys_write(fd, ln, o) 138 sys_close(fd) 139 return 0 140} 141func al_le(q: *u8, i: i64, n: i64) -> i64 { return sj_le(q, i, n) } 142func al_col(q: *u8, ls: i64, le: i64, c: i64, out: *i64) -> i64 { return sj_col(q, ls, le, c, out) } 143func al_span_eq(q: *u8, s1: i64, e1: i64, s2: i64, e2: i64) -> i64 { 144 if e1-s1 != e2-s2 { return 0 } 145 var i: i64 = 0 146 while s1+i < e1 { if q[s1+i]!=q[s2+i] { return 0 } i=i+1 } 147 return 1 148} 149func al_lit_eq(q: *u8, s: i64, e: i64, lit: *u8) -> i64 { 150 var i: i64 = 0 151 while s+i < e { if lit[i]==(0 as u8) { return 0 } if q[s+i]!=lit[i] { return 0 } i=i+1 } 152 if lit[i]!=(0 as u8) { return 0 } 153 return 1 154} 155func al_frames(q: *u8, n: i64) -> i64 { 156 var c: i64 = 0 157 var i: i64 = 0 158 while i < n { let le: i64 = al_le(q,i,n); c=c+1; i = le + 1 } 159 return c 160} 161// successor of frame at ls: next frame (after this line) whose ws (col1) equals this frame's ws. 162// returns line-start or -1. 163func al_succ(q: *u8, cx: *i64, ls: i64) -> i64 { 164 let n: i64 = cx[0] 165 let w1: *i64 = sys_mmap(16) as *i64 166 let w2: *i64 = sys_mmap(16) as *i64 167 let le0: i64 = al_le(q,ls,n) 168 if al_col(q,ls,le0,1,w1)==0 { return -1 } 169 var i: i64 = le0 + 1 170 while i < n { 171 let le: i64 = al_le(q,i,n) 172 if al_col(q,i,le,1,w2)==1 { if al_span_eq(q,w2[0],w2[1],w1[0],w1[1])==1 { return i } } 173 i = le + 1 174 } 175 return -1 176} 177// tool:verb of frame at l1 equals frame at l2? 178func al_tv_eq(q: *u8, cx: *i64, l1: i64, l2: i64) -> i64 { 179 let n: i64 = cx[0] 180 let a: *i64 = sys_mmap(16) as *i64 181 let b: *i64 = sys_mmap(16) as *i64 182 let e1: i64 = al_le(q,l1,n) 183 let e2: i64 = al_le(q,l2,n) 184 if al_col(q,l1,e1,2,a)==0 { return 0 } 185 if al_col(q,l2,e2,2,b)==0 { return 0 } 186 if al_span_eq(q,a[0],a[1],b[0],b[1])==0 { return 0 } 187 if al_col(q,l1,e1,3,a)==0 { return 0 } 188 if al_col(q,l2,e2,3,b)==0 { return 0 } 189 if al_span_eq(q,a[0],a[1],b[0],b[1])==0 { return 0 } 190 return 1 191} 192// bigram at (i,j) content-equal to bigram at (i2,j2)? 193func al_bg_eq(q: *u8, cx: *i64, i: i64, j: i64, i2: i64, j2: i64) -> i64 { 194 if al_tv_eq(q,cx,i,i2)==0 { return 0 } 195 if al_tv_eq(q,cx,j,j2)==0 { return 0 } 196 return 1 197} 198// is (i,j) the FIRST occurrence of its bigram content? scan earlier frames' successor pairs. 199func al_bg_first(q: *u8, cx: *i64, i: i64, j: i64) -> i64 { 200 let n: i64 = cx[0] 201 var k: i64 = 0 202 while k < i { 203 let ke: i64 = al_le(q,k,n) 204 let m: i64 = al_succ(q,cx,k) 205 if m >= 0 { if al_bg_eq(q,cx,k,m,i,j)==1 { return 0 } } 206 k = ke + 1 207 } 208 return 1 209} 210func al_bg_support(q: *u8, cx: *i64, i: i64, j: i64) -> i64 { 211 let n: i64 = cx[0] 212 var c: i64 = 0 213 var k: i64 = 0 214 while k < n { 215 let ke: i64 = al_le(q,k,n) 216 let m: i64 = al_succ(q,cx,k) 217 if m >= 0 { if al_bg_eq(q,cx,k,m,i,j)==1 { c=c+1 } } 218 k = ke + 1 219 } 220 return c 221} 222// trigram (i,j,k2) first + support 223func al_tg_first(q: *u8, cx: *i64, i: i64, j: i64, k2: i64) -> i64 { 224 let n: i64 = cx[0] 225 var a: i64 = 0 226 while a < i { 227 let ae: i64 = al_le(q,a,n) 228 let b: i64 = al_succ(q,cx,a) 229 if b >= 0 { 230 let c: i64 = al_succ(q,cx,b) 231 if c >= 0 { if al_bg_eq(q,cx,a,b,i,j)==1 { if al_tv_eq(q,cx,c,k2)==1 { return 0 } } } 232 } 233 a = ae + 1 234 } 235 return 1 236} 237func al_tg_support(q: *u8, cx: *i64, i: i64, j: i64, k2: i64) -> i64 { 238 let n: i64 = cx[0] 239 var cnt: i64 = 0 240 var a: i64 = 0 241 while a < n { 242 let ae: i64 = al_le(q,a,n) 243 let b: i64 = al_succ(q,cx,a) 244 if b >= 0 { 245 let c: i64 = al_succ(q,cx,b) 246 if c >= 0 { if al_bg_eq(q,cx,a,b,i,j)==1 { if al_tv_eq(q,cx,c,k2)==1 { cnt=cnt+1 } } } 247 } 248 a = ae + 1 249 } 250 return cnt 251} 252func al_jesc(d: *u8, o: i64, q: *u8, s: i64, e: i64, maxb: i64) -> i64 { 253 var p: i64 = o 254 var i: i64 = s 255 var used: i64 = 0 256 while i < e { 257 if used >= maxb { i = e } else { 258 let c: i64 = q[i] as i64 259 if c == 34 { d[p]=92 as u8; p=p+1; d[p]=34 as u8; p=p+1 } else { if c == 92 { d[p]=92 as u8; p=p+1; d[p]=92 as u8; p=p+1 } else { if c < 32 { d[p]=32 as u8; p=p+1 } else { d[p]=c as u8; p=p+1 } } } 260 used = used + 2 261 i = i + 1 262 } 263 } 264 return p 265} 266func al_key(d: *u8, o: i64, name: *u8) -> i64 { 267 d[o]=34 as u8 268 var p: i64 = o + 1 269 p = al_cat(d,p,name) 270 d[p]=34 as u8 271 p = p + 1 272 d[p]=58 as u8 273 p = p + 1 274 return p 275} 276func al_qlit(d: *u8, o: i64, s: *u8) -> i64 { 277 var p: i64 = o 278 d[p]=34 as u8; p=p+1 279 p = al_cat(d,p,s) 280 d[p]=34 as u8; p=p+1 281 return p 282} 283// emit "tool:verb" of frame at l as an escaped json string 284func al_emit_tv(d: *u8, o: i64, q: *u8, cx: *i64, l: i64) -> i64 { 285 let n: i64 = cx[0] 286 let sp: *i64 = sys_mmap(16) as *i64 287 var p: i64 = o 288 let le: i64 = al_le(q,l,n) 289 d[p]=34 as u8; p=p+1 290 if al_col(q,l,le,2,sp)==1 { p = al_jesc(d,p,q,sp[0],sp[1],AL_NAME_MAX) } 291 d[p]=58 as u8; p=p+1 292 if al_col(q,l,le,3,sp)==1 { p = al_jesc(d,p,q,sp[0],sp[1],AL_NAME_MAX) } 293 d[p]=34 as u8; p=p+1 294 return p 295} 296func al_mine_json(q: *u8, cx: *i64, minsup: i64, d: *u8) -> i64 { 297 let n: i64 = cx[0] 298 var p: i64 = 0 299 d[p]=123 as u8; p=p+1 300 p = al_key(d,p,"v" as *u8) 301 p = al_catn(d,p,1) 302 d[p]=44 as u8; p=p+1 303 p = al_key(d,p,"tool" as *u8) 304 p = al_qlit(d,p,"nx_actlog" as *u8) 305 d[p]=44 as u8; p=p+1 306 p = al_key(d,p,"journal" as *u8) 307 d[p]=34 as u8; p=p+1 308 let jp: *u8 = cx[5] as *u8 309 let jl: i64 = al_vlen(jp) 310 p = al_jesc(d,p,jp,0,jl,200) 311 d[p]=34 as u8; p=p+1 312 d[p]=44 as u8; p=p+1 313 p = al_key(d,p,"journal_bytes" as *u8) 314 p = al_catn(d,p,n) 315 d[p]=44 as u8; p=p+1 316 p = al_key(d,p,"window_bytes" as *u8) 317 p = al_catn(d,p,AL_WIN) 318 d[p]=44 as u8; p=p+1 319 p = al_key(d,p,"truncated" as *u8) 320 p = al_catn(d,p,cx[4]) 321 d[p]=44 as u8; p=p+1 322 p = al_key(d,p,"minsup" as *u8) 323 p = al_catn(d,p,minsup) 324 d[p]=44 as u8; p=p+1 325 let fr: i64 = al_frames(q,n) 326 p = al_key(d,p,"frames" as *u8) 327 p = al_catn(d,p,fr) 328 d[p]=44 as u8; p=p+1 329 // bigrams 330 p = al_key(d,p,"bigrams" as *u8) 331 d[p]=91 as u8; p=p+1 332 var bcount: i64 = 0 333 var bcapped: i64 = 0 334 var bfirst: i64 = 1 335 var i: i64 = 0 336 while i < n { 337 let le: i64 = al_le(q,i,n) 338 let j: i64 = al_succ(q,cx,i) 339 if j >= 0 { if al_bg_first(q,cx,i,j)==1 { 340 let sup: i64 = al_bg_support(q,cx,i,j) 341 if sup >= minsup { 342 if bcount >= AL_BIGRAM_CAP { bcapped=1 } else { if p > AL_SOFT { bcapped=1 } else { 343 if bfirst==0 { d[p]=44 as u8; p=p+1 } 344 bfirst=0 345 d[p]=123 as u8; p=p+1 346 p = al_key(d,p,"a" as *u8) 347 p = al_emit_tv(d,p,q,cx,i) 348 d[p]=44 as u8; p=p+1 349 p = al_key(d,p,"b" as *u8) 350 p = al_emit_tv(d,p,q,cx,j) 351 d[p]=44 as u8; p=p+1 352 p = al_key(d,p,"support" as *u8) 353 p = al_catn(d,p,sup) 354 d[p]=125 as u8; p=p+1 355 bcount = bcount + 1 356 } } 357 } 358 } } 359 i = le + 1 360 } 361 d[p]=93 as u8; p=p+1 362 d[p]=44 as u8; p=p+1 363 p = al_key(d,p,"bigrams_capped" as *u8) 364 p = al_catn(d,p,bcapped) 365 d[p]=44 as u8; p=p+1 366 // trigrams 367 p = al_key(d,p,"trigrams" as *u8) 368 d[p]=91 as u8; p=p+1 369 var tcount: i64 = 0 370 var tcapped: i64 = 0 371 var tfirst: i64 = 1 372 var a: i64 = 0 373 while a < n { 374 let ae: i64 = al_le(q,a,n) 375 let b: i64 = al_succ(q,cx,a) 376 if b >= 0 { 377 let c: i64 = al_succ(q,cx,b) 378 if c >= 0 { if al_tg_first(q,cx,a,b,c)==1 { 379 let sup2: i64 = al_tg_support(q,cx,a,b,c) 380 if sup2 >= minsup { 381 if tcount >= AL_TRIGRAM_CAP { tcapped=1 } else { if p > AL_SOFT { tcapped=1 } else { 382 if tfirst==0 { d[p]=44 as u8; p=p+1 } 383 tfirst=0 384 d[p]=123 as u8; p=p+1 385 p = al_key(d,p,"a" as *u8) 386 p = al_emit_tv(d,p,q,cx,a) 387 d[p]=44 as u8; p=p+1 388 p = al_key(d,p,"b" as *u8) 389 p = al_emit_tv(d,p,q,cx,b) 390 d[p]=44 as u8; p=p+1 391 p = al_key(d,p,"c" as *u8) 392 p = al_emit_tv(d,p,q,cx,c) 393 d[p]=44 as u8; p=p+1 394 p = al_key(d,p,"support" as *u8) 395 p = al_catn(d,p,sup2) 396 d[p]=125 as u8; p=p+1 397 tcount = tcount + 1 398 } } 399 } 400 } } 401 } 402 a = ae + 1 403 } 404 d[p]=93 as u8; p=p+1 405 d[p]=44 as u8; p=p+1 406 p = al_key(d,p,"trigrams_capped" as *u8) 407 p = al_catn(d,p,tcapped) 408 d[p]=125 as u8; p=p+1 409 d[p]=10 as u8; p=p+1 410 return p 411} 412func al_find(d: *u8, dn: i64, lit: *u8) -> i64 { 413 let ll: i64 = al_vlen(lit) 414 if ll == 0 { return 0 } 415 var i: i64 = 0 416 while i + ll <= dn { 417 var k: i64 = 0 418 var ok: i64 = 1 419 while k < ll { if d[i+k]!=lit[k] { ok=0; k=ll } else { k=k+1 } } 420 if ok==1 { return 1 } 421 i = i + 1 422 } 423 return 0 424} 425 426// per-tool:verb FREQUENCY over the WHOLE journal (ws-agnostic) -- the fallback-log RANKING verb. 427// "which primary/backup engages most" is a frequency question the sequence miner structurally 428// cannot answer (a lone fallback row has no successor bigram). Ranked by bounded selection 429// (exact, no sort infra), capped + declared like every emitter (scale-law envelope). 430func al_tv_count(q: *u8, cx: *i64, l: i64) -> i64 { 431 let n: i64 = cx[0] 432 var c: i64 = 0 433 var k: i64 = 0 434 while k < n { 435 let ke: i64 = al_le(q,k,n) 436 if al_tv_eq(q,cx,l,k)==1 { c=c+1 } 437 k = ke + 1 438 } 439 return c 440} 441func al_tv_first(q: *u8, cx: *i64, l: i64) -> i64 { 442 var k: i64 = 0 443 while k < l { 444 let ke: i64 = al_le(q,k,cx[0]) 445 if al_tv_eq(q,cx,l,k)==1 { return 0 } 446 k = ke + 1 447 } 448 return 1 449} 450func al_freq_json(q: *u8, cx: *i64, d: *u8) -> i64 { 451 let n: i64 = cx[0] 452 let starts: *i64 = sys_mmap(8 * AL_FREQ_SLOTS) as *i64 453 let counts: *i64 = sys_mmap(8 * AL_FREQ_SLOTS) as *i64 454 let done: *i64 = sys_mmap(8 * AL_FREQ_SLOTS) as *i64 455 var nf: i64 = 0 456 var fcapped: i64 = 0 457 var i: i64 = 0 458 while i < n { 459 let le: i64 = al_le(q,i,n) 460 if al_tv_first(q,cx,i)==1 { 461 if nf >= AL_FREQ_SLOTS { fcapped=1 } else { 462 starts[nf]=i 463 counts[nf]=al_tv_count(q,cx,i) 464 nf=nf+1 465 } 466 } 467 i = le + 1 468 } 469 var p: i64 = 0 470 d[p]=123 as u8; p=p+1 471 p = al_key(d,p,"v" as *u8); p = al_catn(d,p,1); d[p]=44 as u8; p=p+1 472 p = al_key(d,p,"tool" as *u8); p = al_qlit(d,p,"nx_actlog" as *u8); d[p]=44 as u8; p=p+1 473 p = al_key(d,p,"averb" as *u8); p = al_qlit(d,p,"freq" as *u8); d[p]=44 as u8; p=p+1 474 p = al_key(d,p,"journal" as *u8) 475 d[p]=34 as u8; p=p+1 476 let jp: *u8 = cx[5] as *u8 477 let jl: i64 = al_vlen(jp) 478 p = al_jesc(d,p,jp,0,jl,200) 479 d[p]=34 as u8; p=p+1 480 d[p]=44 as u8; p=p+1 481 p = al_key(d,p,"journal_bytes" as *u8); p = al_catn(d,p,n); d[p]=44 as u8; p=p+1 482 p = al_key(d,p,"truncated" as *u8); p = al_catn(d,p,cx[4]); d[p]=44 as u8; p=p+1 483 p = al_key(d,p,"frames" as *u8); p = al_catn(d,p,al_frames(q,n)); d[p]=44 as u8; p=p+1 484 p = al_key(d,p,"distinct" as *u8); p = al_catn(d,p,nf); d[p]=44 as u8; p=p+1 485 p = al_key(d,p,"freq" as *u8) 486 d[p]=91 as u8; p=p+1 487 var shown: i64 = 0 488 var efirst: i64 = 1 489 var pass: i64 = 0 490 while pass < nf { 491 if shown < AL_FREQ_CAP { if p <= AL_SOFT { 492 var mi: i64 = 0 - 1 493 var mx: i64 = 0 - 1 494 var k: i64 = 0 495 while k < nf { 496 if done[k]==0 { if counts[k] > mx { mx = counts[k]; mi = k } } 497 k = k + 1 498 } 499 if mi >= 0 { 500 done[mi] = 1 501 if efirst==0 { d[p]=44 as u8; p=p+1 } 502 efirst = 0 503 d[p]=123 as u8; p=p+1 504 p = al_key(d,p,"tv" as *u8) 505 p = al_emit_tv(d,p,q,cx,starts[mi]) 506 d[p]=44 as u8; p=p+1 507 p = al_key(d,p,"count" as *u8) 508 p = al_catn(d,p,mx) 509 d[p]=125 as u8; p=p+1 510 shown = shown + 1 511 } 512 } } 513 pass = pass + 1 514 } 515 d[p]=93 as u8; p=p+1 516 d[p]=44 as u8; p=p+1 517 p = al_key(d,p,"shown" as *u8); p = al_catn(d,p,shown); d[p]=44 as u8; p=p+1 518 p = al_key(d,p,"freq_capped" as *u8); p = al_catn(d,p,fcapped) 519 d[p]=125 as u8; p=p+1 520 d[p]=10 as u8; p=p+1 521 return p 522} 523 524// harden: the F872 rung-3 CLOSER -- every tool:verb recurring >= minsup auto-files a hardening 525// debt through the ALLOWLIST-RESOLVED filer (never a hardcoded sibling path -- the execve-127 526// lesson: allowlist rows are not name-derivable). The desc is CANONICAL and COUNT-FREE so 527// nx_debt's content-idempotent add (F868) makes every re-run a NO-OP for already-filed 528// recurrences: a beat cannot spam. The filer is INJECTABLE (argecho in the gate) so the 529// selftest never writes the production debt plane. 530// DELEGATES to the shared base (rule-15 extraction 2026-07-23) -- the ORIGINAL of the 7 copies 531func al_allow_path(name: *u8, outp: *u8) -> i64 { return sj_allow_path(name, outp) } 532func al_harden_json(q: *u8, cx: *i64, minsup: i64, sev: i64, filer: *u8, d: *u8) -> i64 { 533 let n: i64 = cx[0] 534 let starts: *i64 = sys_mmap(8 * AL_FREQ_SLOTS) as *i64 535 let counts: *i64 = sys_mmap(8 * AL_FREQ_SLOTS) as *i64 536 var nf: i64 = 0 537 var i: i64 = 0 538 while i < n { 539 let le: i64 = al_le(q,i,n) 540 if al_tv_first(q,cx,i)==1 { if nf < AL_FREQ_SLOTS { 541 starts[nf]=i 542 counts[nf]=al_tv_count(q,cx,i) 543 nf=nf+1 544 } } 545 i = le + 1 546 } 547 let fpath: *u8 = sys_mmap(512) 548 let fok: i64 = al_allow_path(filer, fpath) 549 var p: i64 = 0 550 d[p]=123 as u8; p=p+1 551 p = al_key(d,p,"v" as *u8); p = al_catn(d,p,1); d[p]=44 as u8; p=p+1 552 p = al_key(d,p,"tool" as *u8); p = al_qlit(d,p,"nx_actlog" as *u8); d[p]=44 as u8; p=p+1 553 p = al_key(d,p,"averb" as *u8); p = al_qlit(d,p,"harden" as *u8); d[p]=44 as u8; p=p+1 554 p = al_key(d,p,"minsup" as *u8); p = al_catn(d,p,minsup); d[p]=44 as u8; p=p+1 555 p = al_key(d,p,"sev" as *u8); p = al_catn(d,p,sev); d[p]=44 as u8; p=p+1 556 p = al_key(d,p,"filer" as *u8) 557 d[p]=34 as u8; p=p+1 558 p = al_jesc(d,p,filer,0,al_vlen(filer),120) 559 d[p]=34 as u8; p=p+1 560 d[p]=44 as u8; p=p+1 561 p = al_key(d,p,"filer_resolved" as *u8); p = al_catn(d,p,fok); d[p]=44 as u8; p=p+1 562 p = al_key(d,p,"filed" as *u8) 563 d[p]=91 as u8; p=p+1 564 var recur: i64 = 0 565 var attempted: i64 = 0 566 var hcapped: i64 = 0 567 var efirst: i64 = 1 568 var k: i64 = 0 569 while k < nf { 570 if counts[k] >= minsup { 571 recur = recur + 1 572 if attempted >= AL_HARDEN_CAP { hcapped=1 } else { if fok==1 { 573 let tvb: *u8 = sys_mmap(256) 574 let sp2: *i64 = sys_mmap(16) as *i64 575 let le2: i64 = al_le(q,starts[k],n) 576 var to: i64 = 0 577 if al_col(q,starts[k],le2,2,sp2)==1 { var z: i64=sp2[0]; while z<sp2[1] { if to<100 { tvb[to]=q[z]; to=to+1 } z=z+1 } } 578 tvb[to]=58 as u8 579 to=to+1 580 if al_col(q,starts[k],le2,3,sp2)==1 { var z2: i64=sp2[0]; while z2<sp2[1] { if to<220 { tvb[to]=q[z2]; to=to+1 } z2=z2+1 } } 581 tvb[to]=0 as u8 582 let desc: *u8 = sys_mmap(AL_MAGIC_1024) 583 var dso: i64 = 0 584 dso = al_cat(desc,dso,"FALLBACK-RECURRENCE " as *u8) 585 dso = al_cat(desc,dso,tvb) 586 dso = al_cat(desc,dso," (auto-filed by nx_actlog harden): this backup method engages repeatedly -- root-cause and HARDEN THE PRIMARY; current counts via nx_actlog freq, per-engagement why/evidence in the journal rows" as *u8) 587 desc[dso]=0 as u8 588 let sevs: *u8 = sys_mmap(8) 589 var so: i64 = al_catn(sevs,0,sev) 590 sevs[so]=0 as u8 591 let av: *i64 = sys_mmap(64) as *i64 592 av[0]=fpath as i64 593 av[1]="add" as *u8 as i64 594 av[2]=sevs as i64 595 av[3]="fallback" as *u8 as i64 596 av[4]=desc as i64 597 av[5]=0 598 let cout: *u8 = sys_mmap(AL_MAGIC_4096) 599 let colen: *i64 = sys_mmap(8) as *i64 600 let ex: i64 = tr_run_capture(fpath, av, cout, AL_MAGIC_4090, colen) 601 if efirst==0 { d[p]=44 as u8; p=p+1 } 602 efirst=0 603 d[p]=123 as u8; p=p+1 604 p = al_key(d,p,"tv" as *u8) 605 d[p]=34 as u8; p=p+1 606 p = al_jesc(d,p,tvb,0,al_vlen(tvb),240) 607 d[p]=34 as u8; p=p+1 608 d[p]=44 as u8; p=p+1 609 p = al_key(d,p,"exit" as *u8); p = al_catn(d,p,ex); d[p]=44 as u8; p=p+1 610 p = al_key(d,p,"out" as *u8) 611 d[p]=34 as u8; p=p+1 612 var ce: i64 = colen[0] 613 if ce > 400 { ce = 400 } 614 p = al_jesc(d,p,cout,0,ce,800) 615 d[p]=34 as u8; p=p+1 616 d[p]=125 as u8; p=p+1 617 attempted = attempted + 1 618 } } 619 } 620 k = k + 1 621 } 622 d[p]=93 as u8; p=p+1 623 d[p]=44 as u8; p=p+1 624 p = al_key(d,p,"recurring" as *u8); p = al_catn(d,p,recur); d[p]=44 as u8; p=p+1 625 p = al_key(d,p,"attempted" as *u8); p = al_catn(d,p,attempted); d[p]=44 as u8; p=p+1 626 p = al_key(d,p,"harden_capped" as *u8); p = al_catn(d,p,hcapped) 627 d[p]=125 as u8; p=p+1 628 d[p]=10 as u8; p=p+1 629 return p 630} 631 632// ---------- seq626 O(F) INDEXED MINER ---------- 633// One hash-interned pass replaces the O(F^2/F^3) pair scans that died (rc=-1) on the first 634// real-scale journal (8184 frames, F964 backfill). The slow al_succ/al_bg_*/al_tg_*/al_tv_* 635// primitives above are KEPT: the selftest computes supports through them (T4/T5) while the 636// fast emitters produce the JSON (T6/T7/T8) -- fast path must agree with the slow oracle on 637// the fixture. Emission order preserved: first-occurrence, count-desc selection for freq. 638func al_z_eq(a: *u8, b: *u8) -> i64 { 639 var i: i64 = 0 640 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 641 if b[i] != (0 as u8) { return 0 } 642 return 1 643} 644func al_z_hash(s: *u8) -> i64 { 645 var h: i64 = AL_MAGIC_5381 646 var i: i64 = 0 647 while s[i] != (0 as u8) { h = (h * 31 + (s[i] as i64)) % AL_IX_HMOD; i = i + 1 } 648 return h 649} 650// string intern: open-addressing hash holds id+1; ids are first-seen order; strings in arena. 651func al_ix_sintern(z: *u8, hash: *i64, off: *i64, hslots: i64, maxn: i64, ar: *u8, an: *i64, nn: *i64) -> i64 { 652 var h: i64 = al_z_hash(z) % hslots 653 var probes: i64 = 0 654 while probes < hslots { 655 let v: i64 = hash[h] 656 if v == 0 { 657 if nn[0] >= maxn { return -1 } 658 let zl: i64 = al_vlen(z) 659 if an[0] + zl + 1 >= AL_IX_ARENA { return -1 } 660 let id: i64 = nn[0] 661 off[id] = an[0] 662 var k: i64 = 0 663 while k <= zl { ar[an[0] + k] = z[k]; k = k + 1 } 664 an[0] = an[0] + zl + 1 665 hash[h] = id + 1 666 nn[0] = id + 1 667 return id 668 } 669 if al_z_eq(((ar as i64) + off[v-1]) as *u8, z) == 1 { return v - 1 } 670 h = h + 1 671 if h >= hslots { h = 0 } 672 probes = probes + 1 673 } 674 return -1 675} 676// numeric-key intern (bigram/trigram packed keys) 677func al_ix_kintern(key: i64, hash: *i64, keys: *i64, hslots: i64, maxn: i64, nn: *i64) -> i64 { 678 var h: i64 = key % hslots 679 if h < 0 { h = 0 - h } 680 var probes: i64 = 0 681 while probes < hslots { 682 let v: i64 = hash[h] 683 if v == 0 { 684 if nn[0] >= maxn { return -1 } 685 let id: i64 = nn[0] 686 keys[id] = key 687 hash[h] = id + 1 688 nn[0] = id + 1 689 return id 690 } 691 if keys[v-1] == key { return v - 1 } 692 h = h + 1 693 if h >= hslots { h = 0 } 694 probes = probes + 1 695 } 696 return -1 697} 698// ix ptr slots: 0 tvhash 1 tvoff 2 tvcnt 3 ntv 4 arena 5 aused 6 wshash 7 wsoff 8 wslast 9 wslast2 699// 10 nws 11 bghash 12 bgkey 13 bgcnt 14 nbg 15 tghash 16 tgkey 17 tgcnt 18 ntg 19 frames 20 overflow 700func al_ix_build(q: *u8, cx: *i64, ix: *i64, maxgap: i64) -> i64 { 701 ix[0] = sys_mmap(8 * AL_IX_HSLOTS) as i64 702 ix[1] = sys_mmap(8 * AL_IX_TVMAX) as i64 703 ix[2] = sys_mmap(8 * AL_IX_TVMAX) as i64 704 ix[3] = sys_mmap(16) as i64 705 ix[4] = sys_mmap(AL_IX_ARENA) as i64 706 ix[5] = sys_mmap(16) as i64 707 ix[6] = sys_mmap(8 * AL_IX_HSLOTS) as i64 708 ix[7] = sys_mmap(8 * AL_IX_TVMAX) as i64 709 ix[8] = sys_mmap(8 * AL_IX_TVMAX * AL_IX_RING) as i64 710 ix[9] = sys_mmap(8 * AL_IX_TVMAX) as i64 711 ix[10] = sys_mmap(16) as i64 712 // INDEX SIZED FROM THE INPUT (2026-09-05): distinct bigrams and trigrams can never exceed the frame 713 // count, so the gram tables are DERIVED from a newline census of the journal; AL_IX_GMAX / AL_IX_GHSLOTS 714 // remain only as FLOORS. Measured on the live 54 MB journal the fixed cap read index_overflow=1: every 715 // pair past the 16,384th was silently uncounted while the miner still published a ranking. mmap faults 716 // pages in on demand, so a large table costs address space, not resident memory (a cap is not a number 717 // to tune -- derive it). ix[21]=gmax ix[22]=ghslots are VALUES (the other slots are pointers). 718 let n: i64 = cx[0] 719 var frames: i64 = 0 720 var fi: i64 = 0 721 while fi < n { if q[fi] == (10 as u8) { frames = frames + 1 } fi = fi + 1 } 722 if n > 0 { if q[n - 1] != (10 as u8) { frames = frames + 1 } } 723 var gmax: i64 = frames + 1 724 if gmax < AL_IX_GMAX { gmax = AL_IX_GMAX } 725 var ghslots: i64 = 2 * gmax + 1 726 if ghslots < AL_IX_GHSLOTS { ghslots = AL_IX_GHSLOTS } 727 ix[21] = gmax 728 ix[22] = ghslots 729 ix[11] = sys_mmap(8 * ghslots) as i64 730 ix[12] = sys_mmap(8 * gmax) as i64 731 ix[13] = sys_mmap(8 * gmax) as i64 732 ix[14] = sys_mmap(16) as i64 733 ix[15] = sys_mmap(8 * ghslots) as i64 734 ix[16] = sys_mmap(8 * gmax) as i64 735 ix[17] = sys_mmap(8 * gmax) as i64 736 ix[18] = sys_mmap(16) as i64 737 ix[19] = sys_mmap(16) as i64 738 // ov[0] any overflow (the contract every reader holds) ov[1] string-intern overflows ov[2] gram-table overflows 739 ix[20] = sys_mmap(32) as i64 740 // ES27 QUALITY AXIS: a failure count beside every gram count (a frame whose outcome column is not ok taints the 741 // grams it closes), and a per-workstream ring of frame badness beside the tool-id ring: ix[23] bgfail ix[24] tgfail ix[25] badring 742 ix[23] = sys_mmap(8 * gmax) as i64 743 ix[24] = sys_mmap(8 * gmax) as i64 744 ix[25] = sys_mmap(8 * AL_IX_TVMAX * AL_IX_RING) as i64 745 let sp: *i64 = sys_mmap(16) as *i64 746 let tvb: *u8 = sys_mmap(512) 747 let wsb: *u8 = sys_mmap(256) 748 let fp: *i64 = ix[19] as *i64 749 let ov: *i64 = ix[20] as *i64 750 var i: i64 = 0 751 while i < n { 752 let le: i64 = al_le(q,i,n) 753 fp[0] = fp[0] + 1 754 var ok: i64 = 0 755 var wl: i64 = 0 756 var to: i64 = 0 757 if al_col(q,i,le,1,sp)==1 { 758 var z: i64 = sp[0] 759 while z < sp[1] { if wl < 200 { wsb[wl] = q[z]; wl = wl + 1 } z = z + 1 } 760 wsb[wl] = 0 as u8 761 if al_col(q,i,le,2,sp)==1 { 762 var z2: i64 = sp[0] 763 while z2 < sp[1] { if to < 240 { tvb[to] = q[z2]; to = to + 1 } z2 = z2 + 1 } 764 tvb[to] = 58 as u8 765 to = to + 1 766 if al_col(q,i,le,3,sp)==1 { 767 var z3: i64 = sp[0] 768 while z3 < sp[1] { if to < 480 { tvb[to] = q[z3]; to = to + 1 } z3 = z3 + 1 } 769 tvb[to] = 0 as u8 770 ok = 1 771 } 772 } 773 } 774 var bad: i64 = 0 775 if al_col(q,i,le,4,sp)==1 { if sp[1] - sp[0] != 2 { bad = 1 } else { if q[sp[0]] != (111 as u8) { bad = 1 } else { if q[sp[0]+1] != (107 as u8) { bad = 1 } } } } 776 if ok == 1 { 777 let tid: i64 = al_ix_sintern(tvb, ix[0] as *i64, ix[1] as *i64, AL_IX_HSLOTS, AL_IX_TVMAX, ix[4] as *u8, ix[5] as *i64, ix[3] as *i64) 778 let wid: i64 = al_ix_sintern(wsb, ix[6] as *i64, ix[7] as *i64, AL_IX_HSLOTS, AL_IX_TVMAX, ix[4] as *u8, ix[5] as *i64, ix[10] as *i64) 779 if tid >= 0 { if wid >= 0 { 780 let tvcnt: *i64 = ix[2] as *i64 781 tvcnt[tid] = tvcnt[tid] + 1 782 let ring: *i64 = ix[8] as *i64 783 let wln: *i64 = ix[9] as *i64 784 let cnt: i64 = wln[wid] 785 var dd: i64 = 1 786 while dd <= maxgap + 1 { 787 if dd <= cnt { 788 let pv: i64 = ring[wid * AL_IX_RING + ((cnt - dd) % AL_IX_RING)] 789 if pv > 0 { 790 let bkey: i64 = (pv - 1) * AL_IX_KEYB + tid 791 let bid: i64 = al_ix_kintern(bkey, ix[11] as *i64, ix[12] as *i64, ix[22], ix[21], ix[14] as *i64) 792 if bid >= 0 { let bc: *i64 = ix[13] as *i64; bc[bid] = bc[bid] + 1; let bf: *i64 = ix[23] as *i64; let badr: *i64 = ix[25] as *i64; if bad == 1 { bf[bid] = bf[bid] + 1 } else { if badr[wid * AL_IX_RING + ((cnt - dd) % AL_IX_RING)] == 1 { bf[bid] = bf[bid] + 1 } } } else { ov[0] = 1; ov[2] = ov[2] + 1 } 793 if dd == 1 { if cnt >= 2 { 794 let p2v: i64 = ring[wid * AL_IX_RING + ((cnt - 2) % AL_IX_RING)] 795 if p2v > 0 { 796 let tkey: i64 = ((p2v - 1) * AL_IX_KEYB + (pv - 1)) * AL_IX_KEYB + tid 797 let tgid: i64 = al_ix_kintern(tkey, ix[15] as *i64, ix[16] as *i64, ix[22], ix[21], ix[18] as *i64) 798 if tgid >= 0 { let tc: *i64 = ix[17] as *i64; tc[tgid] = tc[tgid] + 1; let tf: *i64 = ix[24] as *i64; let badr2: *i64 = ix[25] as *i64; var tb: i64 = bad; if badr2[wid * AL_IX_RING + ((cnt - 1) % AL_IX_RING)] == 1 { tb = 1 } if badr2[wid * AL_IX_RING + ((cnt - 2) % AL_IX_RING)] == 1 { tb = 1 } if tb == 1 { tf[tgid] = tf[tgid] + 1 } } else { ov[0] = 1; ov[2] = ov[2] + 1 } 799 } 800 } } 801 } 802 } 803 dd = dd + 1 804 } 805 ring[wid * AL_IX_RING + (cnt % AL_IX_RING)] = tid + 1 806 let badw: *i64 = ix[25] as *i64 807 badw[wid * AL_IX_RING + (cnt % AL_IX_RING)] = bad 808 wln[wid] = cnt + 1 809 } else { ov[0] = 1; ov[1] = ov[1] + 1 } } else { ov[0] = 1; ov[1] = ov[1] + 1 } 810 } 811 i = le + 1 812 } 813 return 0 814} 815func al_ix_tv_emit(d: *u8, o: i64, ar: *u8, off: i64) -> i64 { 816 var p: i64 = o 817 d[p]=34 as u8; p=p+1 818 let zl: i64 = al_vlen(((ar as i64) + off) as *u8) 819 p = al_jesc(d,p,ar,off,off+zl,240) 820 d[p]=34 as u8; p=p+1 821 return p 822} 823func al_freq_fast(q: *u8, cx: *i64, d: *u8, fcap: i64) -> i64 { 824 let n: i64 = cx[0] 825 let ix: *i64 = sys_mmap(256) as *i64 826 al_ix_build(q, cx, ix, 0) 827 let ntvp: *i64 = ix[3] as *i64 828 let nf: i64 = ntvp[0] 829 let cnts: *i64 = ix[2] as *i64 830 let offs: *i64 = ix[1] as *i64 831 let ar: *u8 = ix[4] as *u8 832 let fp: *i64 = ix[19] as *i64 833 let ov: *i64 = ix[20] as *i64 834 let done: *i64 = sys_mmap(8 * AL_IX_TVMAX) as *i64 835 var p: i64 = 0 836 d[p]=123 as u8; p=p+1 837 p = al_key(d,p,"v" as *u8); p = al_catn(d,p,1); d[p]=44 as u8; p=p+1 838 p = al_key(d,p,"tool" as *u8); p = al_qlit(d,p,"nx_actlog" as *u8); d[p]=44 as u8; p=p+1 839 p = al_key(d,p,"averb" as *u8); p = al_qlit(d,p,"freq" as *u8); d[p]=44 as u8; p=p+1 840 p = al_key(d,p,"journal" as *u8) 841 d[p]=34 as u8; p=p+1 842 let jp: *u8 = cx[5] as *u8 843 p = al_jesc(d,p,jp,0,al_vlen(jp),200) 844 d[p]=34 as u8; p=p+1 845 d[p]=44 as u8; p=p+1 846 p = al_key(d,p,"journal_bytes" as *u8); p = al_catn(d,p,n); d[p]=44 as u8; p=p+1 847 p = al_key(d,p,"truncated" as *u8); p = al_catn(d,p,cx[4]); d[p]=44 as u8; p=p+1 848 p = al_key(d,p,"frames" as *u8); p = al_catn(d,p,fp[0]); d[p]=44 as u8; p=p+1 849 p = al_key(d,p,"distinct" as *u8); p = al_catn(d,p,nf); d[p]=44 as u8; p=p+1 850 p = al_key(d,p,"freq" as *u8) 851 d[p]=91 as u8; p=p+1 852 var shown: i64 = 0 853 var efirst: i64 = 1 854 var pass: i64 = 0 855 while pass < nf { 856 if shown < fcap { if p <= AL_SOFT { 857 var mi: i64 = 0 - 1 858 var mx: i64 = 0 - 1 859 var k: i64 = 0 860 while k < nf { 861 if done[k]==0 { if cnts[k] > mx { mx = cnts[k]; mi = k } } 862 k = k + 1 863 } 864 if mi >= 0 { 865 done[mi] = 1 866 if efirst==0 { d[p]=44 as u8; p=p+1 } 867 efirst = 0 868 d[p]=123 as u8; p=p+1 869 p = al_key(d,p,"tv" as *u8) 870 p = al_ix_tv_emit(d,p,ar,offs[mi]) 871 d[p]=44 as u8; p=p+1 872 p = al_key(d,p,"count" as *u8) 873 p = al_catn(d,p,mx) 874 d[p]=125 as u8; p=p+1 875 shown = shown + 1 876 } 877 } } 878 pass = pass + 1 879 } 880 d[p]=93 as u8; p=p+1 881 d[p]=44 as u8; p=p+1 882 p = al_key(d,p,"shown" as *u8); p = al_catn(d,p,shown); d[p]=44 as u8; p=p+1 883 p = al_key(d,p,"index_overflow" as *u8); p = al_catn(d,p,ov[0]); d[p]=44 as u8; p=p+1 884 p = al_key(d,p,"index_overflow_strings" as *u8); p = al_catn(d,p,ov[1]); d[p]=44 as u8; p=p+1 885 p = al_key(d,p,"index_overflow_grams" as *u8); p = al_catn(d,p,ov[2]); d[p]=44 as u8; p=p+1 886 p = al_key(d,p,"index_gmax" as *u8); p = al_catn(d,p,ix[21]); d[p]=44 as u8; p=p+1 887 p = al_key(d,p,"index_ghslots" as *u8); p = al_catn(d,p,ix[22]); d[p]=44 as u8; p=p+1 888 p = al_key(d,p,"freq_capped" as *u8); p = al_catn(d,p,ov[0]) 889 d[p]=125 as u8; p=p+1 890 d[p]=10 as u8; p=p+1 891 return p 892} 893// al_bg_is_closed: CLOSED-PATTERN test (CloSpan/BIDE class, the research standard for NON-REDUNDANT 894// sequential mining). A bigram (a,b) is NON-closed (redundant) if some trigram containing it 895// CONTIGUOUSLY -- as prefix (a,b,*) or suffix (*,a,b) -- has the SAME support: its count is fully 896// explained by a longer pattern, so reporting it adds noise. Trigrams are maximal here (no 4-grams) 897// => emitted as closed-up-to-length-3 (declared). Returns 1 closed, 0 subsumed. 898func al_bg_is_closed(a: i64, b: i64, sup: i64, tgkey: *i64, tgcnt: *i64, ntg: i64) -> i64 { 899 var i: i64 = 0 900 while i < ntg { 901 if tgcnt[i] == sup { 902 let ta: i64 = tgkey[i] / (AL_IX_KEYB * AL_IX_KEYB) 903 let tb: i64 = (tgkey[i] / AL_IX_KEYB) % AL_IX_KEYB 904 let tc: i64 = tgkey[i] % AL_IX_KEYB 905 if ta == a { if tb == b { return 0 } } 906 if tb == a { if tc == b { return 0 } } 907 } 908 i = i + 1 909 } 910 return 1 911} 912func al_mine_fast(q: *u8, cx: *i64, minsup: i64, maxgap: i64, closed: i64, d: *u8) -> i64 { 913 let n: i64 = cx[0] 914 let ix: *i64 = sys_mmap(256) as *i64 915 al_ix_build(q, cx, ix, maxgap) 916 let offs: *i64 = ix[1] as *i64 917 let ar: *u8 = ix[4] as *u8 918 let fp: *i64 = ix[19] as *i64 919 let ov: *i64 = ix[20] as *i64 920 let nbgp: *i64 = ix[14] as *i64 921 let bgkey: *i64 = ix[12] as *i64 922 let bgcnt: *i64 = ix[13] as *i64 923 let ntgp: *i64 = ix[18] as *i64 924 let tgkey: *i64 = ix[16] as *i64 925 let tgcnt: *i64 = ix[17] as *i64 926 let tvcnt: *i64 = ix[2] as *i64 927 var p: i64 = 0 928 d[p]=123 as u8; p=p+1 929 p = al_key(d,p,"v" as *u8) 930 p = al_catn(d,p,1) 931 d[p]=44 as u8; p=p+1 932 p = al_key(d,p,"tool" as *u8) 933 p = al_qlit(d,p,"nx_actlog" as *u8) 934 d[p]=44 as u8; p=p+1 935 p = al_key(d,p,"journal" as *u8) 936 d[p]=34 as u8; p=p+1 937 let jp: *u8 = cx[5] as *u8 938 p = al_jesc(d,p,jp,0,al_vlen(jp),200) 939 d[p]=34 as u8; p=p+1 940 d[p]=44 as u8; p=p+1 941 p = al_key(d,p,"journal_bytes" as *u8) 942 p = al_catn(d,p,n) 943 d[p]=44 as u8; p=p+1 944 p = al_key(d,p,"window_bytes" as *u8) 945 p = al_catn(d,p,AL_WIN) 946 d[p]=44 as u8; p=p+1 947 p = al_key(d,p,"truncated" as *u8) 948 p = al_catn(d,p,cx[4]) 949 d[p]=44 as u8; p=p+1 950 p = al_key(d,p,"minsup" as *u8) 951 p = al_catn(d,p,minsup) 952 d[p]=44 as u8; p=p+1 953 p = al_key(d,p,"maxgap" as *u8) 954 p = al_catn(d,p,maxgap) 955 d[p]=44 as u8; p=p+1 956 p = al_key(d,p,"closed" as *u8) 957 p = al_catn(d,p,closed) 958 d[p]=44 as u8; p=p+1 959 p = al_key(d,p,"frames" as *u8) 960 p = al_catn(d,p,fp[0]) 961 d[p]=44 as u8; p=p+1 962 p = al_key(d,p,"bigrams" as *u8) 963 d[p]=91 as u8; p=p+1 964 var bcount: i64 = 0 965 var bcapped: i64 = 0 966 var bfirst: i64 = 1 967 var bi: i64 = 0 968 while bi < nbgp[0] { 969 var bg_ok: i64 = 0 970 if bgcnt[bi] >= minsup { bg_ok = 1 } 971 if bg_ok == 1 { if closed == 1 { if al_bg_is_closed(bgkey[bi] / AL_IX_KEYB, bgkey[bi] % AL_IX_KEYB, bgcnt[bi], tgkey, tgcnt, ntgp[0]) == 0 { bg_ok = 0 } } } 972 if bg_ok == 1 { 973 if bcount >= AL_BIGRAM_CAP { bcapped=1 } else { if p > AL_SOFT { bcapped=1 } else { 974 if bfirst==0 { d[p]=44 as u8; p=p+1 } 975 bfirst=0 976 d[p]=123 as u8; p=p+1 977 p = al_key(d,p,"a" as *u8) 978 p = al_ix_tv_emit(d,p,ar,offs[bgkey[bi] / AL_IX_KEYB]) 979 d[p]=44 as u8; p=p+1 980 p = al_key(d,p,"b" as *u8) 981 p = al_ix_tv_emit(d,p,ar,offs[bgkey[bi] % AL_IX_KEYB]) 982 d[p]=44 as u8; p=p+1 983 p = al_key(d,p,"support" as *u8) 984 p = al_catn(d,p,bgcnt[bi]) 985 d[p]=44 as u8; p=p+1 986 // association-rule CONFIDENCE = P(b follows a) = support / freq(a). Total-independent 987 // strength: surfaces STRONG transitions vs frequent-by-chance ones (Agrawal et al.). 988 p = al_key(d,p,"confidence_permil" as *u8) 989 var conf: i64 = 0 990 let ca: i64 = bgkey[bi] / AL_IX_KEYB 991 if tvcnt[ca] > 0 { conf = bgcnt[bi] * 1000 / tvcnt[ca] } 992 p = al_catn(d,p,conf) 993 d[p]=125 as u8; p=p+1 994 bcount = bcount + 1 995 } } 996 } 997 bi = bi + 1 998 } 999 d[p]=93 as u8; p=p+1 1000 d[p]=44 as u8; p=p+1 1001 p = al_key(d,p,"bigrams_capped" as *u8) 1002 p = al_catn(d,p,bcapped) 1003 d[p]=44 as u8; p=p+1 1004 p = al_key(d,p,"trigrams" as *u8) 1005 d[p]=91 as u8; p=p+1 1006 var tcount: i64 = 0 1007 var tcapped: i64 = 0 1008 var tfirst: i64 = 1 1009 var ti: i64 = 0 1010 while ti < ntgp[0] { 1011 if tgcnt[ti] >= minsup { 1012 if tcount >= AL_TRIGRAM_CAP { tcapped=1 } else { if p > AL_SOFT { tcapped=1 } else { 1013 if tfirst==0 { d[p]=44 as u8; p=p+1 } 1014 tfirst=0 1015 d[p]=123 as u8; p=p+1 1016 p = al_key(d,p,"a" as *u8) 1017 p = al_ix_tv_emit(d,p,ar,offs[tgkey[ti] / (AL_IX_KEYB * AL_IX_KEYB)]) 1018 d[p]=44 as u8; p=p+1 1019 p = al_key(d,p,"b" as *u8) 1020 p = al_ix_tv_emit(d,p,ar,offs[(tgkey[ti] / AL_IX_KEYB) % AL_IX_KEYB]) 1021 d[p]=44 as u8; p=p+1 1022 p = al_key(d,p,"c" as *u8) 1023 p = al_ix_tv_emit(d,p,ar,offs[tgkey[ti] % AL_IX_KEYB]) 1024 d[p]=44 as u8; p=p+1 1025 p = al_key(d,p,"support" as *u8) 1026 p = al_catn(d,p,tgcnt[ti]) 1027 d[p]=125 as u8; p=p+1 1028 tcount = tcount + 1 1029 } } 1030 } 1031 ti = ti + 1 1032 } 1033 d[p]=93 as u8; p=p+1 1034 d[p]=44 as u8; p=p+1 1035 p = al_key(d,p,"trigrams_capped" as *u8) 1036 p = al_catn(d,p,tcapped) 1037 d[p]=44 as u8; p=p+1 1038 p = al_key(d,p,"index_overflow" as *u8) 1039 p = al_catn(d,p,ov[0]) 1040 d[p]=44 as u8; p=p+1 1041 p = al_key(d,p,"index_overflow_strings" as *u8); p = al_catn(d,p,ov[1]); d[p]=44 as u8; p=p+1 1042 p = al_key(d,p,"index_overflow_grams" as *u8); p = al_catn(d,p,ov[2]); d[p]=44 as u8; p=p+1 1043 p = al_key(d,p,"index_gmax" as *u8); p = al_catn(d,p,ix[21]); d[p]=44 as u8; p=p+1 1044 p = al_key(d,p,"index_bigrams" as *u8); p = al_catn(d,p,nbgp[0]); d[p]=44 as u8; p=p+1 1045 p = al_key(d,p,"index_trigrams" as *u8); p = al_catn(d,p,ntgp[0]) 1046 d[p]=125 as u8; p=p+1 1047 d[p]=10 as u8; p=p+1 1048 return p 1049} 1050 1051// ---------- F968 BENCH: miner accuracy vs CONSTRUCTED ground truth ---------- 1052// Synthetic journals with PLANTED patterns = an exact oracle by construction (no external dep): 1053// expected supports are known arithmetic facts about the plant. Adversarial families: gapped plants 1054// (found ONLY at sufficient maxgap, never at gap 0), ws-split decoys (never cross), pure-noise 1055// (nothing fabricated), self-loops + trigrams (exact counts). A wrong support ANYWHERE = RED. 1056// ---------- ES26 STEPS-TO-SOLVE (2026-09-06) ---------- 1057// The operator's one-step goal as a verb on THIS organ (the action journal's own miner), never a new tool: the same 1058// indexed pass as `mine` at maxgap 0 (a ritual is CONSECUTIVE calls), bigrams closed against trigrams (a bigram fully 1059// explained by a longer pattern is not a second ritual), every recurring signature joined to knowledge/stepsolve.conf 1060// through nx_stepsolve_lib and classified ONE-STEP-AVAILABLE / DEPENDENCY / REDUCIBLE / UNDECLARED. Totals are the 1061// WHOLE candidate population (never the shown prefix); the top-N by support carry each row's declared reason or 1062// composed verb; the UNDECLARED worklist follows, most common first; a spine row and the gauge stamp (EXPLAINED 1063// permil in the CE9 heartbeat shape, so a stale stamp reads STALE never zero) are written only when something recurs. 1064// signature text: tool:verb>tool:verb[>tool:verb], chronological (the miner keys are prev*KEYB+cur). 1065func al_steps_sig(sig: *u8, ar: *u8, offs: *i64, kind: i64, idx: i64, bgkey: *i64, tgkey: *i64) -> i64 { 1066 var a: i64 = 0 1067 var b: i64 = 0 1068 var c: i64 = 0 - 1 1069 if kind == 2 { a = bgkey[idx] / AL_IX_KEYB; b = bgkey[idx] % AL_IX_KEYB } else { 1070 a = tgkey[idx] / (AL_IX_KEYB * AL_IX_KEYB); b = (tgkey[idx] / AL_IX_KEYB) % AL_IX_KEYB; c = tgkey[idx] % AL_IX_KEYB 1071 } 1072 var o: i64 = al_cat(sig, 0, ((ar as i64) + offs[a]) as *u8) 1073 sig[o] = SS_GT as u8; o = o + 1 1074 o = al_cat(sig, o, ((ar as i64) + offs[b]) as *u8) 1075 if c >= 0 { sig[o] = SS_GT as u8; o = o + 1; o = al_cat(sig, o, ((ar as i64) + offs[c]) as *u8) } 1076 sig[o] = 0 as u8 1077 return o 1078} 1079func al_steps_emit_one(d: *u8, p0: i64, sig: *u8, ar: *u8, offs: *i64, bgkey: *i64, tgkey: *i64, cq: *u8, tab: *i64, rt: *i64, kind: i64, idx: i64, sup: i64, fail: i64, cls: i64, row: i64, rule: i64) -> i64 { 1080 var p: i64 = p0 1081 let sl: i64 = al_steps_sig(sig, ar, offs, kind, idx, bgkey, tgkey) 1082 d[p]=123 as u8; p=p+1 1083 p = al_key(d,p,"signature" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,sig,0,sl,480); d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1084 p = al_key(d,p,"steps" as *u8); p = al_catn(d,p,kind); d[p]=44 as u8; p=p+1 1085 p = al_key(d,p,"support" as *u8); p = al_catn(d,p,sup); d[p]=44 as u8; p=p+1 1086 p = al_key(d,p,"fail" as *u8); p = al_catn(d,p,fail); d[p]=44 as u8; p=p+1 1087 p = al_key(d,p,"fail_permil" as *u8); p = al_catn(d,p,ss_fail_permil(sup, fail)); d[p]=44 as u8; p=p+1 1088 p = al_key(d,p,"risk" as *u8); p = al_catn(d,p,ss_risk(sup, fail)); d[p]=44 as u8; p=p+1 1089 p = al_key(d,p,"class" as *u8); p = al_qlit(d,p,ss_class_name(cls)); d[p]=44 as u8; p=p+1 1090 if row >= 0 { 1091 let b: i64 = row * SS_R_SLOTS 1092 p = al_key(d,p,"min_steps" as *u8); p = al_catn(d,p,tab[b + SS_R_MIN]); d[p]=44 as u8; p=p+1 1093 p = al_key(d,p,"gap" as *u8); p = al_catn(d,p,kind - tab[b + SS_R_MIN]); d[p]=44 as u8; p=p+1 1094 let rs: *u8 = ((cq as i64) + tab[b + SS_R_REASON]) as *u8 1095 p = al_key(d,p,"reason" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,rs,0,al_vlen(rs),600); d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1096 let vs: *u8 = ((cq as i64) + tab[b + SS_R_VERB]) as *u8 1097 p = al_key(d,p,"one_step_verb" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,vs,0,al_vlen(vs),120); d[p]=34 as u8; p=p+1 1098 } else { 1099 if rule >= 0 { 1100 // BY-RULE: every step is one whole organ run; the rule's verb and reason travel with the row, gap is zero 1101 let ub: i64 = rule * SS_U_SLOTS 1102 p = al_key(d,p,"min_steps" as *u8); p = al_catn(d,p,kind); d[p]=44 as u8; p=p+1 1103 p = al_key(d,p,"gap" as *u8); p = al_catn(d,p,0); d[p]=44 as u8; p=p+1 1104 let rv: *u8 = ((cq as i64) + rt[ub + SS_U_VERB]) as *u8 1105 p = al_key(d,p,"rule_verb" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,rv,0,al_vlen(rv),64); d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1106 let rr: *u8 = ((cq as i64) + rt[ub + SS_U_REASON]) as *u8 1107 p = al_key(d,p,"reason" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,rr,0,al_vlen(rr),600); d[p]=34 as u8; p=p+1 1108 } else { 1109 p = al_key(d,p,"min_steps" as *u8); p = al_qlit(d,p,"UNDECLARED" as *u8); d[p]=44 as u8; p=p+1 1110 p = al_key(d,p,"remedy" as *u8); p = al_qlit(d,p,"declare a steps row in knowledge/stepsolve.conf: the logical minimum with its reason, or the composed verb on the canonical organ" as *u8) 1111 } 1112 } 1113 d[p]=125 as u8; p=p+1 1114 return p 1115} 1116// the rules array: per-rule support and signature count beside its reason, so a rule can never hide what it absorbed 1117// (an unused rule reports zero, it never invents support) 1118func al_steps_emit_rules(d: *u8, p0: i64, cq: *u8, rt: *i64, nrules: i64) -> i64 { 1119 var p: i64 = p0 1120 d[p]=91 as u8; p=p+1 1121 var r: i64 = 0 1122 while r < nrules { 1123 let ub: i64 = r * SS_U_SLOTS 1124 if r > 0 { d[p]=44 as u8; p=p+1 } 1125 d[p]=123 as u8; p=p+1 1126 let rv: *u8 = ((cq as i64) + rt[ub + SS_U_VERB]) as *u8 1127 p = al_key(d,p,"verb" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,rv,0,al_vlen(rv),64); d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1128 p = al_key(d,p,"support" as *u8); p = al_catn(d,p,rt[ub + SS_U_SUP]); d[p]=44 as u8; p=p+1 1129 p = al_key(d,p,"signatures" as *u8); p = al_catn(d,p,rt[ub + SS_U_CNT]); d[p]=44 as u8; p=p+1 1130 let rr: *u8 = ((cq as i64) + rt[ub + SS_U_REASON]) as *u8 1131 p = al_key(d,p,"reason" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,rr,0,al_vlen(rr),600); d[p]=34 as u8; p=p+1 1132 d[p]=125 as u8; p=p+1 1133 r = r + 1 1134 } 1135 d[p]=93 as u8; p=p+1 1136 return p 1137} 1138func al_steps(q: *u8, cx: *i64, minsup: i64, confpath: *u8, topn: i64, now: i64, d: *u8) -> i64 { 1139 let n: i64 = cx[0] 1140 let ix: *i64 = sys_mmap(256) as *i64 1141 al_ix_build(q, cx, ix, 0) 1142 let offs: *i64 = ix[1] as *i64 1143 let ar: *u8 = ix[4] as *u8 1144 let fp: *i64 = ix[19] as *i64 1145 let ov: *i64 = ix[20] as *i64 1146 let nbgp: *i64 = ix[14] as *i64 1147 let bgkey: *i64 = ix[12] as *i64 1148 let bgcnt: *i64 = ix[13] as *i64 1149 let ntgp: *i64 = ix[18] as *i64 1150 let tgkey: *i64 = ix[16] as *i64 1151 let tgcnt: *i64 = ix[17] as *i64 1152 let nbg: i64 = nbgp[0] 1153 let ntg: i64 = ntgp[0] 1154 let bgfail: *i64 = ix[23] as *i64 1155 let tgfail: *i64 = ix[24] as *i64 1156 // the conf: an unreadable conf is an ABSTAINING AXIS -- every signature then reads UNDECLARED and the stamp says BLIND 1157 let t: *i64 = sys_mmap(SS_T_SLOTS * SS_WORD) as *i64 1158 ss_totals_zero(t) 1159 let cln: *i64 = sys_mmap(16) as *i64 1160 let cq: *u8 = sys_read_file(confpath, cln) 1161 var crows: i64 = 0 1162 var tab: *i64 = sys_mmap(SS_R_SLOTS * SS_WORD) as *i64 1163 var rt: *i64 = sys_mmap(SS_U_SLOTS * SS_WORD) as *i64 1164 if (cq as i64) != 0 { if cln[0] > 0 { 1165 t[SS_T_CONF_READ] = 1 1166 let ccap: i64 = ss_capacity(cq, cln[0]) 1167 tab = sys_mmap(ccap * SS_R_SLOTS * SS_WORD) as *i64 1168 rt = sys_mmap(ccap * SS_U_SLOTS * SS_WORD) as *i64 1169 crows = ss_conf_load(cq, cln[0], tab, rt, t) 1170 } } 1171 let nrules: i64 = t[SS_T_CONF_RULES] 1172 // candidates sized from the index (never a picked cap): kind, index, support, class, conf row, rule 1173 let cap: i64 = nbg + ntg + 1 1174 let ckind: *i64 = sys_mmap(cap * SS_WORD) as *i64 1175 let cidx: *i64 = sys_mmap(cap * SS_WORD) as *i64 1176 let csup: *i64 = sys_mmap(cap * SS_WORD) as *i64 1177 let ccls: *i64 = sys_mmap(cap * SS_WORD) as *i64 1178 let crow: *i64 = sys_mmap(cap * SS_WORD) as *i64 1179 let crule: *i64 = sys_mmap(cap * SS_WORD) as *i64 1180 let cfail: *i64 = sys_mmap(cap * SS_WORD) as *i64 1181 var nc: i64 = 0 1182 var nb2: i64 = 0 1183 var nt3: i64 = 0 1184 let sig: *u8 = sys_mmap(AL_MAGIC_1024) 1185 var i: i64 = 0 1186 while i < nbg { 1187 if bgcnt[i] >= minsup { 1188 let a: i64 = bgkey[i] / AL_IX_KEYB 1189 let b: i64 = bgkey[i] % AL_IX_KEYB 1190 if al_bg_is_closed(a, b, bgcnt[i], tgkey, tgcnt, ntg) == 1 { ckind[nc] = 2; cidx[nc] = i; csup[nc] = bgcnt[i]; cfail[nc] = bgfail[i]; nc = nc + 1; nb2 = nb2 + 1 } 1191 } 1192 i = i + 1 1193 } 1194 var j: i64 = 0 1195 while j < ntg { 1196 if tgcnt[j] >= minsup { ckind[nc] = 3; cidx[nc] = j; csup[nc] = tgcnt[j]; cfail[nc] = tgfail[j]; nc = nc + 1; nt3 = nt3 + 1 } 1197 j = j + 1 1198 } 1199 // pass 1: classify the WHOLE population into the totals (the shown prefix below is never the denominator) 1200 var c: i64 = 0 1201 while c < nc { 1202 let sl: i64 = al_steps_sig(sig, ar, offs, ckind[c], cidx[c], bgkey, tgkey) 1203 var row: i64 = 0 - 1 1204 if crows > 0 { row = ss_conf_find(cq, tab, crows, sig, sl) } 1205 var minv: i64 = 0 1206 var hv: i64 = 0 1207 if row >= 0 { minv = tab[row * SS_R_SLOTS + SS_R_MIN]; hv = tab[row * SS_R_SLOTS + SS_R_HASVERB] } 1208 var rule: i64 = 0 - 1 1209 if row < 0 { if nrules > 0 { rule = ss_rule_find(cq, rt, nrules, sig, sl) } } 1210 let cl: i64 = ss_class_of(row, minv, hv, ckind[c], rule) 1211 ccls[c] = cl 1212 crow[c] = row 1213 crule[c] = rule 1214 if cl == SS_C_RULE { ss_rule_add(rt, rule, csup[c]) } 1215 ss_totals_add(t, cl, csup[c], cfail[c]) 1216 c = c + 1 1217 } 1218 var p: i64 = 0 1219 d[p]=123 as u8; p=p+1 1220 p = al_key(d,p,"v" as *u8); p = al_catn(d,p,1); d[p]=44 as u8; p=p+1 1221 p = al_key(d,p,"tool" as *u8); p = al_qlit(d,p,"nx_actlog" as *u8); d[p]=44 as u8; p=p+1 1222 p = al_key(d,p,"averb" as *u8); p = al_qlit(d,p,"steps" as *u8); d[p]=44 as u8; p=p+1 1223 p = al_key(d,p,"journal" as *u8); d[p]=34 as u8; p=p+1 1224 let jp: *u8 = cx[5] as *u8 1225 p = al_jesc(d,p,jp,0,al_vlen(jp),200) 1226 d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1227 p = al_key(d,p,"journal_bytes" as *u8); p = al_catn(d,p,n); d[p]=44 as u8; p=p+1 1228 p = al_key(d,p,"truncated" as *u8); p = al_catn(d,p,cx[4]); d[p]=44 as u8; p=p+1 1229 p = al_key(d,p,"frames" as *u8); p = al_catn(d,p,fp[0]); d[p]=44 as u8; p=p+1 1230 p = al_key(d,p,"minsup" as *u8); p = al_catn(d,p,minsup); d[p]=44 as u8; p=p+1 1231 p = al_key(d,p,"maxgap" as *u8); p = al_catn(d,p,0); d[p]=44 as u8; p=p+1 1232 p = al_key(d,p,"index_overflow" as *u8); p = al_catn(d,p,ov[0]); d[p]=44 as u8; p=p+1 1233 p = al_key(d,p,"conf" as *u8); p = al_qlit(d,p,confpath); d[p]=44 as u8; p=p+1 1234 p = al_key(d,p,"conf_read" as *u8); p = al_catn(d,p,t[SS_T_CONF_READ]); d[p]=44 as u8; p=p+1 1235 p = al_key(d,p,"conf_rows" as *u8); p = al_catn(d,p,t[SS_T_CONF_ROWS]); d[p]=44 as u8; p=p+1 1236 p = al_key(d,p,"conf_malformed" as *u8); p = al_catn(d,p,t[SS_T_CONF_MALFORMED]); d[p]=44 as u8; p=p+1 1237 p = al_key(d,p,"conf_rules" as *u8); p = al_catn(d,p,t[SS_T_CONF_RULES]); d[p]=44 as u8; p=p+1 1238 p = al_key(d,p,"bigrams_closed" as *u8); p = al_catn(d,p,nb2); d[p]=44 as u8; p=p+1 1239 p = al_key(d,p,"trigrams" as *u8); p = al_catn(d,p,nt3); d[p]=44 as u8; p=p+1 1240 p = al_key(d,p,"totals" as *u8); p = ss_emit_totals(d,p,t); d[p]=44 as u8; p=p+1 1241 p = al_key(d,p,"rules" as *u8); p = al_steps_emit_rules(d,p,cq,rt,nrules); d[p]=44 as u8; p=p+1 1242 // top-N by support over every class (bounded selection, exact, no sort infra) 1243 p = al_key(d,p,"signatures" as *u8); d[p]=91 as u8; p=p+1 1244 let done: *i64 = sys_mmap(cap * SS_WORD) as *i64 1245 var shown: i64 = 0 1246 var efirst: i64 = 1 1247 var pass: i64 = 0 1248 while pass < nc { 1249 if shown < topn { if p <= AL_SOFT { 1250 var mi: i64 = 0 - 1 1251 var mx: i64 = 0 - 1 1252 var k: i64 = 0 1253 while k < nc { if done[k]==0 { if csup[k] > mx { mx = csup[k]; mi = k } } k = k + 1 } 1254 if mi >= 0 { 1255 done[mi] = 1 1256 if efirst==0 { d[p]=44 as u8; p=p+1 } 1257 efirst = 0 1258 p = al_steps_emit_one(d, p, sig, ar, offs, bgkey, tgkey, cq, tab, rt, ckind[mi], cidx[mi], csup[mi], cfail[mi], ccls[mi], crow[mi], crule[mi]) 1259 shown = shown + 1 1260 } 1261 } } 1262 pass = pass + 1 1263 } 1264 d[p]=93 as u8; p=p+1; d[p]=44 as u8; p=p+1 1265 p = al_key(d,p,"signatures_shown" as *u8); p = al_catn(d,p,shown); d[p]=44 as u8; p=p+1 1266 p = al_key(d,p,"signatures_of" as *u8); p = al_catn(d,p,nc); d[p]=44 as u8; p=p+1 1267 // the UNDECLARED worklist, most common first: the rows the operator's order asks the estate to explain next 1268 p = al_key(d,p,"worklist_undeclared" as *u8); d[p]=91 as u8; p=p+1 1269 let done2: *i64 = sys_mmap(cap * SS_WORD) as *i64 1270 var wshown: i64 = 0 1271 var wfirst: i64 = 1 1272 var wpass: i64 = 0 1273 while wpass < nc { 1274 if wshown < topn { if p <= AL_SOFT { 1275 var wi: i64 = 0 - 1 1276 var wx: i64 = 0 - 1 1277 var wk: i64 = 0 1278 while wk < nc { if done2[wk]==0 { if ccls[wk] == SS_C_UNDECLARED { if csup[wk] > wx { wx = csup[wk]; wi = wk } } } wk = wk + 1 } 1279 if wi >= 0 { 1280 done2[wi] = 1 1281 if wfirst==0 { d[p]=44 as u8; p=p+1 } 1282 wfirst = 0 1283 let wl: i64 = al_steps_sig(sig, ar, offs, ckind[wi], cidx[wi], bgkey, tgkey) 1284 d[p]=123 as u8; p=p+1 1285 p = al_key(d,p,"signature" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,sig,0,wl,480); d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1286 p = al_key(d,p,"steps" as *u8); p = al_catn(d,p,ckind[wi]); d[p]=44 as u8; p=p+1 1287 p = al_key(d,p,"support" as *u8); p = al_catn(d,p,csup[wi]) 1288 d[p]=125 as u8; p=p+1 1289 wshown = wshown + 1 1290 } 1291 } } 1292 wpass = wpass + 1 1293 } 1294 d[p]=93 as u8; p=p+1; d[p]=44 as u8; p=p+1 1295 p = al_key(d,p,"worklist_shown" as *u8); p = al_catn(d,p,wshown); d[p]=44 as u8; p=p+1 1296 p = al_key(d,p,"worklist_of" as *u8); p = al_catn(d,p,t[SS_T_CNT + SS_C_UNDECLARED]); d[p]=44 as u8; p=p+1 1297 // ES27: the RISK worklist over EVERY class, support x failure permil, most dangerous first, only rituals whose frames 1298 // failed -- a common bad one-step outranks a rare rigorous long one (operator 2026-09-06: a bad 1 step not rigorously 1299 // evaluated is worse than a 40 step perfect deliverable). A FLAG ends the selection, never a sentinel in the cursor. 1300 p = al_key(d,p,"worklist_risk" as *u8); d[p]=91 as u8; p=p+1 1301 let done3: *i64 = sys_mmap(cap * SS_WORD) as *i64 1302 var rshown: i64 = 0 1303 var rfirst: i64 = 1 1304 var rgo: i64 = 1 1305 while rgo == 1 { 1306 if rshown >= topn { rgo = 0 } else { if p > AL_SOFT { rgo = 0 } else { 1307 var ri: i64 = 0 - 1 1308 var rx: i64 = 0 1309 var rk: i64 = 0 1310 while rk < nc { if done3[rk]==0 { let rv: i64 = ss_risk(csup[rk], cfail[rk]); if rv > rx { rx = rv; ri = rk } } rk = rk + 1 } 1311 if ri < 0 { rgo = 0 } else { 1312 done3[ri] = 1 1313 if rfirst==0 { d[p]=44 as u8; p=p+1 } 1314 rfirst = 0 1315 let rl: i64 = al_steps_sig(sig, ar, offs, ckind[ri], cidx[ri], bgkey, tgkey) 1316 d[p]=123 as u8; p=p+1 1317 p = al_key(d,p,"signature" as *u8); d[p]=34 as u8; p=p+1; p = al_jesc(d,p,sig,0,rl,480); d[p]=34 as u8; p=p+1; d[p]=44 as u8; p=p+1 1318 p = al_key(d,p,"steps" as *u8); p = al_catn(d,p,ckind[ri]); d[p]=44 as u8; p=p+1 1319 p = al_key(d,p,"class" as *u8); p = al_qlit(d,p,ss_class_name(ccls[ri])); d[p]=44 as u8; p=p+1 1320 p = al_key(d,p,"support" as *u8); p = al_catn(d,p,csup[ri]); d[p]=44 as u8; p=p+1 1321 p = al_key(d,p,"fail" as *u8); p = al_catn(d,p,cfail[ri]); d[p]=44 as u8; p=p+1 1322 p = al_key(d,p,"fail_permil" as *u8); p = al_catn(d,p,ss_fail_permil(csup[ri], cfail[ri])); d[p]=44 as u8; p=p+1 1323 p = al_key(d,p,"risk" as *u8); p = al_catn(d,p,rx) 1324 d[p]=125 as u8; p=p+1 1325 rshown = rshown + 1 1326 } 1327 } } 1328 } 1329 d[p]=93 as u8; p=p+1; d[p]=44 as u8; p=p+1 1330 p = al_key(d,p,"worklist_risk_shown" as *u8); p = al_catn(d,p,rshown); d[p]=44 as u8; p=p+1 1331 p = ss_publish_json(d, p, jp, now, t) 1332 d[p]=125 as u8; p=p+1 1333 d[p]=10 as u8; p=p+1 1334 return p 1335} 1336func al_bench_path(dst: *u8, prefix: *u8, now: i64, sfx: *u8) -> i64 { 1337 var o: i64 = al_cat(dst, 0, prefix) 1338 o = al_catn(dst, o, now) 1339 o = al_cat(dst, o, sfx) 1340 dst[o] = 0 as u8 1341 // seq672 FIX: TRUNCATE the bench fixture so two selftest runs in the SAME second (now collides) 1342 // start empty instead of doubling appended rows -> the exact-support bench assertions stay idempotent. 1343 let fd: i64 = sys_openat_wr(dst, 0x1a4) 1344 if fd >= 0 { sys_close(fd) } 1345 return 0 1346} 1347func al_bench_case(ctr: *i64, name: *u8, jr: *u8, minsup: i64, maxgap: i64, needle: *u8, want: i64) -> i64 { 1348 let q: *u8 = sys_mmap(AL_WIN) 1349 let cx: *i64 = sys_mmap(64) as *i64 1350 let n: i64 = al_read(jr, q, AL_WIN - 8) 1351 cx[0]=n 1352 cx[1]=0 1353 cx[2]=0 1354 cx[3]=0 1355 cx[4]=0 1356 cx[5]=jr as i64 1357 let d: *u8 = sys_mmap(AL_OUT) 1358 let dl: i64 = al_mine_fast(q,cx,minsup,maxgap,0,d) 1359 var got: i64 = 0 1360 if dl > 0 { got = al_find(d,dl,needle) } 1361 var ok: i64 = 0 1362 if got == want { ok = 1 } 1363 gv_check(name, ok, ctr) 1364 return ok 1365} 1366func al_bench(prefix: *u8) -> i64 { 1367 let ctr: *i64 = gv_ctr() 1368 gv_head("nx_actlog bench -- miner accuracy vs planted-pattern EXACT oracle (F968)" as *u8) 1369 let now: i64 = sys_now_realtime_sec() 1370 let jA: *u8 = sys_mmap(512) 1371 al_bench_path(jA, prefix, now, ".bA" as *u8) 1372 let jB: *u8 = sys_mmap(512) 1373 al_bench_path(jB, prefix, now, ".bB" as *u8) 1374 let jC: *u8 = sys_mmap(512) 1375 al_bench_path(jC, prefix, now, ".bC" as *u8) 1376 let jD: *u8 = sys_mmap(512) 1377 al_bench_path(jD, prefix, now, ".bD" as *u8) 1378 let jE: *u8 = sys_mmap(512) 1379 al_bench_path(jE, prefix, now, ".bE" as *u8) 1380 let jF: *u8 = sys_mmap(512) 1381 al_bench_path(jF, prefix, now, ".bF" as *u8) 1382 // jA: X:a Y:b alternating x3 in w1 (contiguous plant, K=3) 1383 al_append(jA, 900, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1384 al_append(jA, 901, "w1" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1385 al_append(jA, 902, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1386 al_append(jA, 903, "w1" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1387 al_append(jA, 904, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1388 al_append(jA, 905, "w1" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1389 al_bench_case(ctr, "C1 contiguous plant support exact 3 at maxgap 0" as *u8, jA, 2, 0, "\"a\":\"X:a\",\"b\":\"Y:b\",\"support\":3" as *u8, 1) 1390 al_bench_case(ctr, "C2 gap window never inflates the adjacent plant (still 3 at maxgap 1)" as *u8, jA, 2, 1, "\"a\":\"X:a\",\"b\":\"Y:b\",\"support\":3" as *u8, 1) 1391 // jB: X:a N:z Y:b x3 in w1 (gapped plant, gap=1, K=3) 1392 al_append(jB, 910, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1393 al_append(jB, 911, "w1" as *u8, "N" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1394 al_append(jB, 912, "w1" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1395 al_append(jB, 913, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1396 al_append(jB, 914, "w1" as *u8, "N" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1397 al_append(jB, 915, "w1" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1398 al_append(jB, 916, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1399 al_append(jB, 917, "w1" as *u8, "N" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1400 al_append(jB, 918, "w1" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1401 al_bench_case(ctr, "C3 gapped plant INVISIBLE at maxgap 0 (no fabrication)" as *u8, jB, 2, 0, "\"a\":\"X:a\",\"b\":\"Y:b\"" as *u8, 0) 1402 al_bench_case(ctr, "C4 gapped plant found exact 3 at maxgap 1" as *u8, jB, 2, 1, "\"a\":\"X:a\",\"b\":\"Y:b\",\"support\":3" as *u8, 1) 1403 al_bench_case(ctr, "C5 wider window stays exact (3 at maxgap 2, no overcount)" as *u8, jB, 2, 2, "\"a\":\"X:a\",\"b\":\"Y:b\",\"support\":3" as *u8, 1) 1404 // jC: X:a in w1 / Y:b in w2 alternating x3 (ws-split decoy) 1405 al_append(jC, 920, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1406 al_append(jC, 921, "w2" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1407 al_append(jC, 922, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1408 al_append(jC, 923, "w2" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1409 al_append(jC, 924, "w1" as *u8, "X" as *u8, "a" as *u8, "ok" as *u8, "-" as *u8) 1410 al_append(jC, 925, "w2" as *u8, "Y" as *u8, "b" as *u8, "ok" as *u8, "-" as *u8) 1411 al_bench_case(ctr, "C6 ws-split decoy never counted even at maxgap 2 (isolation)" as *u8, jC, 2, 2, "\"a\":\"X:a\",\"b\":\"Y:b\"" as *u8, 0) 1412 // jD: 5 distinct singleton tvs (pure noise) 1413 al_append(jD, 930, "w1" as *u8, "T1" as *u8, "v" as *u8, "ok" as *u8, "-" as *u8) 1414 al_append(jD, 931, "w1" as *u8, "T2" as *u8, "v" as *u8, "ok" as *u8, "-" as *u8) 1415 al_append(jD, 932, "w1" as *u8, "T3" as *u8, "v" as *u8, "ok" as *u8, "-" as *u8) 1416 al_append(jD, 933, "w1" as *u8, "T4" as *u8, "v" as *u8, "ok" as *u8, "-" as *u8) 1417 al_append(jD, 934, "w1" as *u8, "T5" as *u8, "v" as *u8, "ok" as *u8, "-" as *u8) 1418 al_bench_case(ctr, "C7 pure noise yields ZERO patterns at minsup 2" as *u8, jD, 2, 2, "\"support\"" as *u8, 0) 1419 // jE: P:p Q:q R:r x2 (trigram plant, K=2) 1420 al_append(jE, 940, "w1" as *u8, "P" as *u8, "p" as *u8, "ok" as *u8, "-" as *u8) 1421 al_append(jE, 941, "w1" as *u8, "Q" as *u8, "q" as *u8, "ok" as *u8, "-" as *u8) 1422 al_append(jE, 942, "w1" as *u8, "R" as *u8, "r" as *u8, "ok" as *u8, "-" as *u8) 1423 al_append(jE, 943, "w1" as *u8, "P" as *u8, "p" as *u8, "ok" as *u8, "-" as *u8) 1424 al_append(jE, 944, "w1" as *u8, "Q" as *u8, "q" as *u8, "ok" as *u8, "-" as *u8) 1425 al_append(jE, 945, "w1" as *u8, "R" as *u8, "r" as *u8, "ok" as *u8, "-" as *u8) 1426 al_bench_case(ctr, "C8 trigram plant support exact 2" as *u8, jE, 2, 0, "\"a\":\"P:p\",\"b\":\"Q:q\",\"c\":\"R:r\",\"support\":2" as *u8, 1) 1427 // jF: S:s x4 (self-loop, 3 adjacent pairs) 1428 al_append(jF, 950, "w1" as *u8, "S" as *u8, "s" as *u8, "ok" as *u8, "-" as *u8) 1429 al_append(jF, 951, "w1" as *u8, "S" as *u8, "s" as *u8, "ok" as *u8, "-" as *u8) 1430 al_append(jF, 952, "w1" as *u8, "S" as *u8, "s" as *u8, "ok" as *u8, "-" as *u8) 1431 al_append(jF, 953, "w1" as *u8, "S" as *u8, "s" as *u8, "ok" as *u8, "-" as *u8) 1432 al_bench_case(ctr, "C9 self-loop support exact 3 (4 frames, 3 adjacent pairs)" as *u8, jF, 2, 0, "\"a\":\"S:s\",\"b\":\"S:s\",\"support\":3" as *u8, 1) 1433 let rc: i64 = gv_verdict("ACTLOG-BENCH" as *u8, ctr, "planted-pattern oracle: exact supports, honest gaps, ws isolation, zero fabrication" as *u8) 1434 return rc 1435} 1436 1437// ---------- selftest gate (T1..T9, deterministic) ---------- 1438func al_selftest(journal: *u8) -> i64 { 1439 let ctr: *i64 = gv_ctr() 1440 gv_head("nx_actlog selftest -- action journal + sequence mining teeth (SELF-cleans scratch)" as *u8) 1441 // seq672 FIX: truncate the scratch journal to empty so a RE-RUN is idempotent (T1 empty-journal 1442 // held on every run). Was "caller pre-cleans" -> a 2nd run failed T1 -> FALSE erosion in the 1443 // harness miner. Truncate-open (O_WRONLY_CT) not unlinkat (the AT_FDCWD dirfd=0 relative-path bug). 1444 let tfd: i64 = sys_openat_wr(journal, 0x1a4) 1445 if tfd >= 0 { sys_close(tfd) } 1446 let q: *u8 = sys_mmap(AL_WIN) 1447 let cx: *i64 = sys_mmap(64) as *i64 1448 let rcap: i64 = AL_WIN - 8 1449 // T1 empty -> zero frames 1450 var n: i64 = al_read(journal,q,rcap) 1451 cx[0]=n; cx[1]=0; cx[2]=0; cx[3]=0; cx[4]=0; cx[5]=journal as i64 1452 var ok1: i64 = 0 1453 if n==0 { ok1=1 } 1454 gv_check("T1 empty journal zero frames" as *u8, ok1, ctr) 1455 // seed w1: A:x -> B:y -> A:x -> B:y interleaved with w2: C:z after the first frame 1456 al_append(journal, 1000, "w1" as *u8, "A" as *u8, "x" as *u8, "ok" as *u8, "n1" as *u8) 1457 al_append(journal, 1001, "w2" as *u8, "C" as *u8, "z" as *u8, "ok" as *u8, "n2" as *u8) 1458 al_append(journal, 1002, "w1" as *u8, "B" as *u8, "y" as *u8, "ok" as *u8, "n3" as *u8) 1459 al_append(journal, 1003, "w1" as *u8, "A" as *u8, "x" as *u8, "ok" as *u8, "n4" as *u8) 1460 al_append(journal, 1004, "w1" as *u8, "B" as *u8, "y" as *u8, "ok" as *u8, "n5" as *u8) 1461 n = al_read(journal,q,rcap) 1462 cx[0]=n 1463 var ok2: i64 = 0 1464 let fr: i64 = al_frames(q,n) 1465 if fr==5 { ok2=1 } 1466 gv_check("T2 five frames logged" as *u8, ok2, ctr) 1467 // T3 ws isolation: successor of frame0 (w1 A:x) is the w1 B:y frame, NOT the w2 C:z frame 1468 var ok3: i64 = 0 1469 let s0: i64 = al_succ(q,cx,0) 1470 if s0 >= 0 { 1471 let sp: *i64 = sys_mmap(16) as *i64 1472 let se: i64 = al_le(q,s0,n) 1473 if al_col(q,s0,se,2,sp)==1 { if al_lit_eq(q,sp[0],sp[1],"B" as *u8)==1 { ok3=1 } } 1474 } 1475 gv_check("T3 successor stays inside workstream" as *u8, ok3, ctr) 1476 // T4 bigram support: (A:x -> B:y) in w1 occurs twice 1477 var ok4: i64 = 0 1478 let s0b: i64 = al_succ(q,cx,0) 1479 if s0b >= 0 { let sup: i64 = al_bg_support(q,cx,0,s0b); if sup==2 { ok4=1 } } 1480 gv_check("T4 repeated bigram support exact 2" as *u8, ok4, ctr) 1481 // T5 trigram support: (A:x -> B:y -> A:x) occurs once 1482 var ok5: i64 = 0 1483 if s0b >= 0 { 1484 let s1: i64 = al_succ(q,cx,s0b) 1485 if s1 >= 0 { let sup3: i64 = al_tg_support(q,cx,0,s0b,s1); if sup3==1 { ok5=1 } } 1486 } 1487 gv_check("T5 trigram support exact 1" as *u8, ok5, ctr) 1488 // T6 threshold honesty: mine with minsup=99 emits zero bigrams 1489 let d: *u8 = sys_mmap(AL_OUT) 1490 let dl6: i64 = al_mine_fast(q,cx,99,0,0,d) 1491 var ok6: i64 = 0 1492 if dl6 > 0 { if al_find(d,dl6,"\"support\"" as *u8)==0 { ok6=1 } } 1493 gv_check("T6 minsup 99 yields no patterns no fabrication" as *u8, ok6, ctr) 1494 // T7 real mine JSON: support-2 bigram present + envelope keys 1495 let dl7: i64 = al_mine_fast(q,cx,2,0,0,d) 1496 var ok7: i64 = 0 1497 if dl7 > 0 { if d[0]==(123 as u8) { if al_find(d,dl7,"bigrams_capped" as *u8)==1 { if al_find(d,dl7,"A:x" as *u8)==1 { if al_find(d,dl7,"support" as *u8)==1 { ok7=1 } } } } } 1498 gv_check("T7 mine JSON carries pattern plus declared envelope" as *u8, ok7, ctr) 1499 // T8 freq: per-tool:verb frequency over the seeded journal -- A:x 2, B:y 2, C:z 1, distinct 3. 1500 // Non-vacuous two ways: C:z has NO successor so a sequence-only regression cannot emit it, and 1501 // a dedup regression (first-check broken) reads distinct 5 not 3. 1502 let dl8: i64 = al_freq_fast(q,cx,d,AL_FREQ_CAP) 1503 var ok8: i64 = 0 1504 if dl8 > 0 { if al_find(d,dl8,"\"distinct\":3" as *u8)==1 { if al_find(d,dl8,"\"tv\":\"C:z\",\"count\":1" as *u8)==1 { if al_find(d,dl8,"\"tv\":\"A:x\",\"count\":2" as *u8)==1 { ok8=1 } } } } 1505 gv_check("T8 freq ranks per-tool:verb counts (A:x 2, C:z 1, distinct 3 -- dedup + non-sequence coverage)" as *u8, ok8, ctr) 1506 // T9 harden: A:x and B:y recur (count 2 >= minsup 2), C:z does not. With the INJECTED argecho 1507 // filer, exactly those two file -- their echoed argv must carry the REAL canonical desc (a fork 1508 // that never ran leaves out empty), and C:z must be absent (a broken recurrence filter files 3). 1509 let dl9: i64 = al_harden_json(q,cx,2,5,"argecho" as *u8,d) 1510 var ok9: i64 = 0 1511 if dl9 > 0 { if al_find(d,dl9,"\"recurring\":2" as *u8)==1 { if al_find(d,dl9,"FALLBACK-RECURRENCE A:x" as *u8)==1 { if al_find(d,dl9,"FALLBACK-RECURRENCE B:y" as *u8)==1 { if al_find(d,dl9,"C:z" as *u8)==0 { ok9=1 } } } } } 1512 gv_check("T9 harden files EXACTLY the recurring tvs through the injected filer (canonical desc echoed back; C:z absent)" as *u8, ok9, ctr) 1513 // T10/T11 gap-constrained mining (F966 rung 1): w3 = A:x, C:z, B:y -- A->B has ONE intervening frame 1514 al_append(journal, 1010, "w3" as *u8, "A" as *u8, "x" as *u8, "ok" as *u8, "g1" as *u8) 1515 al_append(journal, 1011, "w3" as *u8, "C" as *u8, "z" as *u8, "ok" as *u8, "g2" as *u8) 1516 al_append(journal, 1012, "w3" as *u8, "B" as *u8, "y" as *u8, "ok" as *u8, "g3" as *u8) 1517 n = al_read(journal,q,rcap) 1518 cx[0]=n 1519 let dl10: i64 = al_mine_fast(q,cx,2,0,0,d) 1520 var ok10: i64 = 0 1521 if dl10 > 0 { if al_find(d,dl10,"\"a\":\"A:x\",\"b\":\"B:y\",\"support\":2" as *u8)==1 { ok10=1 } } 1522 gv_check("T10 maxgap 0 never counts the gapped pair (support stays 2)" as *u8, ok10, ctr) 1523 let dl11: i64 = al_mine_fast(q,cx,2,1,0,d) 1524 var ok11: i64 = 0 1525 if dl11 > 0 { if al_find(d,dl11,"\"a\":\"A:x\",\"b\":\"B:y\",\"support\":3" as *u8)==1 { if al_find(d,dl11,"\"maxgap\":1" as *u8)==1 { ok11=1 } } } 1526 gv_check("T11 maxgap 1 finds the interleaved pair (support 3, declared)" as *u8, ok11, ctr) 1527 // T12: the F968 bench itself must be all-exact (accuracy measured, not asserted) 1528 let rb: i64 = al_bench(journal) 1529 var ok12: i64 = 0 1530 if rb == 0 { ok12 = 1 } 1531 gv_check("T12 bench: planted-pattern accuracy harness all-exact" as *u8, ok12, ctr) 1532 // T13/T14 CLOSED PATTERNS (CloSpan/BIDE, benchmarked vs a hand-computed closure oracle). w4 = G:x 1533 // H:y I:z x3 (contiguous) so G:x->H:y and H:y->I:z are SUBSUMED by the trigram G:x->H:y->I:z (equal 1534 // support 3) = NON-closed. w5 = P:x Q:y R:z / P:x Q:y S:z so P:x->Q:y (sup 2) has NO equal-support 1535 // trigram (both P:x->Q:y->{R,S} are sup 1) = CLOSED. Fresh tvs (G/H/I/P/Q/R/S) avoid main-journal collisions. 1536 al_append(journal, AL_MAGIC_1100, "w4" as *u8, "G" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1537 al_append(journal, AL_MAGIC_1101, "w4" as *u8, "H" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1538 al_append(journal, AL_MAGIC_1102, "w4" as *u8, "I" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1539 al_append(journal, AL_MAGIC_1103, "w4" as *u8, "G" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1540 al_append(journal, AL_MAGIC_1104, "w4" as *u8, "H" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1541 al_append(journal, AL_MAGIC_1105, "w4" as *u8, "I" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1542 al_append(journal, AL_MAGIC_1106, "w4" as *u8, "G" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1543 al_append(journal, AL_MAGIC_1107, "w4" as *u8, "H" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1544 al_append(journal, AL_MAGIC_1108, "w4" as *u8, "I" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1545 al_append(journal, AL_MAGIC_1110, "w5" as *u8, "P" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1546 al_append(journal, AL_MAGIC_1111, "w5" as *u8, "Q" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1547 al_append(journal, AL_MAGIC_1112, "w5" as *u8, "R" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1548 al_append(journal, AL_MAGIC_1113, "w5" as *u8, "P" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1549 al_append(journal, AL_MAGIC_1114, "w5" as *u8, "Q" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1550 al_append(journal, AL_MAGIC_1115, "w5" as *u8, "S" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1551 n = al_read(journal,q,rcap) 1552 cx[0]=n 1553 let dlnc: i64 = al_mine_fast(q,cx,2,0,0,d) 1554 var ok13: i64 = 0 1555 if dlnc > 0 { if al_find(d,dlnc,"\"a\":\"G:x\",\"b\":\"H:y\",\"support\":3" as *u8)==1 { if al_find(d,dlnc,"\"closed\":0" as *u8)==1 { ok13=1 } } } 1556 gv_check("T13 non-closed mode emits the subsumed bigram G:x->H:y (support 3)" as *u8, ok13, ctr) 1557 let dlc: i64 = al_mine_fast(q,cx,2,0,1,d) 1558 var ok14: i64 = 0 1559 // the SUBSUMED bigram's specific form ("support" right after "b") must be gone; the trigram 1560 // G:x->H:y->I:z ("c" after "b") legitimately remains and must NOT be matched as the bigram. 1561 if dlc > 0 { if al_find(d,dlc,"\"a\":\"G:x\",\"b\":\"H:y\",\"support\"" as *u8)==0 { if al_find(d,dlc,"\"a\":\"P:x\",\"b\":\"Q:y\",\"support\":2" as *u8)==1 { if al_find(d,dlc,"\"closed\":1" as *u8)==1 { ok14=1 } } } } 1562 gv_check("T14 closed mode DROPS the subsumed bigram, KEEPS the closed P:x->Q:y (CloSpan/BIDE)" as *u8, ok14, ctr) 1563 // T15 CONFIDENCE (association-rule strength, EXACT + total-independent). w6 = M N M N M P => M appears 1564 // 3x, M->N 2x, M->P 1x => confidence(M:x->N:y)=support(2)/freq(M)(3)=666 permil regardless of journal size. 1565 al_append(journal, AL_MAGIC_1100, "w6" as *u8, "M" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1566 al_append(journal, AL_MAGIC_1100, "w6" as *u8, "N" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1567 al_append(journal, AL_MAGIC_1100, "w6" as *u8, "M" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1568 al_append(journal, AL_MAGIC_1100, "w6" as *u8, "N" as *u8, "y" as *u8, "ok" as *u8, "-" as *u8) 1569 al_append(journal, AL_MAGIC_1100, "w6" as *u8, "M" as *u8, "x" as *u8, "ok" as *u8, "-" as *u8) 1570 al_append(journal, AL_MAGIC_1100, "w6" as *u8, "P" as *u8, "z" as *u8, "ok" as *u8, "-" as *u8) 1571 n = al_read(journal,q,rcap) 1572 cx[0]=n 1573 let dlcf: i64 = al_mine_fast(q,cx,2,0,0,d) 1574 var ok15: i64 = 0 1575 if dlcf > 0 { if al_find(d,dlcf,"\"a\":\"M:x\",\"b\":\"N:y\",\"support\":2,\"confidence_permil\":666" as *u8)==1 { ok15=1 } } 1576 gv_check("T15 confidence(M:x->N:y)=666 permil (support 2 / freq(M) 3 -- association-rule strength, exact)" as *u8, ok15, ctr) 1577 // T16/T17 INDEX SIZED FROM THE FRAME COUNT (2026-09-05). Fixture: 130 tools, every ordered pair (Ta,Tb) 1578 // emitted as consecutive frames in one workspace => EXACTLY 130*130 = 16,900 distinct bigrams, which is 1579 // ABOVE the old fixed AL_IX_GMAX (16,384): under the fixed cap this journal read index_overflow=1 with 516 1580 // pairs silently uncounted. The tooth asserts the exact count (a floor-sized table cannot reach it) and that 1581 // the table was DERIVED (gmax = frames + 1 = 33,801, not the 16,384 floor). Written to its own file so the 1582 // capped selftest read buffer cannot truncate the fixture into passing for the wrong reason. 1583 let ovj: *u8 = sys_mmap(512) 1584 var oo: i64 = al_cat(ovj, 0, journal) 1585 oo = al_cat(ovj, oo, ".ovf" as *u8) 1586 ovj[oo] = 0 as u8 1587 let tfd: i64 = sys_openat_wr(ovj, 420) 1588 if tfd >= 0 { sys_close(tfd) } 1589 let ta: *u8 = sys_mmap(32) 1590 let tb: *u8 = sys_mmap(32) 1591 var fa: i64 = 0 1592 while fa < 130 { 1593 var fb: i64 = 0 1594 while fb < 130 { 1595 var ao: i64 = al_cat(ta, 0, "T" as *u8); ao = al_catn(ta, ao, fa); ta[ao] = 0 as u8 1596 var bo: i64 = al_cat(tb, 0, "T" as *u8); bo = al_catn(tb, bo, fb); tb[bo] = 0 as u8 1597 al_append(ovj, AL_MAGIC_1100, "wo" as *u8, ta, "v" as *u8, "ok" as *u8, "-" as *u8) 1598 al_append(ovj, AL_MAGIC_1100, "wo" as *u8, tb, "v" as *u8, "ok" as *u8, "-" as *u8) 1599 fb = fb + 1 1600 } 1601 fa = fa + 1 1602 } 1603 let nn16: *i64 = sys_mmap(16) as *i64 1604 let q16: *u8 = sys_read_file(ovj, nn16) 1605 let cx16: *i64 = sys_mmap(64) as *i64 1606 cx16[0] = nn16[0] 1607 cx16[1] = 0 1608 cx16[2] = 0 1609 cx16[3] = 0 1610 cx16[4] = 0 1611 cx16[5] = ovj as i64 1612 let dl16: i64 = al_mine_fast(q16, cx16, 1, 0, 0, d) 1613 var ok16: i64 = 0 1614 if dl16 > 0 { if al_find(d,dl16,"\"index_bigrams\":16900" as *u8)==1 { if al_find(d,dl16,"\"index_overflow\":0" as *u8)==1 { if al_find(d,dl16,"\"index_overflow_grams\":0" as *u8)==1 { ok16=1 } } } } 1615 gv_check("T16 index sized from the frame count: 16,900 distinct bigrams (above the old 16,384 fixed cap) counted EXACTLY, index_overflow 0" as *u8, ok16, ctr) 1616 var ok17: i64 = 0 1617 if dl16 > 0 { if al_find(d,dl16,"\"index_gmax\":33801" as *u8)==1 { ok17=1 } } 1618 gv_check("T17 fixture-reached-the-condition: the gram table was DERIVED (gmax = 33,800 frames + 1), not the floor" as *u8, ok17, ctr) 1619 let rc: i64 = gv_verdict("ACTLOG-GATE" as *u8, ctr, "action journal + sequence + frequency + harden + gap + bench + closed-pattern + confidence + derived-index teeth green" as *u8) 1620 return rc 1621} 1622 1623func main(argc: i64, argv: *i64) -> i64 { 1624 if argc < 3 { gv_puts("usage: nx_actlog {log <journal> <ws> <tool> <verb> <outcome> <note> | mine <journal> [minsup] [maxgap] [closed] | freq <journal> | harden <journal> [minsup] [filer] | bench <scratch-prefix> | selftest <journal>}\n" as *u8); sys_exit(2); return 2 } 1625 let verb: *u8 = argv[1] as *u8 1626 let journal: *u8 = argv[2] as *u8 1627 let vl: i64 = al_vlen(verb) 1628 if al_lit_eq(verb,0,vl,"selftest" as *u8)==1 { let rc: i64 = al_selftest(journal); sys_exit(rc); return rc } 1629 if al_lit_eq(verb,0,vl,"log" as *u8)==1 { 1630 if argc < 8 { gv_puts("log needs <journal> <ws> <tool> <verb> <outcome> <note>\n" as *u8); sys_exit(2); return 2 } 1631 let ws: *u8 = argv[3] as *u8 1632 let tool: *u8 = argv[4] as *u8 1633 let averb: *u8 = argv[5] as *u8 1634 let outcome: *u8 = argv[6] as *u8 1635 let note: *u8 = argv[7] as *u8 1636 let rc: i64 = al_append(journal, -1, ws, tool, averb, outcome, note) 1637 if rc==0 { gv_puts("ACTLOG OK ws=" as *u8); gv_puts(ws); gv_puts(" " as *u8); gv_puts(tool); gv_puts(":" as *u8); gv_puts(averb); gv_puts("\n" as *u8); sys_exit(0); return 0 } 1638 gv_puts("append FAILED\n" as *u8) 1639 sys_exit(1) 1640 return 1 1641 } 1642 // ES26: steps <journal> [minsup] [conf] [topn] [now] -- the one-step-solve ruler over this journal (prints JSON; writes 1643 // the spine row and gauge stamp only when something recurs; an unreadable journal fails closed, nothing published) 1644 if al_lit_eq(verb,0,vl,"steps" as *u8)==1 { 1645 let snn: *i64 = sys_mmap(16) as *i64 1646 let sq: *u8 = sys_read_file(journal, snn) 1647 if (sq as i64) == 0 { gv_puts("nx_actlog steps: journal unreadable (fail closed, nothing published)\n" as *u8); sys_exit(3); return 3 } 1648 let sn: i64 = snn[0] 1649 let scx: *i64 = sys_mmap(64) as *i64 1650 scx[0]=sn 1651 scx[1]=sys_now_realtime_sec() 1652 scx[2]=0 1653 scx[3]=0 1654 scx[4]=0 1655 scx[5]=journal as i64 1656 var sminsup: i64 = AL_MINSUP_DEF 1657 if argc > 3 { let sm: i64 = al_atoi_z(argv[3] as *u8); if sm > 0 { sminsup = sm } } 1658 var sconf: *u8 = SS_CONF_PROD 1659 if argc > 4 { sconf = argv[4] as *u8 } 1660 var stopn: i64 = AL_FREQ_CAP 1661 if argc > 5 { let stn: i64 = al_atoi_z(argv[5] as *u8); if stn > 0 { stopn = stn } } 1662 var snow: i64 = sys_now_realtime_sec() 1663 if argc > 6 { let snz: i64 = al_atoi_z(argv[6] as *u8); if snz > 0 { snow = snz } } 1664 let sd: *u8 = sys_mmap(AL_OUT) 1665 let sdl: i64 = al_steps(sq, scx, sminsup, sconf, stopn, snow, sd) 1666 sys_write(1, sd, sdl) 1667 sys_exit(0) 1668 return 0 1669 } 1670 if al_lit_eq(verb,0,vl,"mine" as *u8)==1 { 1671 let nn: *i64 = sys_mmap(16) as *i64 1672 let q: *u8 = sys_read_file(journal, nn) 1673 let n: i64 = nn[0] 1674 let rcap: i64 = n + 8 1675 let cx: *i64 = sys_mmap(64) as *i64 1676 cx[0]=n 1677 cx[1]=sys_now_realtime_sec() 1678 cx[2]=0 1679 cx[3]=0 1680 cx[4]=0 1681 if n >= rcap { cx[4]=1 } 1682 cx[5]=journal as i64 1683 var minsup: i64 = AL_MINSUP_DEF 1684 if argc >= 4 { let mz: i64 = al_atoi_z(argv[3] as *u8); if mz > 0 { minsup = mz } } 1685 var maxgap: i64 = 0 1686 if argc >= 5 { let gz: i64 = al_atoi_z(argv[4] as *u8); if gz > 0 { maxgap = gz } } 1687 if maxgap > AL_IX_MAXGAP { maxgap = AL_IX_MAXGAP } 1688 var closed: i64 = 0 1689 if argc >= 6 { let cz: i64 = al_atoi_z(argv[5] as *u8); if cz > 0 { closed = 1 } } 1690 let d: *u8 = sys_mmap(AL_OUT) 1691 let dl: i64 = al_mine_fast(q,cx,minsup,maxgap,closed,d) 1692 sys_write(1,d,dl) 1693 sys_exit(0) 1694 return 0 1695 } 1696 if al_lit_eq(verb,0,vl,"freq" as *u8)==1 { 1697 let nn: *i64 = sys_mmap(16) as *i64 1698 let q: *u8 = sys_read_file(journal, nn) 1699 let n: i64 = nn[0] 1700 let rcap: i64 = n + 8 1701 let cx: *i64 = sys_mmap(64) as *i64 1702 cx[0]=n 1703 cx[1]=0 1704 cx[2]=0 1705 cx[3]=0 1706 cx[4]=0 1707 if n >= rcap { cx[4]=1 } 1708 cx[5]=journal as i64 1709 var fcap: i64 = AL_FREQ_CAP 1710 if argc >= 4 { let fz: i64 = al_atoi_z(argv[3] as *u8); if fz > 0 { fcap = fz } } 1711 let d: *u8 = sys_mmap(AL_OUT) 1712 let dl: i64 = al_freq_fast(q,cx,d,fcap) 1713 sys_write(1,d,dl) 1714 sys_exit(0) 1715 return 0 1716 } 1717 if al_lit_eq(verb,0,vl,"harden" as *u8)==1 { 1718 let nn: *i64 = sys_mmap(16) as *i64 1719 let q: *u8 = sys_read_file(journal, nn) 1720 let n: i64 = nn[0] 1721 let rcap: i64 = n + 8 1722 let cx: *i64 = sys_mmap(64) as *i64 1723 cx[0]=n 1724 cx[1]=0 1725 cx[2]=0 1726 cx[3]=0 1727 cx[4]=0 1728 if n >= rcap { cx[4]=1 } 1729 cx[5]=journal as i64 1730 var minsup: i64 = AL_MINSUP_DEF 1731 if argc >= 4 { let mz: i64 = al_atoi_z(argv[3] as *u8); if mz > 0 { minsup = mz } } 1732 let filer: *u8 = sys_mmap(128) 1733 var fo2: i64 = 0 1734 if argc >= 5 { fo2 = al_cat(filer,0,argv[4] as *u8) } else { fo2 = al_cat(filer,0,"nx_debt" as *u8) } 1735 filer[fo2]=0 as u8 1736 let d: *u8 = sys_mmap(AL_OUT) 1737 let dl: i64 = al_harden_json(q,cx,minsup,AL_HARDEN_SEV,filer,d) 1738 sys_write(1,d,dl) 1739 sys_exit(0) 1740 return 0 1741 } 1742 if al_lit_eq(verb,0,vl,"bench" as *u8)==1 { 1743 let rb: i64 = al_bench(journal) 1744 sys_exit(rb) 1745 return rb 1746 } 1747 gv_puts("unknown verb\n" as *u8) 1748 sys_exit(2) 1749 return 2 1750}