code wiki / _hdl_build / nx_transient_monitor.nx
nx_transient_monitor.nx source
↩ module page · 103 lines · 6336 B
1// nx_transient_monitor.nx -- S-CLASS transient / flakiness monitor (hardware-rung-up). The Nishi ecosystem must
2// ACCOUNT FOR every transient (intermittent failure, watchdog timeout) -- NEVER hand-wave "transient, watch if
3// it recurs". This runs a target N times under a per-run watchdog, records EVERY outcome (exit code + duration),
4// and turns "transient" into a MEASURED flakiness rate + verdict (STABLE / FLAKY / BROKEN) with a durable
5// SOVEREIGN record (seg-store pattern: per-key file + index under knowledge/store, NO tsv/csv/json).
6// usage: nx_transient_monitor <runs> <timeout_ms> <elf-path>
7// exit 0 = STABLE, 1 = FLAKY (a transient is real -> root-cause), 2 = BROKEN
8// license_tier: ORIGINAL
9import "nx_syscalls.nx"
10const TM_MAGIC_1000000000: i64 = 1000000000
11const TM_MAGIC_2048: i64 = 2048
12
13const TM_STORE_DIR: *u8 = "knowledge/store"
14
15func tm_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
16func tm_wn(v: i64) -> i64 { var m: i64=v; var k: i64=0; if m<0{tm_w("-" as *u8);m=0-m} let t: *u8=sys_mmap(24); 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} var o: *u8=sys_mmap(24); var w: i64=0; var q: i64=k-1; while q>=0{o[w]=t[q];w=w+1;q=q-1} sys_write(1,o,w); return 0 }
17func tm_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){dst[o]=s[i];o=o+1;i=i+1} return o }
18func tm_n(dst: *u8, off: i64, v: i64) -> i64 { var o: i64=off; var m: i64=v; if m<0{dst[o]=45 as u8;o=o+1;m=0-m} let t: *u8=sys_mmap(24); 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} var i: i64=0; while i<k{dst[o+i]=t[k-1-i];i=i+1} return o+k }
19func tm_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ if s[i]>=(48 as u8){ if s[i]<=(57 as u8){ v=v*10+((s[i] as i64)-48) } } i=i+1 } return v }
20
21// fork target (stdout/stderr -> /dev/null) + a watchdog timer; wait. returns exit code, -9 on signal/timeout.
22func tm_run_once(elf: *u8, timeout_ms: i64, dur_out: *i64) -> i64 {
23 let t0: i64 = sys_now_ms()
24 let pid: i64 = sys_fork()
25 if pid == 0 {
26 let av: *i64 = sys_mmap(16) as *i64; av[0]=elf as i64; av[1]=0
27 let ev: *i64 = sys_mmap(16) as *i64; ev[0]="PATH=/usr/bin:/bin" as *u8 as i64; ev[1]=0
28 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4)
29 if dn >= 0 { sys_dup3(dn, 1, 0); sys_dup3(dn, 2, 0) }
30 sys_execve(elf, av, ev); sys_exit(127)
31 }
32 let wd: i64 = sys_fork()
33 if wd == 0 { sys_sleep_ms(timeout_ms); nx_kill(pid, 9); sys_exit(0) }
34 let st: *i64 = sys_mmap(16) as *i64
35 sys_wait4(pid, st, 0)
36 nx_kill(wd, 9)
37 let st2: *i64 = sys_mmap(16) as *i64; sys_wait4(wd, st2, 0)
38 dur_out[0] = sys_now_ms() - t0
39 if (st[0] % 256) != 0 { return 0 - 9 }
40 return (st[0] >> 8) & 0xff
41}
42
43// run N times. out: [pass, fail, timeout, min_ms, max_ms, sum_ms]
44func tm_probe(elf: *u8, runs: i64, timeout_ms: i64, out: *i64) -> i64 {
45 var pass: i64=0; var fail: i64=0; var to: i64=0
46 var mn: i64=TM_MAGIC_1000000000; var mx: i64=0; var sm: i64=0
47 let dur: *i64 = sys_mmap(16) as *i64
48 var i: i64 = 0
49 while i < runs {
50 let ex: i64 = tm_run_once(elf, timeout_ms, dur)
51 let d: i64 = dur[0]
52 if d < mn { mn = d }
53 if d > mx { mx = d }
54 sm = sm + d
55 if ex == 0 { pass=pass+1 } else { if ex == (0-9) { to=to+1 } else { fail=fail+1 } }
56 i = i + 1
57 }
58 out[0]=pass; out[1]=fail; out[2]=to; out[3]=mn; out[4]=mx; out[5]=sm
59 return 0
60}
61
62// 0 STABLE (all pass), 1 FLAKY (some pass some not), 2 BROKEN (none pass)
63func tm_verdict(pass: i64, runs: i64) -> i64 { if pass==runs {return 0} if pass==0 {return 2} return 1 }
64
65// durable SOVEREIGN record -- seg-store pattern: per-key file knowledge/store/transient-<ts> + index transient-ids (NO tsv)
66func tm_record(elf: *u8, runs: i64, out: *i64, verdict: i64) -> i64 {
67 sys_mkdir(TM_STORE_DIR, 0x1ff)
68 let ts: i64 = sys_now_realtime_sec()
69 let path: *u8 = sys_mmap(512); var o: i64 = tm_cat(path,0,TM_STORE_DIR); path[o]=47 as u8; o=o+1; o=tm_cat(path,o,"transient-" as *u8); o=tm_n(path,o,ts); path[o]=0 as u8
70 let rec: *u8 = sys_mmap(TM_MAGIC_2048); var r: i64 = 0
71 r=tm_cat(rec,r,"target=" as *u8); r=tm_cat(rec,r,elf); rec[r]=10 as u8; r=r+1
72 r=tm_cat(rec,r,"runs=" as *u8); r=tm_n(rec,r,runs); rec[r]=10 as u8; r=r+1
73 r=tm_cat(rec,r,"pass=" as *u8); r=tm_n(rec,r,out[0]); r=tm_cat(rec,r," fail=" as *u8); r=tm_n(rec,r,out[1]); r=tm_cat(rec,r," timeout=" as *u8); r=tm_n(rec,r,out[2]); rec[r]=10 as u8; r=r+1
74 r=tm_cat(rec,r,"verdict=" as *u8)
75 if verdict==0 { r=tm_cat(rec,r,"STABLE" as *u8) }
76 if verdict==1 { r=tm_cat(rec,r,"FLAKY" as *u8) }
77 if verdict==2 { r=tm_cat(rec,r,"BROKEN" as *u8) }
78 rec[r]=10 as u8; r=r+1
79 r=tm_cat(rec,r,"min_ms=" as *u8); r=tm_n(rec,r,out[3]); r=tm_cat(rec,r," max_ms=" as *u8); r=tm_n(rec,r,out[4]); rec[r]=10 as u8; r=r+1
80 let fd: i64 = sys_openat_wr(path, 0x1a4); if fd>=0 { sys_write(fd,rec,r); sys_close(fd) }
81 let ip: *u8 = sys_mmap(512); var io: i64 = tm_cat(ip,0,TM_STORE_DIR); ip[io]=47 as u8; io=io+1; io=tm_cat(ip,io,"transient-ids" as *u8); ip[io]=0 as u8
82 let idr: *u8 = sys_mmap(32); var z: i64 = tm_n(idr,0,ts); idr[z]=10 as u8; z=z+1
83 let ifd: i64 = sys_openat_append(ip, 0x1a4); if ifd>=0 { sys_write(ifd,idr,z); sys_close(ifd) }
84 return 0
85}
86
87func main(argc: i64, argv: *i64) -> i64 {
88 if argc < 4 { tm_w("usage: nx_transient_monitor <runs> <timeout_ms> <elf-path>\n" as *u8); return 2 }
89 let runs: i64 = tm_atoi(argv[1] as *u8)
90 let timeout: i64 = tm_atoi(argv[2] as *u8)
91 let elf: *u8 = argv[3] as *u8
92 let out: *i64 = sys_mmap(8*8) as *i64
93 tm_probe(elf, runs, timeout, out)
94 let v: i64 = tm_verdict(out[0], runs)
95 tm_w("TRANSIENT-MONITOR target=" as *u8); tm_w(elf); tm_w(" runs=" as *u8); tm_wn(runs)
96 tm_w(" | pass=" as *u8); tm_wn(out[0]); tm_w(" fail=" as *u8); tm_wn(out[1]); tm_w(" timeout=" as *u8); tm_wn(out[2])
97 tm_w(" | dur_ms min=" as *u8); tm_wn(out[3]); tm_w(" max=" as *u8); tm_wn(out[4]); tm_w(" => " as *u8)
98 if v==0 { tm_w("STABLE\n" as *u8) }
99 if v==1 { tm_w("FLAKY (transient ACCOUNTED -> root-cause required, not hand-waved)\n" as *u8) }
100 if v==2 { tm_w("BROKEN\n" as *u8) }
101 tm_record(elf, runs, out, v)
102 return v
103}