code wiki / _hdl_build / nx_ocr_legibility_census.nx

nx_ocr_legibility_census.nx source

↩ module page · 209 lines · 12358 B

1// nx_ocr_legibility_census.nx -- THE MECHANICAL LEGIBILITY JUDGE (operator 2026-07-03: "it should be an 2// ocr compare between what we generate and what chrome and bing do", replacing eyeball mockups). 3// 4// Pipeline this scores: the SAME bench page (known ground truth) rendered by (a) OUR browser core at 5// 100% + at 2x zoom (labeled), (b) Chrome headless, (c) Edge headless -- all read by the SAME neutral 6// OCR instrument (Windows.Media.Ocr; a 3rd-party MEASURING INSTRUMENT like qemu/openssl oracles, never 7// a runtime dependency). This organ is the SOVEREIGN SCORER: word-level RECALL (what fraction of the 8// ground-truth words the OCR recovered from the render = how much of the page a reader can actually 9// read) + F1, integer PERMILLE, SQuAD normalization (mirrors nx_qa_score's proven metric semantics: 10// lowercase, non-alnum->space, drop articles, multiset match). 11// 12// HONESTY/TEETH: the verdict is HARNESS INTEGRITY, never the score -- C1 truth is substantial (>=25 13// tokens); C2 NEG/liar-kill: garbage text scores ~0 against the truth (metric can't be rigged); C3 all 14// four OCR files present (a missing incumbent row would silently inflate us); C4 report artifacts 15// written. The SCORES are printed raw, whatever they say. license_tier: ORIGINAL expect_exit: 0 16import "nx_syscalls.nx" 17const K_MAGIC_16384: i64 = 16384 18const K_MAGIC_8192: i64 = 8192 19const K_MAGIC_2000: i64 = 2000 20const K_MAGIC_65536: i64 = 65536 21const K_MAGIC_1024: i64 = 1024 22 23func oc_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 24func oc_num(v: i64) -> i64 { let b: *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 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 25func oc_app(buf: *u8, pos: i64, s: *u8) -> i64 { var p: i64=pos; var i: i64=0; while s[i]!=(0 as u8) { buf[p]=s[i]; p=p+1; i=i+1 } return p } 26func oc_appd(buf: *u8, pos: i64, v: i64) -> i64 { 27 var p: i64=pos 28 var m: i64=v 29 if m<0 { buf[p]=45 as u8; p=p+1; m=0-m } 30 let t: *u8=sys_mmap(28) 31 var k: i64=0 32 if m==0 { t[0]=48 as u8; k=1 } 33 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 34 var i: i64=0 35 while i<k { buf[p]=t[k-1-i]; p=p+1; i=i+1 } 36 return p 37} 38func oc_write_file(path: *u8, data: *u8, n: i64) -> i64 { 39 let fd: i64 = sys_openat_wr(path, 0x1a4) 40 if fd<=0 { return 0 - 1 } 41 sys_write(fd, data, n) 42 sys_close(fd) 43 return n 44} 45// read a text file NUL-terminated; returns len (0 if absent) 46func oc_read(path: *u8, out: *u8, cap: i64) -> i64 { 47 let lp: *i64 = sys_mmap(16) as *i64 48 lp[0] = 0 - 1 49 let b: *u8 = sys_read_file(path, lp) 50 if lp[0] <= 0 { out[0]=0 as u8; return 0 } 51 var n: i64 = lp[0] 52 if n > cap-2 { n = cap-2 } 53 var i: i64=0 54 while i<n { out[i]=b[i]; i=i+1 } 55 out[n]=0 as u8 56 return n 57} 58 59// ---- the metric (mirrors nx_qa_score's SQuAD semantics: norm, tokenize, multiset common) ---- 60func oc_norm(src: *u8, dst: *u8) -> i64 { 61 var i: i64=0 62 var j: i64=0 63 while src[i]!=(0 as u8) { 64 var c: i64 = src[i] as i64 65 if c>=65 { if c<=90 { c=c+32 } } 66 var keep: i64=0 67 if c>=97 { if c<=122 { keep=1 } } 68 if c>=48 { if c<=57 { keep=1 } } 69 if keep==1 { dst[j]=(c as u8) } else { dst[j]=(32 as u8) } 70 j=j+1; i=i+1 71 } 72 dst[j]=(0 as u8) 73 return j 74} 75func oc_is_article(buf: *u8, off: i64, len: i64) -> i64 { 76 if len==1 { if buf[off]==(97 as u8){ return 1 } } 77 if len==2 { if buf[off]==(97 as u8){ if buf[off+1]==(110 as u8){ return 1 } } } 78 if len==3 { if buf[off]==(116 as u8){ if buf[off+1]==(104 as u8){ if buf[off+2]==(101 as u8){ return 1 } } } } 79 return 0 80} 81func oc_tok(buf: *u8, blen: i64, toff: *i64, tlen: *i64, maxn: i64) -> i64 { 82 var n: i64=0 83 var start: i64 = 0-1 84 var i: i64=0 85 while i<=blen { 86 var sp: i64=1 87 if i<blen { if buf[i]!=(32 as u8) { sp=0 } } 88 if sp==0 { if start<0 { start=i } } 89 else { 90 if start>=0 { 91 let ln: i64 = i-start 92 if oc_is_article(buf,start,ln)==0 { if n<maxn { toff[n]=start; tlen[n]=ln; n=n+1 } } 93 start = 0-1 94 } 95 } 96 i=i+1 97 } 98 return n 99} 100func oc_teq(pb: *u8, po: i64, pl: i64, gb: *u8, go: i64, gl: i64) -> i64 { 101 if pl!=gl { return 0 } 102 var k: i64=0 103 while k<pl { if pb[po+k]!=gb[go+k] { return 0 } k=k+1 } 104 return 1 105} 106// scores[0]=recall permille, scores[1]=f1 permille, scores[2]=pred tokens, scores[3]=gold tokens 107func oc_score(pred: *u8, gold: *u8, scores: *i64) -> i64 { 108 let pb: *u8=sys_mmap(K_MAGIC_16384) 109 let gb: *u8=sys_mmap(K_MAGIC_16384) 110 let pl: i64=oc_norm(pred,pb) 111 let gl: i64=oc_norm(gold,gb) 112 let ptoff: *i64=sys_mmap(K_MAGIC_8192) as *i64 113 let ptlen: *i64=sys_mmap(K_MAGIC_8192) as *i64 114 let gtoff: *i64=sys_mmap(K_MAGIC_8192) as *i64 115 let gtlen: *i64=sys_mmap(K_MAGIC_8192) as *i64 116 let np: i64=oc_tok(pb,pl,ptoff,ptlen,1000) 117 let ng: i64=oc_tok(gb,gl,gtoff,gtlen,1000) 118 scores[2]=np 119 scores[3]=ng 120 if ng==0 { scores[0]=0; scores[1]=0; return 0 } 121 if np==0 { scores[0]=0; scores[1]=0; return 0 } 122 let used: *i64=sys_mmap(K_MAGIC_8192) as *i64 123 var g: i64=0 124 while g<ng { used[g]=0; g=g+1 } 125 var common: i64=0 126 var p: i64=0 127 while p<np { 128 var gg: i64=0 129 var found: i64=0 130 while gg<ng { 131 if found==0 { if used[gg]==0 { 132 if oc_teq(pb,ptoff[p],ptlen[p], gb,gtoff[gg],gtlen[gg])==1 { used[gg]=1; common=common+1; found=1 } 133 } } 134 gg=gg+1 135 } 136 p=p+1 137 } 138 scores[0]=(1000*common)/ng 139 scores[1]=(K_MAGIC_2000*common)/(np+ng) 140 return 0 141} 142 143func main() -> i64 { 144 oc_puts("OCR-LEGIBILITY census: the SAME page + the SAME OCR judge over our render vs Chrome vs Edge\n" as *u8) 145 let CAP: i64=K_MAGIC_16384 146 let truth: *u8=sys_mmap(CAP) 147 let ours: *u8=sys_mmap(CAP) 148 let ours2: *u8=sys_mmap(CAP) 149 let chrome: *u8=sys_mmap(CAP) 150 let edge: *u8=sys_mmap(CAP) 151 let tn: i64=oc_read("knowledge/status/ocr_bench_truth.txt\x00" as *u8, truth, CAP) 152 let on: i64=oc_read("knowledge/status/ocr_bench_ours_ocr.txt\x00" as *u8, ours, CAP) 153 let o2n: i64=oc_read("knowledge/status/ocr_bench_old8_ocr.txt\x00" as *u8, ours2, CAP) 154 let cn: i64=oc_read("knowledge/status/ocr_bench_chrome_ocr.txt\x00" as *u8, chrome, CAP) 155 let en: i64=oc_read("knowledge/status/ocr_bench_edge_ocr.txt\x00" as *u8, edge, CAP) 156 157 let so: *i64=sys_mmap(64) as *i64 158 let so2: *i64=sys_mmap(64) as *i64 159 let sc: *i64=sys_mmap(64) as *i64 160 let se: *i64=sys_mmap(64) as *i64 161 oc_score(ours, truth, so) 162 oc_score(ours2, truth, so2) 163 oc_score(chrome, truth, sc) 164 oc_score(edge, truth, se) 165 166 oc_puts(" SCORECARD (recall = permille of ground-truth words the OCR could read off the render; all @100%)\n" as *u8) 167 oc_puts(" nishi 16px recall=" as *u8); oc_num(so[0]); oc_puts(" f1=" as *u8); oc_num(so[1]); oc_puts(" (tokens " as *u8); oc_num(so[2]); oc_puts("/" as *u8); oc_num(so[3]); oc_puts(")\n" as *u8) 168 oc_puts(" nishi 8px-ctl recall=" as *u8); oc_num(so2[0]); oc_puts(" f1=" as *u8); oc_num(so2[1]); oc_puts(" (small-text control; the ORIGINAL monospace baseline was 153)\n" as *u8) 169 oc_puts(" chrome recall=" as *u8); oc_num(sc[0]); oc_puts(" f1=" as *u8); oc_num(sc[1]); oc_puts("\n" as *u8) 170 oc_puts(" edge recall=" as *u8); oc_num(se[0]); oc_puts(" f1=" as *u8); oc_num(se[1]); oc_puts("\n" as *u8) 171 172 // teeth 173 var pass: i64=0 174 var ttl: i64=0 175 let gtoks: i64 = so[3] 176 ttl=ttl+1; oc_puts(" C1 truth substantial (>=25 tokens, got " as *u8); oc_num(gtoks); oc_puts("): " as *u8) 177 if gtoks>=25 { pass=pass+1; oc_puts("PASS\n" as *u8) } else { oc_puts("FAIL\n" as *u8) } 178 let sneg: *i64=sys_mmap(64) as *i64 179 oc_score("zzz qqq flurb xxxt gnort wibble\x00" as *u8, truth, sneg) 180 ttl=ttl+1; oc_puts(" C2 NEG/liar-kill: garbage scores ~0 vs truth (recall=" as *u8); oc_num(sneg[0]); oc_puts("): " as *u8) 181 if sneg[0]<100 { pass=pass+1; oc_puts("PASS\n" as *u8) } else { oc_puts("FAIL\n" as *u8) } 182 ttl=ttl+1; oc_puts(" C3 all four OCR inputs present (no silent side-drop): " as *u8) 183 if on>0 { if o2n>0 { if cn>0 { if en>0 { pass=pass+1; oc_puts("PASS\n" as *u8) } else { oc_puts("FAIL\n" as *u8) } } else { oc_puts("FAIL\n" as *u8) } } else { oc_puts("FAIL\n" as *u8) } } else { oc_puts("FAIL\n" as *u8) } 184 185 // report artifacts 186 let hb: *u8=sys_mmap(K_MAGIC_65536) 187 var hp: i64=0 188 hp=oc_app(hb,hp,"<!doctype html><html><head><title>OCR legibility: nishi vs chrome vs edge</title></head><body style=\x27background:#0b1020;color:#dbe4ff;font-family:monospace;padding:24px\x27><h2>OCR legibility judge -- same page, same OCR instrument, every render</h2><p style=\x27color:#8fa3cc\x27>recall = permille of ground-truth words Windows OCR could read off the render. The mechanical replacement for eyeball font mockups.</p><table style=\x27border-collapse:collapse\x27><tr><th style=\x27text-align:left;padding:4px 12px\x27>render</th><th style=\x27text-align:left;padding:4px 12px\x27>recall</th><th style=\x27text-align:left;padding:4px 12px\x27>f1</th></tr>\x00" as *u8) 189 hp=oc_app(hb,hp,"<tr><td style=\x27padding:3px 12px\x27>nishi 16px (new default)</td><td style=\x27padding:3px 12px;color:#f59e0b\x27>\x00" as *u8); hp=oc_appd(hb,hp,so[0]); hp=oc_app(hb,hp,"</td><td style=\x27padding:3px 12px\x27>\x00" as *u8); hp=oc_appd(hb,hp,so[1]); hp=oc_app(hb,hp,"</td></tr>\x00" as *u8) 190 hp=oc_app(hb,hp,"<tr><td style=\x27padding:3px 12px\x27>nishi 8px (small-text control; original monospace baseline was 153)</td><td style=\x27padding:3px 12px\x27>\x00" as *u8); hp=oc_appd(hb,hp,so2[0]); hp=oc_app(hb,hp,"</td><td style=\x27padding:3px 12px\x27>\x00" as *u8); hp=oc_appd(hb,hp,so2[1]); hp=oc_app(hb,hp,"</td></tr>\x00" as *u8) 191 hp=oc_app(hb,hp,"<tr><td style=\x27padding:3px 12px\x27>chrome @100%</td><td style=\x27padding:3px 12px;color:#22c55e\x27>\x00" as *u8); hp=oc_appd(hb,hp,sc[0]); hp=oc_app(hb,hp,"</td><td style=\x27padding:3px 12px\x27>\x00" as *u8); hp=oc_appd(hb,hp,sc[1]); hp=oc_app(hb,hp,"</td></tr>\x00" as *u8) 192 hp=oc_app(hb,hp,"<tr><td style=\x27padding:3px 12px\x27>edge @100%</td><td style=\x27padding:3px 12px;color:#22c55e\x27>\x00" as *u8); hp=oc_appd(hb,hp,se[0]); hp=oc_app(hb,hp,"</td><td style=\x27padding:3px 12px\x27>\x00" as *u8); hp=oc_appd(hb,hp,se[1]); hp=oc_app(hb,hp,"</td></tr>\x00" as *u8) 193 hp=oc_app(hb,hp,"</table><p style=\x27color:#7c8db5;margin-top:14px\x27>renders: <a style=\x27color:#8ab4ff\x27 href=\x27ocr_bench_ours.png\x27>ours 16px</a> &middot; <a style=\x27color:#8ab4ff\x27 href=\x27ocr_bench_old8.png\x27>ours old-8px</a> &middot; <a style=\x27color:#8ab4ff\x27 href=\x27ocr_bench_chrome.png\x27>chrome</a> &middot; <a style=\x27color:#8ab4ff\x27 href=\x27ocr_bench_edge.png\x27>edge</a>. Judge = Windows.Media.Ocr (same instrument every side; a measuring tool, not a runtime dependency). Scorer sovereign (SQuAD-normalized word recall/F1, integer permille).</p></body></html>\x00" as *u8) 194 let hw: i64=oc_write_file("knowledge/status/ocr_legibility.html\x00" as *u8, hb, hp) 195 let lb: *u8=sys_mmap(K_MAGIC_1024) 196 var lp2: i64=0 197 lp2=oc_app(lb,lp2,"OCR-LEGIBILITY ours=\x00" as *u8); lp2=oc_appd(lb,lp2,so[0]) 198 lp2=oc_app(lb,lp2," ours2x=\x00" as *u8); lp2=oc_appd(lb,lp2,so2[0]) 199 lp2=oc_app(lb,lp2," chrome=\x00" as *u8); lp2=oc_appd(lb,lp2,sc[0]) 200 lp2=oc_app(lb,lp2," edge=\x00" as *u8); lp2=oc_appd(lb,lp2,se[0]) 201 lp2=oc_app(lb,lp2," (recall permille)\x0A\x00" as *u8) 202 let lw: i64=oc_write_file("knowledge/status/ocr_legibility.log\x00" as *u8, lb, lp2) 203 ttl=ttl+1; oc_puts(" C4 report artifacts written: " as *u8) 204 if hw>0 { if lw>0 { pass=pass+1; oc_puts("PASS\n" as *u8) } else { oc_puts("FAIL\n" as *u8) } } else { oc_puts("FAIL\n" as *u8) } 205 206 oc_puts("OCR-LEGIBILITY-GATE passed " as *u8); oc_num(pass); oc_puts("/" as *u8); oc_num(ttl) 207 if pass==ttl { oc_puts(" verdict=GREEN (scores above are the measurement; open knowledge/status/ocr_legibility.html)\n" as *u8); sys_exit(0); return 0 } 208 oc_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 209}