code wiki / _hdl_build / nx_extract_heal.nx

nx_extract_heal.nx source

↩ module page · 222 lines · 10320 B

1// nx_extract_heal.nx -- SELF-HEALING, ADAPTIVE media-URL recognition. The insight: make pattern recognition 2// DATA-DRIVEN (a pattern TABLE, not hardcoded logic), so the system can LEARN a new pattern from a failure 3// and ADAPT -- instead of a human editing code every time a site changes. Flow: classify via the table; on a 4// MISS for a URL a critic/adversary confirms IS media, LOG it + LEARN (add a pattern derived from the URL, e.g. 5// its CDN host) so the next URL from that source is caught. This is how "auto-heal + adapt" beats yt-dlp's 6// break-then-hand-patch cycle. Seeds with the same knowledge as nx_media_signal's xt_classify (now as DATA). 7import "nx_syscalls.nx" 8import "nx_media_signal.nx" // xt_find + XT_* kind consts 9const XSIG_MAGIC_4096: i64 = 4096 10const XSIG_MAGIC_4095: i64 = 4095 11const XSIG_MAGIC_1048576: i64 = 1048576 12 13const XSIG_EXT: i64 = 1 14const XSIG_PATH: i64 = 2 15const XSIG_HOST: i64 = 3 16const XH_STRIDE: i64 = 5 // per-pattern: [sigtype, pat_ptr, patlen, kind, conf] 17const XH_MAXPAT: i64 = 1024 18 19func xh_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 20func xh_new() -> *i64 { let t: *i64 = sys_mmap(8 * (1 + XH_MAXPAT * XH_STRIDE)) as *i64; t[0] = 0; return t } 21func xh_add(t: *i64, sigtype: i64, pat: *u8, patlen: i64, kind: i64, conf: i64) -> i64 { 22 if t[0] >= XH_MAXPAT { return 1 } 23 let b: i64 = 1 + t[0] * XH_STRIDE 24 t[b] = sigtype; t[b+1] = pat as i64; t[b+2] = patlen; t[b+3] = kind; t[b+4] = conf 25 t[0] = t[0] + 1 26 return 0 27} 28func xh_addc(t: *i64, sigtype: i64, pat: *u8, kind: i64, conf: i64) -> i64 { return xh_add(t, sigtype, pat, xh_slen(pat), kind, conf) } 29// seed the table with the base knowledge (was hardcoded in xt_classify; now DATA so it can be extended live). 30func xh_seed(t: *i64) -> i64 { 31 xh_addc(t, XSIG_EXT, ".m3u8" as *u8, XT_HLS, 95) 32 xh_addc(t, XSIG_EXT, ".mpd" as *u8, XT_DASH, 95) 33 xh_addc(t, XSIG_EXT, ".mp4" as *u8, XT_DIRECT, 90) 34 xh_addc(t, XSIG_EXT, ".webm" as *u8, XT_DIRECT, 90) 35 xh_addc(t, XSIG_EXT, ".m4s" as *u8, XT_SEGMENT, 85) 36 xh_addc(t, XSIG_EXT, ".ts" as *u8, XT_SEGMENT, 82) 37 xh_addc(t, XSIG_PATH, "/videoplayback" as *u8, XT_DIRECT, 70) 38 xh_addc(t, XSIG_PATH, "/master" as *u8, XT_HLS, 65) 39 xh_addc(t, XSIG_PATH, "/playlist" as *u8, XT_HLS, 62) 40 xh_addc(t, XSIG_PATH, "/hls/" as *u8, XT_HLS, 60) 41 xh_addc(t, XSIG_HOST, "googlevideo.com" as *u8, XT_DIRECT, 45) 42 return 0 43} 44// DATA-DRIVEN ranker: pick the BEST candidate from a newline-separated URL list, classifying each via the 45// TABLE (so learned patterns rank too -- the static xt_best would drop a healed URL). Mirrors xt_best. 46func xh_best(t: *i64, list: *u8, listlen: i64, out: *u8, cap: i64, kind: *i64) -> i64 { 47 let line: *u8 = sys_mmap(XSIG_MAGIC_4096) 48 let kb: *i64 = sys_mmap(8) as *i64 49 var best_score: i64 = 0 50 var best_conf: i64 = 0 51 var best_kind: i64 = XT_NONE 52 out[0] = 0 as u8 53 var p: i64 = 0 54 var go: i64 = 1 55 while go == 1 { 56 if p >= listlen { go = 0 } 57 else { 58 if (list[p] & 0xff) == 0 { go = 0 } 59 else { 60 var q: i64 = 0 61 var inl: i64 = 1 62 while inl == 1 { 63 let c: i64 = list[p] & 0xff 64 if c == 0 { inl = 0 } else { if c == 10 { inl = 0; p = p + 1 } else { if q < XSIG_MAGIC_4095 { line[q] = c as u8; q = q + 1 } p = p + 1 } } 65 } 66 line[q] = 0 as u8 67 if q > 0 { 68 let conf: i64 = xh_classify(t, line, q, kb) 69 let sc: i64 = xt_score(kb[0], conf) 70 if sc > best_score { best_score = sc; best_conf = conf; best_kind = kb[0]; var a: i64=0; while a<q { out[a]=line[a]; a=a+1 } out[q]=0 as u8 } 71 } 72 } 73 } 74 } 75 kind[0] = best_kind 76 return best_conf 77} 78// DATA-DRIVEN classify: scan the table, return the best (kind, conf). 79func xh_classify(t: *i64, url: *u8, ul: i64, out_kind: *i64) -> i64 { 80 var best_score: i64 = 0 81 var best_conf: i64 = 0 82 var best_kind: i64 = XT_NONE 83 var i: i64 = 0 84 while i < t[0] { 85 let b: i64 = 1 + i * XH_STRIDE 86 let pat: *u8 = (t[b+1]) as *u8 87 if xt_find(url, ul, pat, t[b+2], 0) >= 0 { 88 let k: i64 = t[b+3]; let c: i64 = t[b+4] 89 let sc: i64 = k * 100 + c 90 if sc > best_score { best_score = sc; best_conf = c; best_kind = k } 91 } 92 i = i + 1 93 } 94 out_kind[0] = best_kind 95 return best_conf 96} 97// extract the host from a URL (between "://" and the next '/' or ':'). 98func xh_host(url: *u8, ul: i64, out: *u8, cap: i64) -> i64 { 99 let p: i64 = xt_find(url, ul, "://" as *u8, 3, 0) 100 if p < 0 { out[0] = 0 as u8; return 0 } 101 var s: i64 = p + 3 102 var w: i64 = 0 103 var go: i64 = 1 104 while go == 1 { 105 if s >= ul { go = 0 } 106 else { let c: i64 = url[s] & 0xff; if c == 47 { go = 0 } else { if c == 58 { go = 0 } else { if w < (cap-1) { out[w] = c as u8; w = w + 1 } s = s + 1 } } } 107 } 108 out[w] = 0 as u8 109 return w 110} 111// is a host already a pattern in the table? (dedup so repeated failures don't bloat it) 112func xh_has_host(t: *i64, host: *u8, hl: i64) -> i64 { 113 var i: i64 = 0 114 while i < t[0] { 115 let b: i64 = 1 + i * XH_STRIDE 116 if t[b] == XSIG_HOST { let pat: *u8 = (t[b+1]) as *u8; if t[b+2] == hl { if xt_find(pat, hl, host, hl, 0) == 0 { return 1 } } } 117 i = i + 1 118 } 119 return 0 120} 121// AUTO-HEAL: a URL that IS media (known_kind, per critic/adversary) but the table MISSED -> learn a HOST 122// pattern from it so future URLs from that source are caught. Returns 1 if a new pattern was added, 0 if 123// already known / no host. (Host learned at conf 55 = a candidate; real media still out-ranks via extension.) 124func xh_learn(t: *i64, url: *u8, ul: i64, known_kind: i64) -> i64 { 125 let host: *u8 = sys_mmap(512) // persistent (the pattern points here) 126 let hl: i64 = xh_host(url, ul, host, 512) 127 if hl <= 0 { return 0 } 128 if xh_has_host(t, host, hl) == 1 { return 0 } 129 xh_add(t, XSIG_HOST, host, hl, known_kind, 55) 130 return 1 131} 132// FAILURE LOG: append "url<TAB>reason\n" to logbuf at offset; returns new offset. (Persist via a flush.) 133func xh_log(logbuf: *u8, off: i64, cap: i64, url: *u8, ul: i64, reason: *u8) -> i64 { 134 var o: i64 = off 135 var i: i64 = 0 136 while i < ul { if o < (cap-2) { logbuf[o] = url[i]; o = o + 1 } i = i + 1 } 137 if o < (cap-2) { logbuf[o] = 9 as u8; o = o + 1 } // TAB 138 i = 0 139 while reason[i] != (0 as u8) { if o < (cap-2) { logbuf[o] = reason[i]; o = o + 1 } i = i + 1 } 140 if o < (cap-2) { logbuf[o] = 10 as u8; o = o + 1 } // NL 141 logbuf[o] = 0 as u8 142 return o 143} 144// flush the accumulated log to a file (append via read-existing + rewrite, since sys_openat_wr truncates). 145func xh_flush(path: *u8, logbuf: *u8, loglen: i64) -> i64 { 146 let fd: i64 = sys_openat_wr(path, 0x1a4) 147 if fd < 0 { return 0 - 1 } 148 sys_write(fd, logbuf, loglen) 149 sys_close(fd) 150 return 0 151} 152func xh_putn(dst: *u8, off: i64, v: i64) -> i64 { var m: i64=v; if m==0 { dst[off]=48 as u8; return off+1 } let t: *u8=sys_mmap(24); var k: i64=0; while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } var j: i64=0; while j<k { dst[off]=t[k-1-j]; off=off+1; j=j+1 } return off } 153// parse a base-10 int at *ip, skipping leading spaces; leaves ip[0] pointing at the first non-digit. 154func xh_pint(buf: *u8, ip: *i64) -> i64 { 155 var i: i64 = ip[0] 156 while (buf[i] & 0xff) == 32 { i = i + 1 } // skip leading spaces 157 var v: i64 = 0 158 var go: i64 = 1 159 while go == 1 { 160 let c: i64 = buf[i] & 0xff 161 var dig: i64 = 0 162 if c >= 48 { if c <= 57 { dig = 1 } } 163 if dig == 1 { v = v * 10 + (c - 48); i = i + 1 } 164 if dig == 0 { go = 0 } 165 } 166 ip[0] = i 167 return v 168} 169// PERSIST the pattern table -> `path` as lines "<sigtype> <kind> <conf> <pattern>" (durable healing: learned 170// patterns survive a restart). Persistence via seg_store is the ecosystem-preferred store; a flat file is the 171// portable form used here + by the gate. 172func xh_save(t: *i64, path: *u8) -> i64 { 173 let buf: *u8 = sys_mmap(XSIG_MAGIC_1048576) 174 var o: i64 = 0 175 var i: i64 = 0 176 while i < t[0] { 177 let b: i64 = 1 + i * XH_STRIDE 178 o = xh_putn(buf, o, t[b]); buf[o] = 32 as u8; o = o + 1 179 o = xh_putn(buf, o, t[b+3]); buf[o] = 32 as u8; o = o + 1 180 o = xh_putn(buf, o, t[b+4]); buf[o] = 32 as u8; o = o + 1 181 let pat: *u8 = (t[b+1]) as *u8; let pl: i64 = t[b+2] 182 var k: i64 = 0; while k < pl { buf[o] = pat[k]; o = o + 1; k = k + 1 } 183 buf[o] = 10 as u8; o = o + 1 184 i = i + 1 185 } 186 let fd: i64 = sys_openat_wr(path, 0x1a4) 187 if fd < 0 { return 0 - 1 } 188 sys_write(fd, buf, o); sys_close(fd) 189 return 0 190} 191// LOAD patterns from `path` into `t` (fresh/empty). Copies each pattern to a persistent buffer. Returns count 192// (0 if the file is absent = first run -> caller seeds). This is what makes a learned pattern outlive the run. 193func xh_load(t: *i64, path: *u8) -> i64 { 194 let buf: *u8 = sys_mmap(XSIG_MAGIC_1048576) 195 let fd: i64 = sys_openat_rd(path) 196 if fd < 0 { return 0 } 197 let n: i64 = sys_read(fd, buf, XSIG_MAGIC_1048576); sys_close(fd) 198 let ip: *i64 = sys_mmap(8) as *i64 199 var loaded: i64 = 0 200 ip[0] = 0 201 var go: i64 = 1 202 while go == 1 { 203 if ip[0] >= n { go = 0 } 204 else { 205 if (buf[ip[0]] & 0xff) == 10 { ip[0] = ip[0] + 1 } 206 else { 207 let sigtype: i64 = xh_pint(buf, ip) 208 let kind: i64 = xh_pint(buf, ip) 209 let conf: i64 = xh_pint(buf, ip) 210 var s: i64 = ip[0] 211 while (buf[s] & 0xff) == 32 { s = s + 1 } // skip the space before the pattern 212 var e: i64 = s 213 var fe: i64 = 0 214 while fe == 0 { if e >= n { fe = 1 } else { if (buf[e]&0xff) == 10 { fe = 1 } else { e = e + 1 } } } 215 let pl: i64 = e - s 216 if pl > 0 { let pat: *u8 = sys_mmap(pl + 1); var k: i64=0; while k<pl { pat[k]=buf[s+k]; k=k+1 } pat[pl]=0 as u8; xh_add(t, sigtype, pat, pl, kind, conf); loaded = loaded + 1 } 217 ip[0] = e + 1 218 } 219 } 220 } 221 return loaded 222}