@tangle-network/agent-bench 0.7.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/HARNESS.md +2 -2
  3. package/dist/adapters.js +6 -2
  4. package/dist/adapters.js.map +1 -1
  5. package/dist/benchmarks/appworld.d.ts +61 -2
  6. package/dist/benchmarks/appworld.js +111 -40
  7. package/dist/benchmarks/appworld.js.map +1 -1
  8. package/dist/benchmarks/cadbench.js +1 -1
  9. package/dist/benchmarks/cadgenbench.js +1 -1
  10. package/dist/benchmarks/finresearchbench.js +16 -22
  11. package/dist/benchmarks/finresearchbench.js.map +1 -1
  12. package/dist/benchmarks/finsearchcomp.js +16 -22
  13. package/dist/benchmarks/finsearchcomp.js.map +1 -1
  14. package/dist/benchmarks/frames.js +18 -20
  15. package/dist/benchmarks/frames.js.map +1 -1
  16. package/dist/benchmarks/mcad-bench.d.ts +106 -0
  17. package/dist/benchmarks/mcad-bench.js +569 -0
  18. package/dist/benchmarks/mcad-bench.js.map +1 -0
  19. package/dist/benchmarks/mcad-cq-bench.d.ts +82 -0
  20. package/dist/benchmarks/mcad-cq-bench.js +339 -0
  21. package/dist/benchmarks/mcad-cq-bench.js.map +1 -0
  22. package/dist/benchmarks/mcad-cq-golds.d.ts +36 -0
  23. package/dist/benchmarks/mcad-cq-golds.js +342 -0
  24. package/dist/benchmarks/mcad-cq-golds.js.map +1 -0
  25. package/dist/benchmarks/mcad-golds.d.ts +20 -0
  26. package/dist/benchmarks/mcad-golds.js +318 -0
  27. package/dist/benchmarks/mcad-golds.js.map +1 -0
  28. package/dist/benchmarks/mcad-tasks.d.ts +66 -0
  29. package/dist/benchmarks/mcad-tasks.js +508 -0
  30. package/dist/benchmarks/mcad-tasks.js.map +1 -0
  31. package/dist/benchmarks/simpleqa.js +15 -19
  32. package/dist/benchmarks/simpleqa.js.map +1 -1
  33. package/dist/benchmarks/trata-hedge.js +20 -23
  34. package/dist/benchmarks/trata-hedge.js.map +1 -1
  35. package/dist/{cadbench-BrpwOU6A.js → cadbench-BLSyxR1N.js} +21 -20
  36. package/dist/cadbench-BLSyxR1N.js.map +1 -0
  37. package/dist/{cadgenbench-DF7hYHdl.js → cadgenbench-x2OFkf8y.js} +2 -2
  38. package/dist/cadgenbench-x2OFkf8y.js.map +1 -0
  39. package/dist/index.d.ts +0 -1
  40. package/dist/index.js +10 -9
  41. package/dist/index.js.map +1 -1
  42. package/dist/router-turn-C2wMiDoo.js +31 -0
  43. package/dist/router-turn-C2wMiDoo.js.map +1 -0
  44. package/package.json +7 -7
  45. package/scripts/appworld_driver.py +1 -170
  46. package/scripts/run-package-tests.mjs +56 -36
  47. package/scripts/run-package-tests.test.mjs +33 -0
  48. package/scripts/trata-hedge/README.md +3 -3
  49. package/scripts/trata-hedge/run.sh +6 -2
  50. package/src/adapters.ts +11 -0
  51. package/src/aec-gate.mts +30 -9
  52. package/src/agent-graphs-gen2.mts +523 -0
  53. package/src/agent-graphs-gen3.mts +660 -0
  54. package/src/agent-graphs-improve/offline-seams.mts +128 -0
  55. package/src/agent-graphs-improve.mts +747 -0
  56. package/src/atom-humaneval.mts +76 -55
  57. package/src/atom-mcp-e2e.mts +27 -13
  58. package/src/benchmarks/appworld.test.mts +119 -1
  59. package/src/benchmarks/appworld.ts +156 -33
  60. package/src/benchmarks/cadbench.ts +21 -8
  61. package/src/benchmarks/finresearchbench.ts +20 -16
  62. package/src/benchmarks/finsearchcomp.ts +20 -20
  63. package/src/benchmarks/frames.ts +19 -18
  64. package/src/benchmarks/mcad-bench.test.mts +455 -0
  65. package/src/benchmarks/mcad-bench.ts +561 -0
  66. package/src/benchmarks/mcad-cq-bench.ts +423 -0
  67. package/src/benchmarks/mcad-cq-golds.ts +374 -0
  68. package/src/benchmarks/mcad-cq.test.mts +386 -0
  69. package/src/benchmarks/mcad-golds.ts +359 -0
  70. package/src/benchmarks/mcad-tasks.ts +490 -0
  71. package/src/benchmarks/simpleqa.ts +19 -17
  72. package/src/benchmarks/trata-hedge.ts +26 -18
  73. package/src/browser/ui-reviewer.ts +1 -1
  74. package/src/clbench-context-gate.mts +45 -9
  75. package/src/cloud-loop.mts +24 -6
  76. package/src/commit0-env-run.mts +6 -3
  77. package/src/commit0-env.ts +2 -3
  78. package/src/commit0-gate.mts +53 -24
  79. package/src/corpus.ts +3 -3
  80. package/src/david-attribution.mts +28 -9
  81. package/src/david-goliath.mts +31 -12
  82. package/src/egress-probe.mts +3 -3
  83. package/src/examples/lean-proof-gate.mts +10 -3
  84. package/src/examples/math-demo.mts +10 -3
  85. package/src/examples/strategy-demo.mts +10 -4
  86. package/src/fleet.mts +30 -8
  87. package/src/gate-cli.mts +9 -4
  88. package/src/gate.test.mts +7 -2
  89. package/src/gate.ts +23 -75
  90. package/src/generate-eval/certify.ts +13 -5
  91. package/src/hev-eval.mts +39 -10
  92. package/src/hev-improve.mts +28 -16
  93. package/src/hev-structural.mts +28 -20
  94. package/src/humaneval-gate.mts +24 -8
  95. package/src/humaneval-object-ablation.mts +52 -14
  96. package/src/humaneval-repair-gate.mts +53 -14
  97. package/src/mbpp-structural.mts +28 -20
  98. package/src/mcp-mount-probe.mts +23 -11
  99. package/src/official-optimizer-config.mts +61 -12
  100. package/src/official-optimizer-config.test.mts +72 -3
  101. package/src/quant-arena/profiles/quant-researcher.profile.json +6 -1
  102. package/src/quant-arena/quant-loop.mts +88 -61
  103. package/src/research-shot.ts +21 -11
  104. package/src/resolve-client.ts +6 -8
  105. package/src/rollout-ledger/backfill-swe-arena.test.mts +7 -2
  106. package/src/router-executor.ts +1 -1
  107. package/src/router-turn.ts +135 -0
  108. package/src/run-benchmarks.ts +7 -2
  109. package/src/sandbox-run.ts +23 -41
  110. package/src/search-bench/bridge.ts +66 -8
  111. package/src/search-bench/parametric-check.mts +19 -4
  112. package/src/search-bench/profiles.ts +24 -9
  113. package/src/search-bench/run.mts +3 -4
  114. package/src/smoke-structural-rollout.mts +21 -5
  115. package/src/supervisor-arena.mts +28 -20
  116. package/src/swe-arena/arms.ts +73 -15
  117. package/src/swe-arena/capacity.ts +44 -41
  118. package/src/swe-arena/diagnosis-ensemble.ts +51 -48
  119. package/src/swe-arena/execution.test.mts +12 -12
  120. package/src/swe-arena/gepa-seat.mts +12 -5
  121. package/src/swe-arena/gepa-seat.test.mts +45 -33
  122. package/src/swe-arena/outer-loop.mts +94 -70
  123. package/src/swe-arena/premeasured-from-cells.mts +16 -1
  124. package/src/swe-arena/premeasured-from-cells.test.mts +21 -1
  125. package/src/swe-arena/profiles/deepseek-author.profile.json +12 -0
  126. package/src/swe-arena/profiles/default-author.profile.json +9 -1
  127. package/src/swe-arena/proposer-fanout.mts +52 -99
  128. package/src/swe-arena/proposer-fanout.test.mts +92 -57
  129. package/src/swe-arena/proposer-provenance.mts +1 -1
  130. package/src/swe-code-improve.mts +30 -52
  131. package/src/swe-emit-patch.mts +26 -5
  132. package/src/swe-improve.mts +27 -8
  133. package/src/swe-jail.test.ts +128 -0
  134. package/src/swe-jail.ts +106 -22
  135. package/src/swe-local-proof.mts +27 -5
  136. package/src/swe-repro-calibrate.mts +5 -0
  137. package/src/swe-self-improve.mts +45 -10
  138. package/src/swe-stream.mts +68 -6
  139. package/src/swe-structural.mts +46 -7
  140. package/src/tb-container-executor.mts +38 -6
  141. package/src/tb-container-executor.test.mts +11 -3
  142. package/src/tb-supervisor-sidecar.mts +11 -27
  143. package/src/terminal-compare.ts +38 -18
  144. package/src/trata-gate.mts +26 -26
  145. package/src/trata-gepa.mts +25 -16
  146. package/src/trata-hedge-solve.mts +80 -0
  147. package/src/worker-blender.ts +21 -11
  148. package/src/worker-browser.ts +18 -5
  149. package/src/worker-build123d.ts +17 -8
  150. package/src/worker-cad.ts +31 -12
  151. package/src/worker.ts +1 -1
  152. package/tb_agents/opencode_router_agent.py +84 -42
  153. package/dist/cadbench-BrpwOU6A.js.map +0 -1
  154. package/dist/cadgenbench-DF7hYHdl.js.map +0 -1
  155. package/scripts/trata-hedge/solve.py +0 -83
