nx_behaveprobe_review_candidate_t371.nx source
↩ module page · 251 lines · 14297 B
1// nx_behaveprobe.nx -- paired workload observations for reviewed promotion evidence.
2// Complete capture and matching outputs/exits are observations, not sufficient proof of behavior,
3// workload coverage, or deployment quality. The caller must qualify the workload and exit contract.
4// Running a supplied workload executes it twice; the caller owns its side-effect authorization.
5// Existing CLI directions and helper entrypoints remain available.
6import "nx_tool_run.nx"
7import "json_emit.nx"
8import "nx_itoa_lib.nx"
9
10const BP_HOST: *u8 = "/volume1/homes/elderwesto/nishihost"
11const BP_CAP: i64 = 262144
12const BP_TMO: i64 = 120000
13// THIRD DIRECTION (2026-09-05): `self` compares LIVE against ITSELF. It needs no staged twin and no .prev, so
14// a referee can ask the live ruler how it reads a subject (its rc, its evidence grade) and whether the
15// subject's output is deterministic across two runs -- the question that surfaced today when the served
16// probe, older than the estate's own wait-status rule, reported rc=0 for a gate the crash guard had killed.
17// A signal death reads 128+signal from wait_status_rc (SIGTERM 143; SIGSEGV surfaces as 139 through the
18// crash guard); BP_SIGNAL_RC_BASE is that base, named once, so the grader can SAY signalled instead of
19// leaving a caller to notice that a rc above 128 is not a verdict.
20const BP_SIGNAL_RC_BASE: i64 = 128
21func bp_eq(a: *u8, b: *u8) -> i64 {
22 var i: i64 = 0
23 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
24 if b[i] != (0 as u8) { return 0 }
25 return 1
26}
27
28func bp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
29func be(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 }
30func bn(v:i64)->i64{return nxi_out(v)}
31func bcat(d: *u8, o: i64, s: *u8) -> i64 { var x: i64=o; var i: i64=0; while s[i]!=(0 as u8){d[x]=s[i];x=x+1;i=i+1} return x }
32func bexists(p: *u8) -> i64 { let fd: i64 = sys_openat_rd(p); if fd < 0 { return 0 } sys_close(fd); return 1 }
33
34// TEST THE HYPOTHESIS, NOT A PROXY FOR IT (2026-08-07). The 200-byte floor below existed to catch "both
35// sides printed the same USAGE LINE". Size is only a PROXY for that, and it is wrong in both directions:
36// MEASURED -- nx_fsops size <file> answered 70 B of correct output on a real argv, rc=0 both sides,
37// verdict IDENTICAL, and was graded WEAK. A byte-identical response to a real workload is the STRONGEST
38// signal this probe can produce, and a threshold on length threw it away.
39// So ask the real question: does the captured output actually CONTAIN a usage banner?
40// * WHEN YOU CAN TEST THE HYPOTHESIS DIRECTLY, A THRESHOLD ON A CORRELATE IS A WORSE INSTRUMENT, NOT A
41// CHEAPER ONE -- and it fails silently on every organ whose correct answer is short.
42func bp_has(buf: *u8, n: i64, needle: *u8) -> i64 {
43 var m: i64 = 0
44 while needle[m] != (0 as u8) { m = m + 1 }
45 if m == 0 { return 0 }
46 var i: i64 = 0
47 while i + m <= n {
48 var k: i64 = 0
49 var ok: i64 = 1
50 while k < m {
51 if buf[i + k] != needle[k] { ok = 0; k = m }
52 else { k = k + 1 }
53 }
54 if ok == 1 { return 1 }
55 i = i + 1
56 }
57 return 0
58}
59
60
61const BP_UNQUALIFIED:i64=-301
62const BP_INVALID:i64=-302
63const BP_G_WEAK:i64=1
64const BP_G_HARNESS:i64=2
65const BP_G_SIGNALLED:i64=3
66const BP_G_GRADED:i64=4
67const BP_G_STRONG:i64=5
68struct NxBehaviorRequest { live:*u8,other:*u8,cwd:*u8,args:*i64,arg_count:i64,timeout_ms:i64,max_capture_bytes:i64 }
69struct NxBehaviorResult { state:i64,matched:i64,same_output:i64,same_exit:i64,grade:i64,live_rc:i64,other_rc:i64,live_bytes:i64,other_bytes:i64,first_diff:i64,live_wait:i64,other_wait:i64,live_exit:i64,other_exit:i64,live_signal:i64,other_signal:i64,live_setup:i64,other_setup:i64,live_exec:i64,other_exec:i64,live_reaped:i64,other_reaped:i64,live_capacity:i64,other_capacity:i64,live_timeout:i64,other_timeout:i64,coverage_verified:i64 }
70func bp_result_init(r:*NxBehaviorResult)->i64{
71 r.state=BP_INVALID;r.matched=0;r.same_output=0;r.same_exit=0;r.grade=BP_G_HARNESS
72 r.live_rc=BP_INVALID;r.other_rc=BP_INVALID;r.live_bytes=0;r.other_bytes=0;r.first_diff=-1
73 r.live_wait=-1;r.other_wait=-1;r.live_exit=-1;r.other_exit=-1;r.live_signal=0;r.other_signal=0
74 r.live_setup=0;r.other_setup=0;r.live_exec=0;r.other_exec=0;r.live_reaped=0;r.other_reaped=0
75 r.live_capacity=0;r.other_capacity=0;r.live_timeout=0;r.other_timeout=0;r.coverage_verified=0;return 0
76}
77// Retained-output variant executes each authorized workload once; never reruns for review.
78func bp_run_owned_result(q:*NxBehaviorRequest,r:*NxBehaviorResult,a:*NxBufOwned,b:*NxBufOwned)->i64{
79 bp_result_init(r)
80 if nx_bo_state(a)!=0||nx_bo_state(b)!=0{return 2}
81 if a.len!=0||a.cap!=0||b.len!=0||b.cap!=0{return 2}
82 if q.arg_count<0||q.arg_count>NX_BO_I64_MAX/__size_of(i64)-2{return 2}
83 if q.timeout_ms<0||q.max_capture_bytes<0{return 2}
84 if (q.live as i64)<=0||(q.other as i64)<=0{return 2}
85 if q.arg_count>0{if (q.args as i64)<=0{return 2}}
86 let extent:i64=(q.arg_count+2)*__size_of(i64)
87 let av1:*i64=sys_mmap_try(extent) as *i64;let av2:*i64=sys_mmap_try(extent) as *i64
88 if (av1 as i64)<=0||(av2 as i64)<=0{
89 if (av1 as i64)>0{sys_munmap_direct(av1 as *u8,extent)}
90 if (av2 as i64)>0{sys_munmap_direct(av2 as *u8,extent)}
91 r.state=NX_BO_ALLOCATION;return 2
92 }
93 av1[0]=q.live as i64;av2[0]=q.other as i64
94 var i:i64=0;var valid:i64=1
95 while i<q.arg_count{if q.args[i]<=0{valid=0};av1[i+1]=q.args[i];av2[i+1]=q.args[i];i=i+1}
96 av1[q.arg_count+1]=0;av2[q.arg_count+1]=0
97 if valid==0{sys_munmap_direct(av1 as *u8,extent);sys_munmap_direct(av2 as *u8,extent);return 2}
98 var x:NxRunEvidence;var y:NxRunEvidence
99 r.live_rc=tr_run_capture_owned_result(q.live,av1,a,q.timeout_ms,q.max_capture_bytes,q.cwd,&x)
100 r.other_rc=tr_run_capture_owned_result(q.other,av2,b,q.timeout_ms,q.max_capture_bytes,q.cwd,&y)
101 sys_munmap_direct(av1 as *u8,extent);sys_munmap_direct(av2 as *u8,extent)
102 r.live_bytes=a.len;r.other_bytes=b.len;r.live_capacity=a.cap;r.other_capacity=b.cap
103 r.live_wait=x.raw_wait;r.other_wait=y.raw_wait;r.live_exit=x.exit_code;r.other_exit=y.exit_code
104 r.live_signal=x.signal;r.other_signal=y.signal;r.live_setup=x.setup_error;r.other_setup=y.setup_error
105 r.live_exec=x.exec_error;r.other_exec=y.exec_error;r.live_reaped=x.reaped;r.other_reaped=y.reaped
106 r.live_timeout=x.timed_out;r.other_timeout=y.timed_out
107 r.state=0
108 if r.live_rc<0{r.state=r.live_rc}
109 if r.other_rc<0{r.state=r.other_rc}
110 if x.setup_error<0||y.setup_error<0||x.exec_error<0||y.exec_error<0{r.state=BP_UNQUALIFIED}
111 if x.reaped!=1||y.reaped!=1{r.state=BP_UNQUALIFIED}
112 if r.state==0{
113 r.same_output=1;if a.len!=b.len{r.same_output=0}
114 var lim:i64=a.len;if b.len<lim{lim=b.len}
115 i=0;while i<lim{if a.buf[i]!=b.buf[i]{r.first_diff=i;r.same_output=0;i=lim}else{i=i+1}}
116 if r.same_output==0{if r.first_diff<0{r.first_diff=lim}}
117 if x.exited==y.exited&&x.exit_code==y.exit_code&&x.signal==y.signal{r.same_exit=1}
118 if r.same_output==1&&r.same_exit==1{r.matched=1}
119 r.grade=BP_G_STRONG
120 if a.len==0||b.len==0{r.grade=BP_G_WEAK}
121 if bp_has(a.buf,a.len,"usage:")==1||bp_has(b.buf,b.len,"usage:")==1||bp_has(a.buf,a.len,"Usage:")==1||bp_has(b.buf,b.len,"Usage:")==1{r.grade=BP_G_WEAK}
122 if x.exit_code!=0||y.exit_code!=0{if r.grade!=BP_G_WEAK{r.grade=BP_G_GRADED}}
123 if x.signal!=0||y.signal!=0{r.grade=BP_G_SIGNALLED;r.state=BP_UNQUALIFIED}
124 }
125 if r.state!=0{return 2}
126 if r.matched==1{return 0};return 1
127}
128
129// The caller owns both captures, including partial bytes on unqualified execution.
130// Compatibility entrypoint preserves the prior release-on-return contract.
131func bp_run_result(q:*NxBehaviorRequest,r:*NxBehaviorResult)->i64{
132 var a:NxBufOwned;var b:NxBufOwned
133 a.buf=0 as *u8;a.len=0;a.cap=0;b.buf=0 as *u8;b.len=0;b.cap=0
134 let rc:i64=bp_run_owned_result(q,r,&a,&b)
135 let ar:i64=nx_bo_release(&a);let br:i64=nx_bo_release(&b)
136 if ar<0{r.state=ar;r.grade=BP_G_HARNESS};if br<0{r.state=br;r.grade=BP_G_HARNESS}
137 if ar<0||br<0{return 2};return rc
138}
139
140func bp_len(s:*u8)->i64{var n:i64=0;while s[n]!=(0 as u8){n=n+1};return n}
141
142struct BpRecordWriter { owned:*NxBufOwned,number:*u8,max_bytes:i64,error:i64 }
143func bp_record_bytes(w:*BpRecordWriter,s:*u8,n:i64)->i64{
144 if w.error!=0{return w.error}
145 w.error=nx_bo_append(w.owned,s,n,w.max_bytes);return w.error
146}
147func bp_record_literal(w:*BpRecordWriter,s:*u8)->i64{return bp_record_bytes(w,s,bp_len(s))}
148func bp_record_string(w:*BpRecordWriter,s:*u8)->i64{
149 if w.error!=0{return w.error}
150 let n:i64=bp_len(s)
151 if n>(NX_BO_I64_MAX-2)/6{w.error=NX_BO_RANGE;return w.error}
152 let cap:i64=n*6+2
153 let tmp:*u8=sys_mmap_try(cap)
154 if (tmp as i64)<=0{w.error=NX_BO_ALLOCATION;return w.error}
155 var j:JsonWriter;j.buf=tmp;j.pos=0;j.cap=cap;j.depth=0;j.prior=0 as *u8
156 let rc:i64=je_emit_string_raw(&j,s,n)
157 if rc==0{bp_record_bytes(w,tmp,j.pos)}else{w.error=rc}
158 let freed:i64=sys_munmap_direct(tmp,cap)
159 if freed<0{w.error=NX_BO_RELEASE};return w.error
160}
161func bp_record_number(w:*BpRecordWriter,name:*u8,value:i64)->i64{
162 if w.error!=0{return w.error}
163 bp_record_literal(w,",");bp_record_string(w,name);bp_record_literal(w,":")
164 if w.error!=0{return w.error}
165 // All signed values use the same shared integer emitter.
166 let n:i64=nxi_buf(w.number,0,value)
167 return bp_record_bytes(w,w.number,n)
168}
169func bp_grade_text(grade:i64)->*u8{
170 if grade==BP_G_HARNESS{return "HARNESS: execution or complete capture unqualified"}
171 if grade==BP_G_SIGNALLED{return "SIGNALLED: actual terminating signal observed; no behavioral acceptance"}
172 if grade==BP_G_WEAK{return "WEAK: empty capture or usage-pattern observation; workload coverage unverified"}
173 if grade==BP_G_GRADED{return "GRADED: normal nonzero exit observed; caller must verify its workload contract"}
174 return "STRONG: legacy label for normal zero exits and nonempty non-usage capture; quality and coverage unverified"
175}
176func bp_build_result(target:*u8,mode:*u8,r:*NxBehaviorResult,owned:*NxBufOwned,max_bytes:i64)->i64{
177 if nx_bo_state(owned)!=0{return NX_BO_INVALID}
178 if owned.len!=0||owned.cap!=0{return NX_BO_INVALID}
179 if max_bytes<0{return NX_BO_INVALID}
180 if r.grade<BP_G_WEAK||r.grade>BP_G_STRONG{return BP_INVALID}
181 let number:*u8=sys_mmap_try(NXI_BUF)
182 if (number as i64)<=0{return NX_BO_ALLOCATION}
183 var w:BpRecordWriter;w.owned=owned;w.number=number;w.max_bytes=max_bytes;w.error=0
184 bp_record_literal(&w,"{\"organ\":\"nx_behaveprobe\",\"target\":")
185 bp_record_string(&w,target);bp_record_literal(&w,",\"mode\":");bp_record_string(&w,mode)
186 bp_record_number(&w,"live_rc",r.live_rc);bp_record_number(&w,"other_rc",r.other_rc)
187 bp_record_number(&w,"live_bytes",r.live_bytes);bp_record_number(&w,"other_bytes",r.other_bytes);bp_record_number(&w,"first_diff_off",r.first_diff)
188 bp_record_number(&w,"state",r.state);bp_record_number(&w,"same_output",r.same_output);bp_record_number(&w,"same_exit",r.same_exit)
189 bp_record_number(&w,"live_raw_wait",r.live_wait);bp_record_number(&w,"other_raw_wait",r.other_wait)
190 bp_record_number(&w,"live_exit_code",r.live_exit);bp_record_number(&w,"other_exit_code",r.other_exit)
191 bp_record_number(&w,"live_signal",r.live_signal);bp_record_number(&w,"other_signal",r.other_signal)
192 bp_record_number(&w,"live_setup_error",r.live_setup);bp_record_number(&w,"other_setup_error",r.other_setup)
193 bp_record_number(&w,"live_exec_error",r.live_exec);bp_record_number(&w,"other_exec_error",r.other_exec)
194 bp_record_number(&w,"live_reaped",r.live_reaped);bp_record_number(&w,"other_reaped",r.other_reaped)
195 bp_record_number(&w,"live_capture_capacity",r.live_capacity);bp_record_number(&w,"other_capture_capacity",r.other_capacity)
196 bp_record_number(&w,"live_timeout",r.live_timeout);bp_record_number(&w,"other_timeout",r.other_timeout)
197 bp_record_number(&w,"coverage_verified",r.coverage_verified)
198 bp_record_literal(&w,",\"verdict\":")
199 var verdict:*u8="DIFFERS"
200 if r.state!=0{verdict="UNQUALIFIED"}else{if r.matched==1{verdict="IDENTICAL"}}
201 bp_record_string(&w,verdict);bp_record_literal(&w,",\"evidence\":");bp_record_string(&w,bp_grade_text(r.grade))
202 bp_record_literal(&w,"}\n")
203 let freed:i64=sys_munmap_direct(number,NXI_BUF)
204 if freed<0{w.error=NX_BO_RELEASE}
205 return w.error
206}
207func bp_write_record(fd:i64,b:*NxBufOwned)->i64{
208 let state:i64=nx_bo_state(b);if state!=0{return state}
209 var off:i64=0
210 while off<b.len{
211 let n:i64=sys_write(fd,b.buf+off,b.len-off)
212 if n==TR_EINTR{continue}
213 if n<=0{return TR_ERR_DRAIN}
214 off=off+n
215 }
216 return 0
217}
218func bp_emit_result_fd(fd:i64,target:*u8,mode:*u8,r:*NxBehaviorResult)->i64{
219 var b:NxBufOwned;b.buf=0 as *u8;b.len=0;b.cap=0
220 var rc:i64=bp_build_result(target,mode,r,&b,0)
221 if rc==0{rc=bp_write_record(fd,&b)}
222 let freed:i64=nx_bo_release(&b);if freed<0{rc=freed}
223 if rc!=0{return 2};return 0
224}
225func bp_emit_result(target:*u8,mode:*u8,r:*NxBehaviorResult)->i64{return bp_emit_result_fd(1,target,mode,r)}
226
227func main(argc:i64,argv:*i64)->i64{
228 if argc<2{be("usage: nx_behaveprobe <target> [args...] | prev <target> [args...] | self <target> [args...]\n");return 3}
229 var ai:i64=1;var suffix:*u8=".sov.elf.new";var mode:*u8="live-vs-staged"
230 if bp_eq(argv[1] as *u8,"prev")==1{ai=2;suffix=".elf.prev";mode="live-vs-prev"}
231 if bp_eq(argv[1] as *u8,"self")==1{ai=2;suffix=".elf";mode="live-vs-self"}
232 if ai>=argc{be("nx_behaveprobe: missing target\n");return 3}
233 let target:*u8=argv[ai] as *u8
234 let hn:i64=bp_len(BP_HOST);let tn:i64=bp_len(target);let sn:i64=bp_len(suffix)
235 if hn>NX_BO_I64_MAX-tn-2{return 2};let base:i64=hn+tn+2
236 if base>NX_BO_I64_MAX-sn-4{return 2}
237 let ln:i64=base+4;let on:i64=base+sn
238 let lp:*u8=sys_mmap_try(ln);let op:*u8=sys_mmap_try(on)
239 if (lp as i64)<=0||(op as i64)<=0{
240 if (lp as i64)>0{sys_munmap_direct(lp,ln)}
241 if (op as i64)>0{sys_munmap_direct(op,on)};return 2
242 }
243 var z:i64=bcat(lp,0,BP_HOST);z=bcat(lp,z,"/");z=bcat(lp,z,target);z=bcat(lp,z,".elf");lp[z]=0 as u8
244 z=bcat(op,0,BP_HOST);z=bcat(op,z,"/");z=bcat(op,z,target);z=bcat(op,z,suffix);op[z]=0 as u8
245 var q:NxBehaviorRequest
246 q.live=lp;q.other=op;q.cwd=BP_HOST;q.args=((argv as i64)+(ai+1)*__size_of(i64)) as *i64;q.arg_count=argc-ai-1;q.timeout_ms=BP_TMO;q.max_capture_bytes=0
247 var r:NxBehaviorResult;let rc:i64=bp_run_result(&q,&r)
248 let emitted:i64=bp_emit_result(target,mode,&r)
249 sys_munmap_direct(lp,ln);sys_munmap_direct(op,on)
250 if emitted!=0{return emitted};return rc
251}