code wiki / _hdl_build / nx_site_quality_gate.nx

nx_site_quality_gate.nx source

↩ module page · 156 lines · 8336 B

1// nx_site_quality_gate.nx -- the STANDING site-quality gate (operator 2026-06-09: "easy for a 2// nielsen norman or other award winning ux cx benchmarking and ada and w3c compliant and all that 3// OVER AND OVER with simple management"). Composes the team's sourced rubric line (nx_ux_benchmark = 4// NN/g + WCAG 2.1 AA) into a RE-RUNNABLE mechanical gate over any HTML artifact: a DATA-DRIVEN 5// criteria table (law #11 -- the team EXPANDS quality by adding rows, never by editing logic), 6// permil score, per-criterion verdicts, durable log. Wire into the Conductor's loop so every site 7// edit re-gates automatically (hot content already swaps live; now quality re-checks ride along). 8// Rung-1 criteria = the mechanically-checkable WCAG/NN slice; contrast/keyboard-order need a DOM/CSS 9// rung (flagged, not faked). license_tier: ORIGINAL 10import "nx_syscalls.nx" 11func _p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func _pn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 13func _fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 14func _fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 15func sq_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 16func sq_read(path: *u8, buf: *u8, cap: i64) -> i64 { 17 let fd: i64 = sys_openat_rd(path) 18 if fd < 0 { return 0 - 1 } 19 var total: i64 = 0 20 var go: i64 = 1 21 while go == 1 { 22 let base: i64 = buf as i64 23 let n: i64 = sys_read(fd, (base + total) as *u8, cap - total) 24 if n <= 0 { go = 0 } else { total = total + n } 25 if total >= cap { go = 0 } 26 } 27 sys_close(fd) 28 return total 29} 30func sq_count(buf: *u8, n: i64, pat: *u8) -> i64 { 31 let pl: i64 = sq_slen(pat) 32 var cnt: i64 = 0 33 var i: i64 = 0 34 while i + pl <= n { 35 var k: i64 = 0 36 var hit: i64 = 1 37 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 38 if hit == 1 { cnt = cnt + 1 } 39 i = i + 1 40 } 41 return cnt 42} 43// THE CRITERIA TABLE (data-driven: the team expands quality by ADDING ROWS here). 44// kind 1 = pattern must appear >= mincount; kind 2 = count(pat) must equal count(pat2) (pairing, 45// e.g. every <img needs alt=); kind 3 = pattern must appear AT MOST maxcount (anti-pattern). 46func sq_criterion(id: i64, buf: *u8, n: i64) -> i64 { 47 // WCAG 3.1.1 language of page 48 if id == 0 { if sq_count(buf, n, "<html lang=" as *u8) >= 1 { return 1 } return 0 } 49 // WCAG 2.4.2 page titled 50 if id == 1 { if sq_count(buf, n, "<title>" as *u8) >= 1 { return 1 } return 0 } 51 // mobile/responsive baseline (NN/g + WCAG 1.4.10 reflow) 52 if id == 2 { if sq_count(buf, n, "name=\"viewport\"" as *u8) >= 1 { return 1 } return 0 } 53 // WCAG 1.1.1 non-text content: every <img has an alt= 54 if id == 3 { if sq_count(buf, n, "<img" as *u8) == sq_count(buf, n, "alt=" as *u8) { return 1 } return 0 } 55 // WCAG 1.3.1 landmarks: nav + main + footer present 56 if id == 4 { if sq_count(buf, n, "<nav" as *u8) >= 1 { if sq_count(buf, n, "<main" as *u8) >= 1 { if sq_count(buf, n, "<footer" as *u8) >= 1 { return 1 } } } return 0 } 57 // NN/g visibility of structure: exactly one <h1 58 if id == 5 { if sq_count(buf, n, "<h1" as *u8) == 1 { return 1 } return 0 } 59 // WCAG 2.4.1 bypass blocks: skip link 60 if id == 6 { if sq_count(buf, n, "skip" as *u8) >= 1 { return 1 } return 0 } 61 // anti-pattern: inline event handlers (CSP/a11y smell) -- at most 0 62 if id == 7 { if sq_count(buf, n, "onclick=" as *u8) == 0 { return 1 } return 0 } 63 // WCAG 1.3.1/4.1.2 forms: every <input has a <label OR aria-label (both are valid techniques -- 64 // criterion REFINED 2026-06-09 after a false FAIL on an aria-labelled search input) 65 if id == 8 { if sq_count(buf, n, "<input" as *u8) <= sq_count(buf, n, "<label" as *u8) + sq_count(buf, n, "aria-label=" as *u8) { return 1 } return 0 } 66 // NN/g recognition: charset declared (encoding errors = #1 trust killer) 67 if id == 9 { if sq_count(buf, n, "charset=" as *u8) >= 1 { return 1 } return 0 } 68 // POSITIONAL criteria (rung-2: placement conventions, operator 2026-06-09 "weirdly positioned 69 // things like the search bar in the middle of the page") 70 // NN/g convention: site search lives in the header region (offset(search) < offset(</header>)) 71 if id == 10 { 72 let ps: i64 = sq_pos(buf, n, "role=\"search\"" as *u8) 73 if ps < 0 { return 1 } 74 let ph: i64 = sq_pos(buf, n, "</header>" as *u8) 75 if ph < 0 { return 0 } 76 if ps < ph { return 1 } 77 return 0 78 } 79 // heading hierarchy order: the h1 precedes the first h2 80 if id == 11 { 81 let p1: i64 = sq_pos(buf, n, "<h1" as *u8) 82 let p2: i64 = sq_pos(buf, n, "<h2" as *u8) 83 if p2 < 0 { return 1 } 84 if p1 < 0 { return 0 } 85 if p1 < p2 { return 1 } 86 return 0 87 } 88 // landmark order: main closes before the footer opens (content never trails the footer) 89 if id == 12 { 90 let pm: i64 = sq_pos(buf, n, "</main>" as *u8) 91 let pf: i64 = sq_pos(buf, n, "<footer" as *u8) 92 if pf < 0 { return 0 } 93 if pm < 0 { return 0 } 94 if pm < pf { return 1 } 95 return 0 96 } 97 return 0 - 1 98} 99func sq_pos(buf: *u8, n: i64, pat: *u8) -> i64 { 100 let pl: i64 = sq_slen(pat) 101 var i: i64 = 0 102 while i + pl <= n { 103 var k: i64 = 0 104 var hit: i64 = 1 105 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 106 if hit == 1 { return i } 107 i = i + 1 108 } 109 return 0 - 1 110} 111func sq_name(id: i64) -> *u8 { 112 if id == 0 { return "wcag-3.1.1-lang" as *u8 } 113 if id == 1 { return "wcag-2.4.2-title" as *u8 } 114 if id == 2 { return "reflow-viewport" as *u8 } 115 if id == 3 { return "wcag-1.1.1-img-alt" as *u8 } 116 if id == 4 { return "wcag-1.3.1-landmarks" as *u8 } 117 if id == 5 { return "nng-single-h1" as *u8 } 118 if id == 6 { return "wcag-2.4.1-skip" as *u8 } 119 if id == 7 { return "no-inline-handlers" as *u8 } 120 if id == 8 { return "wcag-1.3.1-labels" as *u8 } 121 if id == 9 { return "charset-declared" as *u8 } 122 if id == 10 { return "nng-search-in-header" as *u8 } 123 if id == 11 { return "heading-order-h1-first" as *u8 } 124 return "main-before-footer" as *u8 125} 126func main(argc: i64, argv: *i64) -> i64 { 127 _p("=== SITE QUALITY GATE (NN/g + WCAG criteria table; re-runnable on ANY page) ===\n" as *u8) 128 var target: *u8 = "knowledge/andelinwest.html" as *u8 129 if argc >= 2 { target = argv[1] as *u8 } 130 _p(" target: " as *u8); _p(target); _p("\n" as *u8) 131 let buf: *u8 = sys_mmap(2097168) 132 let n: i64 = sq_read(target, buf, 2097152) 133 if n <= 0 { _p(" target artifact missing\n" as *u8); sys_exit(1); return 1 } 134 let lfd: i64 = sys_openat_append("knowledge/status/site_quality.log" as *u8, 0x1a4) 135 _fp(lfd, "SITEQ epoch=" as *u8); _fn(lfd, sys_now_realtime_sec()) 136 _fp(lfd, " target=" as *u8); _fp(lfd, target) 137 _fp(lfd, " bytes=" as *u8); _fn(lfd, n); _fp(lfd, "\n" as *u8) 138 var passn: i64 = 0 139 var id: i64 = 0 140 while id < 13 { 141 let v: i64 = sq_criterion(id, buf, n) 142 _p(" " as *u8); _p(sq_name(id)); _p(" = " as *u8) 143 if v == 1 { _p("PASS\n" as *u8); passn = passn + 1 } else { _p("FAIL\n" as *u8) } 144 _fp(lfd, "CRIT name=" as *u8); _fp(lfd, sq_name(id)) 145 _fp(lfd, " pass=" as *u8); _fn(lfd, v); _fp(lfd, "\n" as *u8) 146 id = id + 1 147 } 148 let pm: i64 = (passn * 1000) / 13 149 _p(" SITE-QUALITY score-permil=" as *u8); _pn(pm); _p(" (" as *u8); _pn(passn); _p("/13)\n" as *u8) 150 _fp(lfd, "SITEQ-SCORE permil=" as *u8); _fn(lfd, pm); _fp(lfd, "\n" as *u8) 151 sys_close(lfd) 152 _p(" durable: knowledge/status/site_quality.log -- expand quality by ADDING TABLE ROWS\n" as *u8) 153 if passn >= 12 { sys_exit(0); return 0 } 154 sys_exit(1) 155 return 1 156}