code wiki / _hdl_build / nx_sweepcheck.nx
nx_sweepcheck.nx source
↩ module page · 165 lines · 7447 B
1// nx_sweepcheck.nx -- MECHANISES THE MOST EXPENSIVE RECURRING ERROR OF THIS PROGRAM: reporting a result
2// from a parameter that never reached the code.
3//
4// WHY THIS EXISTS (measured, not theorised). Across one session the same defect class was hit repeatedly:
5// * a reference-weight sweep returned 523/517/518/523 -- flat, because the handler never parsed the
6// argument. I nearly concluded the model change had failed.
7// * an index-offset A/B read 504 vs 508 and was declared "noise". The knob was hardcoded downstream;
8// the 4-point difference was PROMPT TEXT, not the knob.
9// * a dilation sweep at reach 0 / 4 / 12 returned BYTE-IDENTICAL results and was written up as a
10// regression WITH AN INVENTED ROOT CAUSE. The verb had fallen through to a different code path.
11// In every case the tell was the same and free: A SWEPT PARAMETER THAT PRODUCES NO VARIATION IS NOT AN
12// INEFFECTIVE PARAMETER -- IT IS AN UNWIRED ONE. Analysing such results is worse than useless, because a
13// plausible story gets attached to numbers that mean nothing.
14//
15// Per the banked law "A SESSION MUST REMEMBER < A TOOL THAT CANNOT DO THE WRONG THING", the check is
16// mechanised here instead of trusted to discipline. Feed it the measurements from any sweep BEFORE
17// interpreting them; it refuses the ones that carry no information.
18//
19// nx_sweepcheck values <v1> <v2> ... -> GREEN if the sweep varies, RED if it is flat (unwired)
20// nx_sweepcheck selftest
21// expect_exit: 0 license_tier: ORIGINAL
22import "nx_syscalls.nx"
23import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
24
25const SW_MIN_SAMPLES: i64 = 2
26
27func sw_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
28// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
29// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
30// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
31// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
32func sw_n(v: i64) -> i64 { nxi_out(v); return 0 }
33func sw_streq(a: *u8, b: *u8) -> i64 {
34 var i: i64=0
35 while a[i]!=(0 as u8) { if a[i]!=b[i] { return 0 } i=i+1 }
36 if b[i]!=(0 as u8) { return 0 }
37 return 1
38}
39func sw_atoi(s: *u8) -> i64 {
40 var v: i64=0
41 var i: i64=0
42 var neg: i64=0
43 if s[0]==(45 as u8) { neg=1; i=1 }
44 while s[i]!=(0 as u8) { let c: i64=(s[i] as i64)&255; if c>=48 { if c<=57 { v=v*10+(c-48) } } i=i+1 }
45 if neg==1 { return 0-v }
46 return v
47}
48
49// How many DISTINCT values does the sweep contain? 1 = flat = the parameter did nothing at all.
50func sw_distinct(vals: *i64, n: i64) -> i64 {
51 var d: i64 = 0
52 var i: i64 = 0
53 while i < n {
54 var seen: i64 = 0
55 var j: i64 = 0
56 while j < i { if vals[j] == vals[i] { seen = 1 } j = j + 1 }
57 if seen == 0 { d = d + 1 }
58 i = i + 1
59 }
60 return d
61}
62
63func sw_spread(vals: *i64, n: i64) -> i64 {
64 if n <= 0 { return 0 }
65 var lo: i64 = vals[0]
66 var hi: i64 = vals[0]
67 var i: i64 = 1
68 while i < n {
69 if vals[i] < lo { lo = vals[i] }
70 if vals[i] > hi { hi = vals[i] }
71 i = i + 1
72 }
73 return hi - lo
74}
75
76// The verdict. 0 = the sweep carries information; 3 = FLAT, treat as unwired and do not interpret.
77func sw_verdict(vals: *i64, n: i64, emit: i64) -> i64 {
78 if n < SW_MIN_SAMPLES {
79 if emit==1 { sw_w("{\"verdict\":\"RED\",\"why\":\"a sweep needs at least two samples to say anything\"}\n" as *u8) }
80 return 2
81 }
82 let d: i64 = sw_distinct(vals, n)
83 let s: i64 = sw_spread(vals, n)
84 if emit==1 {
85 sw_w("{\"samples\":" as *u8); sw_n(n)
86 sw_w(",\"distinct\":" as *u8); sw_n(d)
87 sw_w(",\"spread\":" as *u8); sw_n(s)
88 if d <= 1 {
89 sw_w(",\"verdict\":\"RED\",\"reading\":\"FLAT -- every sample identical. Treat the parameter as UNWIRED, not ineffective: verify it reaches the code before interpreting anything. Do NOT attach a root cause to these numbers.\"}\n" as *u8)
90 } else {
91 sw_w(",\"verdict\":\"GREEN\",\"reading\":\"the sweep varies, so the parameter demonstrably reaches the code and the results carry information\"}\n" as *u8)
92 }
93 }
94 if d <= 1 { return 3 }
95 return 0
96}
97
98func sw_selftest() -> i64 {
99 var pass: i64 = 0
100 var total: i64 = 0
101 let v: *i64 = sys_mmap(64) as *i64
102
103 // T1 the REAL dilation sweep that fooled me: 371/371/371 must be REFUSED
104 v[0]=371; v[1]=371; v[2]=371
105 total=total+1
106 let a: i64 = sw_verdict(v, 3, 0)
107 if a == 3 { pass=pass+1; sw_w(" [PASS] " as *u8) } else { sw_w(" [FAIL] " as *u8) }
108 sw_w("T1 FLAT-IS-UNWIRED: the real 371/371/371 dilation sweep is REFUSED (rc=" as *u8); sw_n(a); sw_w(")\n" as *u8)
109
110 // T2 the same sweep AFTER the wiring fix: 620/620/622 must PASS (2 distinct is enough)
111 v[0]=620; v[1]=620; v[2]=622
112 total=total+1
113 let b: i64 = sw_verdict(v, 3, 0)
114 if b == 0 { pass=pass+1; sw_w(" [PASS] " as *u8) } else { sw_w(" [FAIL] " as *u8) }
115 sw_w("T2 REAL VARIATION PASSES: the post-fix 620/620/622 sweep is accepted (rc=" as *u8); sw_n(b); sw_w(")\n" as *u8)
116
117 // T3 the ref_weight flat sweep 523/517/518/523 -- NOT identical, so it must NOT be refused as flat.
118 // This is the honest boundary: this organ catches DEAD parameters, not weak ones. A weak-but-live
119 // parameter is a different question and must not be silently folded into "unwired".
120 v[0]=523; v[1]=517; v[2]=518; v[3]=523
121 total=total+1
122 let c: i64 = sw_verdict(v, 4, 0)
123 if c == 0 { pass=pass+1; sw_w(" [PASS] " as *u8) } else { sw_w(" [FAIL] " as *u8) }
124 sw_w("T3 SCOPE HONESTY: a varying-but-weak sweep is NOT called unwired (rc=" as *u8); sw_n(c); sw_w(") -- this tool detects DEAD parameters, not weak ones\n" as *u8)
125
126 // T4 too few samples is refused rather than guessed
127 v[0]=5
128 total=total+1
129 let e: i64 = sw_verdict(v, 1, 0)
130 if e == 2 { pass=pass+1; sw_w(" [PASS] " as *u8) } else { sw_w(" [FAIL] " as *u8) }
131 sw_w("T4 REFUSES A SINGLE SAMPLE: one measurement is not a sweep (rc=" as *u8); sw_n(e); sw_w(")\n" as *u8)
132
133 sw_w("\n=== nx_sweepcheck " as *u8); sw_n(pass); sw_w("/" as *u8); sw_n(total)
134 if pass==total {
135 sw_w(" verdict=GREEN -- refuses the exact flat sweep that produced an invented root cause, accepts the same sweep once wired, and does not overreach into calling a weak parameter dead.\n" as *u8)
136 return 0
137 }
138 sw_w(" verdict=RED\n" as *u8)
139 return 1
140}
141
142func main(argc: i64, argv: *i64) -> i64 {
143 if argc < 2 {
144 sw_w("usage: nx_sweepcheck values <v1> <v2> ... | selftest\n" as *u8)
145 return 2
146 }
147 let verb: *u8 = argv[1] as *u8
148 if sw_streq(verb, "selftest" as *u8)==1 {
149 let f: i64 = sw_selftest()
150 if f==0 { sys_exit(0); return 0 }
151 sys_exit(1); return 1
152 }
153 if sw_streq(verb, "values" as *u8)==1 {
154 let n: i64 = argc - 2
155 if n < 1 { sw_w("{\"verdict\":\"RED\",\"why\":\"no values given\"}\n" as *u8); sys_exit(2); return 2 }
156 let v: *i64 = sys_mmap((n+1)*8) as *i64
157 var i: i64 = 0
158 while i < n { v[i] = sw_atoi(argv[i+2] as *u8); i = i + 1 }
159 let rc: i64 = sw_verdict(v, n, 1)
160 sys_exit(rc)
161 return rc
162 }
163 sw_w("{\"error\":\"unknown verb (values|selftest)\"}\n" as *u8)
164 return 2
165}