code wiki / (root) / nx_swcompare_gapmap.nx

nx_swcompare_gapmap.nx source

↩ module page · 482 lines · 31895 B

1// nx_swcompare_gapmap.nx -- the GENERATIVE gap-finder of Nishi Compare, DOMAIN-PARAMETERIZED. Given a <domain>, it 2// reads knowledge/compare/<domain>.q (to learn the researcher-banked frontier corpus file names) + knowledge/ 3// compare/<domain>.axes (label|organ-path|symbol|frontier-keywords, plus an optional "@title <text>" line) -> for 4// each axis measures OUR presence (symbol on disk, mechanical) x FRONTIER MOMENTUM (keyword count over the banked 5// 2024-2026 corpus) -> classifies OPPORTUNITY (absent+hot = where to test/research), COVERED (present), dormant. 6// A NEW domain = a new .q + .axes pair; ZERO new code. Modes: `nx_swcompare_gapmap <domain>` = console + liar-kill 7// (gate); `nx_swcompare_gapmap <domain> html` = emit the /compare/<domain>/frontier page. 8// NOTE: no '#'/'!' in string literals (nx_cc trap). license_tier: ORIGINAL expect_exit:0 9import "nx_syscalls.nx" 10const K_MAGIC_100000: i64 = 100000 11 12func w(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 } 13func wc(fd: i64, code: i64) -> i64 { let t: *u8 = sys_mmap(2); t[0] = code as u8; sys_write(fd, t, 1); return 0 } 14func wn(fd: i64, v: i64) -> i64 { 15 var m: i64 = v; if m < 0 { w(fd, "-" as *u8); m = 0 - m } 16 let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 17 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 18 let o: *u8 = sys_mmap(24); var i: i64 = 0; while i < k { o[i] = t[k-1-i]; i = i + 1 } sys_write(fd, o, k); return 0 19} 20func streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 21func wj(fd: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c == 34 { wc(fd, 92); wc(fd, 34) } else { if c == 92 { wc(fd, 92); wc(fd, 92) } else { if c < 32 { wc(fd, 32) } else { wc(fd, c) } } } i = i + 1 } return 0 } 22func pj3(dst: *u8, a: *u8, b: *u8, c: *u8) -> i64 { 23 var i: i64 = 0; var j: i64 = 0 24 while a[j] != (0 as u8) { dst[i] = a[j]; i = i + 1; j = j + 1 } 25 j = 0; while b[j] != (0 as u8) { dst[i] = b[j]; i = i + 1; j = j + 1 } 26 j = 0; while c[j] != (0 as u8) { dst[i] = c[j]; i = i + 1; j = j + 1 } 27 dst[i] = 0 as u8; return i 28} 29func c_has(buf: *u8, n: i64, needle: *u8) -> i64 { 30 var i: i64 = 0 31 while i < n { var k: i64 = 0; var hit: i64 = 1 32 while needle[k] != (0 as u8) { if i + k >= n { hit = 0; k = 0 - 1; break } if buf[i+k] != needle[k] { hit = 0; break } k = k + 1 } 33 if hit == 1 { if k > 0 { return 1 } } i = i + 1 } 34 return 0 35} 36// AN ORGAN SOURCE IS READ WHOLE OR NOT AT ALL (2026-09-16). This used to read through a 262,144-byte scratch 37// window, so a symbol defined past that offset (nx_swcompare_lib alone is 316 KB) read ABSENT and the axis was 38// published as a research OPPORTUNITY the estate already covers -- a false gap in the direction nobody audits. 39// sys_read_file sizes its buffer from the file, and the exact mapping is released per axis. 40func c_file_has(path: *u8, needle: *u8) -> i64 { 41 let lenp: *i64 = sys_mmap(16) as *i64 42 let buf: *u8 = sys_read_file(path, lenp) 43 var hit: i64 = 0 44 if (buf as i64) != 0 { 45 let n: i64 = lenp[0] 46 if n > 0 { hit = c_has(buf, n, needle) } 47 sys_free_file(buf, n) 48 } 49 sys_munmap(lenp as *u8, 16) 50 return hit 51} 52func c_count(buf: *u8, n: i64, needle: *u8) -> i64 { 53 var m: i64 = 0; while needle[m] != (0 as u8) { m = m + 1 } 54 if m == 0 { return 0 } 55 var cnt: i64 = 0; var i: i64 = 0 56 while i + m <= n { 57 var k: i64 = 0; var hit: i64 = 1 58 while k < m { if buf[i+k] != needle[k] { hit = 0; break } k = k + 1 } 59 if hit == 1 { cnt = cnt + 1; i = i + m } else { i = i + 1 } 60 } 61 return cnt 62} 63// A KEYWORD COUNTS ONLY WHERE A WORD STARTS, IN ANY LETTER CASE (2026-09-16). Momentum used to be a bare case-sensitive 64// substring count, so "cid" counted inside "decided" and "acid" (mediaingest Content identity CID read 2344) while 65// "graphrag" missed every "GraphRAG" title. A hit now needs the byte before it to be neither a letter nor a digit (or 66// the corpus start). The right edge stays OPEN on purpose, because .axes keywords are written as stems ("symbolic 67// comput", "satisfiab", "neurosymbol"); a keyword ending in GM_WHOLE_WORD_MARK ("fea$") also demands a closed right 68// edge, for the short words a stem match would drown ("fea" inside "feature"). 69const GM_ASCII_UPPER_A: i64 = 65 70const GM_ASCII_UPPER_Z: i64 = 90 71const GM_ASCII_LOWER_A: i64 = 97 72const GM_ASCII_LOWER_Z: i64 = 122 73const GM_ASCII_DIGIT_0: i64 = 48 74const GM_ASCII_DIGIT_9: i64 = 57 75const GM_CASE_DELTA: i64 = 32 76const GM_WHOLE_WORD_MARK: i64 = 36 77const GM_CH_AMP: i64 = 38 78const GM_CH_LT: i64 = 60 79const GM_CH_GT: i64 = 62 80const GM_CH_DQUOTE: i64 = 34 81const GM_CH_SQUOTE: i64 = 39 82const GM_CH_MINUS: i64 = 45 83const GM_DECIMAL: i64 = 10 84const GM_KW_ENTRY_SLACK: i64 = 24 85func gm_lower(c: i64) -> i64 { if c >= GM_ASCII_UPPER_A { if c <= GM_ASCII_UPPER_Z { return c + GM_CASE_DELTA } } return c } 86func gm_is_alnum(c: i64) -> i64 { 87 let l: i64 = gm_lower(c) 88 if l >= GM_ASCII_LOWER_A { if l <= GM_ASCII_LOWER_Z { return 1 } } 89 if c >= GM_ASCII_DIGIT_0 { if c <= GM_ASCII_DIGIT_9 { return 1 } } 90 return 0 91} 92func c_count_word(buf: *u8, n: i64, needle: *u8) -> i64 { 93 var m: i64 = 0; while needle[m] != (0 as u8) { m = m + 1 } 94 var whole: i64 = 0 95 if m > 0 { if (needle[m - 1] as i64) == GM_WHOLE_WORD_MARK { whole = 1; m = m - 1 } } 96 if m == 0 { return 0 } 97 // the first byte is compared inline in both letter cases, so the boundary and case helpers run only at candidates 98 let n0: i64 = gm_lower(needle[0] as i64) 99 var n0u: i64 = n0 100 if n0 >= GM_ASCII_LOWER_A { if n0 <= GM_ASCII_LOWER_Z { n0u = n0 - GM_CASE_DELTA } } 101 var cnt: i64 = 0; var i: i64 = 0 102 while i + m <= n { 103 var hit: i64 = 0 104 let c0: i64 = buf[i] as i64 105 if c0 == n0 { hit = 1 } 106 if c0 == n0u { hit = 1 } 107 if hit == 1 { if i > 0 { if gm_is_alnum(buf[i - 1] as i64) == 1 { hit = 0 } } } 108 if hit == 1 { 109 var k: i64 = 1 110 while k < m { if gm_lower(buf[i + k] as i64) != gm_lower(needle[k] as i64) { hit = 0; break } k = k + 1 } 111 } 112 if hit == 1 { if whole == 1 { if i + m < n { if gm_is_alnum(buf[i + m] as i64) == 1 { hit = 0 } } } } 113 if hit == 1 { cnt = cnt + 1; i = i + m } else { i = i + 1 } 114 } 115 return cnt 116} 117func gm_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64 = off; var i: i64 = 0; while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } dst[o] = 0 as u8; return o } 118// append the decimal of v at dst[off], NUL-terminated; returns the new offset 119func gm_catn(dst: *u8, off: i64, v: i64) -> i64 { 120 var o: i64 = off 121 var m: i64 = v 122 if m < 0 { dst[o] = GM_CH_MINUS as u8; o = o + 1; m = 0 - m } 123 var start: i64 = o 124 if m == 0 { dst[o] = GM_ASCII_DIGIT_0 as u8; o = o + 1 } 125 while m > 0 { dst[o] = (GM_ASCII_DIGIT_0 + (m % GM_DECIMAL)) as u8; m = m / GM_DECIMAL; o = o + 1 } 126 var a: i64 = start; var b: i64 = o - 1 127 while a < b { let t: u8 = dst[a]; dst[a] = dst[b]; dst[b] = t; a = a + 1; b = b - 1 } 128 dst[o] = 0 as u8 129 return o 130} 131// DATA IS ESCAPED WHERE IT ENTERS MARKUP (2026-09-16): the page wrote .axes labels and the @title raw, so the stem title 132// "STEM & Digital-Twin Fabrication" shipped a bare ampersand and any label carrying a less-than sign would open a tag 133func wh(fd: i64, s: *u8) -> i64 { 134 var i: i64 = 0 135 while s[i] != (0 as u8) { 136 let c: i64 = s[i] as i64 137 if c == GM_CH_AMP { w(fd, "&amp;" as *u8) } else { if c == GM_CH_LT { w(fd, "&lt;" as *u8) } else { if c == GM_CH_GT { w(fd, "&gt;" as *u8) } else { if c == GM_CH_DQUOTE { w(fd, "&quot;" as *u8) } else { if c == GM_CH_SQUOTE { w(fd, "&apos;" as *u8) } else { wc(fd, c) } } } } } 138 i = i + 1 139 } 140 return 0 141} 142func load_append(dst: *u8, off: i64, cap: i64, path: *u8) -> i64 { 143 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } 144 var tot: i64 = 0 145 while off + tot < cap { let r: i64 = sys_read(fd, (dst as i64 + off + tot) as *u8, cap - off - tot); if r <= 0 { break } tot = tot + r } 146 sys_close(fd); return tot 147} 148// derive the frontier corpus from <domain>.q bank names: for each "bankname<TAB>url", load knowledge/library/<bankname>.txt 149// THE CORPUS IS SIZED FROM ITS BANKS, NEVER FROM A GUESS (2026-09-16). A fixed 4 MiB loader became a silent FLOOR 150// the day a domain banked seven OpenAlex pages (livingdocs, about 4.7 MB): the envelope announced itself, but the cap 151// was a guessed number that only moved the cliff. ONE walk over the .q rows both SIZES the corpus (sizing=1, lseek END 152// per bank) and LOADS it (sizing=0), so the two passes cannot disagree about which rows name a bank. stats[0] counts 153// the bank rows declared and stats[1] the banks present on disk, so a RED radar can say WHICH conjunct it lacks. 154// A bank that grows between the passes still trips the announced envelope in main. 155const GM_LIB_DIR: *u8 = "knowledge/library/" 156const GM_LIB_EXT: *u8 = ".txt" 157const GM_SEEK_END: i64 = 2 158const GM_PATH_SLACK: i64 = 32 159func q_walk(qb: *u8, qn: i64, FRONT: *u8, fcap: i64, sizing: i64, stats: *i64) -> i64 { 160 var FN: i64 = 0 161 let nameb: *u8 = sys_mmap(qn + 1) 162 let pathb: *u8 = sys_mmap(qn + GM_PATH_SLACK) 163 stats[0] = 0 164 stats[1] = 0 165 var i: i64 = 0 166 while i < qn { 167 var j: i64 = i 168 var tb: i64 = 0 - 1 169 while j < qn { if qb[j] == (10 as u8) { break } if qb[j] == (9 as u8) { if tb < 0 { tb = j } } j = j + 1 } 170 if qb[i] != (35 as u8) { 171 if tb > i { 172 var k: i64 = 0 173 while (i + k) < tb { nameb[k] = qb[i+k]; k = k + 1 } 174 nameb[k] = 0 as u8 175 pj3(pathb, GM_LIB_DIR, nameb, GM_LIB_EXT) 176 stats[0] = stats[0] + 1 177 if sizing == 1 { 178 let fd: i64 = sys_openat_rd(pathb) 179 if fd >= 0 { 180 let sz: i64 = sys_lseek(fd, 0, GM_SEEK_END) 181 if sz > 0 { FN = FN + sz; stats[1] = stats[1] + 1 } 182 sys_close(fd) 183 } 184 } else { 185 let got: i64 = load_append(FRONT, FN, fcap, pathb) 186 if got > 0 { stats[1] = stats[1] + 1 } 187 FN = FN + got 188 } 189 } 190 } 191 i = j + 1 192 } 193 sys_munmap(nameb, qn + 1) 194 sys_munmap(pathb, qn + GM_PATH_SLACK) 195 return FN 196} 197 198func main(argc: i64, argv: *i64) -> i64 { 199 var domain: *u8 = "computational" as *u8 200 if argc >= 2 { domain = argv[1] as *u8 } 201 var html: i64 = 0 202 if argc >= 3 { if streq(argv[2] as *u8, "html" as *u8) == 1 { html = 1 } } 203 var jsonm: i64 = 0 204 if argc >= 3 { if streq(argv[2] as *u8, "json" as *u8) == 1 { jsonm = 1 } } 205 206 var dlen: i64 = 0 207 while domain[dlen] != (0 as u8) { dlen = dlen + 1 } 208 let qpath: *u8 = sys_mmap(dlen + GM_PATH_SLACK); pj3(qpath, "knowledge/compare/" as *u8, domain, ".q" as *u8) 209 let axpath: *u8 = sys_mmap(dlen + GM_PATH_SLACK); pj3(axpath, "knowledge/compare/" as *u8, domain, ".axes" as *u8) 210 211 // the .q roster and the .axes spec are read WHOLE (sys_read_file sizes from the file); an absent file reads as 0 bytes 212 let qlenp: *i64 = sys_mmap(16) as *i64 213 var qb: *u8 = sys_read_file(qpath, qlenp) 214 var qn: i64 = 0 215 if (qb as i64) != 0 { qn = qlenp[0] } 216 if qn <= 0 { qn = 0; qb = sys_mmap(1) } 217 let bstat: *i64 = sys_mmap(16) as *i64 218 let fcap: i64 = q_walk(qb, qn, 0 as *u8, 0, 1, bstat) + 1 219 let FRONT: *u8 = sys_mmap(fcap) 220 let FN: i64 = q_walk(qb, qn, FRONT, fcap, 0, bstat) 221 let banks_declared: i64 = bstat[0] 222 let banks_present: i64 = bstat[1] 223 // scale-law (operator 2026-07-18): NEVER cap silently -- the loader is sized from the banks above, so this can 224 // only fire when a bank GREW between the sizing walk and the load; it is still DECLARED in every output mode. 225 var trunc: i64 = 0 226 if FN >= fcap { trunc = 1 } 227 228 let slenp: *i64 = sys_mmap(16) as *i64 229 var sbuf: *u8 = sys_read_file(axpath, slenp) 230 var sn: i64 = 0 231 if (sbuf as i64) != 0 { sn = slenp[0] } 232 if sn <= 0 { sn = 0; sbuf = sys_mmap(1) } 233 234 // every per-axis table is sized from the spec itself: at most one axis per line, and no field, keyword or label 235 // can be longer than the spec that holds it -- so no row is dropped past a 64-axis table and no field is cut 236 var axcap: i64 = 1 237 var lc: i64 = 0 238 while lc < sn { if sbuf[lc] == (10 as u8) { axcap = axcap + 1 } lc = lc + 1 } 239 let fstride: i64 = sn + 1 240 let al: *i64 = sys_mmap(axcap * 8) 241 let ap: *i64 = sys_mmap(axcap * 8) 242 let ah: *i64 = sys_mmap(axcap * 8) 243 let labarena: *u8 = sys_mmap(fstride) 244 var labpos: i64 = 0 245 let fbuf: *u8 = sys_mmap(fstride * 4) 246 let kbuf: *u8 = sys_mmap(fstride) 247 // per-axis keyword breakdown "kw=n; kw=n": every keyword is a slice of the spec, and each costs at most GM_KW_ENTRY_SLACK 248 // bytes of separator and digits, so the arena is sized from the spec rather than guessed 249 let kwcap: i64 = fstride + (fstride + axcap) * GM_KW_ENTRY_SLACK 250 let kwarena: *u8 = sys_mmap(kwcap) 251 var kwpos: i64 = 0 252 let akw: *i64 = sys_mmap(axcap * 8) 253 let titleb: *u8 = sys_mmap(fstride + dlen) 254 var tset: i64 = 0 255 var n: i64 = 0 256 257 var i: i64 = 0 258 while i < sn { 259 var j: i64 = i 260 while j < sn { if sbuf[j] == (10 as u8) { break } j = j + 1 } 261 if sbuf[i] == (64 as u8) { 262 // "@title <text>" directive: capture text after the first space 263 var d: i64 = i + 1 264 while d < j { if sbuf[d] == (32 as u8) { break } d = d + 1 } 265 d = d + 1 266 var tp: i64 = 0 267 while d < j { titleb[tp] = sbuf[d]; tp = tp + 1; d = d + 1 } 268 titleb[tp] = 0 as u8 269 tset = 1 270 } else { 271 if sbuf[i] != (35 as u8) { 272 if j > i { 273 var fi: i64 = 0; var fp: i64 = 0 274 var q: i64 = i 275 while q < j { 276 let ch: u8 = sbuf[q] 277 if ch == (124 as u8) { fbuf[fi*fstride + fp] = 0 as u8; if fi < 3 { fi = fi + 1 } fp = 0 } else { fbuf[fi*fstride + fp] = ch; fp = fp + 1 } 278 q = q + 1 279 } 280 fbuf[fi*fstride + fp] = 0 as u8 281 if fi == 3 { 282 let f0: *u8 = (fbuf as i64) as *u8 283 let f1: *u8 = (fbuf as i64 + fstride) as *u8 284 let f2: *u8 = (fbuf as i64 + fstride * 2) as *u8 285 let f3: *u8 = (fbuf as i64 + fstride * 3) as *u8 286 var lp: i64 = labpos; var c0: i64 = 0 287 while f0[c0] != (0 as u8) { labarena[lp + c0] = f0[c0]; c0 = c0 + 1 } 288 labarena[lp + c0] = 0 as u8 289 al[n] = (labarena as i64 + lp) 290 labpos = lp + c0 + 1 291 ap[n] = c_file_has(f1, f2) 292 let kwstart: i64 = kwpos 293 kwarena[kwpos] = 0 as u8 294 var hits: i64 = 0; var kp: i64 = 0; var r: i64 = 0 295 while r >= 0 { 296 let ch2: u8 = f3[r] 297 var flush: i64 = 0 298 if ch2 == (0 as u8) { flush = 1 } 299 if ch2 == (59 as u8) { flush = 1 } 300 if flush == 1 { 301 kbuf[kp] = 0 as u8 302 if kp > 0 { 303 let kh: i64 = c_count_word(FRONT, FN, kbuf) 304 hits = hits + kh 305 if kwpos > kwstart { kwpos = gm_cat(kwarena, kwpos, "; " as *u8) } 306 kwpos = gm_cat(kwarena, kwpos, kbuf); kwpos = gm_cat(kwarena, kwpos, "=" as *u8); kwpos = gm_catn(kwarena, kwpos, kh) 307 } 308 kp = 0 309 if ch2 == (0 as u8) { r = 0 - 2 } 310 } else { kbuf[kp] = ch2; kp = kp + 1 } 311 r = r + 1 312 } 313 ah[n] = hits 314 akw[n] = (kwarena as i64 + kwstart) 315 kwpos = kwpos + 1 316 n = n + 1 317 } 318 } 319 } 320 } 321 i = j + 1 322 } 323 if tset == 0 { var c9: i64 = 0; while domain[c9] != (0 as u8) { titleb[c9] = domain[c9]; c9 = c9 + 1 } titleb[c9] = 0 as u8 } 324 325 let order: *i64 = sys_mmap(axcap * 8) 326 var z: i64 = 0; while z < n { order[z] = z; z = z + 1 } 327 var s1: i64 = 0 328 while s1 < n { 329 var best: i64 = s1; var s2: i64 = s1 + 1 330 while s2 < n { if ah[order[s2]] > ah[order[best]] { best = s2 } s2 = s2 + 1 } 331 let tmp: i64 = order[s1]; order[s1] = order[best]; order[best] = tmp 332 s1 = s1 + 1 333 } 334 var maxh: i64 = 0 335 if n > 0 { maxh = ah[order[0]] } 336 337 var opp: i64 = 0; var cov: i64 = 0; var dorm: i64 = 0 338 var t: i64 = 0 339 while t < n { 340 if ap[t] == 1 { cov = cov + 1 } else { if ah[t] > 0 { opp = opp + 1 } else { dorm = dorm + 1 } } 341 t = t + 1 342 } 343 let neg: i64 = c_count(FRONT, FN, "zqxjq_wolfram_notacap" as *u8) 344 345 if jsonm == 1 { 346 wc(1, 123) 347 wc(1, 34); w(1, "v" as *u8); wc(1, 34); wc(1, 58); wn(1, 1); wc(1, 44) 348 // FRESHNESS IS A PROPERTY OF THE EMIT, SO THE EMITTER MUST STAMP IT (2026-08-08). Measured: 349 // computational/video/civic served a live api.json with NO timestamp, so "is this surface still 350 // updating?" was unanswerable for them -- not stale, not fresh, UNOBSERVABLE. A consumer cannot 351 // distinguish a radar regenerated seconds ago from one frozen for a month. 352 // Stamped HERE at emit time, which is a fact this process knows; never hand-written into an 353 // artifact afterwards, which would be a fabricated measurement rather than a recorded one. 354 wc(1, 34); w(1, "generated_unix" as *u8); wc(1, 34); wc(1, 58); wn(1, sys_now_realtime_sec()); wc(1, 44) 355 wc(1, 34); w(1, "domain" as *u8); wc(1, 34); wc(1, 58); wc(1, 34); wj(1, domain); wc(1, 34); wc(1, 44) 356 wc(1, 34); w(1, "title" as *u8); wc(1, 34); wc(1, 58); wc(1, 34); wj(1, titleb); wc(1, 34); wc(1, 44) 357 wc(1, 34); w(1, "kind" as *u8); wc(1, 34); wc(1, 58); wc(1, 34); w(1, "frontier-radar" as *u8); wc(1, 34); wc(1, 44) 358 wc(1, 34); w(1, "corpus_bytes" as *u8); wc(1, 34); wc(1, 58); wn(1, FN); wc(1, 44) 359 wc(1, 34); w(1, "banks_declared" as *u8); wc(1, 34); wc(1, 58); wn(1, banks_declared); wc(1, 44) 360 wc(1, 34); w(1, "banks_present" as *u8); wc(1, 34); wc(1, 58); wn(1, banks_present); wc(1, 44) 361 wc(1, 34); w(1, "corpus_truncated_at_cap" as *u8); wc(1, 34); wc(1, 58); wn(1, trunc); wc(1, 44) 362 wc(1, 34); w(1, "opportunities" as *u8); wc(1, 34); wc(1, 58); wn(1, opp); wc(1, 44) 363 wc(1, 34); w(1, "axes" as *u8); wc(1, 34); wc(1, 58); wc(1, 91) 364 var ji: i64 = 0 365 while ji < n { 366 let ix: i64 = order[ji] 367 if ji > 0 { wc(1, 44) } 368 wc(1, 123) 369 wc(1, 34); w(1, "axis" as *u8); wc(1, 34); wc(1, 58); wc(1, 34); wj(1, al[ix] as *u8); wc(1, 34); wc(1, 44) 370 wc(1, 34); w(1, "keywords" as *u8); wc(1, 34); wc(1, 58); wc(1, 34); wj(1, akw[ix] as *u8); wc(1, 34); wc(1, 44) 371 wc(1, 34); w(1, "present" as *u8); wc(1, 34); wc(1, 58); wn(1, ap[ix]); wc(1, 44) 372 wc(1, 34); w(1, "momentum" as *u8); wc(1, 34); wc(1, 58); wn(1, ah[ix]); wc(1, 44) 373 wc(1, 34); w(1, "signal" as *u8); wc(1, 34); wc(1, 58); wc(1, 34) 374 if ap[ix] == 1 { w(1, "covered" as *u8) } else { if ah[ix] > 0 { w(1, "opportunity" as *u8) } else { w(1, "dormant" as *u8) } } 375 wc(1, 34) 376 wc(1, 125) 377 ji = ji + 1 378 } 379 wc(1, 93); wc(1, 44) 380 wc(1, 34); w(1, "generated_by" as *u8); wc(1, 34); wc(1, 58); wc(1, 34); w(1, "nx_swcompare_gapmap" as *u8); wc(1, 34) 381 wc(1, 125); wc(1, 10) 382 sys_exit(0); return 0 383 } 384 385 if html == 1 { 386 w(1, "<" as *u8); wc(1, 33); w(1, "DOCTYPE html>\n<html lang=\"en\"><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'>\n" as *u8) 387 w(1, "<title>Nishi Compare -- Frontier Radar: " as *u8); wh(1, titleb); w(1, "</title>\n<style>\n" as *u8) 388 w(1, ":root{--nx-color-bg:rgb(255,255,255);--nx-color-fg:rgb(22,22,34);--nx-color-accent:rgb(42,77,143);--bg:var(--nx-color-bg);--fg:var(--nx-color-fg);--ac:var(--nx-color-accent);--y:rgb(26,127,55);--n:rgb(179,38,30);--op:rgb(178,106,0);--line:rgb(227,227,234);--soft:rgb(246,247,251)}\n" as *u8) 389 w(1, "*{box-sizing:border-box}body{background:var(--bg);font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:1000px;margin:0 auto;padding:0 clamp(14px,4vw,20px) 5vh;color:var(--fg);line-height:1.6;font-size:clamp(15px,0.6vw + 13px,17px)}\n" as *u8) 390 w(1, "h1{font-size:clamp(1.6rem,4vw,2rem);margin:0 0 4px;background:linear-gradient(90deg,var(--ac),var(--op));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}.sub{color:rgb(102,102,102);font-size:clamp(.95rem,2vw,1.05rem);margin:0 0 4px}.crumb{font-size:.85rem;margin-bottom:18px}a{color:var(--ac)}\n" as *u8) 391 w(1, ".skip-link{position:absolute;left:-999px;top:0;background:var(--ac);color:rgb(255,255,255);padding:12px 16px;z-index:9;border-radius:0 0 8px 0}.skip-link:focus{left:0}\n" as *u8) 392 w(1, ".hd{background:linear-gradient(90deg,var(--ac),rgb(9,58,136));border-radius:0 0 12px 12px;margin:0 0 20px}.hd nav{display:flex;gap:8px;flex-wrap:wrap;padding:8px 14px}.hd a{color:rgb(255,255,255);text-decoration:none;padding:10px 12px;border-radius:8px;font-weight:600;min-height:44px;display:inline-flex;align-items:center}.hd a:hover{background:rgba(255,255,255,0.16)}\n" as *u8) 393 w(1, ".meth{background:var(--soft);border:1px solid var(--line);border-radius:12px;padding:14px 18px;margin:18px 0;font-size:.9rem;color:rgb(51,51,51)}\n" as *u8) 394 w(1, ".opp{background:rgb(255,248,235);border:1px solid rgb(240,215,170);border-radius:12px;padding:14px 18px;margin:18px 0}.opp b{color:var(--op)}\n" as *u8) 395 w(1, ".wrap{overflow-x:auto;border:1px solid var(--line);border-radius:12px;box-shadow:0 1px 3px rgba(16,20,28,0.08)}table{border-collapse:collapse;width:100%;min-width:720px;font-size:.93rem}\n" as *u8) 396 w(1, "th,td{padding:9px 12px;text-align:left;border-bottom:1px solid var(--line)}thead th{background:var(--soft);font-weight:600}.cat{font-weight:600}\n" as *u8) 397 w(1, ".sig{font-weight:600;font-size:.8rem;padding:2px 9px;border-radius:20px}.sig.o{background:rgb(245,220,180);color:rgb(120,70,0)}.sig.c{background:rgb(200,235,208);color:rgb(20,100,45)}.sig.d{background:var(--soft);color:rgb(120,120,120)}\n" as *u8) 398 w(1, ".barwrap{background:var(--soft);border-radius:6px;height:16px;width:150px;overflow:hidden}.barf{height:16px;background:var(--ac)}.barf.o{background:var(--op)}.mm{font-size:.8rem;color:rgb(102,102,102)}\n" as *u8) 399 w(1, ".foot{margin-top:28px;color:rgb(136,136,136);font-size:.78rem;border-top:1px solid var(--line);padding-top:14px}\n" as *u8) 400 w(1, ":focus-visible{outline:3px solid var(--ac);outline-offset:2px}main>*{animation:rise .5s ease both}main>*:nth-child(2){animation-delay:.05s}main>*:nth-child(3){animation-delay:.1s}main>*:nth-child(4){animation-delay:.15s}@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}.wrap,.opp{animation:rise linear both;animation-timeline:view();animation-range:entry 0% cover 22%}@media(prefers-reduced-motion:reduce){main>*,.wrap,.opp{animation:none}}\n" as *u8) 401 w(1, "@media(prefers-color-scheme:dark){:root{--nx-color-bg:rgb(15,15,20);--nx-color-fg:rgb(230,230,238);--line:rgb(38,38,47);--soft:rgb(23,23,31)}.opp{background:rgb(35,28,15);border-color:rgb(90,70,30)}}\n" as *u8) 402 w(1, "</style></head><body>\n" as *u8) 403 w(1, "<a class='skip-link' href='" as *u8); wc(1, 35); w(1, "main'>Skip to content</a><header class='hd'><nav><svg viewBox='0 0 24 24' width='22' height='22' aria-hidden='true' style='color:rgb(255,255,255)'><circle cx='12' cy='12' r='9' fill='none' stroke='currentColor' stroke-width='2'/><path d='M8 12h8M12 8v8' stroke='currentColor' stroke-width='2'/></svg><a href='/'>Nishi Family</a><a href='/compare'>Compare</a></nav></header><main id='main'>\n" as *u8) 404 w(1, "<p class='crumb'><a href='/'>Nishi Family</a> &rsaquo; <a href='/compare'>Compare</a> &rsaquo; Frontier Radar</p>\n" as *u8) 405 w(1, "<h1>Frontier Radar &mdash; " as *u8); wh(1, titleb); w(1, "</h1>\n<p class='sub'>Where the 2025/26 research frontier is moving, and where Nishi should test, deepen, or research next.</p>\n" as *u8) 406 w(1, "<div class='meth'><b>How this works.</b> The nishi researcher banked the current (2024-2026) frontier for this domain over sovereign TLS (keyless OpenAlex/arXiv). For each capability axis this radar measures <b>frontier momentum</b> = how often the frontier corpus mentions it, times <b>our organ presence</b> (probed on disk). <b>Absent + hot = a research opportunity / where to test</b>. Corpus measured: " as *u8) 407 wn(1, FN); w(1, " bytes. Generated by nx_swcompare_gapmap over a data-only domain spec (" as *u8); w(1, domain); w(1, ".q + " as *u8); w(1, domain); w(1, ".axes) &mdash; zero domain-specific code.</div>\n" as *u8) 408 if trunc == 1 { w(1, "<div class='opp'><b>Envelope declared.</b> The banked corpus FILLED the loader cap (" as *u8); wn(1, fcap); w(1, " bytes) and was truncated &mdash; momentum counts for late .q banks are a <b>floor, not exact</b>. Trim the .q bank set or raise the cap.</div>\n" as *u8) } 409 w(1, "<div class='opp'><b>Top research opportunities</b> (the 2025/26 frontier is active here and Nishi has no organ yet):<ul>\n" as *u8) 410 var oi: i64 = 0 411 while oi < n { 412 let idx: i64 = order[oi] 413 if ap[idx] == 0 { if ah[idx] > 0 { w(1, "<li><b>" as *u8); wh(1, al[idx] as *u8); w(1, "</b> &mdash; frontier momentum " as *u8); wn(1, ah[idx]); w(1, "</li>\n" as *u8) } } 414 oi = oi + 1 415 } 416 w(1, "</ul></div>\n" as *u8) 417 w(1, "<h2 style='font-size:clamp(1.05rem,2.5vw,1.25rem);margin:24px 0 10px'>Capability axes</h2>\n" as *u8) 418 w(1, "<div class='wrap'><table><thead><tr><th>Capability axis</th><th>Nishi organ</th><th>Frontier momentum (2025/26)</th><th>Signal</th></tr></thead><tbody>\n" as *u8) 419 var ri: i64 = 0 420 while ri < n { 421 let idx2: i64 = order[ri] 422 w(1, "<tr><td class='cat'>" as *u8); wh(1, al[idx2] as *u8); w(1, "</td>" as *u8) 423 if ap[idx2] == 1 { w(1, "<td style='color:var(--y);font-weight:600'>present</td>" as *u8) } else { w(1, "<td style='color:var(--n);font-weight:600'>absent</td>" as *u8) } 424 var pct: i64 = 0 425 if maxh > 0 { pct = (ah[idx2] * 100) / maxh } 426 w(1, "<td><div class='barwrap'><div class='barf" as *u8) 427 if ap[idx2] == 0 { w(1, " o" as *u8) } 428 w(1, "' style='width:" as *u8); wn(1, pct); w(1, "%'></div></div><span class='mm'>" as *u8); wn(1, ah[idx2]); w(1, " mentions</span><div class='mm'>" as *u8); wh(1, akw[idx2] as *u8); w(1, "</div></td>" as *u8) 429 if ap[idx2] == 1 { w(1, "<td><span class='sig c'>COVERED</span></td>" as *u8) } else { if ah[idx2] > 0 { w(1, "<td><span class='sig o'>OPPORTUNITY</span></td>" as *u8) } else { w(1, "<td><span class='sig d'>dormant</span></td>" as *u8) } } 430 w(1, "</tr>\n" as *u8) 431 ri = ri + 1 432 } 433 w(1, "</tbody></table></div>\n" as *u8) 434 w(1, "<p class='sub' style='font-size:.9rem;margin-top:16px'>Opportunities " as *u8); wn(1, opp); w(1, " &middot; covered " as *u8); wn(1, cov); w(1, " &middot; dormant " as *u8); wn(1, dorm); w(1, "</p>\n" as *u8) 435 w(1, "<p class='foot'>frontier momentum is a mechanical keyword count over real 2024-2026 works: a keyword counts where a word starts, in any letter case, and each axis lists its per-keyword counts so a keyword that saturates is visible; our presence is probed on disk. A discovery signal, not a ranking of importance. Zero JS, zero trackers.</p>\n" as *u8) 436 w(1, "</main></body></html>\n" as *u8) 437 sys_exit(0); return 0 438 } 439 440 w(1, "=== NX-SWCOMPARE-GAPMAP domain=" as *u8); w(1, domain); w(1, " (researcher-fed 2025/26 frontier radar) ===\n" as *u8) 441 w(1, " title="); w(1, titleb); w(1, " frontier corpus="); wn(1, FN); w(1, " bytes banks="); wn(1, banks_present); w(1, "/"); wn(1, banks_declared); w(1, " axes="); wn(1, n); w(1, "\n" as *u8) 442 if trunc == 1 { w(1, " CORPUS-TRUNCATED-AT-CAP: banks exceed the loader envelope -- late-bank momentum is a FLOOR (declared per scale-law, never silent)\n" as *u8) } 443 var p: i64 = 0 444 while p < n { 445 let idx: i64 = order[p] 446 w(1, " [" as *u8) 447 if ap[idx] == 1 { w(1, "COVERED " as *u8) } else { if ah[idx] > 0 { w(1, "OPPORTUNITY" as *u8) } else { w(1, "dormant " as *u8) } } 448 w(1, "] mom="); wn(1, ah[idx]); w(1, " "); w(1, al[idx] as *u8); w(1, "\n" as *u8) 449 w(1, " keywords: " as *u8); w(1, akw[idx] as *u8); w(1, "\n" as *u8) 450 p = p + 1 451 } 452 w(1, " TALLY: opportunities="); wn(1, opp); w(1, " covered="); wn(1, cov); w(1, " dormant="); wn(1, dorm); w(1, "\n" as *u8) 453 let liar_corpus: i64 = (FN > K_MAGIC_100000) as i64 454 let liar_neg: i64 = (neg == 0) as i64 455 // 2026-07-09: a domain may LEGITIMATELY reach opportunities=0 (the llm 456 // domain closed all axes). The old control (opp>=1) then fired a FALSE 457 // RED. When opp==0, prove the classifier CAN still emit OPPORTUNITY: 458 // probe a reserved, guaranteed-absent organ path through the SAME 459 // presence machinery; absent + the domain's own max momentum (>0) must 460 // classify OPPORTUNITY. Real-opportunity domains keep the old path. 461 let liar_opp_real: i64 = (opp >= 1) as i64 462 var liar_opp: i64 = liar_opp_real 463 var syn_used: i64 = 0 464 if liar_opp == 0 { 465 let synp: i64 = c_file_has("runtime/nx__gapmap_synth_absent__.nx" as *u8, "nx_never" as *u8) 466 if synp == 0 { if maxh > 0 { liar_opp = 1; syn_used = 1 } } 467 } 468 let liar_cov: i64 = (cov >= 1) as i64 469 w(1, " LIAR-KILL: corpus-loaded="); wn(1, liar_corpus); w(1, " neg-control-zero="); wn(1, liar_neg); w(1, " found-opportunities="); wn(1, liar_opp) 470 if syn_used == 1 { w(1, " (ALL-COVERED; synthetic classifier probe green)" as *u8) } 471 w(1, " has-covered="); wn(1, liar_cov); w(1, " corpus_bytes="); wn(1, FN); w(1, " banks="); wn(1, banks_present); w(1, "/"); wn(1, banks_declared); w(1, "\n" as *u8) 472 let ok: i64 = liar_corpus & liar_neg & liar_opp & liar_cov 473 w(1, "NX-SWCOMPARE-GAPMAP domain="); w(1, domain); w(1, " opportunities="); wn(1, opp); w(1, " verdict=") 474 if ok == 1 { w(1, "MEASURED-HONEST (liar-killed) -- researcher-fed frontier radar; opportunities ranked by 2025/26 momentum\n" as *u8); sys_exit(0); return 0 } 475 // the RED names the conjuncts that failed, in the order the LIAR-KILL line prints them, so no reader has to guess which 476 w(1, "RED (failed:" as *u8) 477 if liar_corpus == 0 { w(1, " corpus-loaded" as *u8) } 478 if liar_neg == 0 { w(1, " neg-control-zero" as *u8) } 479 if liar_opp == 0 { w(1, " found-opportunities" as *u8) } 480 if liar_cov == 0 { w(1, " has-covered" as *u8) } 481 w(1, ")\n" as *u8); sys_exit(1); return 1 482}