code wiki / (root) / nx_field_lib.nx

nx_field_lib.nx source

↩ module page · 405 lines · 18041 B

1// nx_field_lib.nx -- THE FIELD DISCOVERY CORE (/compare/fieldwatch FW1, 2026-09-05): the industry's own lists, 2// read mechanically, become a DISCOVERED population of rivals per domain -- never a seat's six picks. 3// 4// WHY (operator 2026-09-05, on the modding board's six columns): "those arent a good sample of the industry ... 5// the /compare emitter lags heavily there instead of giving a true beyond gartner or google search return 6// alternatives and competitors and beyond real view for all these domains." A column is a choice; a field is a 7// measurement. This lib turns three kinds of public list into candidate rows with EVIDENCE COUNTS: 8// wiki-raw Wikipedia wikitext (action=raw): every [[Target]] and [[Target|Text]] link OUTSIDE <ref> blocks and 9// OUTSIDE {{templates}} (citations and infobox plumbing are not rivals), namespace links excluded by 10// their colon (Category: File: Help: Template: ...), counted per occurrence 11// gh-topic a GitHub topic page: the repository anchors, whose markup carries the class token the page itself 12// uses for the repo name; the two-segment href is kept as the link 13// md-list a raw Markdown list (awesome-style): every - [Name](link) or * [Name](link) item 14// One table holds every candidate across seeds; a name seen in several seeds carries a seeds_hit mask and a 15// mentions count, and fl_emit writes rows sorted by seeds then mentions, so "who the field agrees on" is 16// arithmetic. The table is a declared population: when it fills, capped=1 is ANNOUNCED, never silent. 17// license_tier: ORIGINAL No hw writes (Rule 26). 18import "nx_syscalls.nx" 19 20const FL_MAX_CAND: i64 = 4096 // candidates per run; a fill is announced (capped=1), never silently dropped 21const FL_NAME_CAP: i64 = 96 // bytes per name incl. NUL 22const FL_LINK_CAP: i64 = 160 // bytes per link incl. NUL 23const FL_MAX_SEEDS: i64 = 62 // seeds_hit is a bit mask; bit 62 is the last safe bit in an i64 24const FL_REC_W: i64 = 4 // per-candidate words: mentions, seeds_hit, first_seed, kind_of_first 25const FL_KIND_WIKI: i64 = 1 26const FL_KIND_GH: i64 = 2 27const FL_KIND_MD: i64 = 3 28const FL_KIND_NAMED: i64 = 4 // a DECLARED member of the population (seed row seed|key|url|named|why|Display Name): the operator's 29 // 2026-09-05 correction -- Nexus Mods, LoversLab and the other major communities were absent from the 30 // discovered lists, so the population is ENUMERATED as data and the public lists corroborate it 31const FL_CH_LB: i64 = 91 // [ 32const FL_CH_RB: i64 = 93 // ] 33const FL_CH_LBRACE: i64 = 123 // { 34const FL_CH_RBRACE: i64 = 125 // } 35const FL_CH_LT: i64 = 60 // < 36const FL_CH_GT: i64 = 62 // > 37const FL_CH_SLASH: i64 = 47 38const FL_CH_PIPE: i64 = 124 39const FL_CH_COLON: i64 = 58 40const FL_CH_HASH: i64 = 35 41const FL_CH_SPACE: i64 = 32 42const FL_CH_NL: i64 = 10 43const FL_CH_CR: i64 = 13 44const FL_CH_TAB: i64 = 9 45const FL_CH_MINUS: i64 = 45 46const FL_CH_STAR: i64 = 42 47const FL_CH_LPAREN: i64 = 40 48const FL_CH_RPAREN: i64 = 41 49const FL_CH_QUOTE: i64 = 34 50const FL_CH_UPPER_A: i64 = 65 51const FL_CH_UPPER_Z: i64 = 90 52const FL_CASE_DELTA: i64 = 32 53const FL_GH_HREF_BACK: i64 = 400 // bytes to look back from the repo-name anchor for its href 54const FL_ASCII_ZERO: i64 = 48 55const FL_ASCII_NINE: i64 = 57 56 57// ---- the candidate table: names arena, links arena, records ---- 58func fl_tbl_new() -> *i64 { 59 let t: *i64 = sys_mmap(8 * 8) as *i64 60 t[0] = sys_mmap(FL_MAX_CAND * FL_NAME_CAP) as i64 61 t[1] = sys_mmap(FL_MAX_CAND * FL_LINK_CAP) as i64 62 t[2] = sys_mmap(FL_MAX_CAND * FL_REC_W * 8) as i64 63 t[3] = 0 // count 64 t[4] = 0 // capped 65 t[5] = 0 // total mentions added (every accepted occurrence) 66 return t 67} 68func fl_count(t: *i64) -> i64 { return t[3] } 69func fl_capped(t: *i64) -> i64 { return t[4] } 70func fl_mentions_total(t: *i64) -> i64 { return t[5] } 71func fl_name_at(t: *i64, i: i64) -> *u8 { return (t[0] + i * FL_NAME_CAP) as *u8 } 72func fl_link_at(t: *i64, i: i64) -> *u8 { return (t[1] + i * FL_LINK_CAP) as *u8 } 73func fl_rec(t: *i64, i: i64, f: i64) -> i64 { let r: *i64 = t[2] as *i64; return r[i * FL_REC_W + f] } 74func fl_rec_set(t: *i64, i: i64, f: i64, v: i64) -> i64 { let r: *i64 = t[2] as *i64; r[i * FL_REC_W + f] = v; return 0 } 75func fl_lc(c: i64) -> i64 { if c >= FL_CH_UPPER_A { if c <= FL_CH_UPPER_Z { return c + FL_CASE_DELTA } } return c } 76// case-insensitive equality of a NUL-terminated name against a byte span 77func fl_name_eq(name: *u8, b: *u8, s: i64, e: i64) -> i64 { 78 var i: i64 = 0 79 var p: i64 = s 80 while p < e { 81 if name[i] == (0 as u8) { return 0 } 82 if fl_lc(name[i] as i64) != fl_lc(b[p] as i64) { return 0 } 83 i = i + 1 84 p = p + 1 85 } 86 if name[i] != (0 as u8) { return 0 } 87 return 1 88} 89func fl_find(t: *i64, b: *u8, s: i64, e: i64) -> i64 { 90 var i: i64 = 0 91 let n: i64 = t[3] 92 while i < n { if fl_name_eq(fl_name_at(t, i), b, s, e) == 1 { return i } i = i + 1 } 93 return 0 - 1 94} 95// trim ASCII whitespace off a span in place (returns 1 when something is left) 96func fl_trim(b: *u8, sp: *i64, ep: *i64) -> i64 { 97 var s: i64 = sp[0] 98 var e: i64 = ep[0] 99 while s < e { 100 let c: i64 = b[s] as i64 101 if c == FL_CH_SPACE { s = s + 1 } else { if c == FL_CH_TAB { s = s + 1 } else { if c == FL_CH_CR { s = s + 1 } else { break } } } 102 } 103 while e > s { 104 let c: i64 = b[e - 1] as i64 105 if c == FL_CH_SPACE { e = e - 1 } else { if c == FL_CH_TAB { e = e - 1 } else { if c == FL_CH_CR { e = e - 1 } else { break } } } 106 } 107 sp[0] = s 108 ep[0] = e 109 if e > s { return 1 } 110 return 0 111} 112// add one occurrence: returns the candidate index, or -1 when refused (empty, too long, table full) 113func fl_add(t: *i64, b: *u8, s0: i64, e0: i64, link: *u8, ls: i64, le: i64, seed: i64, kind: i64) -> i64 { 114 let sp: *i64 = sys_mmap(16) as *i64 115 let ep: *i64 = sys_mmap(16) as *i64 116 sp[0] = s0 117 ep[0] = e0 118 if fl_trim(b, sp, ep) == 0 { return 0 - 1 } 119 let s: i64 = sp[0] 120 let e: i64 = ep[0] 121 if e - s >= FL_NAME_CAP - 1 { return 0 - 1 } 122 var bit: i64 = 1 123 var k: i64 = 0 124 while k < seed { if k < FL_MAX_SEEDS { bit = bit * 2 } k = k + 1 } 125 if seed >= FL_MAX_SEEDS { bit = 0 } 126 let found: i64 = fl_find(t, b, s, e) 127 if found >= 0 { 128 fl_rec_set(t, found, 0, fl_rec(t, found, 0) + 1) 129 fl_rec_set(t, found, 1, fl_rec(t, found, 1) | bit) 130 t[5] = t[5] + 1 131 return found 132 } 133 if t[3] >= FL_MAX_CAND { t[4] = 1; return 0 - 1 } 134 let i: i64 = t[3] 135 let nm: *u8 = fl_name_at(t, i) 136 var p: i64 = 0 137 while s + p < e { nm[p] = b[s + p]; p = p + 1 } 138 nm[p] = 0 as u8 139 let lk: *u8 = fl_link_at(t, i) 140 var q: i64 = 0 141 if (link as i64) != 0 { 142 while ls + q < le { if q < FL_LINK_CAP - 1 { lk[q] = link[ls + q] } q = q + 1 } 143 if q > FL_LINK_CAP - 1 { q = FL_LINK_CAP - 1 } 144 } 145 lk[q] = 0 as u8 146 fl_rec_set(t, i, 0, 1) 147 fl_rec_set(t, i, 1, bit) 148 fl_rec_set(t, i, 2, seed) 149 fl_rec_set(t, i, 3, kind) 150 t[3] = i + 1 151 t[5] = t[5] + 1 152 return i 153} 154// does the span carry a colon (a namespace link) or a hash (a section anchor)? 155func fl_span_has(b: *u8, s: i64, e: i64, ch: i64) -> i64 { 156 var p: i64 = s 157 while p < e { if (b[p] as i64) == ch { return 1 } p = p + 1 } 158 return 0 159} 160func fl_starts_at(b: *u8, n: i64, p: i64, lit: *u8) -> i64 { 161 var i: i64 = 0 162 while lit[i] != (0 as u8) { 163 if p + i >= n { return 0 } 164 if fl_lc(b[p + i] as i64) != fl_lc(lit[i] as i64) { return 0 } 165 i = i + 1 166 } 167 return 1 168} 169 170// ---- wiki-raw: [[Target]] links outside <ref>...</ref>, <ref .../> and {{...}} ---- 171func fl_wiki_scan(t: *i64, b: *u8, n: i64, seed: i64) -> i64 { 172 var added: i64 = 0 173 var refdepth: i64 = 0 174 var tdepth: i64 = 0 175 var p: i64 = 0 176 while p < n { 177 let c: i64 = b[p] as i64 178 if c == FL_CH_LT { 179 if fl_starts_at(b, n, p, "<ref" as *u8) == 1 { 180 // self-closing <ref name=x/> opens nothing 181 var q: i64 = p 182 var selfclose: i64 = 0 183 while q < n { if (b[q] as i64) == FL_CH_GT { if (b[q - 1] as i64) == FL_CH_SLASH { selfclose = 1 } break } q = q + 1 } 184 if selfclose == 0 { refdepth = refdepth + 1 } 185 p = q + 1 186 continue 187 } 188 if fl_starts_at(b, n, p, "</ref" as *u8) == 1 { 189 if refdepth > 0 { refdepth = refdepth - 1 } 190 var q2: i64 = p 191 while q2 < n { if (b[q2] as i64) == FL_CH_GT { break } q2 = q2 + 1 } 192 p = q2 + 1 193 continue 194 } 195 } 196 if c == FL_CH_LBRACE { if p + 1 < n { if (b[p + 1] as i64) == FL_CH_LBRACE { tdepth = tdepth + 1; p = p + 2; continue } } } 197 if c == FL_CH_RBRACE { if p + 1 < n { if (b[p + 1] as i64) == FL_CH_RBRACE { if tdepth > 0 { tdepth = tdepth - 1 } p = p + 2; continue } } } 198 if c == FL_CH_LB { if p + 1 < n { if (b[p + 1] as i64) == FL_CH_LB { 199 // a link: target runs to | or ]] 200 var s: i64 = p + 2 201 var e: i64 = s 202 var closed: i64 = 0 203 var cut: i64 = 0 - 1 204 while e < n { 205 let d: i64 = b[e] as i64 206 if d == FL_CH_PIPE { if cut < 0 { cut = e } } 207 if d == FL_CH_RB { if e + 1 < n { if (b[e + 1] as i64) == FL_CH_RB { closed = 1; break } } } 208 if d == FL_CH_NL { break } 209 e = e + 1 210 } 211 if closed == 1 { 212 var te: i64 = e 213 if cut >= 0 { te = cut } 214 if refdepth == 0 { if tdepth == 0 { 215 if fl_span_has(b, s, te, FL_CH_COLON) == 0 { if fl_span_has(b, s, te, FL_CH_HASH) == 0 { 216 if fl_add(t, b, s, te, b, s, te, seed, FL_KIND_WIKI) >= 0 { added = added + 1 } 217 } } 218 } } 219 p = e + 2 220 continue 221 } 222 } } } 223 p = p + 1 224 } 225 return added 226} 227 228// ---- gh-topic: repo anchors carrying the page's own repo-name class token ---- 229func fl_gh_scan(t: *i64, b: *u8, n: i64, seed: i64) -> i64 { 230 var added: i64 = 0 231 let tok: *u8 = "class=\x22Link text-bold wb-break-word\x22>" as *u8 232 var tl: i64 = 0 233 while tok[tl] != (0 as u8) { tl = tl + 1 } 234 var p: i64 = 0 235 while p + tl <= n { 236 if fl_starts_at(b, n, p, tok) == 1 { 237 let s: i64 = p + tl 238 var e: i64 = s 239 while e < n { if (b[e] as i64) == FL_CH_LT { break } e = e + 1 } 240 // the href sits shortly before the class token: href="/owner/repo" 241 var hs: i64 = 0 - 1 242 var he: i64 = 0 - 1 243 var back: i64 = p 244 var lim: i64 = p - FL_GH_HREF_BACK 245 if lim < 0 { lim = 0 } 246 while back > lim { 247 if fl_starts_at(b, n, back, "href=\x22" as *u8) == 1 { 248 hs = back + 6 249 he = hs 250 while he < n { if (b[he] as i64) == FL_CH_QUOTE { break } he = he + 1 } 251 break 252 } 253 back = back - 1 254 } 255 if e > s { 256 if hs >= 0 { if fl_add(t, b, s, e, b, hs, he, seed, FL_KIND_GH) >= 0 { added = added + 1 } } 257 if hs < 0 { if fl_add(t, b, s, e, 0 as *u8, 0, 0, seed, FL_KIND_GH) >= 0 { added = added + 1 } } 258 } 259 p = e 260 continue 261 } 262 p = p + 1 263 } 264 return added 265} 266 267// ---- md-list: - [Name](link) and * [Name](link) items ---- 268func fl_md_scan(t: *i64, b: *u8, n: i64, seed: i64) -> i64 { 269 var added: i64 = 0 270 var p: i64 = 0 271 while p < n { 272 // line start 273 var q: i64 = p 274 while q < n { if (b[q] as i64) != FL_CH_SPACE { if (b[q] as i64) != FL_CH_TAB { break } } q = q + 1 } 275 if q < n { 276 let c: i64 = b[q] as i64 277 var isitem: i64 = 0 278 if c == FL_CH_MINUS { isitem = 1 } 279 if c == FL_CH_STAR { isitem = 1 } 280 if isitem == 1 { if q + 2 < n { if (b[q + 1] as i64) == FL_CH_SPACE { if (b[q + 2] as i64) == FL_CH_LB { 281 let s: i64 = q + 3 282 var e: i64 = s 283 while e < n { if (b[e] as i64) == FL_CH_RB { break } if (b[e] as i64) == FL_CH_NL { break } e = e + 1 } 284 if e < n { if (b[e] as i64) == FL_CH_RB { if e + 1 < n { if (b[e + 1] as i64) == FL_CH_LPAREN { 285 let ls: i64 = e + 2 286 var le: i64 = ls 287 while le < n { if (b[le] as i64) == FL_CH_RPAREN { break } if (b[le] as i64) == FL_CH_NL { break } le = le + 1 } 288 if fl_add(t, b, s, e, b, ls, le, seed, FL_KIND_MD) >= 0 { added = added + 1 } 289 } } } } 290 } } } } 291 } 292 // next line 293 while p < n { if (b[p] as i64) == FL_CH_NL { break } p = p + 1 } 294 p = p + 1 295 } 296 return added 297} 298 299// ---- emit: rows sorted by seeds hit (popcount of the mask) then mentions, both descending ---- 300func fl_popcount(v: i64) -> i64 { var c: i64 = 0; var x: i64 = v; while x > 0 { c = c + (x & 1); x = x >> 1 } return c } 301func fl_puts(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 } 302func fl_putn(fd: i64, v: i64) -> i64 { 303 let b: *u8 = sys_mmap(32) 304 var x: i64 = v 305 if x < 0 { b[0] = FL_CH_MINUS as u8; sys_write(fd, b, 1); x = 0 - x } 306 if x == 0 { b[0] = FL_ASCII_ZERO as u8; sys_write(fd, b, 1); return 0 } 307 var d: i64 = 0 308 var y: i64 = x 309 while y > 0 { d = d + 1; y = y / 10 } 310 var i: i64 = d 311 while i > 0 { i = i - 1; b[i] = ((x % 10) + FL_ASCII_ZERO) as u8; x = x / 10 } 312 sys_write(fd, b, d) 313 return 0 314} 315func fl_kind_name(k: i64) -> *u8 { 316 if k == FL_KIND_WIKI { return "wiki-raw" as *u8 } 317 if k == FL_KIND_GH { return "gh-topic" as *u8 } 318 if k == FL_KIND_MD { return "md-list" as *u8 } 319 if k == FL_KIND_NAMED { return "named" as *u8 } 320 return "unknown" as *u8 321} 322// A DECLARED member of the population: name and url are NUL-terminated; it merges case-insensitively into a rival 323// the public lists already named (so seeds_hit counts the corroboration) or enters as its own row with kind named. 324// An empty name is refused (-1): a member with no name is not a member. 325// FL_DECLARED_TIER lifts a declared member above every lead in fl_order: it exceeds the largest possible seed 326// popcount (FL_MAX_SEEDS bits), so no number of corroborating lists can rank a lead above a member. 327const FL_DECLARED_TIER: i64 = 64 328func fl_named_add(t: *i64, name: *u8, url: *u8, seed: i64) -> i64 { 329 var nl: i64 = 0 330 while name[nl] != (0 as u8) { nl = nl + 1 } 331 if nl < 1 { return 0 - 1 } 332 var ul: i64 = 0 333 while url[ul] != (0 as u8) { ul = ul + 1 } 334 let idx: i64 = fl_add(t, name, 0, nl, url, 0, ul, seed, FL_KIND_NAMED) 335 // a member the public lists already named keeps its seed bits and BECOMES declared: the kind word is the 336 // population flag the page and the ordering read, so a merged member is not left looking like a lead 337 if idx >= 0 { fl_rec_set(t, idx, 3, FL_KIND_NAMED) } 338 return idx 339} 340// a pipe inside a name or link would break the row grammar: it is replaced by a space at emit time 341func fl_puts_nopipe(fd: i64, s: *u8) -> i64 { 342 var n: i64 = 0 343 while s[n] != (0 as u8) { n = n + 1 } 344 let c: *u8 = sys_mmap(n + 1) 345 var i: i64 = 0 346 while i < n { if (s[i] as i64) == FL_CH_PIPE { c[i] = FL_CH_SPACE as u8 } else { c[i] = s[i] } i = i + 1 } 347 sys_write(fd, c, n) 348 return 0 349} 350// order[] receives candidate indices sorted; returns the count. Selection sort is O(n^2) over at most 351// FL_MAX_CAND rows, deterministic, and fast enough for a population this size. 352func fl_order(t: *i64, order: *i64) -> i64 { 353 let n: i64 = t[3] 354 let used: *i64 = sys_mmap(n * 8 + 8) as *i64 355 var k: i64 = 0 356 while k < n { 357 var best: i64 = 0 - 1 358 var bs: i64 = 0 - 1 359 var bm: i64 = 0 - 1 360 var i: i64 = 0 361 while i < n { 362 if used[i] == 0 { 363 // DECLARED members are the population and rank as a tier above every lead: a member with one seed and 364 // one mention must not sit below hundreds of encyclopedia links (measured 2026-09-05 -- 31 declared 365 // communities would have fallen outside the 60 rendered rows). Within a tier: seeds, then mentions. 366 var sc: i64 = fl_popcount(fl_rec(t, i, 1)) 367 if fl_rec(t, i, 3) == FL_KIND_NAMED { sc = sc + FL_DECLARED_TIER } 368 let mc: i64 = fl_rec(t, i, 0) 369 var better: i64 = 0 370 if sc > bs { better = 1 } 371 if sc == bs { if mc > bm { better = 1 } } 372 if better == 1 { best = i; bs = sc; bm = mc } 373 } 374 i = i + 1 375 } 376 used[best] = 1 377 order[k] = best 378 k = k + 1 379 } 380 return n 381} 382// rows: rival|<name>|<seeds_hit>|<mentions>|<first_seed_key>|<link>|<kind> 383func fl_emit(t: *i64, fd: i64, seedkeys: *i64, nseeds: i64) -> i64 { 384 let n: i64 = t[3] 385 let order: *i64 = sys_mmap(n * 8 + 8) as *i64 386 fl_order(t, order) 387 var k: i64 = 0 388 while k < n { 389 let i: i64 = order[k] 390 fl_puts(fd, "rival|" as *u8) 391 fl_puts_nopipe(fd, fl_name_at(t, i)) 392 fl_puts(fd, "|" as *u8); fl_putn(fd, fl_popcount(fl_rec(t, i, 1))) 393 fl_puts(fd, "|" as *u8); fl_putn(fd, fl_rec(t, i, 0)) 394 fl_puts(fd, "|" as *u8) 395 let fs: i64 = fl_rec(t, i, 2) 396 if fs >= 0 { if fs < nseeds { fl_puts_nopipe(fd, seedkeys[fs] as *u8) } } 397 fl_puts(fd, "|" as *u8) 398 fl_puts_nopipe(fd, fl_link_at(t, i)) 399 fl_puts(fd, "|" as *u8) 400 fl_puts(fd, fl_kind_name(fl_rec(t, i, 3))) 401 fl_puts(fd, "\n" as *u8) 402 k = k + 1 403 } 404 return n 405}