nx_drift_watch.nx source
↩ module page · 104 lines · 6905 B
1// nx_drift_watch.nx -- STANDING deploy-drift guardrail (zero-Claude, cron-run; arch-board 06:20 precedent).
2// The F-004 stale serve AND the compare-generator drifts both accumulated SILENTLY -- nothing watched for
3// "deployed binary lags its source" (esp. after a compiler/toolchain change, which staleness-flags EVERY
4// pre-fix binary). This daily check reads a data-driven watch-list and, per target, rebuilds it --build-only
5// and byte-compares to the deployed buildroot/_offc/<t>.elf (the SAME logic as nx_stale_check, INLINED to
6// stay single-nest -- a double-nested fork of nx_stale_check-of-nx_sov_build_run fails builds). Stub-trap
7// guarded (fresh<<deployed => AMBIGUOUS, not STALE). Logs verdicts + a tally to knowledge/status/drift_watch.log.
8// nx_drift_watch [listpath] [broot] list default knowledge/registry/drift_watch.list ; broot default buildroot
9// Exit 0 always (a guardrail never fails the fleet); the LOG carries the verdict. license_tier: ORIGINAL
10import "nx_tool_run.nx"
11const K_MAGIC_4096: i64 = 4096
12const K_MAGIC_65536: i64 = 65536
13const K_MAGIC_65535: i64 = 65535
14const K_MAGIC_8388608: i64 = 8388608
15
16func 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 }
17func wn(fd: i64, v: i64) -> i64 { var m: i64=v; if m<0{w(fd,"-" as *u8);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let o: *u8=sys_mmap(28); var i: i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(fd,o,k); return 0 }
18func d_cat(dst: *u8, off: i64, src: *u8) -> i64 { var o: i64=off; var j: i64=0; while src[j]!=(0 as u8){dst[o]=src[j];o=o+1;j=j+1} return o }
19func d_read(path: *u8, buf: *u8, cap: i64) -> i64 {
20 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 - 1 }
21 var n: i64 = 0; var go: i64 = 1
22 while go == 1 { let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } }
23 sys_close(fd); return n
24}
25// returns 1 CURRENT, 2 STALE, 3 AMBIGUOUS, 4 BUILDFAIL, 5 NOELF, 6 NOSOURCE. writes fresh/dep sizes to sz[0]/sz[1].
26func d_check(tgt: *u8, out: *u8, ocap: i64, ol: *i64, fb: *u8, db: *u8, fcap: i64, sz: *i64) -> i64 {
27 // source present?
28 let s1: *u8 = sys_mmap(256); var o1: i64 = d_cat(s1, 0, "runtime/" as *u8); o1 = d_cat(s1, o1, tgt); o1 = d_cat(s1, o1, ".nx" as *u8); s1[o1] = 0 as u8
29 let s2: *u8 = sys_mmap(256); var o2: i64 = d_cat(s2, 0, "runtime/_hdl_build/" as *u8); o2 = d_cat(s2, o2, tgt); o2 = d_cat(s2, o2, ".nx" as *u8); s2[o2] = 0 as u8
30 let f1: i64 = sys_openat_rd(s1); var have: i64 = 0; if f1 >= 0 { sys_close(f1); have = 1 }
31 if have == 0 { let f2: i64 = sys_openat_rd(s2); if f2 >= 0 { sys_close(f2); have = 1 } }
32 if have == 0 { return 6 }
33 // build --build-only (single nested fork -- the reliable pattern)
34 let av: *i64 = sys_mmap(64) as *i64
35 av[0] = "_offc/nx_sov_build_run.elf" as i64; av[1] = tgt as i64; av[2] = "--build-only" as i64; av[3] = 0
36 let rc: i64 = tr_run_capture("_offc/nx_sov_build_run.elf" as *u8, av, out, ocap, ol)
37 if rc != 0 { return 4 }
38 let fresh: *u8 = sys_mmap(256); var of: i64 = d_cat(fresh, 0, "/tmp/" as *u8); of = d_cat(fresh, of, tgt); of = d_cat(fresh, of, ".sov.elf" as *u8); fresh[of] = 0 as u8
39 let dep: *u8 = sys_mmap(256); var od: i64 = d_cat(dep, 0, "_offc/" as *u8); od = d_cat(dep, od, tgt); od = d_cat(dep, od, ".elf" as *u8); dep[od] = 0 as u8
40 let fn: i64 = d_read(fresh, fb, fcap)
41 let dn: i64 = d_read(dep, db, fcap)
42 sz[0] = fn; sz[1] = dn
43 if fn < 0 { return 4 }
44 if dn < 0 { return 5 }
45 if fn == dn { var i: i64 = 0; var same: i64 = 1; while i < fn { if fb[i] != db[i] { same = 0; i = fn } else { i = i + 1 } } if same == 1 { return 1 } }
46 if fn * 2 < dn { if fn < K_MAGIC_4096 { return 3 } }
47 return 2
48}
49
50func main(argc: i64, argv: *i64) -> i64 {
51 var listp: *u8 = "knowledge/registry/drift_watch.list" as *u8
52 if argc >= 2 { listp = argv[1] as *u8 }
53 var broot: *u8 = "buildroot" as *u8
54 if argc >= 3 { broot = argv[2] as *u8 }
55
56 let lst: *u8 = sys_mmap(K_MAGIC_65536)
57 let ln: i64 = d_read(listp, lst, K_MAGIC_65535)
58 if ln <= 0 { w(1, "nx_drift_watch: watch-list missing\n" as *u8); sys_exit(0); return 0 }
59 // resolve the log path BEFORE chdir (it is relative to the run cwd), then chdir into the build tree.
60 let lfd: i64 = sys_openat_append("knowledge/status/drift_watch.log" as *u8, 0x1a4)
61 if sys_chdir(broot) != 0 { w(1, "nx_drift_watch: cannot chdir build tree\n" as *u8); if lfd>=0 { sys_close(lfd) } sys_exit(0); return 0 }
62
63 let ocap: i64 = K_MAGIC_65536
64 let out: *u8 = sys_mmap(ocap)
65 let ol: *i64 = sys_mmap(16) as *i64
66 let fcap: i64 = K_MAGIC_8388608
67 let fb: *u8 = sys_mmap(fcap)
68 let db: *u8 = sys_mmap(fcap)
69 let sz: *i64 = sys_mmap(16) as *i64
70 let tgt: *u8 = sys_mmap(128)
71
72 var nstale: i64=0; var namb: i64=0; var ncur: i64=0; var noth: i64=0; var ntot: i64=0
73 var p: i64 = 0
74 while p < ln {
75 var q: i64 = p
76 while q < ln { if lst[q] == (10 as u8) { break } q = q + 1 }
77 var ti: i64 = 0; var s: i64 = p
78 while s < q { let c: i64 = lst[s]; if c == 13 { s = q } else { if ti < 120 { tgt[ti] = lst[s] as u8; ti = ti + 1 } s = s + 1 } }
79 tgt[ti] = 0 as u8
80 p = q + 1
81 if ti == 0 { } else { if tgt[0] == (35 as u8) { } else {
82 ntot = ntot + 1
83 let v: i64 = d_check(tgt, out, ocap, ol, fb, db, fcap, sz)
84 if v == 1 { ncur = ncur + 1 } else {
85 if v == 2 { nstale = nstale + 1 } else { if v == 3 { namb = namb + 1 } else { noth = noth + 1 } }
86 if lfd >= 0 {
87 w(lfd, " " as *u8)
88 if v == 2 { w(lfd, "STALE " as *u8) } else { if v == 3 { w(lfd, "AMBIGUOUS " as *u8) } else { if v == 4 { w(lfd, "BUILDFAIL " as *u8) } else { if v == 5 { w(lfd, "NOELF " as *u8) } else { w(lfd, "NOSOURCE " as *u8) } } } }
89 w(lfd, tgt); w(lfd, " (fresh=" as *u8); wn(lfd, sz[0]); w(lfd, " deployed=" as *u8); wn(lfd, sz[1]); w(lfd, ")\n" as *u8)
90 }
91 }
92 } }
93 }
94 if lfd >= 0 {
95 w(lfd, "DRIFT-WATCH epoch=" as *u8); wn(lfd, sys_now_realtime_sec())
96 w(lfd, " checked=" as *u8); wn(lfd, ntot); w(lfd, " current=" as *u8); wn(lfd, ncur)
97 w(lfd, " STALE=" as *u8); wn(lfd, nstale); w(lfd, " ambiguous=" as *u8); wn(lfd, namb); w(lfd, " other=" as *u8); wn(lfd, noth)
98 if nstale > 0 { w(lfd, " verdict=DRIFT-DETECTED\n" as *u8) } else { w(lfd, " verdict=CLEAN\n" as *u8) }
99 sys_close(lfd)
100 }
101 w(1, "nx_drift_watch: checked=" as *u8); wn(1, ntot); w(1, " current=" as *u8); wn(1, ncur); w(1, " STALE=" as *u8); wn(1, nstale); w(1, " ambiguous=" as *u8); wn(1, namb); w(1, " other=" as *u8); wn(1, noth); w(1, "\n" as *u8)
102 sys_exit(0)
103 return 0
104}