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}