code wiki / (root) / nx_unread_sensor.nx

nx_unread_sensor.nx source

↩ module page · 256 lines · 11394 B

1// nx_unread_sensor.nx -- WHICH STATUS ARTIFACTS DOES NOTHING NAME. 2// 3// usage: nx_unread_sensor [statusdir] default knowledge/status/ 4// exit: 0 GREEN (single-namer count at or below its ratchet) | 1 RED (it rose) | 3 UNPROVEN 5// 6// See nx_unread_sensor_lib.nx for why this exists and for the blind spots it declares. In short: this 7// estate rediscovered "a sensor nothing reads" four times in one day, and owned no instrument that could 8// have found the fifth. Every number below is a FLOOR on readers, so a row here is a QUESTION. 9// 10// IT REFUSES TO RUN ON A SATURATED BOX. Composing ct_admit_now costs one small /proc read and no fork, 11// and the alternative is a corpus-wide scan that becomes the load it was built to explain -- 12// A DIAGNOSTIC THAT CANNOT REFUSE TO RUN IS A LOAD GENERATOR WITH GOOD INTENTIONS. 13// 14// THE RATCHET SELF-BASELINES ON FIRST SIGHT, so shipping it cannot turn every build red on day one, and 15// it is written ONLY on a fall or a first run: a ratchet that rewrites its baseline on a RISE launders 16// itself green and is worse than no ratchet at all. 17// license_tier: ORIGINAL expect_exit: 0 Read-only. No hw writes (Rule 26). 18import "nx_syscalls.nx" 19import "nx_gatekit_lib.nx" 20import "nx_ctxtop_lib.nx" 21import "nx_unread_sensor_lib.nx" 22 23const UR_MAXART: i64 = 512 24const UR_STRIDE: i64 = 96 25const UR_NAMES_BYTES: i64 = 49152 // UR_MAXART * UR_STRIDE 26const UR_I64_BYTES: i64 = 4096 // UR_MAXART * 8 27const UR_FILECAP: i64 = 262144 28const UR_PATHCAP: i64 = 1024 29const UR_CORPUS_STRIDE: i64 = 256 30const UR_DIRBUF: i64 = 65536 31const UR_DIRENT_NAME_OFF: i64 = 19 32const UR_BASELINE: *u8 = "knowledge/status/unread_sensor.baseline" 33const UR_BASELINE_NAME: *u8 = "unread_sensor.baseline" 34const UR_MODE_644: i64 = 420 35const UR_EXIT_GREEN: i64 = 0 36const UR_EXIT_RED: i64 = 1 37const UR_EXIT_UNPROVEN: i64 = 3 38const UR_NEEDLE: *u8 = "knowledge/status/" 39const UR_NEEDLE_LEN: i64 = 17 40 41func ur_puts(s: *u8) -> i64 { sys_write(1, s, us_len(s)); return 0 } 42func ur_num(v: i64) -> i64 { 43 let b: *u8 = sys_mmap(32) 44 var o: i64 = gk_catn(b, 0, v) 45 sys_write(1, b, o) 46 sys_munmap(b, 32) 47 return 0 48} 49 50func main(argc: i64, argv: *i64) -> i64 { 51 var sdir: *u8 = "knowledge/status/" as *u8 52 if argc >= 2 { sdir = argv[1] as *u8 } 53 54 // ---- ADMISSION FIRST, before a single corpus byte is read ---- 55 if ct_admit_now() != 1 { 56 ur_puts("REFUSED-BUSY the box is saturated and this census reads the whole source corpus.\n" as *u8) 57 ur_puts("Nothing was scanned, so nothing is claimed. Re-run when load clears.\n" as *u8) 58 ur_puts("verdict=UNPROVEN\n" as *u8) 59 return UR_EXIT_UNPROVEN 60 } 61 62 // ---- 1. enumerate the status artifacts ---- 63 let names: *u8 = sys_mmap(UR_NAMES_BYTES) 64 let refs: *i64 = sys_mmap(UR_I64_BYTES) as *i64 65 let lastsrc: *i64 = sys_mmap(UR_I64_BYTES) as *i64 66 var nart: i64 = 0 67 var art_full: i64 = 0 68 let dfd: i64 = sys_openat_rd(sdir) 69 if dfd < 0 { 70 ur_puts("STATUSDIR-UNREADABLE " as *u8); ur_puts(sdir); ur_puts("\n" as *u8) 71 ur_puts("verdict=UNPROVEN\n" as *u8) 72 return UR_EXIT_UNPROVEN 73 } 74 let db: *u8 = sys_mmap(UR_DIRBUF) 75 var go: i64 = 1 76 while go == 1 { 77 let nr: i64 = sys_getdents64(dfd, db, UR_DIRBUF) 78 if nr <= 0 { go = 0 } 79 if nr > 0 { 80 var pos: i64 = 0 81 while pos < nr { 82 let rec: *u8 = ((db as i64) + pos) as *u8 83 let rl: i64 = (rec[16] as i64) | ((rec[17] as i64) << 8) 84 if rl <= 0 { pos = nr } 85 if rl > 0 { 86 let nm: *u8 = ((rec as i64) + UR_DIRENT_NAME_OFF) as *u8 87 // '.' and '..' fail the name test on their own: a bare dot run is not an artifact. 88 if us_isnamechar(nm[0] as i64) == 1 { 89 if nm[0] != (US_DOT as u8) { 90 if nart < UR_MAXART { 91 let dst: *u8 = ((names as i64) + nart * UR_STRIDE) as *u8 92 var k: i64 = 0 93 while nm[k] != (0 as u8) { if k < UR_STRIDE - 1 { dst[k] = nm[k] } k = k + 1 } 94 dst[k] = 0 as u8 95 refs[nart] = 0 96 lastsrc[nart] = 0 - 1 97 nart = nart + 1 98 } 99 if nart >= UR_MAXART { art_full = 1 } 100 } 101 } 102 pos = pos + rl 103 } 104 } 105 } 106 } 107 sys_munmap(db, UR_DIRBUF) 108 sys_close(dfd) 109 110 // ---- 2. ONE pass over the .nx corpus, counting DISTINCT namers per artifact ---- 111 let maxlen: *i64 = sys_mmap(64) as *i64 112 let ncorp: i64 = gk_corpus_count(maxlen) 113 if ncorp <= 0 { 114 ur_puts("CORPUS-UNREADABLE the source tree could not be enumerated, so absence cannot be proven.\n" as *u8) 115 ur_puts("verdict=UNPROVEN\n" as *u8) 116 return UR_EXIT_UNPROVEN 117 } 118 let paths: *u8 = sys_mmap(ncorp * UR_CORPUS_STRIDE + UR_CORPUS_STRIDE) 119 let got: i64 = gk_corpus_scan(paths, UR_CORPUS_STRIDE, ncorp + 1) 120 let fbuf: *u8 = sys_mmap(UR_FILECAP) 121 let tok: *u8 = sys_mmap(US_NAMECAP) 122 var scanned: i64 = 0 123 var truncated: i64 = 0 124 var unreadable: i64 = 0 125 var si: i64 = 0 126 while si < got { 127 let p: *u8 = ((paths as i64) + si * UR_CORPUS_STRIDE) as *u8 128 // THE READ IS SIZED FROM THE FILE, NOT FROM A CAP. The first cut used a 256 KB buffer and 8 of 129 // 19,391 sources overflowed it, turning a whole-corpus census into a partial one and making every 130 // absence UNPROVEN. The fix for a cap you hit is to MEASURE THE INPUT, never to pick a bigger 131 // number: sys_read_file lseeks to END, sizes its own buffer, and cannot short-read. 132 let flen: *i64 = sys_mmap(64) as *i64 133 let fb: *u8 = sys_read_file(p, flen) 134 if fb == (0 as *u8) { unreadable = unreadable + 1 } 135 if fb != (0 as *u8) { 136 let tot: i64 = flen[0] 137 let fbuf: *u8 = fb 138 scanned = scanned + 1 139 var at: i64 = 0 140 var fgo: i64 = 1 141 while fgo == 1 { 142 let h: i64 = us_find_from(fbuf, tot, at, UR_NEEDLE) 143 if h < 0 { fgo = 0 } 144 if h >= 0 { 145 let tl: i64 = us_name_at(fbuf, tot, h + UR_NEEDLE_LEN, tok, US_NAMECAP) 146 if tl > 0 { 147 let ix: i64 = us_tbl_find(names, UR_STRIDE, nart, tok) 148 if ix >= 0 { 149 // count each SOURCE once per artifact: a file that names the same artifact 150 // five times is one namer, and counting mentions would flatter every row. 151 if lastsrc[ix] != si { refs[ix] = refs[ix] + 1; lastsrc[ix] = si } 152 } 153 } 154 at = h + UR_NEEDLE_LEN 155 } 156 } 157 sys_munmap(fb, tot + 16) 158 } 159 sys_munmap(flen as *u8, 64) 160 si = si + 1 161 } 162 163 // ---- 3. classify, print the worklist, reconcile the partition ---- 164 var c_none: i64 = 0 165 var c_single: i64 = 0 166 var c_several: i64 = 0 167 var c_shard: i64 = 0 168 var c_self: i64 = 0 169 ur_puts("=== NX-UNREAD-SENSOR: status artifacts nothing else names ===\n" as *u8) 170 var ai: i64 = 0 171 while ai < nart { 172 let nm: *u8 = ((names as i64) + ai * UR_STRIDE) as *u8 173 var cls: i64 = us_classify(nm, refs[ai]) 174 if us_is_self(nm, UR_BASELINE_NAME) == 1 { cls = US_CLASS_SEVERAL; c_self = 1 } 175 if cls == US_CLASS_NONE { c_none = c_none + 1 } 176 if cls == US_CLASS_SINGLE { c_single = c_single + 1 } 177 if cls == US_CLASS_SEVERAL { c_several = c_several + 1 } 178 if cls == US_CLASS_SHARD { c_shard = c_shard + 1 } 179 if cls != US_CLASS_SEVERAL { if cls != US_CLASS_SHARD { 180 ur_puts(" " as *u8); ur_puts(us_class_name(cls)) 181 ur_puts(" namers=" as *u8); ur_num(refs[ai]) 182 ur_puts(" " as *u8); ur_puts(nm) 183 ur_puts("\n" as *u8) 184 } } 185 ai = ai + 1 186 } 187 let csum: i64 = c_none + c_single + c_several + c_shard 188 ur_puts("artifacts=" as *u8); ur_num(nart) 189 ur_puts(" no_literal_reference=" as *u8); ur_num(c_none) 190 ur_puts(" single_namer=" as *u8); ur_num(c_single) 191 ur_puts(" named_by_several=" as *u8); ur_num(c_several) 192 ur_puts(" store_family=" as *u8); ur_num(c_shard) 193 ur_puts(" self_bookkeeping_excluded=" as *u8); ur_num(c_self) 194 ur_puts(" sum=" as *u8); ur_num(csum) 195 ur_puts("\n" as *u8) 196 ur_puts("corpus_declared=" as *u8); ur_num(ncorp) 197 ur_puts(" scanned=" as *u8); ur_num(scanned) 198 ur_puts(" unreadable=" as *u8); ur_num(unreadable) 199 ur_puts(" truncated_at_cap=" as *u8); ur_num(truncated) 200 ur_puts(" corpus_complete=" as *u8) 201 var complete: i64 = 1 202 if unreadable > 0 { complete = 0 } 203 if art_full == 1 { complete = 0 } 204 if scanned != got { complete = 0 } 205 ur_num(complete) 206 ur_puts("\n" as *u8) 207 if art_full == 1 { ur_puts("ARTIFACT-TABLE-FULL the counts above are a FLOOR, not a total\n" as *u8) } 208 if complete == 0 { ur_puts("COVERAGE-PARTIAL at least one source was unreadable or read only to its cap, so a NO-LITERAL-REFERENCE row is UNPROVEN rather than absent\n" as *u8) } 209 210 // ---- 4. the ratchet ---- 211 let bb: *u8 = sys_mmap(64) 212 let bfd: i64 = sys_openat_rd(UR_BASELINE) 213 var base: i64 = 0 - 1 214 if bfd >= 0 { 215 let bn: i64 = sys_read(bfd, bb, 63) 216 sys_close(bfd) 217 if bn > 0 { 218 bb[bn] = 0 as u8 219 var v: i64 = 0 220 var bi: i64 = 0 221 var any: i64 = 0 222 while bi < bn { 223 let c: i64 = bb[bi] as i64 224 if c >= US_D0 { if c <= US_D9 { v = v * 10 + (c - US_D0); any = 1 } } 225 bi = bi + 1 226 } 227 if any == 1 { base = v } 228 } 229 } 230 var rc: i64 = UR_EXIT_GREEN 231 // A ratchet may only be rewritten on a FALL or on a first sight. Rewriting it on a RISE is how a 232 // detector launders itself green, and it is the one mutation that makes the whole thing decorative. 233 var write_base: i64 = 0 234 if base < 0 { write_base = 1 } 235 if base >= 0 { if c_single < base { write_base = 1 } } 236 if base >= 0 { if c_single > base { rc = UR_EXIT_RED } } 237 if complete == 0 { rc = UR_EXIT_UNPROVEN } 238 if write_base == 1 { 239 let wfd: i64 = sys_openat_wr(UR_BASELINE, UR_MODE_644) 240 if wfd >= 0 { 241 let ob: *u8 = sys_mmap(64) 242 var oo: i64 = gk_catn(ob, 0, c_single) 243 ob[oo] = 10 as u8 244 sys_write(wfd, ob, oo + 1) 245 sys_close(wfd) 246 } 247 } 248 ur_puts("ratchet baseline=" as *u8); ur_num(base) 249 ur_puts(" current=" as *u8); ur_num(c_single) 250 ur_puts(" rewritten=" as *u8); ur_num(write_base) 251 ur_puts("\n" as *u8) 252 if rc == UR_EXIT_GREEN { ur_puts("verdict=GREEN\n" as *u8) } 253 if rc == UR_EXIT_RED { ur_puts("verdict=RED the single-namer count ROSE above its baseline -- a new sensor was shipped with nothing reading it\n" as *u8) } 254 if rc == UR_EXIT_UNPROVEN { ur_puts("verdict=UNPROVEN coverage was partial, so the count is a floor and the ratchet is not judged\n" as *u8) } 255 return rc 256}