@@ -0,0 +1,318 @@
1
+ /** Gold OpenSCAD source per task id. */
2
+ const MCAD_GOLDS = {
3
+ "calibration-block": `
4
+ $fn=96;
5
+
6
+ // The chamfer is the hull between the full-size body and a 2 mm inset top plate,
7
+ // so it lands on the top perimeter only and leaves the bore walls square.
8
+ module chamfered_block(l, w, h, c) {
9
+ hull() {
10
+ translate([-l/2, -w/2, 0]) cube([l, w, h - c]);
11
+ translate([-l/2 + c, -w/2 + c, h - c]) cube([l - 2*c, w - 2*c, c]);
12
+ }
13
+ }
14
+
15
+ difference() {
16
+ chamfered_block(100, 60, 20, 2);
17
+ for (x = [-35, 35]) for (y = [-20, 20])
18
+ translate([x, y, -1]) cylinder(h = 22, d = 8);
19
+ }
20
+ `.trim(),
21
+ "circular-flange": `
22
+ $fn=96;
23
+
24
+ // Revolved section: a 15..40 mm x 0..10 mm rectangle whose corners are rounded by
25
+ // 1.5 mm (shrink then grow). That carries the required round on both outside
26
+ // circular edges; the same round lands on the bore edges, which the prompt does
27
+ // not ask for and does not forbid.
28
+ difference() {
29
+ rotate_extrude()
30
+ offset(r = 1.5) offset(delta = -1.5)
31
+ polygon([[15, 0], [40, 0], [40, 10], [15, 10]]);
32
+ for (i = [0:5]) rotate([0, 0, i * 60])
33
+ translate([30, 0, -1]) cylinder(h = 12, d = 6);
34
+ }
35
+ `.trim(),
36
+ "l-bracket": `
37
+ $fn=96;
38
+
39
+ // The L is a (Y, Z) section extruded along X. rotate([90,0,90]) maps local
40
+ // (x, y, z) to global (z, x, y), so a 2D point (y, z) extrudes along +X.
41
+ r = 2; // round on the outside corner where the base and the back plate meet
42
+ arc = [for (i = [0:8]) [25 - r + r*cos(-90 + 90*i/8), r + r*sin(-90 + 90*i/8)]];
43
+ section = concat([[-25, 0], [25 - r, 0]], arc, [[25, 58], [17, 58], [17, 8], [-25, 8]]);
44
+
45
+ difference() {
46
+ union() {
47
+ translate([-40, 0, 0]) rotate([90, 0, 90]) linear_extrude(80) polygon(section);
48
+ // gussets: right triangle 30 tall x 30 deep, 8 mm thick in X, at X = +/-20
49
+ for (x = [-20, 20])
50
+ translate([x - 4, 0, 0]) rotate([90, 0, 90]) linear_extrude(8)
51
+ polygon([[17, 8], [-13, 8], [17, 38]]);
52
+ }
53
+ // base plate through-holes; the cutter stops flush at the base top (Z=8) so it
54
+ // cannot notch the gussets that stand on that face
55
+ for (x = [-25, 25]) translate([x, -10, -1]) cylinder(h = 9, d = 6);
56
+ // back plate through-holes, along +Y through the 8 mm thickness
57
+ for (x = [-25, 25]) translate([x, 17, 30]) rotate([-90, 0, 0]) cylinder(h = 9, d = 6);
58
+ }
59
+ `.trim(),
60
+ "stepped-shaft-keyway": `
61
+ $fn=96;
62
+
63
+ // Every section is a cylinder laid along +X; the two end chamfers are 1 mm frusta.
64
+ module seg(x, len, r1, r2) {
65
+ translate([x, 0, 0]) rotate([0, 90, 0]) cylinder(h = len, r1 = r1, r2 = r2);
66
+ }
67
+
68
+ difference() {
69
+ union() {
70
+ seg(0, 1, 9, 10);
71
+ seg(1, 29, 10, 10);
72
+ seg(30, 60, 15, 15);
73
+ seg(90, 29, 10, 10);
74
+ seg(119, 1, 10, 9);
75
+ }
76
+ // keyway: 6 mm wide in Y, 3 mm deep from the Z=15 top, X = 40..80
77
+ translate([40, -3, 12]) cube([40, 6, 5]);
78
+ }
79
+ `.trim(),
80
+ "open-top-electronics-enclosure": `
81
+ $fn=96;
82
+
83
+ // Outer box with 2 mm rounds on the four vertical corners.
84
+ module rounded_box(l, w, h, r) {
85
+ hull() for (x = [-l/2 + r, l/2 - r]) for (y = [-w/2 + r, w/2 - r])
86
+ translate([x, y, 0]) cylinder(h = h, r = r);
87
+ }
88
+
89
+ union() {
90
+ difference() {
91
+ rounded_box(100, 70, 30, 2);
92
+ // interior cavity: 3 mm walls, 3 mm floor, open at the top
93
+ translate([-47, -32, 3]) cube([94, 64, 31]);
94
+ }
95
+ // standoffs rising from the inside floor, each with a 3 mm x 8 mm blind hole
96
+ for (x = [-35, 35]) for (y = [-25, 25])
97
+ translate([x, y, 3]) difference() {
98
+ cylinder(h = 12, d = 10);
99
+ translate([0, 0, 4]) cylinder(h = 9, d = 3);
100
+ }
101
+ }
102
+ `.trim(),
103
+ "clevis-bracket-lightening-cutouts": `
104
+ $fn=96;
105
+
106
+ // Base plate, 3 mm rounds on the four vertical perimeter corners.
107
+ module base_plate() {
108
+ hull() for (x = [-57, 57]) for (y = [-27, 27])
109
+ translate([x, y, 0]) cylinder(h = 10, r = 3);
110
+ }
111
+
112
+ // One clevis lug: an (X, Z) side profile extruded 18 mm in Y. The straight part
113
+ // runs Z=10..34 and the semicircular cap is r=18 about Z=34, so the lug top is at
114
+ // Z=52 -- exactly 42 mm above the base, as the prompt states.
115
+ module lug() {
116
+ translate([0, 26, 0]) rotate([90, 0, 0]) linear_extrude(18)
117
+ union() {
118
+ translate([-18, 10]) square([36, 24]);
119
+ translate([0, 34]) circle(r = 18);
120
+ }
121
+ }
122
+
123
+ // 2 mm transition flare where the lug foot meets the base plate.
124
+ module lug_foot() {
125
+ hull() {
126
+ translate([-20, 6, 10]) cube([40, 22, 0.01]);
127
+ translate([-18, 8, 12]) cube([36, 18, 0.01]);
128
+ }
129
+ }
130
+
131
+ // Diagonal reinforcing rib, 6 mm thick in Y, lying against the lug's outer face.
132
+ module rib() {
133
+ translate([0, 26, 0]) rotate([90, 0, 0]) linear_extrude(6)
134
+ polygon([[18, 10], [40, 10], [18, 34]]);
135
+ }
136
+
137
+ difference() {
138
+ union() {
139
+ base_plate();
140
+ lug(); mirror([0, 1, 0]) lug();
141
+ lug_foot(); mirror([0, 1, 0]) lug_foot();
142
+ rib(); mirror([0, 1, 0]) rib();
143
+ }
144
+ // clevis pin bore, 14 mm through both lugs along Y at X=0, Z=34
145
+ translate([0, -27, 34]) rotate([-90, 0, 0]) cylinder(h = 54, d = 14);
146
+ // four 7 mm base mounting holes
147
+ for (x = [-45, 45]) for (y = [-20, 20])
148
+ translate([x, y, -1]) cylinder(h = 12, d = 7);
149
+ // triangular lightening cutouts through the base web, corners rounded 3 mm
150
+ for (x = [-31, 31]) translate([x, 0, -1]) linear_extrude(12)
151
+ offset(r = 3) polygon([[6, 0], [-3, 5.2], [-3, -5.2]]);
152
+ }
153
+ `.trim(),
154
+ "radial-engine-cylinder": `
155
+ $fn=96;
156
+
157
+ // One cooling fin: a 2 mm disc whose outer edge carries the 1 mm round, so the
158
+ // fin outside diameter is 2*(30+1) = 62 mm. The round's own section is coarse
159
+ // ($fn=24): at 96 it puts ~18k triangles on each of the 12 fins and takes the
160
+ // CGAL union past two minutes for a 1 mm cosmetic edge.
161
+ module fin(z) {
162
+ translate([0, 0, z]) union() {
163
+ cylinder(h = 2, r = 30);
164
+ translate([0, 0, 1]) rotate_extrude() translate([30, 0]) circle(r = 1, $fn = 24);
165
+ }
166
+ }
167
+
168
+ difference() {
169
+ union() {
170
+ cylinder(h = 70, r = 18); // barrel
171
+ for (i = [0:11]) fin(10 + 5 * i); // 12 fins, Z = 10..67
172
+ // base flange OD 70 x 8, 1 mm rounds on its outer edges. The profile starts
173
+ // at x=1 (not 0) so the revolve never sees a negative radius; the barrel
174
+ // above fills that 1 mm core.
175
+ rotate_extrude() offset(r = 1) offset(delta = -1)
176
+ polygon([[1, 0], [35, 0], [35, 8], [1, 8]]);
177
+ translate([0, 0, 70]) cylinder(h = 8, r = 22); // top cap
178
+ // spark-plug boss: 12 mm dia, 24 mm long, 35 deg above horizontal, +X, rooted
179
+ // inside the top cap so it fuses with it
180
+ translate([10, 0, 72]) rotate([0, 55, 0]) cylinder(h = 24, d = 12);
181
+ }
182
+ // six 5 mm mounting holes on the 56 mm bolt circle of the base flange
183
+ for (i = [0:5]) rotate([0, 0, i * 60]) translate([28, 0, -1]) cylinder(h = 10, d = 5);
184
+ // 5 mm bore along the boss axis
185
+ translate([10, 0, 72]) rotate([0, 55, 0]) cylinder(h = 25, d = 5);
186
+ }
187
+ `.trim(),
188
+ "centrifugal-impeller": `
189
+ $fn=96;
190
+
191
+ // Blade centreline: radius 18 -> 43 while sweeping 45 degrees backward. The blade
192
+ // is the swept 3 mm disc along that path, so its thickness is 3 mm everywhere.
193
+ function bp(t) = [(18 + 25*t) * cos(-45*t), (18 + 25*t) * sin(-45*t)];
194
+
195
+ module blade() {
196
+ for (i = [0:11]) hull() {
197
+ translate(bp(i/12)) circle(d = 3, $fn = 32);
198
+ translate(bp((i+1)/12)) circle(d = 3, $fn = 32);
199
+ }
200
+ }
201
+
202
+ difference() {
203
+ union() {
204
+ // backplate OD 90 x 6 with 1.5 mm rounds on both outer circular edges
205
+ rotate_extrude() offset(r = 1.5) offset(delta = -1.5)
206
+ polygon([[1, 0], [45, 0], [45, 6], [1, 6]]);
207
+ translate([0, 0, 6]) cylinder(h = 22, r = 13); // hub
208
+ // 12 blades, 16 mm tall above the backplate. The prompt's own radii leave a
209
+ // 5 mm gap between the blade roots (r=18) and the hub (r=13), so the stated
210
+ // blade-to-hub root fillet has nothing to fillet and is omitted.
211
+ for (i = [0:11]) rotate([0, 0, i * 30])
212
+ translate([0, 0, 6]) linear_extrude(16) blade();
213
+ }
214
+ translate([0, 0, -1]) cylinder(h = 30, d = 8); // through-bore
215
+ }
216
+ `.trim(),
217
+ "spiral-staircase": `
218
+ $fn=96;
219
+
220
+ n = 20; // treads
221
+ z0 = 4; // first tread bottom
222
+ rise = 6; // Z step per tread
223
+ turn = 18; // degrees per tread
224
+ rail_r = 66; rail_z0 = 14; rail_z1 = 130;
225
+
226
+ // Handrail height at a given plan angle, measured counter-clockwise from +X.
227
+ function rail_z(a) = rail_z0 + (rail_z1 - rail_z0) * a / 360;
228
+
229
+ // A wedge tread: annulus sector from ri to ro over "ang" degrees.
230
+ module tread(ri, ro, ang, h) {
231
+ m = 24;
232
+ linear_extrude(h) polygon(concat(
233
+ [for (i = [0:m]) [ri * cos(ang*i/m), ri * sin(ang*i/m)]],
234
+ [for (i = [m:-1:0]) [ro * cos(ang*i/m), ro * sin(ang*i/m)]]));
235
+ }
236
+
237
+ union() {
238
+ cylinder(h = 140, r = 7); // central column
239
+ cylinder(h = 5, r = 45); // base disk, Z = 0..5 (overlaps the first tread)
240
+ for (k = [0:n-1]) {
241
+ rotate([0, 0, k * turn]) translate([0, 0, z0 + k * rise]) tread(10, 62, 24, 4);
242
+ // baluster at the tread's outer end, mid-width, reaching the handrail centre
243
+ rotate([0, 0, k * turn + 12]) translate([63, 0, z0 + k * rise])
244
+ cylinder(h = rail_z(k * turn + 12) - (z0 + k * rise), d = 3);
245
+ }
246
+ // helical handrail: a 5 mm circle at radius 66 swept one counter-clockwise turn
247
+ // (OpenSCAD's positive twist is clockwise) while rising Z=14 -> 130
248
+ translate([0, 0, rail_z0])
249
+ linear_extrude(height = rail_z1 - rail_z0, twist = -360, slices = 96)
250
+ translate([rail_r, 0]) circle(d = 5, $fn = 48);
251
+ }
252
+ `.trim(),
253
+ "planetary-gear-stage": `
254
+ $fn=96;
255
+
256
+ // Straight-sided trapezoidal teeth: each tooth is a four-point polygon between the
257
+ // root and tip circles, unioned onto (external) or subtracted from (internal) the
258
+ // gear blank. Half-angles are given at the root and the tip.
259
+ module ext_gear(n, r_root, r_tip, ha_root, ha_tip, phase) {
260
+ union() {
261
+ circle(r = r_root);
262
+ for (i = [0:n-1]) rotate(phase + 360*i/n)
263
+ polygon([[r_root*cos(-ha_root), r_root*sin(-ha_root)],
264
+ [r_tip*cos(-ha_tip), r_tip*sin(-ha_tip)],
265
+ [r_tip*cos(ha_tip), r_tip*sin(ha_tip)],
266
+ [r_root*cos(ha_root), r_root*sin(ha_root)]]);
267
+ }
268
+ }
269
+
270
+ module int_gear(n, r_tip, r_root, r_out, ha_tip, ha_root, phase) {
271
+ difference() {
272
+ circle(r = r_out);
273
+ difference() {
274
+ circle(r = r_root);
275
+ for (i = [0:n-1]) rotate(phase + 360*i/n)
276
+ polygon([[r_root*cos(-ha_root), r_root*sin(-ha_root)],
277
+ [r_tip*cos(-ha_tip), r_tip*sin(-ha_tip)],
278
+ [r_tip*cos(ha_tip), r_tip*sin(ha_tip)],
279
+ [r_root*cos(ha_root), r_root*sin(ha_root)]]);
280
+ }
281
+ }
282
+ }
283
+
284
+ gz = 16; // gear underside; the pins (Z=0..14) stop 2 mm short of it
285
+ gt = 8; // gear thickness
286
+
287
+ // sun: 24 teeth, root d42, OD 54. Phase 7.5 puts a tooth SPACE on each of the
288
+ // three planet directions (0/120/240 deg), which is the only phase where the sun
289
+ // tip circle clears the planet root circle at all.
290
+ translate([0, 0, gz]) linear_extrude(gt) difference() {
291
+ ext_gear(24, 21, 27, 4, 0.2, 7.5);
292
+ circle(d = 10);
293
+ }
294
+
295
+ // three planets: 18 teeth, root d31, OD 41, centres on r=42 every 120 deg. Phase 0
296
+ // puts a tooth on the sun side (local 180) and on the ring side (local 0).
297
+ for (i = [0:2]) rotate(120*i) translate([42, 0, gz])
298
+ linear_extrude(gt) ext_gear(18, 15.5, 20.5, 5, 2, 0);
299
+
300
+ // ring: 60 internal teeth, OD 140, internal root d126.
301
+ // DEVIATION: internal tooth-tip diameter is 116, not the prompt's 114. At 114 the
302
+ // ring tooth tips sit at r=57 while the planet ROOT circles reach r=42+15.5=57.5,
303
+ // so every planet overlaps every ring tooth and the required nine separate bodies
304
+ // cannot exist at any phase or rotation. 116 restores 0.5 mm of tip clearance and
305
+ // leaves every other stated diameter untouched.
306
+ translate([0, 0, gz]) linear_extrude(gt) int_gear(60, 58, 63, 70, 1.0, 1.5, 3);
307
+
308
+ // carrier plate, Z = -5..-1
309
+ translate([0, 0, -5]) cylinder(h = 4, r = 52.5);
310
+
311
+ // three planet pins, Z = 0..14, clear of both the carrier and the gears
312
+ for (i = [0:2]) rotate(120*i) translate([42, 0, 0]) cylinder(h = 14, d = 6);
313
+ `.trim()
314
+ };
315
+ //#endregion
316
+ export { MCAD_GOLDS };
317
+
318
+ //# sourceMappingURL=mcad-golds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcad-golds.js","names":[],"sources":["../../src/benchmarks/mcad-golds.ts"],"sourcesContent":["/**\n * MCAD gold oracles — one OpenSCAD model per task in `mcad-tasks.ts`.\n *\n * These are CALIBRATION artifacts, not exemplar answers: their whole job is to\n * prove the judge's accept direction fires, so they are written plain (no clever\n * parametrics, `$fn=96` on round features) and every one of them has been run\n * through `createMcadBenchAdapter().judge()` on this host. A task is marked\n * `calibrated: true` in `mcad-tasks.ts` only when its gold below scores 1.0.\n *\n * Where a gold deviates from the prompt's literal dimensions, the deviation is\n * named in a comment at the point of the deviation, with the reason. There is one\n * such deviation (task 10's ring tooth-tip diameter — the prompt's own numbers\n * make a coplanar 9-body assembly geometrically impossible; see the comment).\n */\n\n/** 01 — 100 x 60 x 20 block, four 8 mm through-holes, 2 mm top-perimeter chamfer. */\nconst CALIBRATION_BLOCK = `\n$fn=96;\n\n// The chamfer is the hull between the full-size body and a 2 mm inset top plate,\n// so it lands on the top perimeter only and leaves the bore walls square.\nmodule chamfered_block(l, w, h, c) {\n hull() {\n translate([-l/2, -w/2, 0]) cube([l, w, h - c]);\n translate([-l/2 + c, -w/2 + c, h - c]) cube([l - 2*c, w - 2*c, c]);\n }\n}\n\ndifference() {\n chamfered_block(100, 60, 20, 2);\n for (x = [-35, 35]) for (y = [-20, 20])\n translate([x, y, -1]) cylinder(h = 22, d = 8);\n}\n`.trim()\n\n/** 02 — OD 80 x 10 flange, 30 mm central bore, six 6 mm holes on a 60 mm bolt circle. */\nconst CIRCULAR_FLANGE = `\n$fn=96;\n\n// Revolved section: a 15..40 mm x 0..10 mm rectangle whose corners are rounded by\n// 1.5 mm (shrink then grow). That carries the required round on both outside\n// circular edges; the same round lands on the bore edges, which the prompt does\n// not ask for and does not forbid.\ndifference() {\n rotate_extrude()\n offset(r = 1.5) offset(delta = -1.5)\n polygon([[15, 0], [40, 0], [40, 10], [15, 10]]);\n for (i = [0:5]) rotate([0, 0, i * 60])\n translate([30, 0, -1]) cylinder(h = 12, d = 6);\n}\n`.trim()\n\n/** 03 — L bracket: 80 x 50 x 8 base, 80 x 8 x 50 back plate, 4 holes, 2 gussets. */\nconst L_BRACKET = `\n$fn=96;\n\n// The L is a (Y, Z) section extruded along X. rotate([90,0,90]) maps local\n// (x, y, z) to global (z, x, y), so a 2D point (y, z) extrudes along +X.\nr = 2; // round on the outside corner where the base and the back plate meet\narc = [for (i = [0:8]) [25 - r + r*cos(-90 + 90*i/8), r + r*sin(-90 + 90*i/8)]];\nsection = concat([[-25, 0], [25 - r, 0]], arc, [[25, 58], [17, 58], [17, 8], [-25, 8]]);\n\ndifference() {\n union() {\n translate([-40, 0, 0]) rotate([90, 0, 90]) linear_extrude(80) polygon(section);\n // gussets: right triangle 30 tall x 30 deep, 8 mm thick in X, at X = +/-20\n for (x = [-20, 20])\n translate([x - 4, 0, 0]) rotate([90, 0, 90]) linear_extrude(8)\n polygon([[17, 8], [-13, 8], [17, 38]]);\n }\n // base plate through-holes; the cutter stops flush at the base top (Z=8) so it\n // cannot notch the gussets that stand on that face\n for (x = [-25, 25]) translate([x, -10, -1]) cylinder(h = 9, d = 6);\n // back plate through-holes, along +Y through the 8 mm thickness\n for (x = [-25, 25]) translate([x, 17, 30]) rotate([-90, 0, 0]) cylinder(h = 9, d = 6);\n}\n`.trim()\n\n/** 04 — stepped shaft along X with 1 mm end chamfers and a top keyway. */\nconst STEPPED_SHAFT_KEYWAY = `\n$fn=96;\n\n// Every section is a cylinder laid along +X; the two end chamfers are 1 mm frusta.\nmodule seg(x, len, r1, r2) {\n translate([x, 0, 0]) rotate([0, 90, 0]) cylinder(h = len, r1 = r1, r2 = r2);\n}\n\ndifference() {\n union() {\n seg(0, 1, 9, 10);\n seg(1, 29, 10, 10);\n seg(30, 60, 15, 15);\n seg(90, 29, 10, 10);\n seg(119, 1, 10, 9);\n }\n // keyway: 6 mm wide in Y, 3 mm deep from the Z=15 top, X = 40..80\n translate([40, -3, 12]) cube([40, 6, 5]);\n}\n`.trim()\n\n/** 05 — open-top enclosure, 3 mm walls/floor, four standoffs with blind holes. */\nconst OPEN_TOP_ELECTRONICS_ENCLOSURE = `\n$fn=96;\n\n// Outer box with 2 mm rounds on the four vertical corners.\nmodule rounded_box(l, w, h, r) {\n hull() for (x = [-l/2 + r, l/2 - r]) for (y = [-w/2 + r, w/2 - r])\n translate([x, y, 0]) cylinder(h = h, r = r);\n}\n\nunion() {\n difference() {\n rounded_box(100, 70, 30, 2);\n // interior cavity: 3 mm walls, 3 mm floor, open at the top\n translate([-47, -32, 3]) cube([94, 64, 31]);\n }\n // standoffs rising from the inside floor, each with a 3 mm x 8 mm blind hole\n for (x = [-35, 35]) for (y = [-25, 25])\n translate([x, y, 3]) difference() {\n cylinder(h = 12, d = 10);\n translate([0, 0, 4]) cylinder(h = 9, d = 3);\n }\n}\n`.trim()\n\n/** 06 — clevis bracket: base plate, two lugs with a 14 mm pin bore, ribs, cutouts. */\nconst CLEVIS_BRACKET = `\n$fn=96;\n\n// Base plate, 3 mm rounds on the four vertical perimeter corners.\nmodule base_plate() {\n hull() for (x = [-57, 57]) for (y = [-27, 27])\n translate([x, y, 0]) cylinder(h = 10, r = 3);\n}\n\n// One clevis lug: an (X, Z) side profile extruded 18 mm in Y. The straight part\n// runs Z=10..34 and the semicircular cap is r=18 about Z=34, so the lug top is at\n// Z=52 -- exactly 42 mm above the base, as the prompt states.\nmodule lug() {\n translate([0, 26, 0]) rotate([90, 0, 0]) linear_extrude(18)\n union() {\n translate([-18, 10]) square([36, 24]);\n translate([0, 34]) circle(r = 18);\n }\n}\n\n// 2 mm transition flare where the lug foot meets the base plate.\nmodule lug_foot() {\n hull() {\n translate([-20, 6, 10]) cube([40, 22, 0.01]);\n translate([-18, 8, 12]) cube([36, 18, 0.01]);\n }\n}\n\n// Diagonal reinforcing rib, 6 mm thick in Y, lying against the lug's outer face.\nmodule rib() {\n translate([0, 26, 0]) rotate([90, 0, 0]) linear_extrude(6)\n polygon([[18, 10], [40, 10], [18, 34]]);\n}\n\ndifference() {\n union() {\n base_plate();\n lug(); mirror([0, 1, 0]) lug();\n lug_foot(); mirror([0, 1, 0]) lug_foot();\n rib(); mirror([0, 1, 0]) rib();\n }\n // clevis pin bore, 14 mm through both lugs along Y at X=0, Z=34\n translate([0, -27, 34]) rotate([-90, 0, 0]) cylinder(h = 54, d = 14);\n // four 7 mm base mounting holes\n for (x = [-45, 45]) for (y = [-20, 20])\n translate([x, y, -1]) cylinder(h = 12, d = 7);\n // triangular lightening cutouts through the base web, corners rounded 3 mm\n for (x = [-31, 31]) translate([x, 0, -1]) linear_extrude(12)\n offset(r = 3) polygon([[6, 0], [-3, 5.2], [-3, -5.2]]);\n}\n`.trim()\n\n/** 07 — radial engine cylinder: barrel, 12 fins, base flange, top cap, plug boss. */\nconst RADIAL_ENGINE_CYLINDER = `\n$fn=96;\n\n// One cooling fin: a 2 mm disc whose outer edge carries the 1 mm round, so the\n// fin outside diameter is 2*(30+1) = 62 mm. The round's own section is coarse\n// ($fn=24): at 96 it puts ~18k triangles on each of the 12 fins and takes the\n// CGAL union past two minutes for a 1 mm cosmetic edge.\nmodule fin(z) {\n translate([0, 0, z]) union() {\n cylinder(h = 2, r = 30);\n translate([0, 0, 1]) rotate_extrude() translate([30, 0]) circle(r = 1, $fn = 24);\n }\n}\n\ndifference() {\n union() {\n cylinder(h = 70, r = 18); // barrel\n for (i = [0:11]) fin(10 + 5 * i); // 12 fins, Z = 10..67\n // base flange OD 70 x 8, 1 mm rounds on its outer edges. The profile starts\n // at x=1 (not 0) so the revolve never sees a negative radius; the barrel\n // above fills that 1 mm core.\n rotate_extrude() offset(r = 1) offset(delta = -1)\n polygon([[1, 0], [35, 0], [35, 8], [1, 8]]);\n translate([0, 0, 70]) cylinder(h = 8, r = 22); // top cap\n // spark-plug boss: 12 mm dia, 24 mm long, 35 deg above horizontal, +X, rooted\n // inside the top cap so it fuses with it\n translate([10, 0, 72]) rotate([0, 55, 0]) cylinder(h = 24, d = 12);\n }\n // six 5 mm mounting holes on the 56 mm bolt circle of the base flange\n for (i = [0:5]) rotate([0, 0, i * 60]) translate([28, 0, -1]) cylinder(h = 10, d = 5);\n // 5 mm bore along the boss axis\n translate([10, 0, 72]) rotate([0, 55, 0]) cylinder(h = 25, d = 5);\n}\n`.trim()\n\n/** 08 — centrifugal impeller: backplate, hub, 12 backward-curved blades, bore. */\nconst CENTRIFUGAL_IMPELLER = `\n$fn=96;\n\n// Blade centreline: radius 18 -> 43 while sweeping 45 degrees backward. The blade\n// is the swept 3 mm disc along that path, so its thickness is 3 mm everywhere.\nfunction bp(t) = [(18 + 25*t) * cos(-45*t), (18 + 25*t) * sin(-45*t)];\n\nmodule blade() {\n for (i = [0:11]) hull() {\n translate(bp(i/12)) circle(d = 3, $fn = 32);\n translate(bp((i+1)/12)) circle(d = 3, $fn = 32);\n }\n}\n\ndifference() {\n union() {\n // backplate OD 90 x 6 with 1.5 mm rounds on both outer circular edges\n rotate_extrude() offset(r = 1.5) offset(delta = -1.5)\n polygon([[1, 0], [45, 0], [45, 6], [1, 6]]);\n translate([0, 0, 6]) cylinder(h = 22, r = 13); // hub\n // 12 blades, 16 mm tall above the backplate. The prompt's own radii leave a\n // 5 mm gap between the blade roots (r=18) and the hub (r=13), so the stated\n // blade-to-hub root fillet has nothing to fillet and is omitted.\n for (i = [0:11]) rotate([0, 0, i * 30])\n translate([0, 0, 6]) linear_extrude(16) blade();\n }\n translate([0, 0, -1]) cylinder(h = 30, d = 8); // through-bore\n}\n`.trim()\n\n/** 09 — spiral staircase: column, 20 helical treads, helical handrail, balusters. */\nconst SPIRAL_STAIRCASE = `\n$fn=96;\n\nn = 20; // treads\nz0 = 4; // first tread bottom\nrise = 6; // Z step per tread\nturn = 18; // degrees per tread\nrail_r = 66; rail_z0 = 14; rail_z1 = 130;\n\n// Handrail height at a given plan angle, measured counter-clockwise from +X.\nfunction rail_z(a) = rail_z0 + (rail_z1 - rail_z0) * a / 360;\n\n// A wedge tread: annulus sector from ri to ro over \"ang\" degrees.\nmodule tread(ri, ro, ang, h) {\n m = 24;\n linear_extrude(h) polygon(concat(\n [for (i = [0:m]) [ri * cos(ang*i/m), ri * sin(ang*i/m)]],\n [for (i = [m:-1:0]) [ro * cos(ang*i/m), ro * sin(ang*i/m)]]));\n}\n\nunion() {\n cylinder(h = 140, r = 7); // central column\n cylinder(h = 5, r = 45); // base disk, Z = 0..5 (overlaps the first tread)\n for (k = [0:n-1]) {\n rotate([0, 0, k * turn]) translate([0, 0, z0 + k * rise]) tread(10, 62, 24, 4);\n // baluster at the tread's outer end, mid-width, reaching the handrail centre\n rotate([0, 0, k * turn + 12]) translate([63, 0, z0 + k * rise])\n cylinder(h = rail_z(k * turn + 12) - (z0 + k * rise), d = 3);\n }\n // helical handrail: a 5 mm circle at radius 66 swept one counter-clockwise turn\n // (OpenSCAD's positive twist is clockwise) while rising Z=14 -> 130\n translate([0, 0, rail_z0])\n linear_extrude(height = rail_z1 - rail_z0, twist = -360, slices = 96)\n translate([rail_r, 0]) circle(d = 5, $fn = 48);\n}\n`.trim()\n\n/** 10 — planetary gear stage: 9 separate bodies (sun, 3 planets, ring, carrier, 3 pins). */\nconst PLANETARY_GEAR_STAGE = `\n$fn=96;\n\n// Straight-sided trapezoidal teeth: each tooth is a four-point polygon between the\n// root and tip circles, unioned onto (external) or subtracted from (internal) the\n// gear blank. Half-angles are given at the root and the tip.\nmodule ext_gear(n, r_root, r_tip, ha_root, ha_tip, phase) {\n union() {\n circle(r = r_root);\n for (i = [0:n-1]) rotate(phase + 360*i/n)\n polygon([[r_root*cos(-ha_root), r_root*sin(-ha_root)],\n [r_tip*cos(-ha_tip), r_tip*sin(-ha_tip)],\n [r_tip*cos(ha_tip), r_tip*sin(ha_tip)],\n [r_root*cos(ha_root), r_root*sin(ha_root)]]);\n }\n}\n\nmodule int_gear(n, r_tip, r_root, r_out, ha_tip, ha_root, phase) {\n difference() {\n circle(r = r_out);\n difference() {\n circle(r = r_root);\n for (i = [0:n-1]) rotate(phase + 360*i/n)\n polygon([[r_root*cos(-ha_root), r_root*sin(-ha_root)],\n [r_tip*cos(-ha_tip), r_tip*sin(-ha_tip)],\n [r_tip*cos(ha_tip), r_tip*sin(ha_tip)],\n [r_root*cos(ha_root), r_root*sin(ha_root)]]);\n }\n }\n}\n\ngz = 16; // gear underside; the pins (Z=0..14) stop 2 mm short of it\ngt = 8; // gear thickness\n\n// sun: 24 teeth, root d42, OD 54. Phase 7.5 puts a tooth SPACE on each of the\n// three planet directions (0/120/240 deg), which is the only phase where the sun\n// tip circle clears the planet root circle at all.\ntranslate([0, 0, gz]) linear_extrude(gt) difference() {\n ext_gear(24, 21, 27, 4, 0.2, 7.5);\n circle(d = 10);\n}\n\n// three planets: 18 teeth, root d31, OD 41, centres on r=42 every 120 deg. Phase 0\n// puts a tooth on the sun side (local 180) and on the ring side (local 0).\nfor (i = [0:2]) rotate(120*i) translate([42, 0, gz])\n linear_extrude(gt) ext_gear(18, 15.5, 20.5, 5, 2, 0);\n\n// ring: 60 internal teeth, OD 140, internal root d126.\n// DEVIATION: internal tooth-tip diameter is 116, not the prompt's 114. At 114 the\n// ring tooth tips sit at r=57 while the planet ROOT circles reach r=42+15.5=57.5,\n// so every planet overlaps every ring tooth and the required nine separate bodies\n// cannot exist at any phase or rotation. 116 restores 0.5 mm of tip clearance and\n// leaves every other stated diameter untouched.\ntranslate([0, 0, gz]) linear_extrude(gt) int_gear(60, 58, 63, 70, 1.0, 1.5, 3);\n\n// carrier plate, Z = -5..-1\ntranslate([0, 0, -5]) cylinder(h = 4, r = 52.5);\n\n// three planet pins, Z = 0..14, clear of both the carrier and the gears\nfor (i = [0:2]) rotate(120*i) translate([42, 0, 0]) cylinder(h = 14, d = 6);\n`.trim()\n\n/** Gold OpenSCAD source per task id. */\nexport const MCAD_GOLDS: Record<string, string> = {\n 'calibration-block': CALIBRATION_BLOCK,\n 'circular-flange': CIRCULAR_FLANGE,\n 'l-bracket': L_BRACKET,\n 'stepped-shaft-keyway': STEPPED_SHAFT_KEYWAY,\n 'open-top-electronics-enclosure': OPEN_TOP_ELECTRONICS_ENCLOSURE,\n 'clevis-bracket-lightening-cutouts': CLEVIS_BRACKET,\n 'radial-engine-cylinder': RADIAL_ENGINE_CYLINDER,\n 'centrifugal-impeller': CENTRIFUGAL_IMPELLER,\n 'spiral-staircase': SPIRAL_STAIRCASE,\n 'planetary-gear-stage': PLANETARY_GEAR_STAGE,\n}\n"],"mappings":";AA2VA,MAAa,aAAqC;CAChD,qBA5UwB;;;;;;;;;;;;;;;;;EAiBxB,KA2TqB;CACrB,mBAzTsB;;;;;;;;;;;;;;EActB,KA2SmB;CACnB,aAzSgB;;;;;;;;;;;;;;;;;;;;;;;EAuBhB,KAkRa;CACb,wBAhR2B;;;;;;;;;;;;;;;;;;;EAmB3B,KA6PwB;CACxB,kCA3PqC;;;;;;;;;;;;;;;;;;;;;;EAsBrC,KAqOkC;CAClC,qCAnOqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkDrB,KAiLqC;CACrC,0BA/K6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC7B,KA8I0B;CAC1B,wBA5I2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B3B,KAgHwB;CACxB,oBA9GuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCvB,KA2EoB;CACpB,wBAzE2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4D3B,KAawB;AAC1B"}
@@ -0,0 +1,66 @@
1
+ //#region src/benchmarks/mcad-tasks.d.ts
2
+ /**
3
+ * MCAD task specs — 10 dimensioned mechanical parts adopted from the MIT-licensed
4
+ * text-to-cad benchmark set (github.com/earthtojake/text-to-cad, `benchmarks/`).
5
+ *
6
+ * Upstream ships each part as a prompt plus a human checklist ("four through-holes,
7
+ * 8 mm each; no floating gussets") with NO grader. This file is the machine-checkable
8
+ * form: every assertion below is derivable in closed form from the upstream prompt,
9
+ * and every derivation is shown in a comment beside its number. An assertion that
10
+ * cannot be derived in closed form is OMITTED, never guessed — the judge only
11
+ * asserts what the prompt actually pins.
12
+ *
13
+ * FORMAT DEVIATION, stated once: upstream asks for STEP export. The v1 judge
14
+ * compiles OpenSCAD and grades the STL mesh (same judge deps as `cad-design`);
15
+ * OpenSCAD cannot emit STEP. The geometric content of every check is preserved;
16
+ * the "STEP imports" row is replaced by "compiles + watertight". Tasks keep the
17
+ * upstream dimensional text verbatim inside an OpenSCAD-deliverable wrapper.
18
+ *
19
+ * Probes are the hole/pocket checks: a point the finished solid must NOT contain
20
+ * (inside a hole bore) or MUST contain (in the surrounding material). Locations
21
+ * come from the prompt's own dimensions, with clearance chosen so a hole that is
22
+ * missing, misplaced by more than ~1 mm, or wrong in diameter by more than ~1 mm
23
+ * flips at least one probe.
24
+ */
25
+ interface McadSpec {
26
+ /** Overall axis-aligned extents in mm, [min, max] per axis. */
27
+ bbox?: {
28
+ x?: [number, number];
29
+ y?: [number, number];
30
+ z?: [number, number];
31
+ };
32
+ /** Enclosed mesh volume band in mm^3 — closed-form only, derivation in a comment. */
33
+ volume?: [number, number];
34
+ /** Disconnected-solid count band (fused parts must read as ONE solid). */
35
+ solids?: [number, number];
36
+ /** Triangle floor — rejects degenerate single-box answers where relevant. */
37
+ minTriangles?: number;
38
+ /** Points (mm) that must test INSIDE the solid (material present). */
39
+ probesInsideSolid?: Array<[number, number, number]>;
40
+ /** Points (mm) that must test OUTSIDE the solid (hole/pocket/clearance present). */
41
+ probesOutsideSolid?: Array<[number, number, number]>;
42
+ }
43
+ interface McadTask {
44
+ id: string;
45
+ /** Upstream dimensional brief, verbatim, wrapped for the OpenSCAD deliverable. */
46
+ prompt: string;
47
+ spec: McadSpec;
48
+ /** Upstream file this was adopted from. */
49
+ source: string;
50
+ /** False when the spec has no verified gold yet — the judge still runs, but the
51
+ * accept direction is uncalibrated and the loader surfaces that in metadata. */
52
+ calibrated: boolean;
53
+ }
54
+ /** Exported so a sibling adapter can SWAP this preamble for its own deliverable
55
+ * (see `mcad-cq-bench.ts`) by prefix, instead of re-authoring ten prompts and
56
+ * letting the two copies drift. The upstream dimensional text stays the tail. */
57
+ declare const MCAD_DELIVERABLE: string;
58
+ /** Task 10 is an ASSEMBLY, not a part: its own text says "use separate solid bodies"
59
+ * and its checklist pins nine of them, which the single-solid boilerplate above
60
+ * flatly contradicts. A worker cannot satisfy both, so that task gets this
61
+ * preamble instead; everything else about the deliverable is unchanged. */
62
+ declare const MCAD_DELIVERABLE_MULTIBODY: string;
63
+ declare const MCAD_TASKS: McadTask[];
64
+ //#endregion
65
+ export { MCAD_DELIVERABLE, MCAD_DELIVERABLE_MULTIBODY, MCAD_TASKS, McadSpec, McadTask };
66
+ //# sourceMappingURL=mcad-tasks.d.ts.map