code wiki / _hdl_build / nx_apistack_breaker_gate.nx

nx_apistack_breaker_gate.nx source

↩ module page · 47 lines · 3311 B

1// nx_apistack_breaker_gate.nx -- hermetic gate for CAP-API-BREAKER. Proves the CLOSED->OPEN->HALF->CLOSED/OPEN 2// transitions: closed allows, threshold failures open it, open fails fast in cooldown, cooldown -> half-open probe, 3// probe success recovers, probe failure re-opens. Sovereign: nx_syscalls + nx_apistack_breaker. expect_exit: 0 4import "nx_syscalls.nx" 5import "nx_apistack_breaker.nx" 6import "nx_gate_verdict.nx" 7 8func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 9func gn(v: i64) -> i64 { var t: i64=v; if t<0{sys_write(1,"-" as *u8,1);t=0-t} let tm:*u8=sys_mmap(24); var k:i64=0; if t==0{tm[0]=48 as u8;k=1} while t>0{tm[k]=(48+(t%10)) as u8;t=t/10;k=k+1} let b:*u8=sys_mmap(24); var j:i64=0; while j<k{b[j]=tm[k-1-j];j=j+1} sys_write(1,b,k); return 0 } 10 11func main(argc: i64, argv: *i64) -> i64 { 12 gp("=== nx_apistack_breaker_gate (circuit-breaker CLOSED/OPEN/HALF) ===\n" as *u8) 13 let cb: *i64 = sys_mmap(64) as *i64 // cb[0]=CLOSED(0) cb[1]=0 cb[2]=0 14 var pass: i64 = 0; var fail: i64 = 0 15 16 // T1 closed -> allow 17 if cb_allow(cb, 0, 10) == 1 { pass=pass+1; gp(" T1 CLOSED -> allow PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL\n" as *u8) } 18 19 // T2 3 failures -> OPEN, then fail-fast within cooldown 20 cb_record(cb, 0, 3, 1); cb_record(cb, 0, 3, 2); cb_record(cb, 0, 3, 3) 21 if cb[0] == CB_OPEN { if cb_allow(cb, 5, 10) == 0 { pass=pass+1; gp(" T2 3 fails -> OPEN, fail-fast in cooldown PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL not rejecting\n" as *u8) } } else { fail=fail+1; gp(" T2 FAIL not open\n" as *u8) } 22 23 // T3 cooldown elapsed -> HALF (probe allowed) 24 let a3: i64 = cb_allow(cb, 15, 10) 25 if a3 == 1 { if cb[0] == CB_HALF { pass=pass+1; gp(" T3 cooldown -> HALF-OPEN probe allowed PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL not half\n" as *u8) } } else { fail=fail+1; gp(" T3 FAIL probe blocked\n" as *u8) } 26 27 // T4 probe success -> CLOSED (recovered) 28 cb_record(cb, 1, 3, 16) 29 if cb[0] == CB_CLOSED { pass=pass+1; gp(" T4 probe success -> CLOSED (recovered) PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL\n" as *u8) } 30 31 // T5 re-open then probe FAILURE -> OPEN again 32 cb_record(cb, 0, 3, 20); cb_record(cb, 0, 3, 21); cb_record(cb, 0, 3, 22) // -> OPEN (open_since=22) 33 cb_allow(cb, 40, 10) // -> HALF 34 cb_record(cb, 0, 3, 41) // probe fails in HALF -> OPEN 35 if cb[0] == CB_OPEN { pass=pass+1; gp(" T5 probe failure -> OPEN again PASS\n" as *u8) } else { fail=fail+1; gp(" T5 FAIL\n" as *u8) } 36 37 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 38 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 39 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 40 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 41 let ctr__dry: *i64 = gv_ctr() 42 ctr__dry[0] = pass 43 ctr__dry[1] = pass + fail 44 let rc__dry: i64 = gv_verdict("APISTACK-BREAKER-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 45 sys_exit(rc__dry) 46 return rc__dry 47}