code wiki / _hdl_build / nx_wflow_onerr_gate.nx
nx_wflow_onerr_gate.nx source
↩ module page · 109 lines · 5399 B
1// nx_wflow_onerr_gate.nx -- R10 ON-ERROR gate: optional 8th step field = forward on-fail target. On
2// exhausted attempts the failure stays RECORDED (FAILSTEP + ONFAIL), wf_error=yes + wf_error_step land on
3// the variable plane, remaining normal-path steps SKIP (recorded), execution lands at the handler -- which
4// is guarded by an R9 condition (wf_error=yes) so the SUCCESS path skips it naturally. Composition of
5// R8 vars + R9 conds, not a new mechanism. Hard failures (bad subst, denied approval) still hard-stop.
6// ZERO forks. license_tier: ORIGINAL expect_exit: 0
7import "nx_wflow_engine.nx"
8
9func eg_n(led: *u8, ridtok: *u8, st: *u8) -> i64 {
10 let szp: *i64 = sys_mmap(8) as *i64
11 let b: *u8 = wf_readall(led, szp)
12 if (b as i64) == 0 { return 0 - 1 }
13 return wf_lines_with2(b, szp[0], ridtok, st)
14}
15
16func main() -> i64 {
17 p("=== NX-WFLOW-ONERR GATE (R10: on-fail routes to a later handler step; failure stays recorded) ===\n" as *u8)
18 var ok: i64 = 1
19 let now: i64 = wf_now()
20 let led: *u8 = sys_mmap(128)
21 var lo: i64 = 0
22 lo = wf_cat(led, lo, "/tmp/wfoe_" as *u8)
23 lo = wf_catn(led, lo, now)
24 lo = wf_cat(led, lo, ".log" as *u8)
25 led[lo] = 0 as u8
26
27 let flows: *i64 = sys_mmap(8 * 4) as *i64
28 flows[0] = "fe1|risky|-" as *u8 as i64
29 flows[1] = "fe2|safe|-" as *u8 as i64
30 flows[2] = "fe3|old|-" as *u8 as i64
31 let steps: *i64 = sys_mmap(8 * 12) as *i64
32 steps[0] = "fe1|1|create-task|-|Attempt the risky thing|1|-|-" as *u8 as i64
33 steps[1] = "fe1|2|probe-fail|-|9|2|-|4" as *u8 as i64
34 steps[2] = "fe1|3|notify|-|Normal path continues|1" as *u8 as i64
35 steps[3] = "fe1|4|notify|-|Recovered from {wf_error_step}|1|wf_error=yes" as *u8 as i64
36 steps[4] = "fe1|5|notify|-|Always tail|1" as *u8 as i64
37 steps[5] = "fe2|1|probe-fail|-|1|1|-|3" as *u8 as i64
38 steps[6] = "fe2|2|notify|-|Normal completes|1" as *u8 as i64
39 steps[7] = "fe2|3|notify|-|Handler never fires|1|wf_error=yes" as *u8 as i64
40 steps[8] = "fe3|1|probe-fail|-|9|1" as *u8 as i64
41 let cx: *i64 = sys_mmap(32) as *i64
42 cx[0] = steps as i64
43 cx[1] = 9
44 cx[2] = led as i64
45 cx[3] = 0
46
47 // T0 load: 8-field rows valid; backward on-fail target refused; non-numeric refused
48 let l0: i64 = wf_load(steps, 9)
49 let bad: *i64 = sys_mmap(16) as *i64
50 bad[0] = "f9|2|notify|-|x|1|-|1" as *u8 as i64
51 let lb: i64 = wf_load(bad, 1)
52 let bad2: *i64 = sys_mmap(16) as *i64
53 bad2[0] = "f9|1|notify|-|x|1|-|abc" as *u8 as i64
54 let lb2: i64 = wf_load(bad2, 1)
55 p(" T0 load=" as *u8); pn(l0); p(" backTarget=" as *u8); pn(lb); p(" nonNum=" as *u8); pn(lb2); p("\n" as *u8)
56 if l0 != 9 { ok = 0 }
57 if lb != (0 - 1) { ok = 0 }
58 if lb2 != (0 - 1) { ok = 0 }
59
60 // T1 failure -> handler -> RECOVERED: FAILSTEP+ONFAIL recorded, step3 skipped, handler ran with
61 // {wf_error_step} substituted, tail ran, run DONE (not FAILED)
62 wf_fire(cx, flows, 3, "risky~id=R1" as *u8)
63 let fs: i64 = eg_n(led, " rid=R1.fe1 " as *u8, "status=FAILSTEP" as *u8)
64 let of: i64 = eg_n(led, " rid=R1.fe1 " as *u8, "status=ONFAIL" as *u8)
65 let s3: i64 = eg_n(led, " rid=R1.fe1 " as *u8, " step=3 status=SKIP" as *u8)
66 let h4: i64 = eg_n(led, " rid=R1.fe1 " as *u8, " step=4 status=OK" as *u8)
67 let t5: i64 = eg_n(led, " rid=R1.fe1 " as *u8, " step=5 status=OK" as *u8)
68 let ev: i64 = eg_n(led, " rid=R1.fe1 " as *u8, "k=wf_error_step v=step2" as *u8)
69 let d1: i64 = eg_n(led, " rid=R1.fe1 " as *u8, "status=DONE" as *u8)
70 let f1: i64 = eg_n(led, " rid=R1.fe1 " as *u8, "status=FAILED" as *u8)
71 p(" T1 recover failstep=" as *u8); pn(fs); p(" onfail=" as *u8); pn(of); p(" s3skip=" as *u8); pn(s3)
72 p(" handler=" as *u8); pn(h4); p(" tail=" as *u8); pn(t5); p(" errvar=" as *u8); pn(ev); p(" done=" as *u8); pn(d1); p(" failed=" as *u8); pn(f1); p("\n" as *u8)
73 if fs != 1 { ok = 0 }
74 if of != 1 { ok = 0 }
75 if s3 != 1 { ok = 0 }
76 if h4 != 1 { ok = 0 }
77 if t5 != 1 { ok = 0 }
78 if ev != 1 { ok = 0 }
79 if d1 != 1 { ok = 0 }
80 if f1 != 0 { ok = 0 }
81
82 // T2 SUCCESS path: handler (wf_error guard) skips naturally, no ONFAIL, DONE
83 wf_fire(cx, flows, 3, "safe~id=R2" as *u8)
84 let of2: i64 = eg_n(led, " rid=R2.fe2 " as *u8, "status=ONFAIL" as *u8)
85 let h3: i64 = eg_n(led, " rid=R2.fe2 " as *u8, " step=3 status=SKIP" as *u8)
86 let d2: i64 = eg_n(led, " rid=R2.fe2 " as *u8, "status=DONE" as *u8)
87 p(" T2 success onfail=" as *u8); pn(of2); p(" handlerSkipped=" as *u8); pn(h3); p(" done=" as *u8); pn(d2); p("\n" as *u8)
88 if of2 != 0 { ok = 0 }
89 if h3 != 1 { ok = 0 }
90 if d2 != 1 { ok = 0 }
91
92 // T3 no on-fail field = the old hard-stop contract, unchanged
93 wf_fire(cx, flows, 3, "old~id=R3" as *u8)
94 let f3: i64 = eg_n(led, " rid=R3.fe3 " as *u8, "status=FAILED" as *u8)
95 let d3: i64 = eg_n(led, " rid=R3.fe3 " as *u8, "status=DONE" as *u8)
96 p(" T3 hardstop failed=" as *u8); pn(f3); p(" done=" as *u8); pn(d3); p("\n" as *u8)
97 if f3 != 1 { ok = 0 }
98 if d3 != 0 { ok = 0 }
99
100 // T4 negctl
101 let ban: i64 = eg_n(led, "WFRUN" as *u8, "status=BANANA" as *u8)
102 p(" T4 negctl nonsense=" as *u8); pn(ban); p("\n" as *u8)
103 if ban != 0 { ok = 0 }
104
105 p("NX-WFLOW-ONERR-GATE ledger=" as *u8); p(led); p(" forks=0 " as *u8)
106 if ok == 1 { p("verdict=GREEN\n" as *u8); return 0 }
107 p("verdict=RED\n" as *u8)
108 return 1
109}