nx_canon_solver_gate.nx source
↩ module page · 205 lines · 9693 B
1// nx_canon_solver_gate.nx -- GATE for the canon→constraint bridge (B1a, /world/procgen plan). Fixtures are
2// synthetic mini-canons ASSEMBLED AT RUNTIME with exactly-known typed placements, so the three outcomes are
3// asserted EXACTLY: CLEAN (deltas 0), ADJUSTED (the lint fires on precisely the planted defect and moves it
4// the right DIRECTION), INCONSISTENT (refused, worst named). gv-based. The REAL canon runs as a parse census
5// behind gv_need (its part indices are not yet identity-verified -- stated, not assumed).
6// license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_part_solver_lib.nx"
9import "nx_gate_verdict.nx"
10
11func gc_wfile(path: *u8, s: *u8) -> i64 {
12 let fd: i64 = sys_openat_wr(path, 0x1a4)
13 if fd < 0 { return 0 }
14 sys_write(fd, s, ps_slen(s))
15 sys_close(fd)
16 return 1
17}
18// run the bridge INLINE (same logic as the CLI: parse canon text -> part rows + rules -> solve).
19// Returns solver verdict; deltas checked by the caller via ps_x/y/z vs the known typed values.
20func gc_run(canon: *u8, rules: *u8) -> i64 {
21 let conf: *u8 = sys_mmap(65536)
22 // parse the canon the same way the organ does -- P rows only, fixed known layout for fixtures
23 // (fixture canons here use ONLY single-line P/R rows, so a tiny reader suffices; the organ's own
24 // reader is exercised end-to-end by the registered CLI -- this gate proves the SOLVE contract)
25 var o: i64 = 0
26 var i: i64 = 0
27 let n: i64 = ps_slen(canon)
28 var np: i64 = 0
29 while i < n {
30 if (canon[i] as i64) == 80 {
31 // P mirror rot ox oy oz ...
32 let pos: *i64 = sys_mmap(16) as *i64
33 pos[0] = i + 1
34 var e: i64 = i
35 var fe: i64 = 1
36 while fe == 1 { if e >= n { fe = 0 } else { if (canon[e] as i64) == 10 { fe = 0 } else { e = e + 1 } } }
37 gc_rd(canon, pos, e)
38 gc_rd(canon, pos, e)
39 let ox: i64 = gc_rd(canon, pos, e)
40 let oy: i64 = gc_rd(canon, pos, e)
41 let oz: i64 = gc_rd(canon, pos, e)
42 o = gc_cats(conf, o, "part p" as *u8)
43 o = gc_catn(conf, o, np)
44 o = gc_cats(conf, o, " " as *u8)
45 o = gc_catn(conf, o, ox)
46 o = gc_cats(conf, o, " " as *u8)
47 o = gc_catn(conf, o, oy)
48 o = gc_cats(conf, o, " " as *u8)
49 o = gc_catn(conf, o, oz)
50 o = gc_cats(conf, o, " 10\n" as *u8)
51 np = np + 1
52 i = e
53 }
54 i = i + 1
55 }
56 var q: i64 = 0
57 while rules[q] != (0 as u8) { conf[o] = rules[q]; o = o + 1; q = q + 1 }
58 if ps_load(conf, o) != 0 { return 0 - 9 }
59 return ps_solve()
60}
61func gc_rd(b: *u8, pos: *i64, end: i64) -> i64 {
62 var i: i64 = pos[0]
63 var go: i64 = 1
64 while go == 1 {
65 if i >= end { go = 0 } else {
66 let c: i64 = b[i] as i64
67 if c == 45 { go = 0 } else { if c >= 48 { if c <= 57 { go = 0 } else { i = i+1 } } else { i = i+1 } }
68 }
69 }
70 var sg: i64 = 1
71 if i < end { if (b[i] as i64) == 45 { sg = 0-1; i = i+1 } }
72 var v: i64 = 0
73 var g2: i64 = 1
74 while g2 == 1 {
75 if i >= end { g2 = 0 } else {
76 let c: i64 = b[i] as i64
77 if c >= 48 { if c <= 57 { v = v*10 + (c-48); i = i+1 } else { g2 = 0 } } else { g2 = 0 }
78 }
79 }
80 pos[0] = i
81 return v*sg
82}
83func gc_cats(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p }
84func gc_catn(d: *u8, o: i64, v: i64) -> i64 {
85 var p: i64 = o
86 var m: i64 = v
87 if m < 0 { d[p] = 45 as u8; p = p + 1; m = 0 - m }
88 if m == 0 { d[p] = 48 as u8; return p + 1 }
89 let t: *u8 = sys_mmap(32)
90 var k: i64 = 0
91 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
92 var i: i64 = 0
93 while i < k { d[p] = t[k-1-i]; p = p + 1; i = i + 1 }
94 return p
95}
96
97func main() -> i64 {
98 let ctr: *i64 = gv_ctr()
99 gv_head("nx_canon_solver_gate -- the canon beauty linter: CLEAN / ADJUSTED / INCONSISTENT asserted exactly" as *u8)
100
101 // mini-canon: head p0 at origin, eye-pair p1 at (33,5,40), mouth p2 at (0,-70,20)
102 let canon: *u8 = "P 0 0 0 0 0 0\nR 0 0 0 100 100\nP 1 90 33 5 40 1\nR 0 0 0 12 12\nP 0 0 0 -70 20 0\nR 0 0 0 10 8\n" as *u8
103
104 // T1 CLEAN: rules the typed canon already satisfies -> solved, every part delta 0
105 let r1: *u8 = "station p1 30 44\ninside p1 p0 80\nband p2 p0 60 90\n" as *u8
106 var t1: i64 = 0
107 if gc_run(canon, r1) == 1 {
108 if ps_x(1) == 33 { if ps_y(1) == 5 { if ps_z(1) == 40 { if ps_x(2) == 0 { if ps_z(2) == 20 { t1 = 1 } } } } }
109 }
110 gv_check("T1 CLEAN: satisfying canon passes with zero deltas (typed positions untouched)" as *u8, t1, ctr)
111
112 // T2 LINT fires on the planted defect ONLY: p2 station band [40,60] while typed z=20
113 let r2: *u8 = "station p1 30 44\nstation p2 40 60\n" as *u8
114 var t2: i64 = 0
115 if gc_run(canon, r2) == 1 {
116 if ps_z(2) >= 40 { if ps_z(2) <= 60 {
117 if ps_x(1) == 33 { if ps_y(1) == 5 { if ps_z(1) == 40 { t2 = 1 } } }
118 } }
119 }
120 gv_puts(" lint moved p2 z: 20 -> " as *u8); gv_num(ps_z(2)); gv_puts(" (band 40..60); p1 untouched\n" as *u8)
121 gv_check("T2 ADJUSTED: the planted band defect moves p2 into band, correct direction, others untouched" as *u8, t2, ctr)
122
123 // T3 INCONSISTENT: attach p1 to p0 at zero offset vs clear 400 -> refused, worst named
124 let r3: *u8 = "attach p1 p0 0 0 0\nclear p1 p0 400\n" as *u8
125 var t3: i64 = 0
126 if gc_run(canon, r3) == 0 { if ps_worst() >= 0 { t3 = 1 } }
127 gv_puts(" inconsistent worst=" as *u8); gv_puts(ps_kindname(ps_ckind(ps_worst()))); gv_puts("\n" as *u8)
128 gv_check("T3 INCONSISTENT: unsatisfiable rules refused with the worst constraint NAMED" as *u8, t3, ctr)
129
130 // T4 determinism
131 gc_run(canon, r2)
132 let z1: i64 = ps_z(2)
133 gc_run(canon, r2)
134 gv_check("T4 deterministic: identical solve on re-run" as *u8, ps_z(2) == z1, ctr)
135
136 // T6/T7 the ANCHOR-GUARD mechanism (documented placement as an immovable anchor part; `inside`
137 // moves ONLY the child): clean when the canon matches, lints ONLY the drifted part when it does not
138 let r4: *u8 = "part anchor 33 5 40 1\ninside p1 anchor 4\n" as *u8
139 var t6: i64 = 0
140 if gc_run(canon, r4) == 1 { if ps_x(1) == 33 { if ps_y(1) == 5 { if ps_z(1) == 40 { t6 = 1 } } } }
141 gv_check("T6 anchor-guard CLEAN: matching placement untouched (zero delta)" as *u8, t6, ctr)
142 let r5: *u8 = "part anchor 33 5 50 1\ninside p1 anchor 4\n" as *u8
143 var t7: i64 = 0
144 if gc_run(canon, r5) == 1 {
145 if ps_x(1) == 33 { if ps_z(1) >= 44 { if ps_z(1) <= 47 { if ps_x(2) == 0 { if ps_z(2) == 20 { t7 = 1 } } } } }
146 }
147 gv_puts(" drifted anchor: p1 z 40 -> " as *u8); gv_num(ps_z(1)); gv_puts(" (toward anchor z=50, tol 4); p2 untouched\n" as *u8)
148 gv_check("T7 anchor-guard LINTS drift: only the drifted part moves, correct direction, anchor immovable" as *u8, t7, ctr)
149
150 // T5 the REAL canon parses at census level (indices not identity-verified yet -- stated)
151 var havecanon: i64 = 0
152 let cfd: i64 = sys_openat_rd("knowledge/canon_merge2.dat" as *u8)
153 if cfd >= 0 { havecanon = 1; sys_close(cfd) }
154 if gv_need("knowledge/canon_merge2.dat" as *u8, havecanon, ctr) == 1 {
155 let lp: *i64 = sys_mmap(16) as *i64
156 let cb: *u8 = sys_read_file("knowledge/canon_merge2.dat" as *u8, lp)
157 var np2: i64 = 0
158 var nr2: i64 = 0
159 var eyec: i64 = 0
160 var eyeox: i64 = 0
161 var eyeoz: i64 = 0
162 var i2: i64 = 0
163 var bol: i64 = 1
164 while i2 < lp[0] {
165 if bol == 1 {
166 if (cb[i2] as i64) == 80 {
167 np2 = np2 + 1
168 let pos2: *i64 = sys_mmap(16) as *i64
169 pos2[0] = i2 + 1
170 var e2: i64 = i2
171 var f2: i64 = 1
172 while f2 == 1 { if e2 >= lp[0] { f2 = 0 } else { if (cb[e2] as i64) == 10 { f2 = 0 } else { e2 = e2 + 1 } } }
173 gc_rd(cb, pos2, e2)
174 gc_rd(cb, pos2, e2)
175 let ox2: i64 = gc_rd(cb, pos2, e2)
176 gc_rd(cb, pos2, e2)
177 let oz2: i64 = gc_rd(cb, pos2, e2)
178 let mat2: i64 = gc_rd(cb, pos2, e2)
179 if mat2 == 1 { eyec = eyec + 1; eyeox = ox2; eyeoz = oz2 }
180 }
181 if (cb[i2] as i64) == 82 { nr2 = nr2 + 1 }
182 }
183 if (cb[i2] as i64) == 10 { bol = 1 } else { bol = 0 }
184 i2 = i2 + 1
185 }
186 gv_puts(" canon_merge2: P rows=" as *u8); gv_num(np2)
187 gv_puts(" R rows=" as *u8); gv_num(nr2)
188 gv_puts(" eye-rows(mat=1)=" as *u8); gv_num(eyec)
189 gv_puts(" eye ox=" as *u8); gv_num(eyeox)
190 gv_puts(" oz=" as *u8); gv_num(eyeoz)
191 gv_puts("\n" as *u8)
192 var t5: i64 = 0
193 if np2 >= 5 { if np2 <= 256 { if nr2 > np2 { t5 = 1 } } }
194 gv_check("T5 the real face canon parses at census level (parts in solver range, rings present)" as *u8, t5, ctr)
195 // the 3-way identity, asserted mechanically: exactly ONE mat=1 row, at the documented 66mm
196 // interpupillary (ox 19 permil) and the sec56 forward offset (oz 50)
197 var t8: i64 = 0
198 if eyec == 1 { if eyeox == 19 { if eyeoz == 50 { t8 = 1 } } }
199 gv_check("T8 EYE IDENTITY gate-proven: one mat=1 part at ox=19 (66mm IPD) oz=50 (sec56 fix)" as *u8, t8, ctr)
200 }
201
202 let rc: i64 = gv_verdict("CANON-SOLVER-GATE" as *u8, ctr, "the canon lints against beauty/anatomy rules: CLEAN, ADJUSTED with named deltas, or refused" as *u8)
203 sys_exit(rc)
204 return rc
205}