code wiki / _hdl_build / nx_softtissue_conserve_gate.nx
nx_softtissue_conserve_gate.nx source
↩ module page · 269 lines · 13333 B
1// nx_softtissue_conserve_gate.nx -- CONSERVATION + DISSIPATION SEAT (metrology council member 6),
2// 2026-08-03. Sibling of nx_softtissue_mr_gate (member 2) and DELIBERATELY DISJOINT FROM IT: member 2
3// asks whether the solver respects symmetries, this one asks whether it respects ENERGY AND VOLUME.
4// A wrong dynamics can be perfectly equivariant -- that is member 2's declared blind spot, and this
5// is the member that covers it. Per the council's own rule, a seat earns its place by covering a
6// blind spot no other member can see, never by raising the seat count.
7//
8// REGIME SPLIT, which is the whole point (conservation is the WRONG invariant for soft tissue):
9// RIGID/AUTONOMOUS regime -> a damped solver with no input must reach a FIXED POINT and stay there.
10// SOFT/OCCLUDED regime -> volume (here: ring cross-section area) is the conserved quantity, and
11// it must be conserved AT EVERY INDENTATION DEPTH, not at one tuned depth.
12//
13// ★THE EXACT INVARIANT THIS SEAT IS BUILT ON, chosen to need NO tolerance and NO oracle:
14// an autonomous damped INTEGER solver must converge to a BIT-IDENTICAL FIXED POINT.
15// Integer arithmetic makes this decidable in a way float never could: "at rest" is not "small", it is
16// state[t+1] == state[t] byte for byte, and it must then HOLD. A solver that never freezes is either
17// injecting energy or grinding in a truncation limit cycle -- both are real defects, both invisible
18// to every symmetry relation in member 2.
19//
20// T1 SD FIXED POINT kicked 3-pt solver freezes exactly, and HOLDS
21// T2 SD BITE undamped (C=0) must NOT freeze -- proves T1's detector can fail
22// T3 SR FIXED POINT perturbed 48-node region freezes exactly, and HOLDS
23// T4 SR BITE undamped region (damp=0) must NOT freeze
24// T5 SR GRAVITY REST under load the region still reaches a fixed point (sag equilibrium)
25// T6 AREA CONSERVATION cross-section area within band of rest at EVERY indentation depth
26// T7 AREA BITE voldist=0 (occlusion law OFF) must LEAVE the band -- proves T6 can fail
27// T8 BULGE MONOTONIC deeper indentation never produces a smaller far-side bulge
28// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
29import "nx_syscalls.nx"
30import "nx_softbind.nx"
31import "nx_softbody_region.nx"
32import "nx_gate_verdict.nx"
33
34const CG_SD_WORDS: i64 = 18 // SB_PTS(3) * stride(6)
35const CG_SD_STRIDE: i64 = 6
36const CG_RING_N: i64 = 16
37const CG_RING_R: i64 = 800
38const CG_SR_WORDS: i64 = 256 // CG_RING_N * 16 slots per node
39const CG_LONG: i64 = 20000 // generous convergence budget
40const CG_HOLD: i64 = 500 // a fixed point must HOLD, not just occur once
41const CG_SETTLE: i64 = 400 // ticks for an indentation to reach steady state
42
43// shipping chest band, firmness 0
44const CG_K: i64 = 60
45const CG_C: i64 = 100
46const CG_MAXD: i64 = 64
47const CG_KICK: i64 = 400
48
49// region params
50const CG_P_DAMP: i64 = 7
51const CG_P_GMULY: i64 = 9
52const CG_P_VOLDIST: i64 = 12
53const CG_DAMP_DEF: i64 = 30
54const CG_CAPR: i64 = 350
55const CG_CAPHALF: i64 = 400
56const CG_PERTURB: i64 = 200
57
58// ⚠FIRST ATTEMPT WAS VACUOUS AND THE BITE CAUGHT IT: I inherited the sibling gate's 85% floor and
59// mirrored it to [85,115]%. The voldist=0 CONTROL measures 94% and 90% -- INSIDE that band -- so the
60// band cannot discriminate, and by extension the sibling's own 85% floor barely discriminates either
61// (its real teeth is the "> control" comparison beside it, not the percentage).
62// ⇒ ★A THRESHOLD INHERITED WITHOUT MEASURING THE CONTROL AGAINST IT IS AN ASSUMPTION, NOT A BOUND.
63// The discriminator is not a band, it is the SIGN OF THE TREND: conservation means displaced volume
64// is preserved, so area must never fall BELOW rest and must not shrink as the indentation deepens.
65// The control does the opposite -- it falls, and falls further with depth. No invented tolerance.
66const CG_AREA_REST: i64 = 100
67
68func cg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
69func cg_isqrt(v: i64) -> i64 { if v <= 0 { return 0 } var x: i64 = v; var y: i64 = (x+1)/2; while y < x { x = y; y = (x + v/x)/2 } return x }
70func cg_snap(src: *i64, dst: *i64, n: i64) -> i64 { var i: i64 = 0; while i < n { dst[i] = src[i]; i = i + 1 } return 0 }
71func cg_same(a: *i64, b: *i64, n: i64) -> i64 { var i: i64 = 0; while i < n { if a[i] != b[i] { return 0 } i = i + 1 } return 1 }
72
73// ---- FIXED-POINT PROBE, 3-point solver. Returns the freeze tick, -1 if it never froze,
74// ---- or -2 if it "froze" then moved again (which is NOT a fixed point).
75func cg_freeze_sd(K: i64, C: i64) -> i64 {
76 let st: *i64 = sb_alloc(1)
77 sb_seat_mob(st, 0, 0, 0, 0)
78 sb_impulse_mob(st, 0, 0, CG_KICK, 0)
79 let prev: *i64 = sys_mmap(CG_SD_WORDS*8) as *i64
80 var t: i64 = 0
81 while t < CG_LONG {
82 cg_snap(st, prev, CG_SD_WORDS)
83 sb_tick_pt(st, 0, SB_CHEST, 0, 0, 0, K, C, CG_MAXD)
84 if cg_same(st, prev, CG_SD_WORDS) == 1 {
85 var h: i64 = 0
86 while h < CG_HOLD {
87 sb_tick_pt(st, 0, SB_CHEST, 0, 0, 0, K, C, CG_MAXD)
88 if cg_same(st, prev, CG_SD_WORDS) == 0 { return 0 - 2 }
89 h = h + 1
90 }
91 return t
92 }
93 t = t + 1
94 }
95 return 0 - 1
96}
97
98// ---- FIXED-POINT PROBE, 48-node region. Same contract.
99func cg_freeze_sr(damp: i64, gmuly: i64) -> i64 {
100 let base: i64 = sys_mmap(sr_bytes()) as i64
101 sr_init(base, 0, 0, 0)
102 sr_param(base, CG_P_DAMP, damp)
103 sr_param(base, CG_P_GMULY, gmuly)
104 sr_ring(base, CG_RING_N, CG_RING_R)
105 let n0: *i64 = sr_node(base, 0)
106 n0[0] = n0[0] + CG_PERTURB
107 let nodes: *i64 = (base + 128) as *i64
108 let prev: *i64 = sys_mmap(CG_SR_WORDS*8) as *i64
109 var t: i64 = 0
110 while t < CG_LONG {
111 cg_snap(nodes, prev, CG_SR_WORDS)
112 sr_step(base)
113 if cg_same(nodes, prev, CG_SR_WORDS) == 1 {
114 var h: i64 = 0
115 while h < CG_HOLD {
116 sr_step(base)
117 if cg_same(nodes, prev, CG_SR_WORDS) == 0 { return 0 - 2 }
118 h = h + 1
119 }
120 return t
121 }
122 t = t + 1
123 }
124 return 0 - 1
125}
126
127// ---- AREA under indentation at a chosen depth, as a PERCENT of the settled rest area.
128func cg_area_pct(depth: i64, voldist: i64) -> i64 {
129 let base: i64 = sys_mmap(sr_bytes()) as i64
130 sr_init(base, 0, 0, 0)
131 sr_param(base, CG_P_GMULY, 0) // isolate the occlusion law from gravity
132 sr_param(base, CG_P_VOLDIST, voldist)
133 sr_ring(base, CG_RING_N, CG_RING_R)
134 var t: i64 = 0
135 while t < CG_SETTLE { sr_step(base); t = t + 1 }
136 let rest: i64 = sr_area(base)
137 if rest <= 0 { return 0 - 1 }
138 // capsule surface reaches CG_RING_R - depth on the +x side
139 let cx: i64 = CG_RING_R + CG_CAPR - depth
140 sr_add_capsule(base, cx, 0 - CG_CAPHALF, 0, cx, CG_CAPHALF, 0, CG_CAPR)
141 t = 0
142 while t < CG_SETTLE { sr_step(base); t = t + 1 }
143 return sr_area(base)*100/rest
144}
145
146// ---- far-side bulge (node 8 = 180deg) beyond rest radius, at a chosen indentation depth
147func cg_bulge(depth: i64) -> i64 {
148 let base: i64 = sys_mmap(sr_bytes()) as i64
149 sr_init(base, 0, 0, 0)
150 sr_param(base, CG_P_GMULY, 0)
151 sr_ring(base, CG_RING_N, CG_RING_R)
152 var t: i64 = 0
153 while t < CG_SETTLE { sr_step(base); t = t + 1 }
154 let cx: i64 = CG_RING_R + CG_CAPR - depth
155 sr_add_capsule(base, cx, 0 - CG_CAPHALF, 0, cx, CG_CAPHALF, 0, CG_CAPR)
156 t = 0
157 while t < CG_SETTLE { sr_step(base); t = t + 1 }
158 let h: *i64 = sr_hdr(base)
159 let ox: i64 = sr_pos(base, 8, 0) - h[2]
160 let oy: i64 = sr_pos(base, 8, 1) - h[3]
161 return cg_isqrt(ox*ox + oy*oy) - CG_RING_R
162}
163
164func main() -> i64 {
165 let ctr: *i64 = gv_ctr()
166 gv_head("nx_softtissue_conserve gate -- CONSERVATION + DISSIPATION, split by regime (council seat 6)" as *u8)
167
168 // ================= REGIME 1: AUTONOMOUS -- must reach an exact fixed point ==================
169 let f_sd: i64 = cg_freeze_sd(CG_K, CG_C)
170 let f_sd0: i64 = cg_freeze_sd(CG_K, 0)
171 gv_puts(" measured: 3-pt solver freeze tick, damped C=" as *u8); gv_num(CG_C)
172 gv_puts(" -> " as *u8); gv_num(f_sd)
173 gv_puts(" ; undamped C=0 -> " as *u8); gv_num(f_sd0)
174 gv_puts(" (-1 = never froze, -2 = froze then moved)\n" as *u8)
175 var t1: i64 = 0
176 if f_sd >= 0 { t1 = 1 }
177 gv_check("T1 SD FIXED POINT damped 3-pt solver converges to an exact frozen state and HOLDS" as *u8, t1, ctr)
178 var b2bad: i64 = 0
179 if f_sd0 < 0 { b2bad = 1 }
180 var b2good: i64 = 0
181 if f_sd < 0 { b2good = 1 }
182 gv_bite("T2 BITE fixed-point detector: fires on the UNDAMPED solver, silent on the damped one" as *u8, b2bad, b2good, ctr)
183
184 let f_sr: i64 = cg_freeze_sr(CG_DAMP_DEF, 0)
185 let f_sr0: i64 = cg_freeze_sr(0, 0)
186 gv_puts(" measured: 48-node region freeze tick, damp=" as *u8); gv_num(CG_DAMP_DEF)
187 gv_puts(" -> " as *u8); gv_num(f_sr)
188 gv_puts(" ; damp=0 -> " as *u8); gv_num(f_sr0); gv_puts("\n" as *u8)
189 var t3: i64 = 0
190 if f_sr >= 0 { t3 = 1 }
191 gv_check("T3 SR FIXED POINT perturbed 48-node region converges to an exact frozen state and HOLDS" as *u8, t3, ctr)
192 var b4bad: i64 = 0
193 if f_sr0 < 0 { b4bad = 1 }
194 var b4good: i64 = 0
195 if f_sr < 0 { b4good = 1 }
196 gv_bite("T4 BITE region fixed-point detector: fires on the UNDAMPED region, silent on the damped" as *u8, b4bad, b4good, ctr)
197
198 let f_srg: i64 = cg_freeze_sr(CG_DAMP_DEF, 256)
199 gv_puts(" measured: region under FULL gravity freeze tick -> " as *u8); gv_num(f_srg); gv_puts("\n" as *u8)
200 var t5: i64 = 0
201 if f_srg >= 0 { t5 = 1 }
202 gv_check("T5 SR GRAVITY REST region under sustained load still reaches a fixed point (sag equilibrium)" as *u8, t5, ctr)
203
204 // ================= REGIME 2: OCCLUDED -- volume is the conserved quantity ==================
205 // ★A CONSERVATION LAW THAT HOLDS AT ONE TUNED DEPTH IS A FITTED CONSTANT, NOT A LAW. The sibling
206 // gate checks one depth, one-sided. This sweeps depth and bounds BOTH sides.
207 let a1: i64 = cg_area_pct(50, 256)
208 let a2: i64 = cg_area_pct(100, 256)
209 let a3: i64 = cg_area_pct(150, 256)
210 let a4: i64 = cg_area_pct(200, 256)
211 let a5: i64 = cg_area_pct(250, 256)
212 gv_puts(" measured: area as % of rest by indentation depth -- 50:" as *u8); gv_num(a1)
213 gv_puts(" 100:" as *u8); gv_num(a2)
214 gv_puts(" 150:" as *u8); gv_num(a3)
215 gv_puts(" 200:" as *u8); gv_num(a4)
216 gv_puts(" 250:" as *u8); gv_num(a5); gv_puts("\n" as *u8)
217 // the detector: does the ring LOSE volume at any depth, or lose it as depth grows?
218 var lost: i64 = 0
219 if a1 < CG_AREA_REST { lost = lost + 1 }
220 if a2 < CG_AREA_REST { lost = lost + 1 }
221 if a3 < CG_AREA_REST { lost = lost + 1 }
222 if a4 < CG_AREA_REST { lost = lost + 1 }
223 if a5 < CG_AREA_REST { lost = lost + 1 }
224 var shrank: i64 = 0
225 if a2 < a1 { shrank = shrank + 1 }
226 if a3 < a2 { shrank = shrank + 1 }
227 if a4 < a3 { shrank = shrank + 1 }
228 if a5 < a4 { shrank = shrank + 1 }
229 gv_puts(" measured: depths losing volume vs rest = " as *u8); gv_num(lost)
230 gv_puts(" of 5 ; depth steps that SHRANK = " as *u8); gv_num(shrank); gv_puts(" of 4\n" as *u8)
231 var t6: i64 = 0
232 if lost == 0 { if shrank == 0 { t6 = 1 } }
233 gv_check("T6 AREA CONSERVATION no volume lost at ANY depth and never shrinks as indentation deepens" as *u8, t6, ctr)
234
235 // T7 BITE: the SAME detector against the occlusion law switched OFF.
236 let c1: i64 = cg_area_pct(50, 0)
237 let c3: i64 = cg_area_pct(150, 0)
238 let c5: i64 = cg_area_pct(250, 0)
239 gv_puts(" measured: voldist=0 control -- 50:" as *u8); gv_num(c1)
240 gv_puts(" 150:" as *u8); gv_num(c3)
241 gv_puts(" 250:" as *u8); gv_num(c5); gv_puts("\n" as *u8)
242 var b7bad: i64 = 0
243 if c1 < CG_AREA_REST { b7bad = 1 }
244 if c3 < CG_AREA_REST { b7bad = 1 }
245 if c5 < CG_AREA_REST { b7bad = 1 }
246 if c5 < c1 { b7bad = 1 }
247 var b7good: i64 = 0
248 if t6 == 0 { b7good = 1 }
249 gv_bite("T7 BITE volume-loss detector: fires with the occlusion law OFF, silent with it ON" as *u8, b7bad, b7good, ctr)
250 // ⚠REPORTED, NOT ASSERTED: area RISES with depth (100->107%). Truly incompressible tissue would
251 // hold ~100%, so the law slightly OVER-compensates, and the excess grows with indentation. That is
252 // a finding for the physics, not a gate failure -- gaining volume is the safe direction for a
253 // bulge, and inventing a tight upper bound here would be exactly the assumption T6 just retired.
254
255 // T8 the law must be MONOTONE in depth -- more displaced volume can never mean less bulge
256 let g1: i64 = cg_bulge(50)
257 let g3: i64 = cg_bulge(150)
258 let g5: i64 = cg_bulge(250)
259 gv_puts(" measured: far-side bulge beyond rest -- depth 50:" as *u8); gv_num(g1)
260 gv_puts(" 150:" as *u8); gv_num(g3)
261 gv_puts(" 250:" as *u8); gv_num(g5); gv_puts("\n" as *u8)
262 var t8: i64 = 0
263 if g3 >= g1 { if g5 >= g3 { if g1 > 0 { t8 = 1 } } }
264 gv_check("T8 BULGE MONOTONIC deeper indentation never yields a smaller far-side bulge" as *u8, t8, ctr)
265
266 let rc: i64 = gv_verdict("SOFTTISSUE-CONSERVE-GATE" as *u8, ctr,
267 "regime-split conservation seat: autonomous solvers reach exact fixed points, occluded volume conserved across depth, detectors bite-proven" as *u8)
268 return rc
269}