code wiki / (root) / nx_accept_lib.nx

nx_accept_lib.nx source

↩ module page · 1032 lines · 45494 B

1// nx_accept_lib.nx -- THE THREE-PARTY ACCEPTANCE LEDGER: the decision core behind every ACCEPTANCE cell on 2// /compare (2026-08-30). Operator standing order, verbatim: "doing it poorly isn't a complete and needs to be 3// shown as that on /compare and your work; it's not complete till you and I and the nishi team agree." 4// 5// A subject is ACCEPTED iff ALL THREE signatures hold, each read from its own sovereign plane: 6// 1. OPERATOR -- knowledge/store/accept- : the LATEST row whose actor is `operator` and whose targets field 7// carries the token ga_accept_<subject> says ACCEPT (REJECT, UNJUDGED, absent do not). 8// 2. REFEREE -- knowledge/store/referee- : the LATEST row for <subject> says composite GOOD AND its percept is 9// at or above floor_percept_<tier> READ FROM knowledge/cjc_panel.conf (never a literal here), its 10// tier is in the panel receipt's tiers_admitted list, and that receipt says admitted=1. The row's 11// own word GOOD is necessary and NOT sufficient: the floor is re-derived so a row cannot lie. 12// 3. SEAT -- knowledge/store/attest- : a row for <subject> naming the shipping seat and its stamp. 13// Anything less is INCOMPLETE, and INCOMPLETE names WHICH signature is missing and WHY. 14// 15// HOW THE BOARD FLIPS. `nx_accept emit` regenerates buildroot/runtime/nx_accept_decl.nx from the planes: one 16// top-level declaration ga_accept_<subject> per ACCEPTED subject and NOTHING for any other. The /compare regen 17// measures that file exactly as it measures every organ (nx_symdecl_lib: a column-0 declaration), so an 18// ACCEPTANCE watch row lands only when the three-party rule holds. A hand-written declaration is a lie: the next 19// emit erases it and nx_accept_gate convicts it (re-derivation must equal the bytes on disk). 20// 21// JOIN RULE, stated once: a plane row GOVERNS subject X iff its targets field carries the token ga_accept_X, bare 22// or domain-qualified (gameengine:ga_accept_X). The subject key IS the suffix of the acceptance symbol, so the 23// board and the ledger cannot name the same thing two ways. Rows with no such token are counted UNMAPPED and 24// printed, never silently dropped. 25// 26// LIB+PROGRAM SPLIT ON PURPOSE: every rule is a function of caller-supplied plane prefixes, conf path and buffers, 27// so nx_accept_gate drives the SAME code over fixture planes under /tmp and never the production planes. 28// COMPOSES, NEVER RE-IMPLEMENTS: nx_seg_store's sequential cursor (plane iteration; ss_get point lookups are the 29// documented quadratic read), nx_comparewatch_lib (tab-field parsing + strict q:<n> keys), nx_lineconf_lib 30// (line-anchored key=value), nx_estate_path (CWD-independent artifact paths). 31// HONEST LIMIT: the actor column is caller-supplied. This ledger buys ATTRIBUTION and TAMPER-EVIDENCE through the 32// plane's own hist- provenance, not cryptographic proof of who the operator is; the signed-row rung (nx_evattest, 33// role=human key) is the named next step, not a claim made here. 34// license_tier: ORIGINAL No hw writes (Rule 26). 35import "nx_syscalls.nx" 36import "nx_seg_store.nx" 37import "nx_comparewatch_lib.nx" 38import "nx_lineconf_lib.nx" 39import "nx_estate_path.nx" 40import "nx_store_seed_lib.nx" // sts_load_fit: the newest-version-per-key row reader (2026-08-31, see al_rows_open) 41 42// ---- the DEFAULTS a program passes; the gate passes fixtures --------------------------------------------- 43const AL_PFX_ACCEPT: *u8 = "knowledge/store/accept-" 44const AL_PFX_REFEREE: *u8 = "knowledge/store/referee-" 45const AL_PFX_ATTEST: *u8 = "knowledge/store/attest-" 46const AL_PANEL_CONF: *u8 = "knowledge/cjc_panel.conf" 47const AL_DECL_PATH: *u8 = "buildroot/runtime/nx_accept_decl.nx" 48const AL_DECL_SIBLING: *u8 = "buildroot/runtime/nx_accept_lib.nx" 49const AL_DECL_BASENAME: *u8 = "nx_accept_decl.nx" 50const AL_DECL_ROW: *u8 = "runtime/nx_accept_decl.nx" 51const AL_BOARDS_DIR: *u8 = "buildroot/knowledge/compare" 52const AL_BOARDS_DIR_FROM_BUILDROOT: *u8 = "knowledge/compare" 53const AL_SYM_PFX: *u8 = "ga_accept_" 54const AL_WATCH_PFX: *u8 = "_ABSENT_:" 55const AL_MATRIX_SFX: *u8 = ".matrix" 56const AL_ACTOR_OPERATOR: *u8 = "operator" 57const AL_KEY_RECEIPT: *u8 = "receipt" 58const AL_KEY_ADMITTED: *u8 = "admitted" 59const AL_KEY_TIERS_ADMITTED: *u8 = "tiers_admitted" 60const AL_KEY_TIERS: *u8 = "tiers" 61const AL_KEY_FLOOR_PFX: *u8 = "floor_percept_" 62const AL_TMP_SFX: *u8 = ".tmp" 63 64// ---- byte constants (named, never bare) -------------------------------------------------------------------- 65const AL_TAB: i64 = 9 66const AL_NL: i64 = 10 67const AL_CR: i64 = 13 68const AL_SPACE: i64 = 32 69const AL_BANG: i64 = 33 70const AL_HASH: i64 = 35 71const AL_COMMA: i64 = 44 72const AL_MINUS: i64 = 45 73const AL_DOT: i64 = 46 74const AL_SLASH: i64 = 47 75const AL_D0: i64 = 48 76const AL_D9: i64 = 57 77const AL_COLON: i64 = 58 78const AL_AT: i64 = 64 79const AL_LOWA: i64 = 97 80const AL_LOWZ: i64 = 122 81const AL_USCORE: i64 = 95 82const AL_PIPE: i64 = 124 83const AL_BASE10: i64 = 10 84const AL_KIND_TOMB: i64 = 2 // seg-store record kind 2 = tombstone (nx_seg_store contract) 85 86// ---- capacities: each announces when exceeded, none is silent ----------------------------------------- 87const AL_MAX_SUBJ: i64 = 64 88const AL_MAX_TOK: i64 = 16 89const AL_MAX_WATCH: i64 = 64 90const AL_NAMEW: i64 = 64 91const AL_ORGW: i64 = 128 92const AL_REC: i64 = 512 93const AL_NUMCAP: i64 = 32 94const AL_PATHCAP: i64 = 1024 95const AL_LISTCAP: i64 = 256 96const AL_KEYCAP: i64 = 128 97const AL_DENTCAP: i64 = 65536 98const AL_DECL_CAP: i64 = 65536 99const AL_LINE_MAX: i64 = 1024 100const AL_DATECAP: i64 = 16 101const AL_SC_WORDS: i64 = 8 102 103// ---- string field offsets/widths inside one subject record (AL_REC bytes) -------------------------------- 104const AL_F_NAME: i64 = 0 105const AL_W_NAME: i64 = 64 106const AL_F_OPID: i64 = 64 107const AL_W_OPID: i64 = 96 108const AL_F_OPDATE: i64 = 160 109const AL_W_DATE: i64 = 16 110const AL_F_OPACTOR: i64 = 176 111const AL_W_ACTOR: i64 = 32 112const AL_F_RTIER: i64 = 208 113const AL_W_TIER: i64 = 16 114const AL_F_RSHA: i64 = 224 115const AL_W_SHA: i64 = 72 116const AL_F_RSEAT: i64 = 296 117const AL_W_SEAT: i64 = 32 118const AL_F_RDATE: i64 = 328 119const AL_F_ASEAT: i64 = 344 120const AL_F_ASTAMP: i64 = 376 121const AL_W_STAMP: i64 = 64 122const AL_F_ADATE: i64 = 440 123 124// ---- integer slots per subject ------------------------------------------------------------------------------- 125const AL_IW: i64 = 16 126const AL_I_OPV: i64 = 0 // operator verdict code (actor == operator rows only) 127const AL_I_ANYV: i64 = 1 // latest verdict of ANY actor (informational) 128const AL_I_RCOMP: i64 = 2 // referee composite code 129const AL_I_RPERCEPT: i64 = 3 130const AL_I_ATT: i64 = 4 // 1 = a usable attestation row exists 131const AL_I_OPSEEN: i64 = 5 132const AL_I_RSEEN: i64 = 6 133const AL_I_ASEEN: i64 = 7 134 135// ---- book header words --------------------------------------------------------------------------------------- 136const AL_BK_WORDS: i64 = 32 137const AL_B_N: i64 = 0 138const AL_B_INTS: i64 = 1 139const AL_B_STRS: i64 = 2 140const AL_B_OVERFLOW: i64 = 3 141const AL_B_ACC_ROWS: i64 = 4 142const AL_B_REF_ROWS: i64 = 5 143const AL_B_ATT_ROWS: i64 = 6 144const AL_B_UNMAPPED: i64 = 7 145const AL_B_MALFORMED: i64 = 8 146const AL_B_ACC_PLANE: i64 = 9 147const AL_B_REF_PLANE: i64 = 10 148const AL_B_ATT_PLANE: i64 = 11 149const AL_B_TOMB: i64 = 12 150const AL_B_FOREIGN: i64 = 13 151const AL_B_BADNAME: i64 = 14 152const AL_B_ACC_PATH: i64 = 16 153const AL_B_REF_PATH: i64 = 17 154const AL_B_ATT_PATH: i64 = 18 155 156// ---- accept- row fields: id | subject-or-description | verdict | date | actor | words | targets -------------- 157const AL_AF_ID: i64 = 0 158const AL_AF_VERDICT: i64 = 2 159const AL_AF_DATE: i64 = 3 160const AL_AF_ACTOR: i64 = 4 161const AL_AF_TARGETS: i64 = 6 162// ---- referee- row fields: id | subject | frame_sha256 | composite | percept | tier | date | seat ----------- 163const AL_RF_SUBJECT: i64 = 1 164const AL_RF_SHA: i64 = 2 165const AL_RF_COMP: i64 = 3 166const AL_RF_PERCEPT: i64 = 4 167const AL_RF_TIER: i64 = 5 168const AL_RF_DATE: i64 = 6 169const AL_RF_SEAT: i64 = 7 170// ---- attest- row fields: id | subject | seat | stamp | words | date -------------------------------------------- 171const AL_TF_SUBJECT: i64 = 1 172const AL_TF_SEAT: i64 = 2 173const AL_TF_STAMP: i64 = 3 174const AL_TF_DATE: i64 = 5 175 176// ---- codes ---------------------------------------------------------------------------------------------------- 177const AL_V_NONE: i64 = 0 178const AL_V_ACCEPT: i64 = 1 179const AL_V_REJECT: i64 = 2 180const AL_V_UNJUDGED: i64 = 3 181const AL_V_INVALID: i64 = 4 182const AL_R_NONE: i64 = 0 183const AL_R_GOOD: i64 = 1 184const AL_R_BAD: i64 = 2 185const AL_R_INVALID: i64 = 3 186const AL_RC_OK: i64 = 0 187const AL_RC_MISSING: i64 = 1 188const AL_RC_BAD: i64 = 2 189const AL_RC_INVALID: i64 = 3 190const AL_RC_TIER_UNADMITTED: i64 = 4 191const AL_RC_NO_FLOOR: i64 = 5 192const AL_RC_BELOW_FLOOR: i64 = 6 193const AL_RC_PANEL_UNADMITTED: i64 = 7 194const AL_ST_UNKNOWN: i64 = 0 195const AL_ST_ACCEPTED: i64 = 1 196const AL_ST_INCOMPLETE: i64 = 2 197const AL_DV_IDENTICAL: i64 = 0 198const AL_DV_DIFFERS: i64 = 1 199const AL_DV_ABSENT: i64 = 2 200const AL_DV_CAP: i64 = 3 201// why[] slots handed back by al_state 202const AL_WHY_OP: i64 = 0 203const AL_WHY_REF: i64 = 1 204const AL_WHY_ATT: i64 = 2 205const AL_WHY_FLOOR: i64 = 3 206const AL_WHY_WORDS: i64 = 4 207 208// ---- conf struct words -------------------------------------------------------------------------------------- 209const AL_CF_WORDS: i64 = 16 210const AL_C_BUF: i64 = 0 211const AL_C_LEN: i64 = 1 212const AL_C_ADMITTED: i64 = 2 213const AL_C_TADM: i64 = 3 214const AL_C_TIERS: i64 = 4 215const AL_C_CONF_OK: i64 = 5 216const AL_C_RCPT_OK: i64 = 6 217const AL_C_PATH: i64 = 7 218const AL_C_RPATH: i64 = 8 219 220// ---- civil date from epoch seconds (Howard Hinnant's days-to-civil; every constant named) ------------------ 221const AL_SEC_PER_DAY: i64 = 86400 222const AL_EPOCH_SHIFT_DAYS: i64 = 719468 223const AL_DAYS_PER_ERA: i64 = 146097 224const AL_YEARS_PER_ERA: i64 = 400 225const AL_DAYS_4Y: i64 = 1460 226const AL_DAYS_100Y: i64 = 36524 227const AL_DAYS_400Y_LESS1: i64 = 146096 228const AL_DAYS_YEAR: i64 = 365 229const AL_LEAP_4: i64 = 4 230const AL_LEAP_100: i64 = 100 231const AL_MP_MUL: i64 = 5 232const AL_MP_ADD: i64 = 2 233const AL_MP_DIV: i64 = 153 234const AL_MONTH_WRAP: i64 = 10 235const AL_MONTH_ADD: i64 = 3 236const AL_MONTH_SUB: i64 = 9 237const AL_FEB: i64 = 2 238const AL_TWO_DIGITS: i64 = 10 239 240// ---- tiny string kit -------------------------------------------------------------------------------------------- 241func al_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 242func al_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p } 243func al_catsl(d: *u8, o: i64, s: *u8, so: i64, n: i64) -> i64 { var i: i64 = 0; var p: i64 = o; while i < n { d[p] = s[so + i]; p = p + 1; i = i + 1 } return p } 244func al_catn(d: *u8, o: i64, v: i64) -> i64 { 245 var m: i64 = v 246 var p: i64 = o 247 if m < 0 { d[p] = AL_MINUS as u8; p = p + 1; m = 0 - m } 248 let t: *u8 = sys_mmap(AL_NUMCAP) 249 var k: i64 = 0 250 if m == 0 { t[0] = AL_D0 as u8; k = 1 } 251 while m > 0 { t[k] = (AL_D0 + (m % AL_BASE10)) as u8; m = m / AL_BASE10; k = k + 1 } 252 var i: i64 = 0 253 while i < k { d[p + i] = t[k - 1 - i]; i = i + 1 } 254 return p + k 255} 256func al_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 } 257func al_strcmp(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return (a[i] as i64) - (b[i] as i64) } i = i + 1 } return 0 - (b[i] as i64) } 258func al_starts(s: *u8, p: *u8) -> i64 { var i: i64 = 0; while p[i] != (0 as u8) { if s[i] != p[i] { return 0 } i = i + 1 } return 1 } 259func al_ends(s: *u8, sfx: *u8) -> i64 { 260 let n: i64 = al_slen(s) 261 let m: i64 = al_slen(sfx) 262 if n < m { return 0 } 263 var k: i64 = 0 264 while k < m { if s[n - m + k] != sfx[k] { return 0 } k = k + 1 } 265 return 1 266} 267// subject identifiers are lowercase [a-z0-9_]+, first byte not a digit -- they become part of a func name 268func al_ident_char(c: i64) -> i64 { 269 if c >= AL_LOWA { if c <= AL_LOWZ { return 1 } } 270 if c >= AL_D0 { if c <= AL_D9 { return 1 } } 271 if c == AL_USCORE { return 1 } 272 return 0 273} 274func al_ident_ok(s: *u8, so: i64, n: i64) -> i64 { 275 if n <= 0 { return 0 } 276 if n >= AL_W_NAME { return 0 } 277 let c0: i64 = s[so] as i64 278 if c0 >= AL_D0 { if c0 <= AL_D9 { return 0 } } 279 var i: i64 = 0 280 while i < n { if al_ident_char(s[so + i] as i64) == 0 { return 0 } i = i + 1 } 281 return 1 282} 283// copy a slice into a fixed-width record field, truncated to width-1 and NUL-terminated 284func al_setf(rec: *u8, off: i64, w: i64, src: *u8, so: i64, n: i64) -> i64 { 285 var m: i64 = n 286 if m > w - 1 { m = w - 1 } 287 var i: i64 = 0 288 while i < m { rec[off + i] = src[so + i]; i = i + 1 } 289 rec[off + m] = 0 as u8 290 return m 291} 292// strict decimal with optional leading minus over a slice; ok[0]=1 when parsed 293func al_parse_int(v: *u8, o: i64, l: i64, ok: *i64) -> i64 { 294 ok[0] = 0 295 if l <= 0 { return 0 } 296 var i: i64 = 0 297 var neg: i64 = 0 298 if (v[o] as i64) == AL_MINUS { neg = 1; i = 1 } 299 var val: i64 = 0 300 var digits: i64 = 0 301 while i < l { 302 let c: i64 = v[o + i] as i64 303 if c < AL_D0 { return 0 } 304 if c > AL_D9 { return 0 } 305 val = val * AL_BASE10 + (c - AL_D0) 306 digits = digits + 1 307 i = i + 1 308 } 309 if digits == 0 { return 0 } 310 ok[0] = 1 311 if neg == 1 { return 0 - val } 312 return val 313} 314// exact token membership in a comma-separated list 315func al_list_has(list: *u8, tok: *u8) -> i64 { 316 if (list as i64) == 0 { return 0 } 317 let tl: i64 = al_slen(tok) 318 if tl == 0 { return 0 } 319 var s: i64 = 0 320 var i: i64 = 0 321 var going: i64 = 1 322 while going == 1 { 323 var atend: i64 = 0 324 if list[i] == (0 as u8) { atend = 1 } else { if (list[i] as i64) == AL_COMMA { atend = 1 } } 325 if atend == 1 { 326 if i - s == tl { 327 var same: i64 = 1 328 var k: i64 = 0 329 while k < tl { if list[s + k] != tok[k] { same = 0; k = tl } else { k = k + 1 } } 330 if same == 1 { return 1 } 331 } 332 if list[i] == (0 as u8) { going = 0 } 333 s = i + 1 334 } 335 i = i + 1 336 } 337 return 0 338} 339// YYYY-MM-DD from epoch seconds (UTC), written NUL-terminated; returns the length 340func al_civil_date(epoch_s: i64, out: *u8) -> i64 { 341 var days: i64 = epoch_s / AL_SEC_PER_DAY 342 let z: i64 = days + AL_EPOCH_SHIFT_DAYS 343 var zz: i64 = z 344 if z < 0 { zz = z - AL_DAYS_400Y_LESS1 } 345 let era: i64 = zz / AL_DAYS_PER_ERA 346 let doe: i64 = z - era * AL_DAYS_PER_ERA 347 let yoe: i64 = (doe - doe / AL_DAYS_4Y + doe / AL_DAYS_100Y - doe / AL_DAYS_400Y_LESS1) / AL_DAYS_YEAR 348 var y: i64 = yoe + era * AL_YEARS_PER_ERA 349 let doy: i64 = doe - (AL_DAYS_YEAR * yoe + yoe / AL_LEAP_4 - yoe / AL_LEAP_100) 350 let mp: i64 = (AL_MP_MUL * doy + AL_MP_ADD) / AL_MP_DIV 351 let d: i64 = doy - (AL_MP_DIV * mp + AL_MP_ADD) / AL_MP_MUL + 1 352 var m: i64 = mp + AL_MONTH_ADD 353 if mp >= AL_MONTH_WRAP { m = mp - AL_MONTH_SUB } 354 if m <= AL_FEB { y = y + 1 } 355 var o: i64 = al_catn(out, 0, y) 356 out[o] = AL_MINUS as u8; o = o + 1 357 if m < AL_TWO_DIGITS { out[o] = AL_D0 as u8; o = o + 1 } 358 o = al_catn(out, o, m) 359 out[o] = AL_MINUS as u8; o = o + 1 360 if d < AL_TWO_DIGITS { out[o] = AL_D0 as u8; o = o + 1 } 361 o = al_catn(out, o, d) 362 out[o] = 0 as u8 363 return o 364} 365 366// ---- the BOOK: every subject the three planes mention, with its three signatures ------------------------- 367func al_bk_new() -> *i64 { 368 let bk: *i64 = sys_mmap(8 * AL_BK_WORDS) as *i64 369 var i: i64 = 0 370 while i < AL_BK_WORDS { bk[i] = 0; i = i + 1 } 371 bk[AL_B_INTS] = sys_mmap(8 * AL_IW * AL_MAX_SUBJ) as i64 372 bk[AL_B_STRS] = sys_mmap(AL_REC * AL_MAX_SUBJ) as i64 373 bk[AL_B_ACC_PATH] = sys_mmap(AL_PATHCAP) as i64 374 bk[AL_B_REF_PATH] = sys_mmap(AL_PATHCAP) as i64 375 bk[AL_B_ATT_PATH] = sys_mmap(AL_PATHCAP) as i64 376 return bk 377} 378func al_bk_rec(bk: *i64, i: i64) -> *u8 { return (bk[AL_B_STRS] + i * AL_REC) as *u8 } 379func al_bk_ints(bk: *i64, i: i64) -> *i64 { return (bk[AL_B_INTS] + i * AL_IW * 8) as *i64 } 380func al_bk_name(bk: *i64, i: i64) -> *u8 { return (bk[AL_B_STRS] + i * AL_REC + AL_F_NAME) as *u8 } 381func al_bk_find(bk: *i64, name: *u8, so: i64, n: i64) -> i64 { 382 var i: i64 = 0 383 while i < bk[AL_B_N] { 384 let nm: *u8 = al_bk_name(bk, i) 385 if cw_field_eq(name, so, n, nm) == 1 { return i } 386 i = i + 1 387 } 388 return 0 - 1 389} 390func al_bk_find_z(bk: *i64, z: *u8) -> i64 { return al_bk_find(bk, z, 0, al_slen(z)) } 391// find-or-add; -1 when the book is full (counted in AL_B_OVERFLOW, announced by every reader) 392func al_bk_get(bk: *i64, name: *u8, so: i64, n: i64) -> i64 { 393 let f: i64 = al_bk_find(bk, name, so, n) 394 if f >= 0 { return f } 395 if bk[AL_B_N] >= AL_MAX_SUBJ { bk[AL_B_OVERFLOW] = bk[AL_B_OVERFLOW] + 1; return 0 - 1 } 396 let i: i64 = bk[AL_B_N] 397 let it: *i64 = al_bk_ints(bk, i) 398 var k: i64 = 0 399 while k < AL_IW { it[k] = 0; k = k + 1 } 400 let rec: *u8 = al_bk_rec(bk, i) 401 var z: i64 = 0 402 while z < AL_REC { rec[z] = 0 as u8; z = z + 1 } 403 al_setf(rec, AL_F_NAME, AL_W_NAME, name, so, n) 404 bk[AL_B_N] = i + 1 405 return i 406} 407 408// every ga_accept_<ident> token inside a targets slice -> subject indices (find-or-add). A token counts only at a 409// boundary (slice start, ',', ':' or ' '), so a longer identifier sharing the prefix is not a match. 410func al_targets_subjects(bk: *i64, v: *u8, o: i64, l: i64, idx: *i64, cap: i64) -> i64 { 411 let pf: *u8 = AL_SYM_PFX 412 let pl: i64 = al_slen(pf) 413 var found: i64 = 0 414 var i: i64 = o 415 let e: i64 = o + l 416 while i + pl <= e { 417 var m: i64 = 1 418 var j: i64 = 0 419 while j < pl { if v[i + j] != pf[j] { m = 0; j = pl } else { j = j + 1 } } 420 var advanced: i64 = 0 421 if m == 1 { 422 var bd: i64 = 0 423 if i == o { bd = 1 } else { 424 let pc: i64 = v[i - 1] as i64 425 if pc == AL_COMMA { bd = 1 } 426 if pc == AL_COLON { bd = 1 } 427 if pc == AL_SPACE { bd = 1 } 428 } 429 if bd == 1 { 430 var k: i64 = i + pl 431 var run: i64 = 1 432 while run == 1 { if k < e { if al_ident_char(v[k] as i64) == 1 { k = k + 1 } else { run = 0 } } else { run = 0 } } 433 let nl: i64 = k - (i + pl) 434 if al_ident_ok(v, i + pl, nl) == 1 { 435 let si: i64 = al_bk_get(bk, v, i + pl, nl) 436 if si >= 0 { if found < cap { idx[found] = si; found = found + 1 } } 437 } else { bk[AL_B_BADNAME] = bk[AL_B_BADNAME] + 1 } 438 i = k 439 advanced = 1 440 } 441 } 442 if advanced == 0 { i = i + 1 } 443 } 444 return found 445} 446// does a NUL-terminated targets string already carry ga_accept_<subject> as a whole token? 447func al_has_token(targets: *u8, subject: *u8) -> i64 { 448 let bk: *i64 = al_bk_new() 449 let idx: *i64 = sys_mmap(8 * AL_MAX_TOK) as *i64 450 al_targets_subjects(bk, targets, 0, al_slen(targets), idx, AL_MAX_TOK) 451 if al_bk_find_z(bk, subject) >= 0 { return 1 } 452 return 0 453} 454 455// ---- plane resolution: a relative prefix from the caller's CWD first, then the estate root ------------------ 456// (the banked planepeek/census trap: a bare or mis-rooted prefix reads a populated plane as EMPTY). The 457// resolved prefix is copied into out either way; the return says whether ANY segment resolved there. 458func al_plane_resolve(rel: *u8, out: *u8) -> i64 { 459 let st: *i64 = ss_cur_open(rel) 460 var o: i64 = al_cat(out, 0, rel) 461 out[o] = 0 as u8 462 if st[1] > 0 { return 1 } 463 if (rel[0] as i64) != AL_SLASH { 464 o = al_cat(out, 0, EP_ROOT) 465 o = al_cat(out, o, rel) 466 out[o] = 0 as u8 467 let st2: *i64 = ss_cur_open(out) 468 if st2[1] > 0 { return 1 } 469 o = al_cat(out, 0, rel) 470 out[o] = 0 as u8 471 } 472 return 0 473} 474// advance the cursor to the next LIVE data record. q:n and foreign keys and tombstones are counted, never folded 475// into the rows. sc[0..3] = key ptr, key len, value ptr, value len. 476func al_next(bk: *i64, pfx: *u8, cur: *i64, sc: *i64) -> i64 { 477 var going: i64 = 1 478 while going == 1 { 479 let r: i64 = ss_cur_next(pfx, cur, sc, ((sc as i64) + 8) as *i64, ((sc as i64) + 16) as *i64, ((sc as i64) + 24) as *i64) 480 if r == 0 { return 0 } 481 let kidx: i64 = cw_key_idx(sc[0] as *u8, sc[1]) 482 if kidx == CW_KEY_FOREIGN { bk[AL_B_FOREIGN] = bk[AL_B_FOREIGN] + 1 } else { 483 if kidx != CW_KEY_COUNT { 484 if cur[6] == AL_KIND_TOMB { bk[AL_B_TOMB] = bk[AL_B_TOMB] + 1 } else { return 1 } 485 } 486 } 487 } 488 return 0 489} 490 491// ---- NEWEST-WINS ROW ITERATION (2026-08-31) --------------------------------------------------------------- 492// The raw cursor (al_next) visits EVERY RECORD IN EVERY SEGMENT, and a plane written by nx_store_put -- which 493// re-seeds the whole plane on every put -- carries one full copy of itself per write. MEASURED on the live 494// accept- plane the first time `nx_accept emit` ran: 5 operator rows read as 15 records (1+2+3+4+5), every 495// counter tripled and every UNMAPPED row printed once per surviving version. The verdicts were right only 496// because the newest copy happened to be visited last -- a correct answer standing on segment order, not on 497// a rule. sts_load_fit is the estate's canonical row reader (q:0..q:n-1, newest version per key, tombstoned 498// keys dropped): the same path nx_store_put itself takes on every write, so the counts below are counts of 499// ROWS, never of versions. al_next is kept for readers that need the raw record stream (foreign keys, 500// tombstones); the three walks and the verb-side helpers read rows through this pair. 501// ROW ORDER IS WRITE ORDER: nx_store_put removes a replaced id and appends the new row at the end, so the 502// last row seen for a subject is the latest write -- the date column is printed, never trusted for ordering. 503const AL_RS_WORDS: i64 = 4 504const AL_RS_BUF: i64 = 0 505const AL_RS_LEN: i64 = 1 506const AL_RS_POS: i64 = 2 507func al_rows_open(pfx: *u8) -> *i64 { 508 let rs: *i64 = sys_mmap(8 * AL_RS_WORDS) as *i64 509 let lp: *i64 = sys_mmap(16) as *i64 510 lp[0] = 0 511 let b: *u8 = sts_load_fit(pfx, lp) 512 rs[AL_RS_BUF] = b as i64 513 rs[AL_RS_LEN] = lp[0] 514 rs[AL_RS_POS] = 0 515 if (b as i64) == 0 { rs[AL_RS_LEN] = 0 } 516 return rs 517} 518// next non-empty row: sc[2] = value ptr, sc[3] = value len (the same slots the cursor walk filled) 519func al_rows_next(rs: *i64, sc: *i64) -> i64 { 520 let b: *u8 = rs[AL_RS_BUF] as *u8 521 let n: i64 = rs[AL_RS_LEN] 522 var p: i64 = rs[AL_RS_POS] 523 while p < n { 524 var e: i64 = p 525 while e < n { if (b[e] as i64) == AL_NL { break } e = e + 1 } 526 var el: i64 = e 527 if el > p { if (b[el - 1] as i64) == AL_CR { el = el - 1 } } 528 rs[AL_RS_POS] = e + 1 529 if el > p { 530 sc[2] = (b as i64) + p 531 sc[3] = el - p 532 return 1 533 } 534 p = e + 1 535 } 536 rs[AL_RS_POS] = n 537 return 0 538} 539 540func al_walk_accept(bk: *i64, pfx: *u8) -> i64 { 541 let cur: *i64 = al_rows_open(pfx) 542 if cur[AL_RS_LEN] <= 0 { return 0 } 543 bk[AL_B_ACC_PLANE] = 1 544 let sc: *i64 = sys_mmap(8 * AL_SC_WORDS) as *i64 545 let f: *i64 = sys_mmap(16) as *i64 546 let idx: *i64 = sys_mmap(8 * AL_MAX_TOK) as *i64 547 while al_rows_next(cur, sc) == 1 { 548 let v: *u8 = sc[2] as *u8 549 let vl: i64 = sc[3] 550 bk[AL_B_ACC_ROWS] = bk[AL_B_ACC_ROWS] + 1 551 if cw_field(v, vl, AL_AF_TARGETS, f) == 0 { bk[AL_B_MALFORMED] = bk[AL_B_MALFORMED] + 1 } else { 552 let nt: i64 = al_targets_subjects(bk, v, f[0], f[1], idx, AL_MAX_TOK) 553 if nt == 0 { bk[AL_B_UNMAPPED] = bk[AL_B_UNMAPPED] + 1 } else { 554 var vc: i64 = AL_V_INVALID 555 if cw_field(v, vl, AL_AF_VERDICT, f) == 1 { 556 if cw_field_eq(v, f[0], f[1], "ACCEPT" as *u8) == 1 { vc = AL_V_ACCEPT } 557 if cw_field_eq(v, f[0], f[1], "REJECT" as *u8) == 1 { vc = AL_V_REJECT } 558 if cw_field_eq(v, f[0], f[1], "UNJUDGED" as *u8) == 1 { vc = AL_V_UNJUDGED } 559 } 560 var isop: i64 = 0 561 if cw_field(v, vl, AL_AF_ACTOR, f) == 1 { if cw_field_eq(v, f[0], f[1], AL_ACTOR_OPERATOR) == 1 { isop = 1 } } 562 var t: i64 = 0 563 while t < nt { 564 let si: i64 = idx[t] 565 let it: *i64 = al_bk_ints(bk, si) 566 let rec: *u8 = al_bk_rec(bk, si) 567 it[AL_I_ANYV] = vc 568 if isop == 1 { 569 it[AL_I_OPV] = vc 570 it[AL_I_OPSEEN] = it[AL_I_OPSEEN] + 1 571 if cw_field(v, vl, AL_AF_ID, f) == 1 { al_setf(rec, AL_F_OPID, AL_W_OPID, v, f[0], f[1]) } 572 if cw_field(v, vl, AL_AF_DATE, f) == 1 { al_setf(rec, AL_F_OPDATE, AL_W_DATE, v, f[0], f[1]) } 573 if cw_field(v, vl, AL_AF_ACTOR, f) == 1 { al_setf(rec, AL_F_OPACTOR, AL_W_ACTOR, v, f[0], f[1]) } 574 } 575 t = t + 1 576 } 577 } 578 } 579 } 580 return 1 581} 582func al_walk_referee(bk: *i64, pfx: *u8) -> i64 { 583 let cur: *i64 = al_rows_open(pfx) 584 if cur[AL_RS_LEN] <= 0 { return 0 } 585 bk[AL_B_REF_PLANE] = 1 586 let sc: *i64 = sys_mmap(8 * AL_SC_WORDS) as *i64 587 let f: *i64 = sys_mmap(16) as *i64 588 let ok: *i64 = sys_mmap(16) as *i64 589 while al_rows_next(cur, sc) == 1 { 590 let v: *u8 = sc[2] as *u8 591 let vl: i64 = sc[3] 592 bk[AL_B_REF_ROWS] = bk[AL_B_REF_ROWS] + 1 593 if cw_field(v, vl, AL_RF_SEAT, f) == 0 { bk[AL_B_MALFORMED] = bk[AL_B_MALFORMED] + 1 } else { 594 cw_field(v, vl, AL_RF_SUBJECT, f) 595 if al_ident_ok(v, f[0], f[1]) == 0 { bk[AL_B_BADNAME] = bk[AL_B_BADNAME] + 1 } else { 596 let si: i64 = al_bk_get(bk, v, f[0], f[1]) 597 if si >= 0 { 598 let it: *i64 = al_bk_ints(bk, si) 599 let rec: *u8 = al_bk_rec(bk, si) 600 it[AL_I_RSEEN] = it[AL_I_RSEEN] + 1 601 var comp: i64 = AL_R_INVALID 602 if cw_field(v, vl, AL_RF_COMP, f) == 1 { 603 if cw_field_eq(v, f[0], f[1], "GOOD" as *u8) == 1 { comp = AL_R_GOOD } 604 if cw_field_eq(v, f[0], f[1], "BAD" as *u8) == 1 { comp = AL_R_BAD } 605 } 606 var p: i64 = 0 607 if cw_field(v, vl, AL_RF_PERCEPT, f) == 1 { p = al_parse_int(v, f[0], f[1], ok); if ok[0] == 0 { comp = AL_R_INVALID } } 608 it[AL_I_RCOMP] = comp 609 it[AL_I_RPERCEPT] = p 610 if cw_field(v, vl, AL_RF_TIER, f) == 1 { al_setf(rec, AL_F_RTIER, AL_W_TIER, v, f[0], f[1]) } 611 if cw_field(v, vl, AL_RF_SHA, f) == 1 { al_setf(rec, AL_F_RSHA, AL_W_SHA, v, f[0], f[1]) } 612 if cw_field(v, vl, AL_RF_SEAT, f) == 1 { al_setf(rec, AL_F_RSEAT, AL_W_SEAT, v, f[0], f[1]) } 613 if cw_field(v, vl, AL_RF_DATE, f) == 1 { al_setf(rec, AL_F_RDATE, AL_W_DATE, v, f[0], f[1]) } 614 } 615 } 616 } 617 } 618 return 1 619} 620func al_walk_attest(bk: *i64, pfx: *u8) -> i64 { 621 let cur: *i64 = al_rows_open(pfx) 622 if cur[AL_RS_LEN] <= 0 { return 0 } 623 bk[AL_B_ATT_PLANE] = 1 624 let sc: *i64 = sys_mmap(8 * AL_SC_WORDS) as *i64 625 let f: *i64 = sys_mmap(16) as *i64 626 while al_rows_next(cur, sc) == 1 { 627 let v: *u8 = sc[2] as *u8 628 let vl: i64 = sc[3] 629 bk[AL_B_ATT_ROWS] = bk[AL_B_ATT_ROWS] + 1 630 if cw_field(v, vl, AL_TF_DATE, f) == 0 { bk[AL_B_MALFORMED] = bk[AL_B_MALFORMED] + 1 } else { 631 cw_field(v, vl, AL_TF_SUBJECT, f) 632 if al_ident_ok(v, f[0], f[1]) == 0 { bk[AL_B_BADNAME] = bk[AL_B_BADNAME] + 1 } else { 633 let si: i64 = al_bk_get(bk, v, f[0], f[1]) 634 if si >= 0 { 635 let it: *i64 = al_bk_ints(bk, si) 636 let rec: *u8 = al_bk_rec(bk, si) 637 it[AL_I_ASEEN] = it[AL_I_ASEEN] + 1 638 var usable: i64 = 1 639 if cw_field(v, vl, AL_TF_SEAT, f) == 1 { if f[1] <= 0 { usable = 0 } al_setf(rec, AL_F_ASEAT, AL_W_SEAT, v, f[0], f[1]) } else { usable = 0 } 640 if cw_field(v, vl, AL_TF_STAMP, f) == 1 { if f[1] <= 0 { usable = 0 } al_setf(rec, AL_F_ASTAMP, AL_W_STAMP, v, f[0], f[1]) } else { usable = 0 } 641 if cw_field(v, vl, AL_TF_DATE, f) == 1 { al_setf(rec, AL_F_ADATE, AL_W_DATE, v, f[0], f[1]) } 642 it[AL_I_ATT] = usable 643 } 644 } 645 } 646 } 647 return 1 648} 649// load all three planes (each resolved CWD-first, then estate root). Returns the number of planes that resolved. 650func al_load(bk: *i64, pfx_acc: *u8, pfx_ref: *u8, pfx_att: *u8) -> i64 { 651 var n: i64 = 0 652 n = n + al_plane_resolve(pfx_acc, bk[AL_B_ACC_PATH] as *u8) 653 n = n + al_plane_resolve(pfx_ref, bk[AL_B_REF_PATH] as *u8) 654 n = n + al_plane_resolve(pfx_att, bk[AL_B_ATT_PATH] as *u8) 655 al_walk_accept(bk, bk[AL_B_ACC_PATH] as *u8) 656 al_walk_referee(bk, bk[AL_B_REF_PATH] as *u8) 657 al_walk_attest(bk, bk[AL_B_ATT_PATH] as *u8) 658 return n 659} 660 661// ---- the panel conf + its admission receipt: the ONLY source of the GOOD floor ----------------------------- 662func al_conf_load(conf_rel: *u8) -> *i64 { 663 let cf: *i64 = sys_mmap(8 * AL_CF_WORDS) as *i64 664 var i: i64 = 0 665 while i < AL_CF_WORDS { cf[i] = 0; i = i + 1 } 666 let path: *u8 = sys_mmap(AL_PATHCAP) 667 path[0] = 0 as u8 668 cf[AL_C_PATH] = path as i64 669 let rpath: *u8 = sys_mmap(AL_PATHCAP) 670 rpath[0] = 0 as u8 671 cf[AL_C_RPATH] = rpath as i64 672 let ta: *u8 = sys_mmap(AL_LISTCAP) 673 ta[0] = 0 as u8 674 cf[AL_C_TADM] = ta as i64 675 let tl: *u8 = sys_mmap(AL_LISTCAP) 676 tl[0] = 0 as u8 677 cf[AL_C_TIERS] = tl as i64 678 if ep_artifact_path(path, conf_rel) == 0 { return cf } 679 let ln: *i64 = sys_mmap(16) as *i64 680 let b: *u8 = sys_read_file(path, ln) 681 if (b as i64) == 0 { return cf } 682 cf[AL_C_BUF] = b as i64 683 cf[AL_C_LEN] = ln[0] 684 cf[AL_C_CONF_OK] = 1 685 let rrel: *u8 = sys_mmap(AL_PATHCAP) 686 if lcf_str(b, ln[0], AL_KEY_RECEIPT, rrel, AL_PATHCAP) <= 0 { return cf } 687 if ep_artifact_path(rpath, rrel) == 0 { return cf } 688 let rl: *i64 = sys_mmap(16) as *i64 689 let rb: *u8 = sys_read_file(rpath, rl) 690 if (rb as i64) == 0 { return cf } 691 cf[AL_C_RCPT_OK] = 1 692 let adm: i64 = lcf_int(rb, rl[0], AL_KEY_ADMITTED) 693 if adm == LCF_MISS { cf[AL_C_ADMITTED] = 0 } else { cf[AL_C_ADMITTED] = adm } 694 lcf_str(rb, rl[0], AL_KEY_TIERS_ADMITTED, ta, AL_LISTCAP) 695 lcf_str(rb, rl[0], AL_KEY_TIERS, tl, AL_LISTCAP) 696 return cf 697} 698// floor_percept_<tier> from the conf; LCF_MISS when the conf is unreadable or the tier has no admitted floor 699func al_floor_for_tier(cf: *i64, tier: *u8) -> i64 { 700 if cf[AL_C_CONF_OK] == 0 { return LCF_MISS } 701 if al_slen(tier) == 0 { return LCF_MISS } 702 let key: *u8 = sys_mmap(AL_KEYCAP) 703 var o: i64 = al_cat(key, 0, AL_KEY_FLOOR_PFX) 704 o = al_cat(key, o, tier) 705 key[o] = 0 as u8 706 return lcf_int(cf[AL_C_BUF] as *u8, cf[AL_C_LEN], key) 707} 708// the referee signature for subject si: AL_RC_OK or the FIRST reason it does not hold (floor_out = the bar used) 709func al_ref_check(bk: *i64, cf: *i64, si: i64, floor_out: *i64) -> i64 { 710 floor_out[0] = LCF_MISS 711 let it: *i64 = al_bk_ints(bk, si) 712 let rec: *u8 = al_bk_rec(bk, si) 713 if it[AL_I_RSEEN] == 0 { return AL_RC_MISSING } 714 if it[AL_I_RCOMP] == AL_R_INVALID { return AL_RC_INVALID } 715 if it[AL_I_RCOMP] == AL_R_NONE { return AL_RC_INVALID } 716 if it[AL_I_RCOMP] == AL_R_BAD { return AL_RC_BAD } 717 if cf[AL_C_ADMITTED] != 1 { return AL_RC_PANEL_UNADMITTED } 718 let tier: *u8 = ((rec as i64) + AL_F_RTIER) as *u8 719 if al_list_has(cf[AL_C_TADM] as *u8, tier) == 0 { return AL_RC_TIER_UNADMITTED } 720 let fl: i64 = al_floor_for_tier(cf, tier) 721 if fl == LCF_MISS { return AL_RC_NO_FLOOR } 722 floor_out[0] = fl 723 if it[AL_I_RPERCEPT] < fl { return AL_RC_BELOW_FLOOR } 724 return AL_RC_OK 725} 726// the derived state; why[] carries the three verdict codes and the floor so a caller can NAME what is missing 727func al_state(bk: *i64, cf: *i64, si: i64, why: *i64) -> i64 { 728 let it: *i64 = al_bk_ints(bk, si) 729 let fo: *i64 = sys_mmap(16) as *i64 730 why[AL_WHY_OP] = it[AL_I_OPV] 731 why[AL_WHY_REF] = al_ref_check(bk, cf, si, fo) 732 why[AL_WHY_ATT] = it[AL_I_ATT] 733 why[AL_WHY_FLOOR] = fo[0] 734 if why[AL_WHY_OP] == AL_V_ACCEPT { if why[AL_WHY_REF] == AL_RC_OK { if why[AL_WHY_ATT] == 1 { return AL_ST_ACCEPTED } } } 735 return AL_ST_INCOMPLETE 736} 737func al_vname(c: i64) -> *u8 { 738 if c == AL_V_ACCEPT { return "ACCEPT" as *u8 } 739 if c == AL_V_REJECT { return "REJECT" as *u8 } 740 if c == AL_V_UNJUDGED { return "UNJUDGED" as *u8 } 741 if c == AL_V_INVALID { return "INVALID" as *u8 } 742 return "NONE" as *u8 743} 744func al_rname(c: i64) -> *u8 { 745 if c == AL_R_GOOD { return "GOOD" as *u8 } 746 if c == AL_R_BAD { return "BAD" as *u8 } 747 if c == AL_R_INVALID { return "INVALID" as *u8 } 748 return "NONE" as *u8 749} 750func al_rcname(c: i64) -> *u8 { 751 if c == AL_RC_OK { return "OK" as *u8 } 752 if c == AL_RC_MISSING { return "REF-MISSING" as *u8 } 753 if c == AL_RC_BAD { return "REF-BAD" as *u8 } 754 if c == AL_RC_INVALID { return "REF-INVALID-ROW" as *u8 } 755 if c == AL_RC_TIER_UNADMITTED { return "REF-TIER-UNADMITTED" as *u8 } 756 if c == AL_RC_NO_FLOOR { return "REF-NO-FLOOR-FOR-TIER" as *u8 } 757 if c == AL_RC_BELOW_FLOOR { return "REF-PERCEPT-BELOW-FLOOR" as *u8 } 758 return "REF-PANEL-UNADMITTED" as *u8 759} 760func al_stname(c: i64) -> *u8 { 761 if c == AL_ST_ACCEPTED { return "ACCEPTED" as *u8 } 762 if c == AL_ST_INCOMPLETE { return "INCOMPLETE" as *u8 } 763 return "UNKNOWN" as *u8 764} 765 766// ---- the generated declaration file, DERIVED and DETERMINISTIC --------------------------------------------- 767// Deliberately no timestamp: two emits over the same planes must be byte-identical, which is what lets the gate 768// convict a hand edit by re-derivation. Accepted subjects are emitted in NAME order, not plane order, so a plane 769// rewrite that reorders rows cannot move the bytes either. 770func al_emit_buf(bk: *i64, cf: *i64, out: *u8, cap: i64) -> i64 { 771 var o: i64 = 0 772 o = al_cat(out, o, "// nx_accept_decl.nx -- GENERATED ACCEPTANCE DECLARATIONS. <" as *u8) 773 out[o] = AL_BANG as u8 774 o = o + 1 775 o = al_cat(out, o, "-- NX-DERIVED: regenerated artefact, not authored memory -->\n" as *u8) 776 o = al_cat(out, o, "// WRITTEN ONLY BY `nx_accept emit` from knowledge/store/accept- + referee- + attest- and the panel floors in\n" as *u8) 777 o = al_cat(out, o, "// knowledge/cjc_panel.conf (per-tier floor_percept_<tier>; receipt admitted + tiers_admitted). One top-level\n" as *u8) 778 o = al_cat(out, o, "// declaration ga_accept_<subject> exists here iff the THREE-PARTY RULE holds for <subject>: latest operator row\n" as *u8) 779 o = al_cat(out, o, "// ACCEPT AND latest referee row GOOD at or above the admitted per-tier floor AND a seat attestation row. Nothing\n" as *u8) 780 o = al_cat(out, o, "// else is declared. The /compare regen measures this file like any organ (column-0 declaration), so an ACCEPTANCE\n" as *u8) 781 o = al_cat(out, o, "// watch row flips ONLY on agreement. A hand-written declaration is convicted by nx_accept_gate (re-derivation must\n" as *u8) 782 o = al_cat(out, o, "// equal these bytes) and erased by the next emit. Do not edit; run `nx_accept emit`.\n" as *u8) 783 let ord: *i64 = sys_mmap(8 * AL_MAX_SUBJ) as *i64 784 let why: *i64 = sys_mmap(8 * 8) as *i64 785 var na: i64 = 0 786 var i: i64 = 0 787 while i < bk[AL_B_N] { 788 if al_state(bk, cf, i, why) == AL_ST_ACCEPTED { ord[na] = i; na = na + 1 } 789 i = i + 1 790 } 791 // selection sort by subject name 792 var a: i64 = 0 793 while a < na { 794 var best: i64 = a 795 var b2: i64 = a + 1 796 while b2 < na { 797 if al_strcmp(al_bk_name(bk, ord[b2]), al_bk_name(bk, ord[best])) < 0 { best = b2 } 798 b2 = b2 + 1 799 } 800 if best != a { let t: i64 = ord[a]; ord[a] = ord[best]; ord[best] = t } 801 a = a + 1 802 } 803 if na == 0 { o = al_cat(out, o, "// (no subject currently satisfies the three-party rule -- no declarations emitted)\n" as *u8) } 804 var k: i64 = 0 805 while k < na { 806 if o + AL_LINE_MAX >= cap { return 0 - 1 } 807 let si: i64 = ord[k] 808 let rec: *u8 = al_bk_rec(bk, si) 809 let it: *i64 = al_bk_ints(bk, si) 810 al_state(bk, cf, si, why) 811 o = al_cat(out, o, "// ACCEPTED " as *u8) 812 o = al_cat(out, o, al_bk_name(bk, si)) 813 o = al_cat(out, o, ": operator=" as *u8) 814 o = al_cat(out, o, ((rec as i64) + AL_F_OPID) as *u8) 815 o = al_cat(out, o, " (" as *u8) 816 o = al_cat(out, o, ((rec as i64) + AL_F_OPDATE) as *u8) 817 o = al_cat(out, o, ") referee=frame:" as *u8) 818 o = al_cat(out, o, ((rec as i64) + AL_F_RSHA) as *u8) 819 o = al_cat(out, o, " percept=" as *u8) 820 o = al_catn(out, o, it[AL_I_RPERCEPT]) 821 o = al_cat(out, o, " floor=" as *u8) 822 o = al_catn(out, o, why[AL_WHY_FLOOR]) 823 o = al_cat(out, o, " tier=" as *u8) 824 o = al_cat(out, o, ((rec as i64) + AL_F_RTIER) as *u8) 825 o = al_cat(out, o, " by=" as *u8) 826 o = al_cat(out, o, ((rec as i64) + AL_F_RSEAT) as *u8) 827 o = al_cat(out, o, " (" as *u8) 828 o = al_cat(out, o, ((rec as i64) + AL_F_RDATE) as *u8) 829 o = al_cat(out, o, ") attest=" as *u8) 830 o = al_cat(out, o, ((rec as i64) + AL_F_ASEAT) as *u8) 831 o = al_cat(out, o, " stamp=" as *u8) 832 o = al_cat(out, o, ((rec as i64) + AL_F_ASTAMP) as *u8) 833 o = al_cat(out, o, " (" as *u8) 834 o = al_cat(out, o, ((rec as i64) + AL_F_ADATE) as *u8) 835 o = al_cat(out, o, ")\n" as *u8) 836 o = al_cat(out, o, "func " as *u8) 837 o = al_cat(out, o, AL_SYM_PFX) 838 o = al_cat(out, o, al_bk_name(bk, si)) 839 o = al_cat(out, o, "() -> i64 { return 1 }\n" as *u8) 840 k = k + 1 841 } 842 out[o] = 0 as u8 843 return o 844} 845// how many ACCEPTED subjects the book holds under this conf 846func al_count_accepted(bk: *i64, cf: *i64) -> i64 { 847 let why: *i64 = sys_mmap(8 * 8) as *i64 848 var n: i64 = 0 849 var i: i64 = 0 850 while i < bk[AL_B_N] { if al_state(bk, cf, i, why) == AL_ST_ACCEPTED { n = n + 1 } i = i + 1 } 851 return n 852} 853// compare the on-disk declaration file with a fresh derivation: IDENTICAL / DIFFERS / ABSENT / CAP 854func al_decl_verify(bk: *i64, cf: *i64, path: *u8) -> i64 { 855 let want: *u8 = sys_mmap(AL_DECL_CAP) 856 let wn: i64 = al_emit_buf(bk, cf, want, AL_DECL_CAP) 857 if wn < 0 { return AL_DV_CAP } 858 let ln: *i64 = sys_mmap(16) as *i64 859 let b: *u8 = sys_read_file(path, ln) 860 if (b as i64) == 0 { return AL_DV_ABSENT } 861 if ln[0] != wn { return AL_DV_DIFFERS } 862 var i: i64 = 0 863 while i < wn { if b[i] != want[i] { return AL_DV_DIFFERS } i = i + 1 } 864 return AL_DV_IDENTICAL 865} 866func al_dvname(c: i64) -> *u8 { 867 if c == AL_DV_IDENTICAL { return "IDENTICAL" as *u8 } 868 if c == AL_DV_DIFFERS { return "DIFFERS" as *u8 } 869 if c == AL_DV_ABSENT { return "ABSENT" as *u8 } 870 return "CAP-EXCEEDED" as *u8 871} 872// tmp + fsync + rename: the file is either the old bytes or the new bytes, never a prefix 873func al_write_atomic(path: *u8, buf: *u8, n: i64) -> i64 { 874 let tmp: *u8 = sys_mmap(AL_PATHCAP) 875 var o: i64 = al_cat(tmp, 0, path) 876 o = al_cat(tmp, o, AL_TMP_SFX) 877 tmp[o] = 0 as u8 878 let fd: i64 = sys_openat_wr(tmp, MODE_0644) 879 if fd < 0 { return 0 - 1 } 880 var off: i64 = 0 881 while off < n { 882 let r: i64 = sys_write(fd, ((buf as i64) + off) as *u8, n - off) 883 if r <= 0 { sys_close(fd); return 0 - 2 } 884 off = off + r 885 } 886 sys_fsync(fd) 887 sys_close(fd) 888 if sys_renameat(tmp, path) != 0 { return 0 - 3 } 889 return 0 890} 891// count column-0 `func ga_accept_` declarations in a buffer -- the regen's own rule, used as a denominator 892func al_count_decls(b: *u8, n: i64) -> i64 { 893 let pf: *u8 = sys_mmap(AL_KEYCAP) 894 var o: i64 = al_cat(pf, 0, "func " as *u8) 895 o = al_cat(pf, o, AL_SYM_PFX) 896 pf[o] = 0 as u8 897 let pl: i64 = o 898 var cnt: i64 = 0 899 var i: i64 = 0 900 while i + pl <= n { 901 var bol: i64 = 0 902 if i == 0 { bol = 1 } else { if (b[i - 1] as i64) == AL_NL { bol = 1 } } 903 if bol == 1 { 904 var m: i64 = 1 905 var j: i64 = 0 906 while j < pl { if b[i + j] != pf[j] { m = 0; j = pl } else { j = j + 1 } } 907 if m == 1 { cnt = cnt + 1 } 908 } 909 i = i + 1 910 } 911 return cnt 912} 913// where the declaration file lives: beside this lib, resolved CWD-independently through the sibling that MUST 914// exist (a probe for the decl file itself would fail before the first emit) 915func al_decl_path(out: *u8) -> i64 { 916 if ep_artifact_path(out, AL_DECL_SIBLING) == 0 { out[0] = 0 as u8; return 0 } 917 var n: i64 = al_slen(out) 918 let sib: i64 = al_slen("nx_accept_lib.nx" as *u8) 919 n = n - sib 920 let o: i64 = al_cat(out, n, AL_DECL_BASENAME) 921 out[o] = 0 as u8 922 return 1 923} 924// the boards directory, CWD-first then the buildroot tree 925func al_boards_dir(out: *u8) -> i64 { 926 var fd: i64 = sys_openat_rd(AL_BOARDS_DIR) 927 if fd >= 0 { sys_close(fd); al_cat(out, 0, AL_BOARDS_DIR); out[al_slen(AL_BOARDS_DIR)] = 0 as u8; return 1 } 928 var o: i64 = al_cat(out, 0, EP_BUILDROOT) 929 o = al_cat(out, o, AL_BOARDS_DIR_FROM_BUILDROOT) 930 out[o] = 0 as u8 931 fd = sys_openat_rd(out) 932 if fd >= 0 { sys_close(fd); return 1 } 933 out[0] = 0 as u8 934 return 0 935} 936// one board: every row whose symbol (watch or landed form) is ga_accept_<ident> -> (subject, domain, organ) 937func al_scan_one_board(dir: *u8, nm: *u8, subj: *u8, doms: *u8, orgs: *u8, cap: i64, count0: i64, over: *i64) -> i64 { 938 var count: i64 = count0 939 let path: *u8 = sys_mmap(AL_PATHCAP) 940 var o: i64 = al_cat(path, 0, dir) 941 path[o] = AL_SLASH as u8 942 o = o + 1 943 o = al_cat(path, o, nm) 944 path[o] = 0 as u8 945 let ln: *i64 = sys_mmap(16) as *i64 946 let b: *u8 = sys_read_file(path, ln) 947 if (b as i64) == 0 { return count } 948 let n: i64 = ln[0] 949 let pf: *u8 = AL_SYM_PFX 950 let pl: i64 = al_slen(pf) 951 let wl: i64 = al_slen(AL_WATCH_PFX) 952 let doml: i64 = al_slen(nm) - al_slen(AL_MATRIX_SFX) 953 var p: i64 = 0 954 while p < n { 955 var e: i64 = p 956 while e < n { if (b[e] as i64) == AL_NL { break } e = e + 1 } 957 var skip: i64 = 0 958 if e == p { skip = 1 } else { 959 let c0: i64 = b[p] as i64 960 if c0 == AL_HASH { skip = 1 } 961 if c0 == AL_AT { skip = 1 } 962 } 963 if skip == 0 { 964 // pipes 1..3 bound organ (field 1) and symbol (field 2) 965 var p1: i64 = 0 - 1 966 var p2: i64 = 0 - 1 967 var p3: i64 = e 968 var q: i64 = p 969 var np: i64 = 0 970 while q < e { 971 if (b[q] as i64) == AL_PIPE { 972 np = np + 1 973 if np == 1 { p1 = q } 974 if np == 2 { p2 = q } 975 if np == 3 { p3 = q; q = e } 976 } 977 q = q + 1 978 } 979 if p2 >= 0 { 980 var ss: i64 = p2 + 1 981 var se: i64 = p3 982 if se - ss > wl { 983 var isw: i64 = 1 984 var w: i64 = 0 985 while w < wl { if b[ss + w] != AL_WATCH_PFX[w] { isw = 0; w = wl } else { w = w + 1 } } 986 if isw == 1 { ss = ss + wl } 987 } 988 if se - ss > pl { 989 var m: i64 = 1 990 var j: i64 = 0 991 while j < pl { if b[ss + j] != pf[j] { m = 0; j = pl } else { j = j + 1 } } 992 if m == 1 { 993 if al_ident_ok(b, ss + pl, se - ss - pl) == 1 { 994 if count < cap { 995 al_setf(subj, count * AL_NAMEW, AL_NAMEW, b, ss + pl, se - ss - pl) 996 al_setf(doms, count * AL_NAMEW, AL_NAMEW, nm, 0, doml) 997 al_setf(orgs, count * AL_ORGW, AL_ORGW, b, p1 + 1, p2 - p1 - 1) 998 count = count + 1 999 } else { over[0] = over[0] + 1 } 1000 } 1001 } 1002 } 1003 } 1004 } 1005 p = e + 1 1006 } 1007 return count 1008} 1009// every ACCEPTANCE watch/landed row across all *.matrix boards in dir. -1 when dir is unreadable. 1010func al_scan_boards(dir: *u8, subj: *u8, doms: *u8, orgs: *u8, cap: i64, over: *i64) -> i64 { 1011 over[0] = 0 1012 let fd: i64 = sys_openat_rd(dir) 1013 if fd < 0 { return 0 - 1 } 1014 let db: *u8 = sys_mmap(AL_DENTCAP) 1015 var count: i64 = 0 1016 var more: i64 = 1 1017 while more == 1 { 1018 let n: i64 = sys_getdents64(fd, db, AL_DENTCAP) 1019 if n <= 0 { more = 0 } else { 1020 var off: i64 = 0 1021 while off < n { 1022 let rec: *u8 = ((db as i64) + off) as *u8 1023 let rl: i64 = dirent_reclen(rec) 1024 let nm: *u8 = dirent_name(rec) 1025 if al_ends(nm, AL_MATRIX_SFX) == 1 { count = al_scan_one_board(dir, nm, subj, doms, orgs, cap, count, over) } 1026 if rl <= 0 { off = n } else { off = off + rl } 1027 } 1028 } 1029 } 1030 sys_close(fd) 1031 return count 1032}