code wiki / _hdl_build / nx_parity_judge.nx
nx_parity_judge.nx source
↩ module page · 169 lines · 7931 B
1// nx_parity_judge.nx -- THE ORGAN EYE (operator 2026-07-16: "this workflow isnt complete until you see
2// the exact same issues i see without your or my involvement"). Given (oracle.png, nishi.png) of the SAME
3// page, it autonomously reports the failure classes a human eyeball found on the top-20 suite -- so the
4// suite self-diagnoses every run with NO human/Claude in the loop:
5// BLANK-NISHI nishi has almost no ink while the oracle has plenty (google: blank page scored 97.3%
6// parity by matching white space -- THE metric hole this organ closes)
7// STRIP-COLLAPSE nishi's ink is squeezed into a narrow vertical band (bing/netflix: 1-char-per-line
8// column collapse from a near-zero-width container)
9// CANVAS-OFF the two sides disagree about the page background color (hackernews: dark canvas vs beige)
10// SPARSE-NISHI nishi paints real ink but a fraction of the oracle's (missing bg-images/sections)
11// CONTENT-OK ink mass + spread comparable -- grade quality by the parity numbers
12// Ink = pixels differing from that side's own dominant background (corner-sampled) by > tol.
13// usage: nx_parity_judge <oracle.png> <nishi.png> [nishi_y_offset] (offset skips the browser chrome bar)
14// license_tier: ORIGINAL
15import "nx_visual_diff.nx"
16const K_MAGIC_4096: i64 = 4096
17
18func rj_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
19func rj_n(v: i64) -> i64 { let t: *u8=sys_mmap(24); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 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} let b: *u8=sys_mmap(24); var j: i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
20func rj_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ let c: i64=(s[i] as i64)&255; if c>=48 { if c<=57 { v=v*10+(c-48) } } i=i+1 } return v }
21
22// dominant background = average of the 4 corner 8x8 patches; writes r,g,b to out
23func rj_bg(im: *VdImg, yoff: i64, out: *i64) -> i64 {
24 var sr: i64 = 0
25 var sg: i64 = 0
26 var sb: i64 = 0
27 var n: i64 = 0
28 var cy: i64 = 0
29 while cy < 2 {
30 var cx: i64 = 0
31 while cx < 2 {
32 var y: i64 = 0
33 while y < 8 {
34 var x: i64 = 0
35 while x < 8 {
36 var px: i64 = x + 2
37 var py: i64 = y + 2
38 if cx == 1 { px = im.w - 26 + x } // inset past the ~14px scrollbar strip (it polluted
39 if cy == 1 { py = (im.h - yoff) - 10 + y } // netflix's corner sample -> ink read 999pm)
40 let o: i64 = ((py + yoff) * im.w + px) * im.nc
41 sr = sr + (im.px[o] as i64)
42 sg = sg + (im.px[o+1] as i64)
43 sb = sb + (im.px[o+2] as i64)
44 n = n + 1
45 x = x + 1
46 }
47 y = y + 1
48 }
49 cx = cx + 1
50 }
51 cy = cy + 1
52 }
53 out[0] = sr / n
54 out[1] = sg / n
55 out[2] = sb / n
56 return 0
57}
58// ink per-mille + the narrowest column-span holding >=80% of the ink (permille of width).
59// cols = a caller-provided i64 scratch of at least im.w entries.
60func rj_ink(im: *VdImg, yoff: i64, bg: *i64, tol: i64, cols: *i64, out: *i64) -> i64 {
61 var i: i64 = 0
62 while i < im.w { cols[i] = 0; i = i + 1 }
63 var ink: i64 = 0
64 var tot: i64 = 0
65 var y: i64 = 0
66 let hh: i64 = im.h - yoff
67 let wmax: i64 = im.w - 14 // exclude the scrollbar column from ink
68 while y < hh {
69 var x: i64 = 0
70 while x < wmax {
71 let o: i64 = ((y + yoff) * im.w + x) * im.nc
72 var dr: i64 = (im.px[o] as i64) - bg[0]
73 if dr < 0 { dr = 0 - dr }
74 var dg: i64 = (im.px[o+1] as i64) - bg[1]
75 if dg < 0 { dg = 0 - dg }
76 var db: i64 = (im.px[o+2] as i64) - bg[2]
77 if db < 0 { db = 0 - db }
78 tot = tot + 1
79 if dr > tol { ink = ink + 1; cols[x] = cols[x] + 1; x = x + 2 }
80 else { if dg > tol { ink = ink + 1; cols[x] = cols[x] + 1; x = x + 2 }
81 else { if db > tol { ink = ink + 1; cols[x] = cols[x] + 1; x = x + 2 }
82 else { x = x + 2 } } }
83 }
84 y = y + 2
85 }
86 out[0] = 0
87 if tot > 0 { out[0] = (ink * 1000) / tot }
88 // narrowest window of columns covering 80% of ink (two-pointer over the column histogram)
89 var total_ink: i64 = 0
90 i = 0
91 while i < im.w { total_ink = total_ink + cols[i]; i = i + 1 }
92 out[1] = 1000
93 if total_ink > 0 {
94 let need: i64 = (total_ink * 8) / 10
95 var lo: i64 = 0
96 var hi: i64 = 0
97 var acc: i64 = 0
98 var best: i64 = im.w
99 while hi < im.w {
100 acc = acc + cols[hi]
101 hi = hi + 1
102 var sh: i64 = 1
103 while sh == 1 {
104 if acc - cols[lo] >= need { acc = acc - cols[lo]; lo = lo + 1 } else { sh = 0 }
105 }
106 if acc >= need { if hi - lo < best { best = hi - lo } }
107 }
108 out[1] = (best * 1000) / im.w
109 }
110 return 0
111}
112
113// classify a loaded pair; returns the class code (0 ok · 1 blank · 2 strip · 3 canvas · 4 sparse ·
114// 5 no-oracle) and prints the metric line. The gate pins these codes to the human truth set.
115func rj_classify(a: *VdImg, b: *VdImg, byoff: i64) -> i64 {
116 let abg: *i64 = sys_mmap(32) as *i64
117 let bbg: *i64 = sys_mmap(32) as *i64
118 rj_bg(a, 0, abg)
119 rj_bg(b, byoff, bbg)
120 let cols: *i64 = sys_mmap((K_MAGIC_4096 * 8) as nx_size) as *i64
121 let ao: *i64 = sys_mmap(32) as *i64
122 let bo: *i64 = sys_mmap(32) as *i64
123 rj_ink(a, 0, abg, 28, cols, ao)
124 rj_ink(b, byoff, bbg, 28, cols, bo)
125 // canvas delta between the two sides' dominant backgrounds
126 var cd: i64 = 0
127 var k: i64 = 0
128 while k < 3 {
129 var d: i64 = abg[k] - bbg[k]
130 if d < 0 { d = 0 - d }
131 cd = cd + d
132 k = k + 1
133 }
134 cd = cd / 3
135 rj_w("oracle: ink=" as *u8); rj_n(ao[0]); rj_w("pm spread80=" as *u8); rj_n(ao[1])
136 rj_w("pm nishi: ink=" as *u8); rj_n(bo[0]); rj_w("pm spread80=" as *u8); rj_n(bo[1])
137 rj_w("pm canvas-delta=" as *u8); rj_n(cd); rj_w("\n" as *u8)
138 // classification (int codes -- never pointer-compare string literals; the gate pins the thresholds
139 // to the HUMAN truth set = today's eyeballed suite images):
140 // 0 ok · 1 blank-nishi · 2 strip-collapse · 3 canvas-off · 4 sparse-nishi · 5 no-oracle-content
141 var cls: i64 = 0
142 if ao[0] < 5 { cls = 5 } // oracle itself blank (bing headless-block)
143 if cls == 0 { if bo[0] >= 2 { if bo[0] <= 60 { if bo[1] < 160 { if ao[1] > 320 { cls = 2 } } } } } // narrow ink strip
144 if cls == 0 { if bo[0] < 8 { if ao[0] >= 15 { if ao[0] >= bo[0] * 4 { cls = 1 } } } } // blank vs real oracle
145 if cls == 0 { if cd > 48 { cls = 3 } }
146 if cls == 0 { if bo[0] * 4 < ao[0] { cls = 4 } }
147 rj_w("JUDGE=" as *u8)
148 if cls == 0 { rj_w("CONTENT-OK" as *u8) }
149 if cls == 1 { rj_w("BLANK-NISHI" as *u8) }
150 if cls == 2 { rj_w("STRIP-COLLAPSE" as *u8) }
151 if cls == 3 { rj_w("CANVAS-OFF" as *u8) }
152 if cls == 4 { rj_w("SPARSE-NISHI" as *u8) }
153 if cls == 5 { rj_w("NO-ORACLE-CONTENT" as *u8) }
154 rj_w("\n" as *u8)
155 return cls
156}
157
158func main(argc: i64, argv: *i64) -> i64 {
159 if argc < 3 { rj_w("usage: nx_parity_judge <oracle.png> <nishi.png> [nishi_y_offset]\n" as *u8); sys_exit(2); return 2 }
160 let a: *VdImg = vd_load(argv[1] as *u8)
161 if (a as i64) == 0 { rj_w("JUDGE=NO-ORACLE\n" as *u8); sys_exit(0); return 0 }
162 let b: *VdImg = vd_load(argv[2] as *u8)
163 if (b as i64) == 0 { rj_w("JUDGE=NO-NISHI\n" as *u8); sys_exit(0); return 0 }
164 var byoff: i64 = 44
165 if argc >= 4 { byoff = rj_atoi(argv[3] as *u8) }
166 rj_classify(a, b, byoff)
167 sys_exit(0)
168 return 0
169}