nx_forge_loop_gate.nx source
↩ module page · 183 lines · 8938 B
1// nx_forge_loop_gate.nx -- gate for the A1 closed maker-checker loop (nx_forge_loop).
2// Deterministic, NO model: a forked stub maker (socket bound+listening BEFORE fork = raceless)
3// serves scripted /gen responses per cycle and CAPTURES each request body, proving:
4// T1 GREEN@1 passthrough: good candidate -> rc=1
5// T1b cycle-1 request carries NO repair header (clean first prompt)
6// T2 REPAIR CONVERGENCE: cycle1 = let-reassign BUILD-FAIL (the 1.5B fbench-T2 failure class;
7// the compiler names the fix) -> cycle2 = fixed candidate -> rc=2
8// T2b cycle-2 request MUST carry "PRIOR ATTEMPT FAILED" + the verbatim compiler word
9// ("reassign") = the little-coder +18% retry lever, mechanized and asserted
10// T3 NEG: a maker that IGNORES the repair ctx (same broken candidate every cycle) must NOT
11// converge -> rc=-21 (anti-rubber-stamp tooth)
12// T4 NEG: no serve listening -> rc=-30 (fail-loud, no silent fallback)
13// Fixture /gen JSONs are BUILT at gate time from the fixture .nx programs via fc_json_esc_bytes
14// (always in sync with the sources). license_tier: ORIGINAL expect_exit: 0
15import "nx_forge_loop.nx"
16import "nx_gate_verdict.nx"
17
18// bind+listen a loopback stub port (SO_REUSEADDR); returns listen fd or negative.
19func flpg_bind(port: i64) -> i64 {
20 let fd: i64 = sys_socket(2, 1, 0)
21 if fd < 0 { return 0 - 1 }
22 let opt: *i64 = sys_mmap(8) as *i64
23 opt[0] = 1
24 __syscall(54, fd, 1, 2, opt as i64, 4, 0)
25 let addr: *u8 = sys_mmap(16) as *u8
26 addr[0] = 2 as u8
27 addr[1] = 0 as u8
28 addr[2] = ((port >> 8) & 255) as u8
29 addr[3] = (port & 255) as u8
30 var z: i64 = 4
31 while z < 16 { addr[z] = 0 as u8; z = z + 1 }
32 if sys_bind(fd, addr, 16) < 0 { sys_close(fd); return 0 - 2 }
33 if sys_listen(fd, 16) < 0 { sys_close(fd); return 0 - 3 }
34 return fd
35}
36
37// serve n scripted requests on lfd: capture request -> caps[i], reply resps[i] as /gen JSON.
38func flpg_serve(lfd: i64, n: i64, resps: *i64, caps: *i64) -> i64 {
39 let h1: *u8 = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " as *u8
40 let h2: *u8 = "\r\nConnection: close\r\n\r\n" as *u8
41 let rq: *u8 = sys_mmap(65536) as *u8
42 let bodyb: *u8 = sys_mmap(65536) as *u8
43 let hdr: *u8 = sys_mmap(256) as *u8
44 var i: i64 = 0
45 while i < n {
46 let cfd: i64 = sys_accept(lfd)
47 if cfd < 0 { i = n }
48 if cfd >= 0 {
49 let r: i64 = sys_read(cfd, rq, 65536)
50 let cp0: i64 = caps[i]
51 let cpath: *u8 = cp0 as *u8
52 let kfd: i64 = sys_openat_wr(cpath, 420)
53 if kfd >= 0 { fc_wb(kfd, rq, r); sys_close(kfd) }
54 let rp0: i64 = resps[i]
55 let rpath: *u8 = rp0 as *u8
56 let bn: i64 = fc_read(rpath, bodyb, 65536)
57 var o: i64 = 0
58 var j: i64 = 0
59 while h1[j] != (0 as u8) { hdr[o] = h1[j]; o = o + 1; j = j + 1 }
60 let dl: i64 = std_itoa(bn, hdr + o)
61 o = o + dl
62 j = 0
63 while h2[j] != (0 as u8) { hdr[o] = h2[j]; o = o + 1; j = j + 1 }
64 sys_write(cfd, hdr, o)
65 sys_write(cfd, bodyb, bn)
66 sys_close(cfd)
67 i = i + 1
68 }
69 }
70 sys_close(lfd)
71 return 0
72}
73
74// build a /gen JSON fixture {"ok":1,"text":"<escaped program>"} from a fixture .nx program.
75func flpg_mkjson(progpath: *u8, outpath: *u8) -> i64 {
76 let pre: *u8 = "{\"ok\":1,\"text\":\"" as *u8
77 let pb: *u8 = sys_mmap(65536) as *u8
78 let jb: *u8 = sys_mmap(131072) as *u8
79 let n: i64 = fc_read(progpath, pb, 65536)
80 if n <= 0 { return 0 - 1 }
81 var o: i64 = 0
82 var i: i64 = 0
83 while pre[i] != (0 as u8) { jb[o] = pre[i]; o = o + 1; i = i + 1 }
84 o = fc_json_esc_bytes(jb, o, pb, n)
85 jb[o] = 34 as u8
86 o = o + 1
87 jb[o] = 125 as u8
88 o = o + 1
89 let fd: i64 = sys_openat_wr(outpath, 420)
90 if fd < 0 { return 0 - 2 }
91 let w: i64 = fc_wb(fd, jb, o)
92 sys_close(fd)
93 if w != 0 { return 0 - 3 }
94 return 0
95}
96
97// run one loop case against a scripted stub maker (bind pre-fork = raceless); returns flp rc.
98func flpg_case(organ: *u8, n: i64, resps: *i64, caps: *i64, port: i64, maxc: i64) -> i64 {
99 let taskp: *u8 = "knowledge/forge/fix/flp_task.txt" as *u8
100 let expp: *u8 = "knowledge/forge/fix/flp_expect.bin" as *u8
101 let packp: *u8 = "knowledge/forge/nishilang_pack_mini_v1.txt" as *u8
102 let lfd: i64 = flpg_bind(port)
103 if lfd < 0 { return 0 - 90 }
104 let pid: i64 = sys_fork()
105 if pid == 0 {
106 flpg_serve(lfd, n, resps, caps)
107 sys_exit(0)
108 }
109 sys_close(lfd)
110 let rc: i64 = flp_run(organ, taskp, expp, packp, port, maxc, 400, 0)
111 let st: *i64 = sys_mmap(64) as *i64
112 sys_wait4(pid, st, 0)
113 return rc
114}
115
116// does the captured request contain needle? 1 yes / 0 no / -1 capture unreadable.
117func flpg_cap_has(cappath: *u8, needle: *u8) -> i64 {
118 let b: *u8 = sys_mmap(65536) as *u8
119 let n: i64 = fc_read(cappath, b, 65536)
120 if n <= 0 { return 0 - 1 }
121 let nl: i64 = std_slen(needle)
122 let h: i64 = fc_contains(b, n, needle, nl)
123 return h
124}
125
126func main(argc: i64, argv: *i64) -> i64 {
127 std_putln("FORGE-LOOP-GATE: A1 closed maker-checker loop (scripted stub maker, raceless bind-pre-fork)" as *u8)
128 let mg: i64 = flpg_mkjson("knowledge/forge/fix/flp_good.nx" as *u8, "/tmp/flp_resp_good.json" as *u8)
129 let mb: i64 = flpg_mkjson("knowledge/forge/fix/flp_broken.nx" as *u8, "/tmp/flp_resp_broken.json" as *u8)
130 let mf: i64 = flpg_mkjson("knowledge/forge/fix/flp_fixed.nx" as *u8, "/tmp/flp_resp_fixed.json" as *u8)
131 if mg != 0 || mb != 0 || mf != 0 {
132 std_putln("GATE-FAIL fixture-json build" as *u8)
133 sys_exit(1)
134 return 1
135 }
136 let resps: *i64 = sys_mmap(64) as *i64
137 let caps: *i64 = sys_mmap(64) as *i64
138 var pass: i64 = 0
139 resps[0] = "/tmp/flp_resp_good.json" as *u8 as i64
140 caps[0] = "/tmp/flp_cap_t1_c1.txt" as *u8 as i64
141 let r1: i64 = flpg_case("nx_flpg_t1" as *u8, 1, resps, caps, 17841, 2)
142 if r1 == 1 { pass = pass + 1; std_putln("T1 PASS green@1" as *u8) }
143 if r1 != 1 { std_puts("T1 FAIL rc=" as *u8); std_pdec(r1); std_puts("\n" as *u8) }
144 let h1: i64 = flpg_cap_has("/tmp/flp_cap_t1_c1.txt" as *u8, "PRIOR ATTEMPT FAILED" as *u8)
145 if h1 == 0 { pass = pass + 1; std_putln("T1b PASS cycle-1 prompt clean (no repair header)" as *u8) }
146 if h1 != 0 { std_putln("T1b FAIL repair header present on cycle 1" as *u8) }
147 resps[0] = "/tmp/flp_resp_broken.json" as *u8 as i64
148 resps[1] = "/tmp/flp_resp_fixed.json" as *u8 as i64
149 caps[0] = "/tmp/flp_cap_t2_c1.txt" as *u8 as i64
150 caps[1] = "/tmp/flp_cap_t2_c2.txt" as *u8 as i64
151 let r2: i64 = flpg_case("nx_flpg_t2" as *u8, 2, resps, caps, 17842, 3)
152 if r2 == 2 { pass = pass + 1; std_putln("T2 PASS repair-converged@2" as *u8) }
153 if r2 != 2 { std_puts("T2 FAIL rc=" as *u8); std_pdec(r2); std_puts("\n" as *u8) }
154 let h2a: i64 = flpg_cap_has("/tmp/flp_cap_t2_c2.txt" as *u8, "PRIOR ATTEMPT FAILED" as *u8)
155 let h2b: i64 = flpg_cap_has("/tmp/flp_cap_t2_c2.txt" as *u8, "reassign" as *u8)
156 if h2a == 1 && h2b == 1 { pass = pass + 1; std_putln("T2b PASS cycle-2 prompt carries verbatim compiler ctx" as *u8) }
157 if h2a != 1 || h2b != 1 { std_putln("T2b FAIL repair ctx missing from cycle-2 prompt" as *u8) }
158 resps[0] = "/tmp/flp_resp_broken.json" as *u8 as i64
159 resps[1] = "/tmp/flp_resp_broken.json" as *u8 as i64
160 caps[0] = "/tmp/flp_cap_t3_c1.txt" as *u8 as i64
161 caps[1] = "/tmp/flp_cap_t3_c2.txt" as *u8 as i64
162 let r3: i64 = flpg_case("nx_flpg_t3" as *u8, 2, resps, caps, 17843, 2)
163 var t3ok: i64 = 0
164 if r3 + 21 == 0 { t3ok = 1 }
165 if t3ok == 1 { pass = pass + 1; std_putln("T3 PASS NEG ignore-repair did NOT converge (rc=-21)" as *u8) }
166 if t3ok == 0 { std_puts("T3 FAIL rc=" as *u8); std_pdec(r3); std_puts("\n" as *u8) }
167 let r4: i64 = flp_run("nx_flpg_t4" as *u8, "knowledge/forge/fix/flp_task.txt" as *u8, "knowledge/forge/fix/flp_expect.bin" as *u8, "knowledge/forge/nishilang_pack_mini_v1.txt" as *u8, 17844, 1, 400, 0)
168 var t4ok: i64 = 0
169 if r4 + 30 == 0 { t4ok = 1 }
170 if t4ok == 1 { pass = pass + 1; std_putln("T4 PASS NEG dead-serve fail-loud (rc=-30)" as *u8) }
171 if t4ok == 0 { std_puts("T4 FAIL rc=" as *u8); std_pdec(r4); std_puts("\n" as *u8) }
172 std_puts("FORGE-LOOP-GATE pass=" as *u8)
173 std_pdec(pass)
174 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
175 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
176 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
177 let ctr__dry: *i64 = gv_ctr()
178 ctr__dry[0] = pass
179 ctr__dry[1] = 6
180 let rc__dry: i64 = gv_verdict("FORGE-LOOP-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
181 sys_exit(rc__dry)
182 return rc__dry
183}