code wiki / (root) / nx_compare_results_lib.nx

nx_compare_results_lib.nx source

↩ module page · 352 lines · 17522 B

1// nx_compare_results_lib.nx -- ONE HOME FOR A BOARD'S RESULTS (ecosystem EC64, 2026-09-17). 2// Operator 2026-09-17, asked where the twin renders could be seen: "i dont want them strewn about like we had with /world 3// pages". A board's results are DATA -- buildroot/knowledge/compare/<dom>.results -- and this lib renders them as ONE page, 4// /compare/<dom>/results/, grouped by kind, newest first, every image behind the estate's one click-to-open primitive 5// (nx_reveal_lib). A result row: 6// result|<slug>|<kind>|<YYYY-MM-DD>|<class>|<title>|<report href or ->|<image href or ->|<headline> 7// slug is the identity: a later row with the same slug SUPERSEDES the earlier one (history stays in the file, the page 8// shows the current one, and the receipt counts what was superseded). A row with the wrong field count is MALFORMED and 9// named by line number; it never becomes a card. No pipes in text fields. 10// license_tier: ORIGINAL No hw writes (Rule 26). 11import "nx_syscalls.nx" 12import "nx_reveal_lib.nx" 13 14const CRES_FIELDS: i64 = 9 15const CRES_F_TAG: i64 = 0 16const CRES_F_SLUG: i64 = 1 17const CRES_F_KIND: i64 = 2 18const CRES_F_DATE: i64 = 3 19const CRES_F_CLASS: i64 = 4 20const CRES_F_TITLE: i64 = 5 21const CRES_F_PAGE: i64 = 6 22const CRES_F_IMAGE: i64 = 7 23const CRES_F_HEAD: i64 = 8 24const CRES_TAG: *u8 = "result" 25const CRES_NONE: *u8 = "-" 26const CRES_I64: i64 = 8 27const CRES_MODE644: i64 = 420 28// a parsed row: CRES_FIELDS starts, then CRES_FIELDS ends, then the live flag (0 = superseded by a later slug twin) 29const CRES_ROW_W: i64 = 19 30const CRES_ROW_LIVE: i64 = 18 31// the receipt 32const CRES_R_LINES: i64 = 0 33const CRES_R_ROWS: i64 = 1 34const CRES_R_MALFORMED: i64 = 2 35const CRES_R_SUPERSEDED: i64 = 3 36const CRES_R_LIVE: i64 = 4 37const CRES_R_KINDS: i64 = 5 38const CRES_R_OPEN: i64 = 6 39const CRES_R_CLICK: i64 = 7 40const CRES_R_GATED: i64 = 8 41const CRES_R_UNKNOWN: i64 = 9 42const CRES_R_ADULT: i64 = 10 43const CRES_R_BARE: i64 = 11 44const CRES_R_HTML_BYTES: i64 = 12 45const CRES_R_FIRST_BAD_LINE: i64 = 13 46const CRES_R_N: i64 = 14 47const CRES_E_READ: i64 = 0 - 3 48const CRES_E_NOROWS: i64 = 0 - 4 49const CRES_E_WRITE: i64 = 0 - 5 50const CRES_E_OVERFLOW: i64 = 0 - 6 51const CRES_E_BARE: i64 = 0 - 7 52// the page buffer is sized from the input: every input byte can grow six-fold under escaping, and every row carries a 53// fixed amount of markup around it; the fixed part holds the head, the stylesheet and the footer 54const CRES_GROW: i64 = 6 55const CRES_PER_ROW: i64 = 2048 56const CRES_FIXED: i64 = 32768 57const CRES_PATHB: i64 = 1024 58const CRES_CH_HASH: i64 = 35 // the fragment mark, written as a byte: the lexer reads that character inside a literal as a comment 59 60func cres_streq_span(buf: *u8, s1: i64, e1: i64, s2: i64, e2: i64) -> i64 { 61 if e1 - s1 != e2 - s2 { return 0 } 62 var i: i64 = 0 63 while s1 + i < e1 { if buf[s1 + i] != buf[s2 + i] { return 0 } i = i + 1 } 64 return 1 65} 66func cres_span_cstr(buf: *u8, s: i64, e: i64) -> *u8 { 67 let out: *u8 = sys_mmap(e - s + 1) 68 var i: i64 = 0 69 while s + i < e { out[i] = buf[s + i]; i = i + 1 } 70 out[e - s] = 0 as u8 71 return out 72} 73func cres_count_lines(buf: *u8, n: i64) -> i64 { 74 var c: i64 = 0 75 var i: i64 = 0 76 while i < n { if ((buf[i] as i64) & RVL_BYTE) == RVL_NL { c = c + 1 } i = i + 1 } 77 return c + 1 78} 79// parse every line into the row table; comment lines (leading slash or hash is avoided: a line that does not start with 80// the result tag and has no pipe is prose and is skipped silently, a line WITH the tag and the wrong field count is 81// MALFORMED). Returns the number of well-formed rows 82func cres_parse(buf: *u8, n: i64, rows: *i64, rep: *i64) -> i64 { 83 var nrows: i64 = 0 84 var line: i64 = 0 85 var i: i64 = 0 86 rep[CRES_R_MALFORMED] = 0 87 rep[CRES_R_FIRST_BAD_LINE] = 0 88 let fs: *i64 = sys_mmap((CRES_FIELDS + 2) * CRES_I64) as *i64 89 while i < n { 90 line = line + 1 91 var e: i64 = i 92 var going: i64 = 1 93 while going == 1 { 94 if e >= n { going = 0 } else { 95 if ((buf[e] as i64) & RVL_BYTE) == RVL_NL { going = 0 } else { e = e + 1 } 96 } 97 } 98 var le: i64 = e 99 if le > i { if ((buf[le - 1] as i64) & RVL_BYTE) == RVL_CR { le = le - 1 } } 100 var nf: i64 = 0 101 fs[0] = i 102 var k: i64 = i 103 while k < le { 104 if ((buf[k] as i64) & RVL_BYTE) == RVL_PIPE { nf = nf + 1; if nf <= CRES_FIELDS { fs[nf] = k + 1 } } 105 k = k + 1 106 } 107 var tagged: i64 = 0 108 if nf >= 1 { tagged = rvl_span_is(buf, fs[0], fs[1] - 1, CRES_TAG) } 109 if tagged == 1 { 110 if nf + 1 == CRES_FIELDS { 111 let b: i64 = nrows * CRES_ROW_W 112 var f: i64 = 0 113 while f < CRES_FIELDS { 114 rows[b + f] = fs[f] 115 if f + 1 < CRES_FIELDS { rows[b + CRES_FIELDS + f] = fs[f + 1] - 1 } else { rows[b + CRES_FIELDS + f] = le } 116 f = f + 1 117 } 118 rows[b + CRES_ROW_LIVE] = 1 119 nrows = nrows + 1 120 } else { 121 rep[CRES_R_MALFORMED] = rep[CRES_R_MALFORMED] + 1 122 if rep[CRES_R_FIRST_BAD_LINE] == 0 { rep[CRES_R_FIRST_BAD_LINE] = line } 123 } 124 } 125 i = e + 1 126 } 127 rep[CRES_R_LINES] = line 128 rep[CRES_R_ROWS] = nrows 129 // a later row with the same slug supersedes the earlier one 130 var sup: i64 = 0 131 var a: i64 = 0 132 while a < nrows { 133 var b2: i64 = a + 1 134 while b2 < nrows { 135 if rows[a * CRES_ROW_W + CRES_ROW_LIVE] == 1 { 136 if cres_streq_span(buf, rows[a * CRES_ROW_W + CRES_F_SLUG], rows[a * CRES_ROW_W + CRES_FIELDS + CRES_F_SLUG], rows[b2 * CRES_ROW_W + CRES_F_SLUG], rows[b2 * CRES_ROW_W + CRES_FIELDS + CRES_F_SLUG]) == 1 { 137 rows[a * CRES_ROW_W + CRES_ROW_LIVE] = 0 138 sup = sup + 1 139 } 140 } 141 b2 = b2 + 1 142 } 143 a = a + 1 144 } 145 rep[CRES_R_SUPERSEDED] = sup 146 rep[CRES_R_LIVE] = nrows - sup 147 return nrows 148} 149func cres_f(out: *u8, o: i64, cap: i64, buf: *u8, rows: *i64, r: i64, f: i64) -> i64 { 150 return rvl_cat_span_esc(out, o, cap, buf, rows[r * CRES_ROW_W + f], rows[r * CRES_ROW_W + CRES_FIELDS + f]) 151} 152func cres_f_is_none(buf: *u8, rows: *i64, r: i64, f: i64) -> i64 { 153 return rvl_span_is(buf, rows[r * CRES_ROW_W + f], rows[r * CRES_ROW_W + CRES_FIELDS + f], CRES_NONE) 154} 155// is row r the FIRST live row of its kind (kinds are listed in first-appearance order) 156func cres_kind_first(buf: *u8, rows: *i64, nrows: i64, r: i64) -> i64 { 157 var a: i64 = 0 158 while a < r { 159 if rows[a * CRES_ROW_W + CRES_ROW_LIVE] == 1 { 160 if cres_streq_span(buf, rows[a * CRES_ROW_W + CRES_F_KIND], rows[a * CRES_ROW_W + CRES_FIELDS + CRES_F_KIND], rows[r * CRES_ROW_W + CRES_F_KIND], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_KIND]) == 1 { return 0 } 161 } 162 a = a + 1 163 } 164 return 1 165} 166func cres_kind_count(buf: *u8, rows: *i64, nrows: i64, r: i64) -> i64 { 167 var c: i64 = 0 168 var a: i64 = 0 169 while a < nrows { 170 if rows[a * CRES_ROW_W + CRES_ROW_LIVE] == 1 { 171 if cres_streq_span(buf, rows[a * CRES_ROW_W + CRES_F_KIND], rows[a * CRES_ROW_W + CRES_FIELDS + CRES_F_KIND], rows[r * CRES_ROW_W + CRES_F_KIND], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_KIND]) == 1 { c = c + 1 } 172 } 173 a = a + 1 174 } 175 return c 176} 177func cres_catn(out: *u8, o: i64, cap: i64, v: i64) -> i64 { 178 let t: *u8 = sys_mmap(32) 179 var m: i64 = v 180 var k: i64 = 0 181 if m == 0 { t[0] = 48 as u8; k = 1 } 182 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 183 let s: *u8 = sys_mmap(32) 184 var j: i64 = 0 185 while j < k { s[j] = t[k - 1 - j]; j = j + 1 } 186 s[k] = 0 as u8 187 return rvl_cat(out, o, cap, s) 188} 189// one card 190func cres_card(out: *u8, o: i64, cap: i64, buf: *u8, rows: *i64, r: i64, pol: *u8, pn: i64, tally: *i64) -> i64 { 191 var p: i64 = rvl_cat(out, o, cap, "<article class=\"card\" id=\"r-" as *u8) 192 p = cres_f(out, p, cap, buf, rows, r, CRES_F_SLUG) 193 p = rvl_cat(out, p, cap, "\"><h3>" as *u8) 194 p = cres_f(out, p, cap, buf, rows, r, CRES_F_TITLE) 195 p = rvl_cat(out, p, cap, "</h3><p class=\"meta\">" as *u8) 196 p = cres_f(out, p, cap, buf, rows, r, CRES_F_DATE) 197 p = rvl_cat(out, p, cap, " &middot; <code>" as *u8) 198 p = cres_f(out, p, cap, buf, rows, r, CRES_F_SLUG) 199 p = rvl_cat(out, p, cap, "</code></p><p class=\"headline\">" as *u8) 200 p = cres_f(out, p, cap, buf, rows, r, CRES_F_HEAD) 201 p = rvl_cat(out, p, cap, "</p>\n" as *u8) 202 if cres_f_is_none(buf, rows, r, CRES_F_IMAGE) == 0 { 203 let cls: *u8 = cres_span_cstr(buf, rows[r * CRES_ROW_W + CRES_F_CLASS], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_CLASS]) 204 let href: *u8 = cres_span_cstr(buf, rows[r * CRES_ROW_W + CRES_F_IMAGE], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_IMAGE]) 205 let title: *u8 = cres_span_cstr(buf, rows[r * CRES_ROW_W + CRES_F_TITLE], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_TITLE]) 206 p = rvl_emit_img(out, p, cap, pol, pn, cls, href, title, title, tally) 207 } 208 if cres_f_is_none(buf, rows, r, CRES_F_PAGE) == 0 { 209 p = rvl_cat(out, p, cap, "<p><a href=\"" as *u8) 210 p = cres_f(out, p, cap, buf, rows, r, CRES_F_PAGE) 211 p = rvl_cat(out, p, cap, "\">Open the full report</a></p>\n" as *u8) 212 } 213 return rvl_cat(out, p, cap, "</article>\n" as *u8) 214} 215// does any live row put an adult-rated item on the page 216func cres_any_adult(buf: *u8, rows: *i64, nrows: i64, pol: *u8, pn: i64) -> i64 { 217 var r: i64 = 0 218 while r < nrows { 219 if rows[r * CRES_ROW_W + CRES_ROW_LIVE] == 1 { 220 if cres_f_is_none(buf, rows, r, CRES_F_IMAGE) == 0 { 221 let cls: *u8 = cres_span_cstr(buf, rows[r * CRES_ROW_W + CRES_F_CLASS], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_CLASS]) 222 if rvl_rating(pol, pn, cls) == RVL_RATING_ADULT { return 1 } 223 } 224 } 225 r = r + 1 226 } 227 return 0 228} 229// THE PAGE: results buffer in, html out. Returns the html length, or a CRES_E_ code. rep carries the receipt 230func cres_render(dom: *u8, buf: *u8, n: i64, pol: *u8, pn: i64, out: *u8, cap: i64, rep: *i64) -> i64 { 231 let lines: i64 = cres_count_lines(buf, n) 232 let rows: *i64 = sys_mmap((lines + 1) * CRES_ROW_W * CRES_I64) as *i64 233 let nrows: i64 = cres_parse(buf, n, rows, rep) 234 if rep[CRES_R_LIVE] <= 0 { return CRES_E_NOROWS } 235 let tally: *i64 = sys_mmap(RVL_T_N * CRES_I64) as *i64 236 rvl_tally_clear(tally) 237 var p: i64 = rvl_cat(out, 0, cap, "<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>Results: " as *u8) 238 p = rvl_cat_esc(out, p, cap, dom) 239 p = rvl_cat(out, p, cap, "</title>\n" as *u8) 240 p = rvl_head_meta(out, p, cap, cres_any_adult(buf, rows, nrows, pol, pn)) 241 p = rvl_cat(out, p, cap, "<style>\n:root{--nx-bg:rgb(11,15,20);--nx-panel:rgb(18,24,33);--nx-line:rgb(42,51,64);--nx-ink:rgb(230,236,242);--nx-dim:rgb(150,162,176);--nx-accent:rgb(124,196,255);--nx-warn:rgb(255,180,84);--nx-wrap:1180px;--nx-card:340px}\n" as *u8) 242 p = rvl_cat(out, p, cap, "body{margin:0;background:var(--nx-bg);color:var(--nx-ink);font:16px/1.5 system-ui,sans-serif}\n.wrap{max-width:var(--nx-wrap);margin:0 auto;padding:1.2rem clamp(.8rem,3vw,2rem)}\na{color:var(--nx-accent)}h1{margin:.2rem 0 .4rem}h2{margin:2rem 0 .6rem;border-bottom:1px solid var(--nx-line);padding-bottom:.3rem}\n" as *u8) 243 p = rvl_cat(out, p, cap, ".lead,.meta{color:var(--nx-dim)}.kinds{display:flex;flex-wrap:wrap;gap:.5rem;padding:0;list-style:none}.kinds a{border:1px solid var(--nx-line);border-radius:999px;padding:.15rem .7rem;text-decoration:none}\n.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fill,minmax(min(100%,var(--nx-card)),1fr))}\n.card{border:1px solid var(--nx-line);border-radius:12px;background:var(--nx-panel);padding:.9rem 1rem}.card h3{margin:.1rem 0 .2rem;font-size:1.05rem}.headline{margin:.4rem 0}\nfooter{color:var(--nx-dim);margin-top:2.5rem;border-top:1px solid var(--nx-line);padding-top:.8rem;font-size:.9rem}\n" as *u8) 244 p = rvl_css(out, p, cap) 245 p = rvl_cat(out, p, cap, "</style></head><body><main class=\"wrap\">\n<header><p><a href=\"/compare/" as *u8) 246 p = rvl_cat_esc(out, p, cap, dom) 247 p = rvl_cat(out, p, cap, "\">Back to the " as *u8) 248 p = rvl_cat_esc(out, p, cap, dom) 249 p = rvl_cat(out, p, cap, " board</a></p><h1>Results: " as *u8) 250 p = rvl_cat_esc(out, p, cap, dom) 251 p = rvl_cat(out, p, cap, "</h1><p class=\"lead\">Every result this board has produced, in one place, newest first inside each kind. Images stay closed until you open them, and each one names its content class before you do. Results shown: " as *u8) 252 p = cres_catn(out, p, cap, rep[CRES_R_LIVE]) 253 p = rvl_cat(out, p, cap, ".</p>\n<ul class=\"kinds\">" as *u8) 254 var kinds: i64 = 0 255 var r: i64 = 0 256 while r < nrows { 257 if rows[r * CRES_ROW_W + CRES_ROW_LIVE] == 1 { if cres_kind_first(buf, rows, nrows, r) == 1 { 258 kinds = kinds + 1 259 p = rvl_cat(out, p, cap, "<li><a href=\"" as *u8) 260 p = rvl_esc_byte(out, p, cap, CRES_CH_HASH) 261 p = rvl_cat(out, p, cap, "k-" as *u8) 262 p = cres_f(out, p, cap, buf, rows, r, CRES_F_KIND) 263 p = rvl_cat(out, p, cap, "\">" as *u8) 264 p = cres_f(out, p, cap, buf, rows, r, CRES_F_KIND) 265 p = rvl_cat(out, p, cap, " (" as *u8) 266 p = cres_catn(out, p, cap, cres_kind_count(buf, rows, nrows, r)) 267 p = rvl_cat(out, p, cap, ")</a></li>" as *u8) 268 } } 269 r = r + 1 270 } 271 rep[CRES_R_KINDS] = kinds 272 p = rvl_cat(out, p, cap, "</ul></header>\n" as *u8) 273 // one section per kind, in first-appearance order; inside a kind the file's LAST row is the newest and goes first 274 r = 0 275 while r < nrows { 276 if rows[r * CRES_ROW_W + CRES_ROW_LIVE] == 1 { if cres_kind_first(buf, rows, nrows, r) == 1 { 277 p = rvl_cat(out, p, cap, "<section id=\"k-" as *u8) 278 p = cres_f(out, p, cap, buf, rows, r, CRES_F_KIND) 279 p = rvl_cat(out, p, cap, "\"><h2>" as *u8) 280 p = cres_f(out, p, cap, buf, rows, r, CRES_F_KIND) 281 p = rvl_cat(out, p, cap, "</h2><div class=\"grid\">\n" as *u8) 282 var q: i64 = nrows - 1 283 while q >= 0 { 284 if rows[q * CRES_ROW_W + CRES_ROW_LIVE] == 1 { 285 if cres_streq_span(buf, rows[q * CRES_ROW_W + CRES_F_KIND], rows[q * CRES_ROW_W + CRES_FIELDS + CRES_F_KIND], rows[r * CRES_ROW_W + CRES_F_KIND], rows[r * CRES_ROW_W + CRES_FIELDS + CRES_F_KIND]) == 1 { 286 p = cres_card(out, p, cap, buf, rows, q, pol, pn, tally) 287 } 288 } 289 q = q - 1 290 } 291 p = rvl_cat(out, p, cap, "</div></section>\n" as *u8) 292 } } 293 r = r + 1 294 } 295 p = rvl_cat(out, p, cap, "<footer>Generated by nx_compare_results from the board's results data. Rows read " as *u8) 296 p = cres_catn(out, p, cap, rep[CRES_R_ROWS]) 297 p = rvl_cat(out, p, cap, ", superseded " as *u8) 298 p = cres_catn(out, p, cap, rep[CRES_R_SUPERSEDED]) 299 p = rvl_cat(out, p, cap, ", malformed " as *u8) 300 p = cres_catn(out, p, cap, rep[CRES_R_MALFORMED]) 301 p = rvl_cat(out, p, cap, ". Images: inline " as *u8) 302 p = cres_catn(out, p, cap, tally[RVL_T_OPEN]) 303 p = rvl_cat(out, p, cap, ", click to open " as *u8) 304 p = cres_catn(out, p, cap, tally[RVL_T_CLICK]) 305 p = rvl_cat(out, p, cap, ", withheld from this public page " as *u8) 306 p = cres_catn(out, p, cap, tally[RVL_T_GATED]) 307 p = rvl_cat(out, p, cap, ".</footer>\n</main></body></html>\n" as *u8) 308 if p < 0 { return CRES_E_OVERFLOW } 309 rep[CRES_R_OPEN] = tally[RVL_T_OPEN] 310 rep[CRES_R_CLICK] = tally[RVL_T_CLICK] 311 rep[CRES_R_GATED] = tally[RVL_T_GATED] 312 rep[CRES_R_UNKNOWN] = tally[RVL_T_UNKNOWN] 313 rep[CRES_R_ADULT] = tally[RVL_T_ADULT] 314 let arep: *i64 = sys_mmap(RVL_A_N * CRES_I64) as *i64 315 rep[CRES_R_BARE] = rvl_audit(out, p, arep) 316 rep[CRES_R_HTML_BYTES] = p 317 if rep[CRES_R_BARE] > 0 { return CRES_E_BARE } 318 return p 319} 320func cres_write(path: *u8, buf: *u8, n: i64) -> i64 { 321 let fd: i64 = sys_openat_wr(path, CRES_MODE644) 322 if fd < 0 { return CRES_E_WRITE } 323 var off: i64 = 0 324 var going: i64 = 1 325 while going == 1 { 326 if off >= n { going = 0 } else { 327 let k: i64 = sys_write(fd, (buf as i64 + off) as *u8, n - off) 328 if k <= 0 { going = 0 } else { off = off + k } 329 } 330 } 331 sys_close(fd) 332 if off != n { return CRES_E_WRITE } 333 return n 334} 335// file in, file out: the verb the CLI and the plans call 336func cres_emit_file(dom: *u8, results_path: *u8, out_path: *u8, rep: *i64) -> i64 { 337 let fl: *i64 = sys_mmap(2 * CRES_I64) as *i64 338 fl[0] = 0 339 let buf: *u8 = sys_read_file(results_path, fl) 340 if (buf as i64) == 0 { return CRES_E_READ } 341 if fl[0] <= 0 { return CRES_E_READ } 342 let pl: *i64 = sys_mmap(CRES_I64) as *i64 343 let pw: *i64 = sys_mmap(CRES_I64) as *i64 344 let pol: *u8 = rvl_policy_load(pl, pw) 345 let lines: i64 = cres_count_lines(buf, fl[0]) 346 let cap: i64 = fl[0] * CRES_GROW + lines * CRES_PER_ROW + CRES_FIXED 347 let out: *u8 = sys_mmap(cap) 348 let hn: i64 = cres_render(dom, buf, fl[0], pol, pl[0], out, cap, rep) 349 if hn < 0 { return hn } 350 if cres_write(out_path, out, hn) < 0 { return CRES_E_WRITE } 351 return hn 352}