code wiki / (root) / nx_crashresume_census_core.nx

nx_crashresume_census_core.nx source

↩ module page · 162 lines · 6267 B

1// nx_crashresume_census_core.nx -- importable CORE of the crash-resume census (CR-R0 of the 2// crash-resume->SOTA roadmap 2026-07-15): MEASURES whether the workstream capture plane is LIVE -- 3// heartbeat staleness (max HBX epoch= in the log vs wall clock), registry/file mtime staleness 4// (newfstatat), and session-activity vs capture LAG (newest transcript mtime vs newest captured 5// state). Bank: registry+heartbeats sat DEAD 5 days at the 07-15 crash while 36 sessions worked -> 6// resume cost ~5h of hand archaeology; this census makes that rot VISIBLE within a cron tick. 7// PURE verdict funcs here (gate-locked). Cells NEVER fabricate: no evidence -> UNKNOWN; bounded 8// reads bias STALE (a truncated log can only under-report freshness, never invent it). Read-only. 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_itoa_lib.nx" 12 13// Buffer sizes promoted out of the call sites (rule 11) as part of the 2026-07-31 mmap-leak 14// root-fix (debt 1785516350). st_mtime lives at byte 88 of the x86_64 struct stat = i64 slot 11. 15const CCZ_EPBUF: i64 = 16 16const CCZ_STATBUF: i64 = 256 17const CCZ_STAT_MTIME_SLOT: i64 = 11 18const CCZ_DENTBUF: i64 = 65536 19const CCZ_PATHBUF: i64 = 2048 20 21const CR_RED: i64 = 0 22const CR_UNKNOWN: i64 = 1 23const CR_GREEN: i64 = 2 24 25func ccz_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 26 27func ccz_max(a: i64, b: i64) -> i64 { if a > b { return a } return b } 28 29// parse leading unsigned decimal from s[off..n): value, or -1 if no digit at off. end offset in endp[0]. 30func ccz_num_at(s: *u8, n: i64, off: i64, endp: *i64) -> i64 { 31 var v: i64 = 0 32 var any: i64 = 0 33 var i: i64 = off 34 var go: i64 = 1 35 while go == 1 { 36 go = 0 37 if i < n { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v*10 + (c-48); any = 1; i = i + 1; go = 1 } } } 38 } 39 endp[0] = i 40 if any == 0 { return 0 - 1 } 41 return v 42} 43 44// bounded whole-file read. -1 absent/unreadable. 45func ccz_read(path: *u8, buf: *u8, cap: i64) -> i64 { 46 let fd: i64 = sys_openat_rd(path) 47 if fd < 0 { return 0 - 1 } 48 var tot: i64 = 0 49 var n: i64 = sys_read(fd, buf, cap) 50 while n > 0 { tot = tot + n; if tot >= cap { n = 0 } else { n = sys_read(fd, (buf as i64 + tot) as *u8, cap - tot) } } 51 sys_close(fd) 52 return tot 53} 54 55// max "epoch=<digits>" value in buf[0..n). 0 if none (upstream -> UNKNOWN, never fabricated). 56func ccz_max_epoch(buf: *u8, n: i64) -> i64 { 57 let pat: *u8 = "epoch=" as *u8 58 let pl: i64 = 6 59 let ep: *i64 = sys_mmap(CCZ_EPBUF) as *i64 60 var best: i64 = 0 61 var i: i64 = 0 62 while i + pl <= n { 63 var k: i64 = 0 64 var ok: i64 = 1 65 while k < pl { if buf[i+k] != pat[k] { ok = 0; k = pl } k = k + 1 } 66 if ok == 1 { 67 let v: i64 = ccz_num_at(buf, n, i + pl, ep) 68 if v > best { best = v } 69 i = ep[0] 70 } else { i = i + 1 } 71 } 72 sys_munmap(ep as *u8, CCZ_EPBUF) 73 return best 74} 75 76// mtime (epoch sec) of path via newfstatat. -1 absent/unreadable. st_mtim.tv_sec @ byte 88 = i64[11]. 77func ccz_mtime(path: *u8) -> i64 { 78 let sb: *u8 = sys_mmap(CCZ_STATBUF) 79 let r: i64 = sys_fstatat(path, sb) 80 // the FAILED-stat path leaked too, and a corpus walk hits it most -- free before every return. 81 if r < 0 { sys_munmap(sb, CCZ_STATBUF); return 0 - 1 } 82 let sw: *i64 = sb as *i64 83 let mt: i64 = sw[CCZ_STAT_MTIME_SLOT] 84 sys_munmap(sb, CCZ_STATBUF) 85 return mt 86} 87 88func ccz_ends_with(name: *u8, ext: *u8) -> i64 { 89 let nl: i64 = ccz_slen(name) 90 let el: i64 = ccz_slen(ext) 91 if el > nl { return 0 } 92 var i: i64 = 0 93 while i < el { if name[nl-el+i] != ext[i] { return 0 } i = i + 1 } 94 return 1 95} 96 97// newest mtime among dir entries whose name ends with ext. -1 if none/unreadable dir. 98func ccz_newest_mtime_ext(dir: *u8, ext: *u8) -> i64 { 99 let fd: i64 = sys_openat_rd(dir) 100 if fd < 0 { return 0 - 1 } 101 let dbuf: *u8 = sys_mmap(CCZ_DENTBUF) 102 let path: *u8 = sys_mmap(CCZ_PATHBUF) 103 var best: i64 = 0 - 1 104 var run: i64 = 1 105 while run == 1 { 106 let n: i64 = sys_getdents64(fd, dbuf, CCZ_DENTBUF) 107 if n <= 0 { run = 0 } else { 108 var off: i64 = 0 109 while off < n { 110 let rec: *u8 = ((dbuf as i64 + off) as *u8) 111 let reclen: i64 = dirent_reclen(rec) 112 if reclen <= 0 { off = n } else { 113 let name: *u8 = dirent_name(rec) 114 if ccz_ends_with(name, ext) == 1 { 115 var o: i64 = 0 116 var a: i64 = 0 117 while dir[a] != (0 as u8) { path[o] = dir[a]; o = o + 1; a = a + 1 } 118 path[o] = 47 as u8 119 o = o + 1 120 a = 0 121 while name[a] != (0 as u8) { path[o] = name[a]; o = o + 1; a = a + 1 } 122 path[o] = 0 as u8 123 let mt: i64 = ccz_mtime(path) 124 if mt > best { best = mt } 125 } 126 off = off + reclen 127 } 128 } 129 } 130 } 131 sys_close(fd) 132 sys_munmap(dbuf, CCZ_DENTBUF) 133 sys_munmap(path, CCZ_PATHBUF) 134 return best 135} 136 137// append s at buf[off..], NUL-terminate, return new off. 138func ccz_cat_str(buf: *u8, off: i64, s: *u8) -> i64 { 139 var o: i64 = off 140 var a: i64 = 0 141 while s[a] != (0 as u8) { buf[o] = s[a]; o = o + 1; a = a + 1 } 142 buf[o] = 0 as u8 143 return o 144} 145 146// append decimal v (handles 0 and negatives) at buf[off..], NUL-terminate, return new off. 147 148// PURE: staleness verdict. ts<=0 -> UNKNOWN (no evidence, never fabricate); age<=window -> GREEN; else RED. 149func ccz_stale_verdict(ts: i64, now: i64, window: i64) -> i64 { 150 if ts <= 0 { return CR_UNKNOWN } 151 if now - ts <= window { return CR_GREEN } 152 return CR_RED 153} 154 155// PURE: capture-lag verdict. src<=0 -> UNKNOWN (no activity evidence); cap<=0 with live src -> RED 156// (activity but ZERO capture); src-cap<=window -> GREEN (capture keeps up); else RED. 157func ccz_lag_verdict(src_ts: i64, cap_ts: i64, window: i64) -> i64 { 158 if src_ts <= 0 { return CR_UNKNOWN } 159 if cap_ts <= 0 { return CR_RED } 160 if src_ts - cap_ts <= window { return CR_GREEN } 161 return CR_RED 162}