code wiki / (root) / nx_auto_supports_v2_target_test.nx

nx_auto_supports_v2_target_test.nx source

↩ module page · 126 lines · 5243 B

1// nx_auto_supports_v2_target_test.nx -- four-pillar MONITOR 2// for the auto-supports mushroom miss surfaced by Phase B2.1 3// (commit prior). This test EXPECTS the bug -- it will FAIL 4// loudly when the v2 fix lands, signalling to update assertions. 5// 6// The bug: nx_slice_pipe_build_supports does NOT detect overhangs 7// on a clean mushroom shape (column 4x4 + cap 10x10 with 3mm 8// shoulder). Empirically: 9// - Direct call to nx_supports_layer_overhang with the column 10// polygon and cap polygon DOES detect overhang vertices 11// (verified by background diagnostic, exit 0) 12// - So the primitive math works. The bug is in the slicer 13// integration: contour-build at z=20.0 coplanar slice, or 14// contour pairing by index at the transition layer, or 15// layer indexing skipping the mushroom shoulder. 16// 17// V2 fix queued (not in this commit): 18// - Contour-centroid tracking for matching across layers 19// - Cumulative-printed-region check (vertex outside any prev 20// layer's contour => overhang) 21// - Handle abrupt shape change (single-vs-multi-contour 22// transitions) 23// 24// When v2 ships, this smoke's expected verdict flips from 25// "v1 misses (plan.n == 0)" to "v2 detects (plan.n > 0)". 26// The body literally says `expect plan.n == 0` -- which means 27// the test FAILS LOUD if v2 ships without updating this smoke. 28// That's the MONITOR pillar. 29// 30// expect_exit: 0 (current: v1 returns plan.n=0; expect that) 31// license_tier: ORIGINAL 32 33import "nx_syscalls.nx" 34import "nx_mesh.nx" 35import "nx_bvh.nx" 36import "nx_machine_graph.nx" 37import "nx_material_profile.nx" 38import "nx_supports.nx" 39import "nx_slice_auto_supports.nx" 40 41const Q14: i64 = 16384 42 43func build_mushroom() -> *NxMesh { 44 let m: *NxMesh = nx_mesh_alloc(16, 24, 0) 45 let col_lo: i64 = 3 * Q14 46 let col_hi: i64 = 7 * Q14 47 let col_top_z: i64 = 20 * Q14 48 nx_mesh_set_vertex(m, 0, col_lo, col_lo, 0, 0) 49 nx_mesh_set_vertex(m, 1, col_hi, col_lo, 0, 0) 50 nx_mesh_set_vertex(m, 2, col_hi, col_hi, 0, 0) 51 nx_mesh_set_vertex(m, 3, col_lo, col_hi, 0, 0) 52 nx_mesh_set_vertex(m, 4, col_lo, col_lo, col_top_z, 0) 53 nx_mesh_set_vertex(m, 5, col_hi, col_lo, col_top_z, 0) 54 nx_mesh_set_vertex(m, 6, col_hi, col_hi, col_top_z, 0) 55 nx_mesh_set_vertex(m, 7, col_lo, col_hi, col_top_z, 0) 56 let cap_lo: i64 = 0 57 let cap_hi: i64 = 10 * Q14 58 let cap_top_z: i64 = 30 * Q14 59 nx_mesh_set_vertex(m, 8, cap_lo, cap_lo, col_top_z, 0) 60 nx_mesh_set_vertex(m, 9, cap_hi, cap_lo, col_top_z, 0) 61 nx_mesh_set_vertex(m, 10, cap_hi, cap_hi, col_top_z, 0) 62 nx_mesh_set_vertex(m, 11, cap_lo, cap_hi, col_top_z, 0) 63 nx_mesh_set_vertex(m, 12, cap_lo, cap_lo, cap_top_z, 0) 64 nx_mesh_set_vertex(m, 13, cap_hi, cap_lo, cap_top_z, 0) 65 nx_mesh_set_vertex(m, 14, cap_hi, cap_hi, cap_top_z, 0) 66 nx_mesh_set_vertex(m, 15, cap_lo, cap_hi, cap_top_z, 0) 67 nx_mesh_set_triangle(m, 0, 0, 1, 2) 68 nx_mesh_set_triangle(m, 1, 0, 2, 3) 69 nx_mesh_set_triangle(m, 2, 4, 6, 5) 70 nx_mesh_set_triangle(m, 3, 4, 7, 6) 71 nx_mesh_set_triangle(m, 4, 0, 1, 5) 72 nx_mesh_set_triangle(m, 5, 0, 5, 4) 73 nx_mesh_set_triangle(m, 6, 1, 2, 6) 74 nx_mesh_set_triangle(m, 7, 1, 6, 5) 75 nx_mesh_set_triangle(m, 8, 2, 3, 7) 76 nx_mesh_set_triangle(m, 9, 2, 7, 6) 77 nx_mesh_set_triangle(m, 10, 3, 0, 4) 78 nx_mesh_set_triangle(m, 11, 3, 4, 7) 79 nx_mesh_set_triangle(m, 12, 8, 10, 9) 80 nx_mesh_set_triangle(m, 13, 8, 11, 10) 81 nx_mesh_set_triangle(m, 14, 12, 13, 14) 82 nx_mesh_set_triangle(m, 15, 12, 14, 15) 83 nx_mesh_set_triangle(m, 16, 8, 9, 13) 84 nx_mesh_set_triangle(m, 17, 8, 13, 12) 85 nx_mesh_set_triangle(m, 18, 9, 10, 14) 86 nx_mesh_set_triangle(m, 19, 9, 14, 13) 87 nx_mesh_set_triangle(m, 20, 10, 11, 15) 88 nx_mesh_set_triangle(m, 21, 10, 15, 14) 89 nx_mesh_set_triangle(m, 22, 11, 8, 12) 90 nx_mesh_set_triangle(m, 23, 11, 12, 15) 91 return m 92} 93 94func main() -> i64 { 95 let pla: *NxMaterialProfile = nx_material_profile_generic_pla() 96 let m: *NxMesh = build_mushroom() 97 let bvh: *NxBvh = nx_bvh_build(m) 98 let lh: i64 = 3277 99 let lw: i64 = 6554 100 101 let plan: *NxSupportPlan = nx_slice_pipe_build_supports( 102 m, bvh, pla, lh, lh, lw * 5, lw * 2) 103 104 if (plan as i64) == 0 { return 10 } // plan was NULL -- precheck failed 105 106 // MONITOR pillar: encode the v1 bug as EXPECTED outcome. 107 // 108 // When auto-supports v2 ships and starts detecting the mushroom 109 // overhang, plan.n becomes positive and the assertion below 110 // fails -- forcing the test author to update this monitor. 111 // 112 // The "expected" sequence: 113 // v1 (today): plan.n == 0 (v1 misses; this smoke PASSES) 114 // v2 future: plan.n > 0 (v2 detects; THIS SMOKE FAILS LOUD) 115 // -> author updates assertion to >=4 116 // -> v2's detection is locked in by 117 // the regression-smoke contract 118 if plan.n != 0 { 119 // V2 LANDED! Update the assertions in this file: 120 // "plan.n >= 4" (4 cap corners predicted as overhangs) 121 // and rename this test from "v2_target" to "v2_check". 122 return 20 123 } 124 125 return 0 126}