code wiki / (root) / nx_release_delta_lib.nx

nx_release_delta_lib.nx source

↩ module page · 412 lines · 20851 B

1// nx_release_delta_lib.nx -- THE RELEASE DELTA: what changed on the boards since the operator last judged (2026-09-04). 2// 3// WHY. /world/beach carried a build stamp and nothing about what that build changed. The operator's acceptance 4// plane (knowledge/store/accept-) held four REJECT rows and one UNJUDGED from 2026-08-30 and nothing after, while 5// every seat since shipped plumbing, telemetry, backends and gates -- progress the review page could not show, so 6// "the review page has not moved" was true of the PAGE even where it was false of the WORK. Operator 2026-09-04: 7// consistent progress each release on the review page. This lib is the pure arithmetic under gpe_release_block: 8// given the accept-plane rows, the referee-plane rows and a board's log rows, it derives (1) the latest operator 9// verdict per subject and the date of the newest one, (2) every `land` row dated strictly AFTER that date, (3) the 10// referee percept beside each subject, and (4) the exact accept-row recipe for THIS build, and renders them as one 11// HTML block. It reads NO files and forks NOTHING: the emitter hands it buffers, the gate hands it fixtures, and 12// the same bytes are judged either way. 13// LAW. THE FLIP IS THE RECEIPT, THE ACCEPT ROW IS THE PROOF. A land row here is a seat's claim that something 14// shipped; only an operator ACCEPT row moves a subject out of INCOMPLETE, and this block prints the row to file. 15// ROW ORDER IS WRITE ORDER (nx_accept_lib's law): the last operator row per subject wins; dates are printed, and 16// the since-date is the GREATEST date over operator rows, never the last row's. Two bounds, both ANNOUNCED in the 17// block: RD_LIST_CAP land rows listed (the rest counted), RD_TEXT_CAP bytes of a row's text (the board keeps all). 18// license_tier: ORIGINAL No hw writes (Rule 26). 19import "nx_syscalls.nx" 20import "nx_comparewatch_lib.nx" 21import "nx_accept_lib.nx" 22 23const RD_NL: i64 = 10 24const RD_CR: i64 = 13 25const RD_TAB: i64 = 9 26const RD_PIPE: i64 = 124 27const RD_SPACE: i64 = 32 28const RD_AMP: i64 = 38 29const RD_HASH: i64 = 35 30const RD_SEMI: i64 = 59 31const RD_LT: i64 = 60 32const RD_GT: i64 = 62 33const RD_DQ: i64 = 34 34const RD_SQ: i64 = 39 35const RD_BSL: i64 = 92 36const RD_D0: i64 = 48 37const RD_D9: i64 = 57 38const RD_BYTE: i64 = 255 39const RD_CTRL_MAX: i64 = 31 // bytes at or below this are control characters: rendered as one space 40const RD_BASE10: i64 = 10 41const RD_DATE_W: i64 = 10 // YYYY-MM-DD 42const RD_LOG_PFX: *u8 = "log|" 43const RD_LOG_PFX_LEN: i64 = 4 44const RD_KIND_LAND: *u8 = "land" 45const RD_KIND_RETRACT: *u8 = "retract" 46const RD_KIND_MEASURE: *u8 = "measure" 47const RD_ACTOR_OPERATOR: *u8 = "operator" 48const RD_V_ACCEPT: *u8 = "ACCEPT" 49// accept- row fields (the nx_accept_lib grammar: id subject verdict date actor words targets) 50const RD_AF_ID: i64 = 0 51const RD_AF_SUBJ: i64 = 1 52const RD_AF_VERD: i64 = 2 53const RD_AF_DATE: i64 = 3 54const RD_AF_ACTOR: i64 = 4 55const RD_AF_WORDS: i64 = 5 56// referee- row fields (id subject sha comp percept tier date seat lens frame) 57const RD_RF_SUBJ: i64 = 1 58const RD_RF_PERCEPT: i64 = 4 59const RD_RF_TIER: i64 = 5 60const RD_RF_DATE: i64 = 6 61// the subject table: fixed-width records so every field is addressable by offset from the gate 62const RD_MAX_SUBJ: i64 = 32 63const RD_REC: i64 = 512 64const RD_F_SUBJ: i64 = 0 65const RD_W_SUBJ: i64 = 64 66const RD_F_VERD: i64 = 64 67const RD_W_VERD: i64 = 16 68const RD_F_DATE: i64 = 80 69const RD_W_DATE: i64 = 16 70const RD_F_ID: i64 = 96 71const RD_W_ID: i64 = 96 72const RD_F_WORDS: i64 = 192 73const RD_W_WORDS: i64 = 160 74const RD_F_RPCT: i64 = 352 75const RD_W_RPCT: i64 = 16 76const RD_F_RDATE: i64 = 368 77const RD_W_RDATE: i64 = 16 78const RD_F_RTIER: i64 = 384 79const RD_W_RTIER: i64 = 16 80const RD_F_RSEEN: i64 = 400 81const RD_F_OPSEEN: i64 = 401 82// listing bounds, both ANNOUNCED by the emitted block 83const RD_LIST_CAP: i64 = 24 84const RD_TEXT_CAP: i64 = 240 85const RD_ENT_MAX: i64 = 6 // the longest entity rd_esc_html emits per input byte 86const RD_ITEM_RESERVE: i64 = 2048 // static bytes one list item or table row can add beside its escaped text 87const RD_COUNTS: i64 = 4 88const RD_C_LAND: i64 = 0 89const RD_C_RETRACT: i64 = 1 90const RD_C_MEASURE: i64 = 2 91const RD_C_LISTED: i64 = 3 92 93func rd_rec(tab: *u8, i: i64) -> *u8 { return ((tab as i64) + i * RD_REC) as *u8 } 94func rd_str(rec: *u8, off: i64) -> *u8 { return ((rec as i64) + off) as *u8 } 95func rd_rec_zero(rec: *u8) -> i64 { var i: i64 = 0; while i < RD_REC { rec[i] = 0 as u8; i = i + 1 } return 0 } 96func rd_byte(b: *u8, i: i64) -> i64 { return (b[i] as i64) & RD_BYTE } 97// compare a[ao..ao+an) against the NUL-terminated b: negative, zero or positive like strcmp 98func rd_cmp_slice(a: *u8, ao: i64, an: i64, b: *u8) -> i64 { 99 var i: i64 = 0 100 while i < an { 101 let bc: i64 = rd_byte(b, i) 102 if bc == 0 { return 1 } 103 let ac: i64 = rd_byte(a, ao + i) 104 if ac != bc { return ac - bc } 105 i = i + 1 106 } 107 if rd_byte(b, an) != 0 { return 0 - 1 } 108 return 0 109} 110func rd_slice_eq(a: *u8, ao: i64, an: i64, b: *u8) -> i64 { if rd_cmp_slice(a, ao, an, b) == 0 { return 1 } return 0 } 111func rd_find_subj(tab: *u8, ns: i64, v: *u8, so: i64, n: i64) -> i64 { 112 var i: i64 = 0 113 while i < ns { 114 if rd_slice_eq(v, so, n, rd_str(rd_rec(tab, i), RD_F_SUBJ)) == 1 { return i } 115 i = i + 1 116 } 117 return 0 - 1 118} 119func rd_find_subj_z(tab: *u8, ns: i64, z: *u8) -> i64 { return rd_find_subj(tab, ns, z, 0, al_slen(z)) } 120func rd_line_end(b: *u8, n: i64, p: i64) -> i64 { 121 var e: i64 = p 122 while e < n { if rd_byte(b, e) == RD_NL { return e } e = e + 1 } 123 return n 124} 125// a new subject record, or -1 when the table is full (the caller announces a full table; it never drops silently) 126func rd_subj_add(tab: *u8, ns: i64, v: *u8, so: i64, n: i64) -> i64 { 127 if ns >= RD_MAX_SUBJ { return 0 - 1 } 128 let rec: *u8 = rd_rec(tab, ns) 129 rd_rec_zero(rec) 130 al_setf(rec, RD_F_SUBJ, RD_W_SUBJ, v, so, n) 131 return ns 132} 133 134// THE SUBJECT KEY IS THE ACCEPT LIB'S OWN RULE: the ga_accept_<name> token in the targets field names the subject 135// (garments, hair, skin, locomotion, face); field 1 is the operator's DESCRIPTION of what was judged. MEASURED on the 136// first served release (2026-09-04): keying on field 1 left every operator row unjoined to its referee row -- ten 137// table rows where five subjects exist, with `unjudged` beside every REJECT. A row with no such token keys on its 138// description, so nothing is dropped; the description is kept beside the key for the reader. 139const RD_AF_TARGETS: i64 = 6 140const RD_SYM_PFX: *u8 = "ga_accept_" 141const RD_SYM_PFX_LEN: i64 = 10 142const RD_COMMA: i64 = 44 143const RD_F_DESC: i64 = 408 144const RD_W_DESC: i64 = 104 145func rd_subject_of(v: *u8, vl: i64, f: *i64) -> i64 { 146 let g: *i64 = sys_mmap(16) as *i64 147 if cw_field(v, vl, RD_AF_TARGETS, g) == 1 { 148 var i: i64 = g[0] 149 let e: i64 = g[0] + g[1] 150 while i + RD_SYM_PFX_LEN <= e { 151 if rd_slice_eq(v, i, RD_SYM_PFX_LEN, RD_SYM_PFX) == 1 { 152 let s: i64 = i + RD_SYM_PFX_LEN 153 var k: i64 = s 154 while k < e { 155 let c: i64 = rd_byte(v, k) 156 if c == RD_COMMA { break } 157 if c == RD_SPACE { break } 158 k = k + 1 159 } 160 if k > s { f[0] = s; f[1] = k - s; return 1 } 161 } 162 i = i + 1 163 } 164 } 165 return cw_field(v, vl, RD_AF_SUBJ, f) 166} 167 168// (1) the operator's latest verdict per subject. Returns the subject count; since_out receives the greatest 169// date over all operator rows and stays empty when there is none -- NEVER JUDGED is a state the block prints. 170func rd_op_latest(rows: *u8, n: i64, tab: *u8, since_out: *u8) -> i64 { 171 since_out[0] = 0 as u8 172 var ns: i64 = 0 173 let f: *i64 = sys_mmap(16) as *i64 174 var p: i64 = 0 175 while p < n { 176 let e: i64 = rd_line_end(rows, n, p) 177 var el: i64 = e 178 if el > p { if rd_byte(rows, el - 1) == RD_CR { el = el - 1 } } 179 let vl: i64 = el - p 180 if vl > 0 { 181 let v: *u8 = ((rows as i64) + p) as *u8 182 var isop: i64 = 0 183 if cw_field(v, vl, RD_AF_ACTOR, f) == 1 { if cw_field_eq(v, f[0], f[1], RD_ACTOR_OPERATOR) == 1 { isop = 1 } } 184 if isop == 1 { if rd_subject_of(v, vl, f) == 1 { if f[1] > 0 { 185 var si: i64 = rd_find_subj(tab, ns, v, f[0], f[1]) 186 if si < 0 { si = rd_subj_add(tab, ns, v, f[0], f[1]); if si >= 0 { ns = ns + 1 } } 187 if si >= 0 { 188 let rec: *u8 = rd_rec(tab, si) 189 rec[RD_F_OPSEEN] = 1 as u8 190 if cw_field(v, vl, RD_AF_SUBJ, f) == 1 { al_setf(rec, RD_F_DESC, RD_W_DESC, v, f[0], f[1]) } 191 if cw_field(v, vl, RD_AF_VERD, f) == 1 { al_setf(rec, RD_F_VERD, RD_W_VERD, v, f[0], f[1]) } 192 if cw_field(v, vl, RD_AF_ID, f) == 1 { al_setf(rec, RD_F_ID, RD_W_ID, v, f[0], f[1]) } 193 if cw_field(v, vl, RD_AF_WORDS, f) == 1 { al_setf(rec, RD_F_WORDS, RD_W_WORDS, v, f[0], f[1]) } 194 if cw_field(v, vl, RD_AF_DATE, f) == 1 { 195 al_setf(rec, RD_F_DATE, RD_W_DATE, v, f[0], f[1]) 196 if rd_cmp_slice(v, f[0], f[1], since_out) > 0 { al_setf(since_out, 0, RD_W_DATE, v, f[0], f[1]) } 197 } 198 } 199 } } } 200 } 201 p = e + 1 202 } 203 return ns 204} 205 206// (2) the referee's latest row per subject (write order, last wins). A subject the operator never judged is 207// APPENDED so a judged-but-unaccepted subject is visible; returns the new subject count. 208func rd_ref_latest(rows: *u8, n: i64, tab: *u8, ns0: i64) -> i64 { 209 var ns: i64 = ns0 210 let f: *i64 = sys_mmap(16) as *i64 211 var p: i64 = 0 212 while p < n { 213 let e: i64 = rd_line_end(rows, n, p) 214 var el: i64 = e 215 if el > p { if rd_byte(rows, el - 1) == RD_CR { el = el - 1 } } 216 let vl: i64 = el - p 217 if vl > 0 { 218 let v: *u8 = ((rows as i64) + p) as *u8 219 if cw_field(v, vl, RD_RF_SUBJ, f) == 1 { if f[1] > 0 { 220 var si: i64 = rd_find_subj(tab, ns, v, f[0], f[1]) 221 if si < 0 { si = rd_subj_add(tab, ns, v, f[0], f[1]); if si >= 0 { ns = ns + 1 } } 222 if si >= 0 { 223 let rec: *u8 = rd_rec(tab, si) 224 rec[RD_F_RSEEN] = 1 as u8 225 if cw_field(v, vl, RD_RF_PERCEPT, f) == 1 { al_setf(rec, RD_F_RPCT, RD_W_RPCT, v, f[0], f[1]) } 226 if cw_field(v, vl, RD_RF_TIER, f) == 1 { al_setf(rec, RD_F_RTIER, RD_W_RTIER, v, f[0], f[1]) } 227 if cw_field(v, vl, RD_RF_DATE, f) == 1 { al_setf(rec, RD_F_RDATE, RD_W_RDATE, v, f[0], f[1]) } 228 } 229 } } 230 } 231 p = e + 1 232 } 233 return ns 234} 235 236// numeric entity: & # digits ; 237func rd_ent_num(out: *u8, o0: i64, v: i64) -> i64 { 238 var o: i64 = o0 239 out[o] = RD_AMP as u8; o = o + 1 240 out[o] = RD_HASH as u8; o = o + 1 241 o = al_catn(out, o, v) 242 out[o] = RD_SEMI as u8; o = o + 1 243 return o 244} 245// HTML-escape src[so..so+n) into out. Also JS-string-safe by construction: the double quote, the single quote 246// and the backslash become entities and every control byte (newline included) becomes one space, so the block 247// can ride inside one double-quoted JS string with no second escaping layer to get wrong. 248func rd_esc_html(out: *u8, o0: i64, src: *u8, so: i64, n: i64) -> i64 { 249 var o: i64 = o0 250 var i: i64 = 0 251 while i < n { 252 let c: i64 = rd_byte(src, so + i) 253 var done: i64 = 0 254 if c == RD_AMP { o = al_cat(out, o, "&amp;" as *u8); done = 1 } 255 if c == RD_LT { o = al_cat(out, o, "&lt;" as *u8); done = 1 } 256 if c == RD_GT { o = al_cat(out, o, "&gt;" as *u8); done = 1 } 257 if c == RD_DQ { o = al_cat(out, o, "&quot;" as *u8); done = 1 } 258 if c == RD_SQ { o = rd_ent_num(out, o, RD_SQ); done = 1 } 259 if c == RD_BSL { o = rd_ent_num(out, o, RD_BSL); done = 1 } 260 if done == 0 { if c <= RD_CTRL_MAX { out[o] = RD_SPACE as u8; o = o + 1; done = 1 } } 261 if done == 0 { out[o] = c as u8; o = o + 1 } 262 i = i + 1 263 } 264 return o 265} 266func rd_esc_z(out: *u8, o: i64, z: *u8) -> i64 { return rd_esc_html(out, o, z, 0, al_slen(z)) } 267 268// (3) land rows dated strictly after `since`. A board log row is log|<epoch>|<rung>|<kind>|<text> (the 269// gameengine.plan grammar). Each land row after the date is rendered as one list item (board, rung, civil 270// date, the first RD_TEXT_CAP bytes of its text, escaped); retract and measure rows after the date are COUNTED 271// so corrections stand beside deliveries. counts[RD_C_LISTED] stops at RD_LIST_CAP while counts[RD_C_LAND] 272// keeps counting: a cap reached in silence becomes a measurement nobody knows is partial. Returns the new offset. 273func rd_land_since(plan: *u8, n: i64, since: *u8, dom: *u8, out: *u8, o0: i64, cap: i64, counts: *i64) -> i64 { 274 var o: i64 = o0 275 let dbuf: *u8 = sys_mmap(RD_W_DATE) 276 var p: i64 = 0 277 while p < n { 278 let e: i64 = rd_line_end(plan, n, p) 279 if e - p > RD_LOG_PFX_LEN { if rd_slice_eq(plan, p, RD_LOG_PFX_LEN, RD_LOG_PFX) == 1 { 280 var q: i64 = p + RD_LOG_PFX_LEN 281 var ep: i64 = 0 282 var any: i64 = 0 283 var digits: i64 = 1 284 while digits == 1 { 285 if q >= e { digits = 0 } else { 286 let c: i64 = rd_byte(plan, q) 287 if c < RD_D0 { digits = 0 } else { if c > RD_D9 { digits = 0 } else { ep = ep * RD_BASE10 + (c - RD_D0); any = 1; q = q + 1 } } 288 } 289 } 290 var shaped: i64 = 0 291 if any == 1 { if q < e { if rd_byte(plan, q) == RD_PIPE { shaped = 1 } } } 292 if shaped == 1 { 293 q = q + 1 294 let rs: i64 = q 295 while q < e { if rd_byte(plan, q) == RD_PIPE { break } q = q + 1 } 296 let rn: i64 = q - rs 297 if q < e { 298 q = q + 1 299 let ks: i64 = q 300 while q < e { if rd_byte(plan, q) == RD_PIPE { break } q = q + 1 } 301 let kn: i64 = q - ks 302 var ts: i64 = q 303 if ts < e { ts = ts + 1 } 304 al_civil_date(ep, dbuf) 305 if rd_cmp_slice(dbuf, 0, RD_DATE_W, since) > 0 { 306 if rd_slice_eq(plan, ks, kn, RD_KIND_LAND) == 1 { 307 counts[RD_C_LAND] = counts[RD_C_LAND] + 1 308 if counts[RD_C_LISTED] < RD_LIST_CAP { if o + RD_ITEM_RESERVE + RD_TEXT_CAP * RD_ENT_MAX < cap { 309 counts[RD_C_LISTED] = counts[RD_C_LISTED] + 1 310 o = al_cat(out, o, "<li><b>" as *u8) 311 o = rd_esc_z(out, o, dom) 312 out[o] = RD_SPACE as u8; o = o + 1 313 o = rd_esc_html(out, o, plan, rs, rn) 314 o = al_cat(out, o, "</b> " as *u8) 315 o = al_cat(out, o, dbuf) 316 o = al_cat(out, o, ": " as *u8) 317 var tn: i64 = e - ts 318 var cut: i64 = 0 319 if tn > RD_TEXT_CAP { tn = RD_TEXT_CAP; cut = 1 } 320 o = rd_esc_html(out, o, plan, ts, tn) 321 if cut == 1 { o = al_cat(out, o, " [...]" as *u8) } 322 o = al_cat(out, o, "</li>" as *u8) 323 } } 324 } 325 if rd_slice_eq(plan, ks, kn, RD_KIND_RETRACT) == 1 { counts[RD_C_RETRACT] = counts[RD_C_RETRACT] + 1 } 326 if rd_slice_eq(plan, ks, kn, RD_KIND_MEASURE) == 1 { counts[RD_C_MEASURE] = counts[RD_C_MEASURE] + 1 } 327 } 328 } 329 } 330 } } 331 p = e + 1 332 } 333 out[o] = 0 as u8 334 return o 335} 336 337// (4) the block. Single-quoted attributes and rgb() colours only, so the output carries no double quote of its 338// own; every data byte passes rd_esc_html. Returns the new offset; out is NUL-terminated. 339func rd_emit(out: *u8, o0: i64, cap: i64, stamp: i64, since: *u8, tab: *u8, ns: i64, land: *u8, counts: *i64, plans_read: i64, plans_declared: i64) -> i64 { 340 var o: i64 = o0 341 let d: *u8 = sys_mmap(RD_W_DATE) 342 al_civil_date(stamp, d) 343 o = al_cat(out, o, "<div style='font:12px/1.6 ui-monospace,monospace;color:rgb(185,177,220);text-align:left;max-width:96vw;border:1px solid rgb(47,42,74);border-radius:4px;padding:8px 12px;margin:6px 0'><b>RELEASE " as *u8) 344 o = al_cat(out, o, d) 345 o = al_cat(out, o, " emit " as *u8) 346 o = al_catn(out, o, stamp) 347 o = al_cat(out, o, "</b> &middot; since the last operator verdict (" as *u8) 348 if rd_byte(since, 0) == 0 { o = al_cat(out, o, "NEVER JUDGED" as *u8) } else { o = rd_esc_z(out, o, since) } 349 o = al_cat(out, o, "): " as *u8) 350 o = al_catn(out, o, counts[RD_C_LAND]) 351 o = al_cat(out, o, " landed &middot; " as *u8) 352 o = al_catn(out, o, counts[RD_C_RETRACT]) 353 o = al_cat(out, o, " retracted &middot; " as *u8) 354 o = al_catn(out, o, counts[RD_C_MEASURE]) 355 o = al_cat(out, o, " measured &middot; boards read " as *u8) 356 o = al_catn(out, o, plans_read) 357 o = al_cat(out, o, "/" as *u8) 358 o = al_catn(out, o, plans_declared) 359 o = al_cat(out, o, "<br><table style='border-collapse:collapse;margin:4px 0'><tr><th style='text-align:left;padding:0 10px 0 0'>subject</th><th style='text-align:left;padding:0 10px 0 0'>operator</th><th style='text-align:left;padding:0 10px 0 0'>on</th><th style='text-align:left;padding:0 10px 0 0'>referee percept</th><th style='text-align:left'>state</th></tr>" as *u8) 360 var i: i64 = 0 361 while i < ns { 362 if o + RD_ITEM_RESERVE >= cap { break } 363 let rec: *u8 = rd_rec(tab, i) 364 o = al_cat(out, o, "<tr><td style='padding:0 10px 0 0'" as *u8) 365 if rd_byte(rec, RD_F_DESC) != 0 { 366 o = al_cat(out, o, " title='" as *u8) 367 o = rd_esc_z(out, o, rd_str(rec, RD_F_DESC)) 368 o = al_cat(out, o, "'" as *u8) 369 } 370 o = al_cat(out, o, ">" as *u8) 371 o = rd_esc_z(out, o, rd_str(rec, RD_F_SUBJ)) 372 o = al_cat(out, o, "</td><td style='padding:0 10px 0 0'>" as *u8) 373 if rd_byte(rec, RD_F_OPSEEN) == 1 { o = rd_esc_z(out, o, rd_str(rec, RD_F_VERD)) } else { o = al_cat(out, o, "no verdict" as *u8) } 374 o = al_cat(out, o, "</td><td style='padding:0 10px 0 0'>" as *u8) 375 if rd_byte(rec, RD_F_OPSEEN) == 1 { o = rd_esc_z(out, o, rd_str(rec, RD_F_DATE)) } else { o = al_cat(out, o, "-" as *u8) } 376 o = al_cat(out, o, "</td><td style='padding:0 10px 0 0'>" as *u8) 377 if rd_byte(rec, RD_F_RSEEN) == 1 { 378 o = rd_esc_z(out, o, rd_str(rec, RD_F_RPCT)) 379 o = al_cat(out, o, " (" as *u8) 380 o = rd_esc_z(out, o, rd_str(rec, RD_F_RTIER)) 381 o = al_cat(out, o, ", " as *u8) 382 o = rd_esc_z(out, o, rd_str(rec, RD_F_RDATE)) 383 o = al_cat(out, o, ")" as *u8) 384 } else { o = al_cat(out, o, "unjudged" as *u8) } 385 o = al_cat(out, o, "</td><td>" as *u8) 386 var accepted: i64 = 0 387 if rd_byte(rec, RD_F_OPSEEN) == 1 { if al_streq(rd_str(rec, RD_F_VERD), RD_V_ACCEPT) == 1 { accepted = 1 } } 388 if accepted == 1 { o = al_cat(out, o, "ACCEPTED BY OPERATOR (completion needs the referee row and the attestation: nx_accept emit)" as *u8) } else { o = al_cat(out, o, "INCOMPLETE" as *u8) } 389 o = al_cat(out, o, "</td></tr>" as *u8) 390 i = i + 1 391 } 392 o = al_cat(out, o, "</table>" as *u8) 393 if counts[RD_C_LISTED] > 0 { 394 o = al_cat(out, o, "<ul style='margin:4px 0;padding-left:18px'>" as *u8) 395 o = al_cat(out, o, land) 396 o = al_cat(out, o, "</ul>" as *u8) 397 } 398 if counts[RD_C_LAND] > counts[RD_C_LISTED] { 399 o = al_cat(out, o, "<i>and " as *u8) 400 o = al_catn(out, o, counts[RD_C_LAND] - counts[RD_C_LISTED]) 401 o = al_cat(out, o, " more landed rows on the boards (listing capped at " as *u8) 402 o = al_catn(out, o, RD_LIST_CAP) 403 o = al_cat(out, o, ")</i>" as *u8) 404 } 405 o = al_cat(out, o, "<br>To judge this build, file ONE row (id, subject, verdict, date, actor, words, targets): nx_store_put knowledge/store/accept- put operator &lt;subject&gt;-b" as *u8) 406 o = al_catn(out, o, stamp) 407 o = al_cat(out, o, " &lt;subject&gt; ACCEPT-or-REJECT " as *u8) 408 o = al_cat(out, o, d) 409 o = al_cat(out, o, " operator &quot;why&quot; ga_accept_&lt;subject&gt; &middot; a REJECT keeps the subject INCOMPLETE and its words drive the next lane; an ACCEPT completes only with the referee row and the seat attestation.</div>" as *u8) 410 out[o] = 0 as u8 411 return o 412}