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}