forgecad 0.9.14 → 0.9.15

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 (219) hide show
  1. package/LICENSE +6 -4
  2. package/README.md +8 -4
  3. package/dist/assets/{AdminPage-eWGs2K6H.js → AdminPage-CDyGUinA.js} +2 -2
  4. package/dist/assets/{BenchmarkPage-CTrLKfpo.js → BenchmarkPage-DfPMY_-d.js} +4 -15
  5. package/dist/assets/{BlogPage-5nPesyds.js → BlogPage-kF0fkdJT.js} +2 -2
  6. package/dist/assets/{DocsPage-C4Y3nbYc.js → DocsPage-B954L3YN.js} +9 -3
  7. package/dist/assets/EditorApp-Beb-IZ0y.js +14014 -0
  8. package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-CuDLxKqL.css} +698 -0
  9. package/dist/assets/{EmbedViewer-C8fB4n5U.js → EmbedViewer-C77B-TrF.js} +3 -3
  10. package/dist/assets/{LandingPageProofDriven-jSz0LaMM.js → LandingPageProofDriven-Cr6fXMDj.js} +35 -37
  11. package/dist/assets/LegalPage-BRlScr9A.css +91 -0
  12. package/dist/assets/LegalPage-Dzklqmmg.js +39 -0
  13. package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
  14. package/dist/assets/{PricingPage-B83B90zh.js → PricingPage-zWXkvlwl.js} +19 -19
  15. package/dist/assets/{SettingsPage-DY889pcu.js → SettingsPage-Bz0of4KQ.js} +2 -2
  16. package/dist/assets/app-CE3sYcV7.css +3890 -0
  17. package/dist/assets/{app-bEww1ic4.js → app-D3kDkggg.js} +2293 -946
  18. package/dist/assets/cli/{render-Cho2uKG_.js → render-DSY3mMQa.js} +337 -7
  19. package/dist/assets/{constructionHistoryWorker-HYwzJY4m.js → constructionHistoryWorker-gpDo-uH2.js} +927 -243
  20. package/dist/assets/{evalWorker-CjQwJSE-.js → evalWorker-CU0Ke6DP.js} +7800 -4164
  21. package/dist/assets/{forgecad_geometry-CH2nvuLA.js → forgecad_geometry-Dgceylq9.js} +43 -1
  22. package/dist/assets/forgecad_geometry_bg-dD4RNQF1.wasm +0 -0
  23. package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-COyp8XXA.js} +927 -243
  24. package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
  25. package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
  26. package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
  27. package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
  28. package/dist/assets/{manifold-CG9Fokx-.js → manifold-BRI5prcH.js} +1 -1
  29. package/dist/assets/{manifold-uRzgk5O8.js → manifold-C-3h2M7p.js} +2 -2
  30. package/dist/assets/{manifold-rmfAcdwF.js → manifold-DNkrUWpA.js} +1 -1
  31. package/dist/assets/{reportWorker-4cW_ZpoS.js → reportWorker-CdBz5bNg.js} +7538 -10857
  32. package/dist/assets/{scalar-sampling-budget-CfDiFvh7.js → scalar-sampling-budget-wJF98aY9.js} +6935 -4331
  33. package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-B-9VbLIs.js} +32 -1
  34. package/dist/assets/{solver-DuJAO8S6.js → solver-BZ9LPTHs.js} +1 -1
  35. package/dist/assets/solver_bg-DAHZJ_rw.wasm +0 -0
  36. package/dist/assets/{targets-D6PWsv6X.js → targets-B9sGB5nB.js} +1 -1
  37. package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
  38. package/dist/cli/render.html +1 -1
  39. package/dist/docs/index.html +2 -2
  40. package/dist/docs-raw/AI/ai-native-cad.md +50 -0
  41. package/dist/docs-raw/AI/usage.md +3 -12
  42. package/dist/docs-raw/CLI.md +30 -10
  43. package/dist/docs-raw/component-model.md +27 -11
  44. package/dist/docs-raw/generated/assembly.md +301 -212
  45. package/dist/docs-raw/generated/concepts.md +235 -237
  46. package/dist/docs-raw/generated/core.md +283 -6
  47. package/dist/docs-raw/generated/curves.md +274 -361
  48. package/dist/docs-raw/generated/lib.md +7 -1
  49. package/dist/docs-raw/generated/output.md +19 -4
  50. package/dist/docs-raw/generated/runtime-names.md +41 -0
  51. package/dist/docs-raw/generated/sdf.md +31 -0
  52. package/dist/docs-raw/generated/sheet-metal.md +9 -0
  53. package/dist/docs-raw/generated/sketch.md +44 -1
  54. package/dist/docs-raw/generated/viewport.md +11 -3
  55. package/dist/docs-raw/guides/coordinate-system.md +20 -16
  56. package/dist/docs-raw/guides/geometry-conventions.md +2 -2
  57. package/dist/docs-raw/guides/inspection-bundles.md +2 -1
  58. package/dist/docs-raw/guides/joint-design.md +24 -0
  59. package/dist/docs-raw/guides/positioning.md +13 -3
  60. package/dist/docs-raw/legal/privacy.md +63 -0
  61. package/dist/docs-raw/legal/software-license.md +55 -0
  62. package/dist/docs-raw/legal/terms.md +87 -0
  63. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +1 -1
  64. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
  65. package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
  66. package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
  67. package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
  68. package/dist/docs-raw/skills/forgecad-lld.md +1 -1
  69. package/dist/docs-raw/skills/forgecad-make-a-model.md +1 -1
  70. package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
  71. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
  72. package/dist/docs-raw/skills/forgecad-project.md +1 -1
  73. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +1 -1
  74. package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
  75. package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
  76. package/dist/docs-raw/skills/forgecad.md +4 -3
  77. package/dist/index.html +40 -12
  78. package/dist/llms.txt +8 -0
  79. package/dist/site.webmanifest +1 -1
  80. package/dist/sitemap.xml +49 -13
  81. package/dist-cli/{check-compiler-U5SOPN7X.js → check-compiler-SDX5QIXI.js} +1 -2
  82. package/dist-cli/{check-query-propagation-XOKNSSYU.js → check-query-propagation-EAYEFT77.js} +1 -2
  83. package/dist-cli/{chunk-EXWGNL6K.js → chunk-N4O47JLF.js} +12540 -9046
  84. package/dist-cli/forgecad.js +1786 -679
  85. package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
  86. package/dist-cli/forgecad_geometry_bg.wasm +0 -0
  87. package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
  88. package/dist-cli/solver_bg.wasm +0 -0
  89. package/dist-skill/CONTEXT.md +1117 -721
  90. package/dist-skill/SKILL.md +3 -2
  91. package/dist-skill/docs/API/core/concepts.md +64 -1
  92. package/dist-skill/docs/CLI.md +30 -10
  93. package/dist-skill/docs/generated/assembly.md +277 -229
  94. package/dist-skill/docs/generated/core.md +283 -6
  95. package/dist-skill/docs/generated/curves.md +272 -362
  96. package/dist-skill/docs/generated/lib.md +7 -1
  97. package/dist-skill/docs/generated/output.md +19 -4
  98. package/dist-skill/docs/generated/runtime-names.md +41 -0
  99. package/dist-skill/docs/generated/sdf.md +31 -0
  100. package/dist-skill/docs/generated/sheet-metal.md +9 -0
  101. package/dist-skill/docs/generated/sketch.md +44 -2
  102. package/dist-skill/docs/generated/viewport.md +2 -87
  103. package/dist-skill/docs/guides/coordinate-system.md +20 -16
  104. package/dist-skill/docs/guides/geometry-conventions.md +2 -2
  105. package/dist-skill/docs/guides/inspection-bundles.md +2 -1
  106. package/dist-skill/docs/guides/joint-design.md +24 -0
  107. package/dist-skill/docs/guides/positioning.md +13 -3
  108. package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
  109. package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
  110. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
  111. package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
  112. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
  113. package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
  114. package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
  115. package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
  116. package/examples/api/assembly-kinematics-limb.forge.js +116 -0
  117. package/examples/api/connector-frame-rig-chain.forge.js +102 -0
  118. package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
  119. package/examples/api/exact-surface-studio.forge.js +6 -8
  120. package/examples/api/helix-basics.forge.js +6 -6
  121. package/examples/api/lean-foundations/README.md +12 -0
  122. package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
  123. package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
  124. package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
  125. package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
  126. package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
  127. package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
  128. package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
  129. package/examples/api/route3d-elbow.forge.js +68 -0
  130. package/examples/api/transition-curves.forge.js +44 -15
  131. package/examples/api/y-blend-corner-showcase.forge.js +0 -2
  132. package/examples/generative/coral-vase.forge.js +1 -1
  133. package/examples/nurbs-tube.forge.js +1 -1
  134. package/package.json +14 -13
  135. package/dist/assets/EditorApp-lXv53A1m.js +0 -13610
  136. package/dist/assets/app-CsHnaBWt.css +0 -1789
  137. package/dist/assets/forgecad_geometry_bg-C5_E9Oa9.wasm +0 -0
  138. package/dist/assets/solver_bg-CWvv4lnN.wasm +0 -0
  139. package/dist/docs-raw/API/README.md +0 -16
  140. package/dist/docs-raw/API/core/concepts.md +0 -118
  141. package/dist/docs-raw/INDEX.md +0 -138
  142. package/dist/docs-raw/RELEASING.md +0 -87
  143. package/dist/docs-raw/agent-native-api.md +0 -27
  144. package/dist/docs-raw/beta-deployment.md +0 -304
  145. package/dist/docs-raw/beta-operations.md +0 -325
  146. package/dist/docs-raw/blueprint-first.md +0 -145
  147. package/dist/docs-raw/cli-monetization.md +0 -112
  148. package/dist/docs-raw/coding-best-practices.md +0 -120
  149. package/dist/docs-raw/coding.md +0 -340
  150. package/dist/docs-raw/deployment.md +0 -374
  151. package/dist/docs-raw/guides/skill-maintenance.md +0 -161
  152. package/dist/docs-raw/guides/surface-members.md +0 -82
  153. package/dist/docs-raw/harbor-cli.md +0 -854
  154. package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
  155. package/dist/docs-raw/internals/compiler.md +0 -307
  156. package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
  157. package/dist/docs-raw/internals/constraint-solver.md +0 -176
  158. package/dist/docs-raw/internals/shape-from-slices.md +0 -152
  159. package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
  160. package/dist/docs-raw/platform/admin.md +0 -45
  161. package/dist/docs-raw/platform/architecture.md +0 -82
  162. package/dist/docs-raw/platform/auth.md +0 -139
  163. package/dist/docs-raw/platform/email.md +0 -67
  164. package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
  165. package/dist/docs-raw/platform/observability.md +0 -197
  166. package/dist/docs-raw/platform/projects.md +0 -111
  167. package/dist/docs-raw/platform/sharing.md +0 -90
  168. package/dist/docs-raw/product/README.md +0 -39
  169. package/dist/docs-raw/product/api-as-product-language.md +0 -13
  170. package/dist/docs-raw/product/business-model.md +0 -15
  171. package/dist/docs-raw/product/competitive-positioning.md +0 -17
  172. package/dist/docs-raw/product/creative-manufacturing.md +0 -15
  173. package/dist/docs-raw/product/founder-story.md +0 -11
  174. package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
  175. package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
  176. package/dist/docs-raw/product/product-loop.md +0 -17
  177. package/dist/docs-raw/product/strategic-decisions.md +0 -22
  178. package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
  179. package/dist/docs-raw/product/user-segments.md +0 -15
  180. package/dist/docs-raw/product/vision.md +0 -26
  181. package/dist/docs-raw/rl-environments.md +0 -350
  182. package/dist/docs-raw/runbook.md +0 -611
  183. package/dist-cli/check-compiler-U5SOPN7X.js.map +0 -1
  184. package/dist-cli/check-query-propagation-XOKNSSYU.js.map +0 -1
  185. package/dist-cli/chunk-EXWGNL6K.js.map +0 -1
  186. package/dist-cli/forgecad.js.map +0 -1
  187. package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
  188. package/dist-cli/solver-46FFSK2U.js.map +0 -1
  189. package/dist-skill/SKILL-dev.md +0 -145
  190. package/dist-skill/docs-dev/API/core/concepts.md +0 -118
  191. package/dist-skill/docs-dev/CLI.md +0 -677
  192. package/dist-skill/docs-dev/agent-native-api.md +0 -27
  193. package/dist-skill/docs-dev/blueprint-first.md +0 -145
  194. package/dist-skill/docs-dev/coding-best-practices.md +0 -120
  195. package/dist-skill/docs-dev/coding.md +0 -340
  196. package/dist-skill/docs-dev/component-model.md +0 -164
  197. package/dist-skill/docs-dev/generated/assembly.md +0 -794
  198. package/dist-skill/docs-dev/generated/core.md +0 -2117
  199. package/dist-skill/docs-dev/generated/curves.md +0 -2583
  200. package/dist-skill/docs-dev/generated/lib.md +0 -169
  201. package/dist-skill/docs-dev/generated/output.md +0 -247
  202. package/dist-skill/docs-dev/generated/sdf.md +0 -446
  203. package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
  204. package/dist-skill/docs-dev/generated/sketch.md +0 -1811
  205. package/dist-skill/docs-dev/generated/viewport.md +0 -585
  206. package/dist-skill/docs-dev/generated/wood.md +0 -108
  207. package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
  208. package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
  209. package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
  210. package/dist-skill/docs-dev/guides/joint-design.md +0 -78
  211. package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
  212. package/dist-skill/docs-dev/guides/positioning.md +0 -161
  213. package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
  214. package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
  215. package/dist-skill/docs-dev/internals/compiler.md +0 -307
  216. package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
  217. package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
  218. package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
  219. package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
@@ -1,5 +1,3 @@
1
- if (getActiveBackend() === 'manifold') setActiveBackend('truck');
2
-
3
1
  const span = param('Span', 128);
4
2
  const depth = param('Depth', 88);
5
3
  const crown = param('Crown', 26);
@@ -41,7 +39,7 @@ const canopySheet = Surface.Nurbs(
41
39
  const canopySolid = canopySheet.thicken(wall).translate(-span * 0.82, 0, 0).color('#9fd3ff');
42
40
  const canopyGhost = canopySheet.translate(-span * 0.82, 0, wall * 2.4).color('#d9f0ff');
43
41
 
44
- const archFront = nurbs3d(
42
+ const archFront = Curve.Nurbs(
45
43
  [
46
44
  [-halfSpan * 0.55, -halfDepth * 0.58, 2],
47
45
  [-halfSpan * 0.18, -halfDepth * 0.58, crown * 0.95],
@@ -50,7 +48,7 @@ const archFront = nurbs3d(
50
48
  ],
51
49
  { degree: 3 },
52
50
  );
53
- const archBack = nurbs3d(
51
+ const archBack = Curve.Nurbs(
54
52
  [
55
53
  [-halfSpan * 0.48, halfDepth * 0.52, 0],
56
54
  [-halfSpan * 0.14, halfDepth * 0.52, crown * 0.68],
@@ -65,7 +63,7 @@ const ruledRibbon = Surface.Ruled(archFront, archBack)
65
63
 
66
64
  const boundaryPatch = Surface.Patch(
67
65
  {
68
- bottom: nurbs3d(
66
+ bottom: Curve.Nurbs(
69
67
  [
70
68
  [-halfSpan * 0.48, -halfDepth * 0.42, -2],
71
69
  [-halfSpan * 0.16, -halfDepth * 0.46, crown * 0.35],
@@ -74,7 +72,7 @@ const boundaryPatch = Surface.Patch(
74
72
  ],
75
73
  { degree: 3 },
76
74
  ),
77
- top: nurbs3d(
75
+ top: Curve.Nurbs(
78
76
  [
79
77
  [-halfSpan * 0.48, halfDepth * 0.4, 1],
80
78
  [-halfSpan * 0.16, halfDepth * 0.43, crown * 0.62],
@@ -83,7 +81,7 @@ const boundaryPatch = Surface.Patch(
83
81
  ],
84
82
  { degree: 3 },
85
83
  ),
86
- left: nurbs3d(
84
+ left: Curve.Nurbs(
87
85
  [
88
86
  [-halfSpan * 0.48, -halfDepth * 0.42, -2],
89
87
  [-halfSpan * 0.58, -halfDepth * 0.12, crown * 0.22],
@@ -92,7 +90,7 @@ const boundaryPatch = Surface.Patch(
92
90
  ],
93
91
  { degree: 3 },
94
92
  ),
95
- right: nurbs3d(
93
+ right: Curve.Nurbs(
96
94
  [
97
95
  [halfSpan * 0.48, -halfDepth * 0.42, -2],
98
96
  [halfSpan * 0.58, -halfDepth * 0.12, crown * 0.22],
@@ -1,14 +1,14 @@
1
- // Helix API basics.
1
+ // Curve.Helix API basics.
2
2
  //
3
- // Helix.path() is the reusable centerline primitive.
4
- // Helix.coil() turns the same helix definition into a solid helix-oriented coil.
3
+ // Curve.Helix.path() is the reusable centerline primitive.
4
+ // Curve.Helix.coil() turns the same helix definition into a solid helix-oriented coil.
5
5
 
6
6
  const radius = Param.number("Radius", 18, { min: 8, max: 32, step: 1, unit: "mm" });
7
7
  const pitch = Param.number("Pitch", 6, { min: 2, max: 12, step: 0.5, unit: "mm" });
8
8
  const turns = Param.number("Turns", 4, { min: 1, max: 7, step: 0.25 });
9
9
  const wireRadius = Param.number("Wire Radius", 1, { min: 0.25, max: 2.5, step: 0.25, unit: "mm" });
10
10
 
11
- const guide = Helix.path({
11
+ const guide = Curve.Helix.path({
12
12
  radius,
13
13
  pitch,
14
14
  turns,
@@ -16,7 +16,7 @@ const guide = Helix.path({
16
16
  samplesPerTurn: 48,
17
17
  });
18
18
 
19
- const circularWireCoil = Helix.coil({
19
+ const circularWireCoil = Curve.Helix.coil({
20
20
  radius,
21
21
  pitch,
22
22
  turns,
@@ -26,7 +26,7 @@ const circularWireCoil = Helix.coil({
26
26
  }).translate(-70, 0, 0);
27
27
 
28
28
  const rectangularProfile = rect(wireRadius * 2.4, wireRadius * 1.1);
29
- const rectangularWireCoil = Helix.coil(rectangularProfile, {
29
+ const rectangularWireCoil = Curve.Helix.coil(rectangularProfile, {
30
30
  radius,
31
31
  height: guide.height,
32
32
  turns,
@@ -0,0 +1,12 @@
1
+ # Selected Lean Foundations Examples
2
+
3
+ This pack contains only the currently selected lean API buckets: Curve / Route and route endpoint canonicalization. Surface, standalone Frame, FaceRef, and topology-selector expansion examples were intentionally left out of this split.
4
+
5
+ Run these with `node dist-cli/forgecad.js run <file>`:
6
+
7
+ - `curve-blend-exact.forge.js` - `Curve.Blend` and `Curve.BlendG2` as exact reference rails that also feed `sweep`.
8
+ - `curve-fit-interpolation.forge.js` - `Curve.Fit` interpolation with residual validation.
9
+ - `curve-helix-canonicalization.forge.js` - `Curve.Helix` path and coil canonicalization.
10
+ - `curve-route-canonicalization.forge.js` - `Curve.Route.fromPolyline()` segment and port preservation.
11
+ - `curve-trim-reverse.forge.js` - exact trim and reverse operations.
12
+ - `exact-curve-arc.forge.js` - exact `Curve.Arc` construction and sweep use.
@@ -0,0 +1,22 @@
1
+ const g1Rail = Curve.Blend(
2
+ { point: [0, 0, 0], tangent: [1, 0, 0], weight: 0.7 },
3
+ { point: [48, 22, 10], tangent: [0, 1, 0], weight: 0.65 },
4
+ );
5
+
6
+ const g2Rail = Curve.BlendG2(
7
+ { point: [0, 18, 0], tangent: [1, 0, 0], curvature: [0, 0.01, 0], weight: 0.55 },
8
+ { point: [48, 42, 10], tangent: [0, 1, 0], curvature: [-0.01, 0, 0], weight: 0.55 },
9
+ );
10
+
11
+ const g1Tube = sweep(circle2d(1.6), g1Rail);
12
+ const g2Tube = sweep(circle2d(1.2), g2Rail).color("#5a8f7b");
13
+
14
+ const close3d = (a, b, tolerance = 1e-6) => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]) <= tolerance;
15
+
16
+ verify.equal("Curve.Blend returns a cubic NURBS", g1Rail.degree, 3);
17
+ verify.equal("Curve.BlendG2 returns a quintic NURBS", g2Rail.degree, 5);
18
+ verify.that("Curve.Blend hits directed endpoints", () => close3d(g1Rail.pointAt(0), [0, 0, 0]) && close3d(g1Rail.pointAt(1), [48, 22, 10]));
19
+ verify.that("Curve.BlendG2 hits directed endpoints", () => close3d(g2Rail.pointAt(0), [0, 18, 0]) && close3d(g2Rail.pointAt(1), [48, 42, 10]));
20
+ verify.greaterThan("Blend rails are usable as sweep paths", g1Tube.boundingBox().max[0], 45);
21
+
22
+ return group(g1Tube, g2Tube);
@@ -0,0 +1,18 @@
1
+ const fittedRail = Curve.Fit(
2
+ [
3
+ [0, 0, 0],
4
+ [16, 8, 10],
5
+ [36, -6, 18],
6
+ [58, 10, 12],
7
+ [78, 0, 0],
8
+ ],
9
+ { degree: 3, tolerance: 0.001 },
10
+ );
11
+
12
+ const tube = sweep(circle2d(2), fittedRail);
13
+
14
+ verify.equal('Curve.Fit returns a cubic NURBS for this rail', fittedRail.degree, 3);
15
+ verify.equal('Curve.Fit keeps one control point per interpolated point', fittedRail.controlPoints.length, 5);
16
+ verify.greaterThan('Curve.Fit rail has positive length', fittedRail.length(), 0);
17
+
18
+ return tube;
@@ -0,0 +1,27 @@
1
+ const guide = Curve.Helix.path({
2
+ radius: 14,
3
+ pitch: 5,
4
+ turns: 3,
5
+ samplesPerTurn: 30,
6
+ });
7
+
8
+ const roundCoil = Curve.Helix.coil({
9
+ radius: 14,
10
+ pitch: 5,
11
+ turns: 3,
12
+ wireRadius: 0.8,
13
+ profileSegments: 16,
14
+ divisionsPerTurn: 100,
15
+ });
16
+
17
+ const rectangularCoil = Curve.Helix.coil(rect(1.2, 0.8), {
18
+ radius: 20,
19
+ height: 15,
20
+ turns: 3,
21
+ divisionsPerTurn: 18,
22
+ }).translate(50, 0, 0);
23
+
24
+ verify.equal('Curve.Helix guide derives height from pitch and turns', guide.height, 15);
25
+ verify.greaterThan('Curve.Helix guide has positive centerline length', guide.length(), 0);
26
+
27
+ return union(roundCoil, rectangularCoil);
@@ -0,0 +1,16 @@
1
+ const route = Curve.Route.fromPolyline(
2
+ [
3
+ [0, 0, 0],
4
+ [0, 0, 48],
5
+ [36, 0, 48],
6
+ [36, 24, 72],
7
+ ],
8
+ { cornerRadius: 10, startPort: 'inlet', endPort: 'outlet' },
9
+ );
10
+
11
+ const tube = sweep(difference2d(circle2d(5), circle2d(3.5)), route);
12
+ verify.equal('Curve.Route keeps line-arc-line-arc-line route intent', route.segments.length, 5);
13
+ verify.equal('Curve.Route exposes named ports', Object.keys(route.ports).length, 2);
14
+ verify.greaterThan('Curve.Route remains usable as a sweep path', tube.boundingBox().max[2], 70);
15
+
16
+ return route;
@@ -0,0 +1,24 @@
1
+ const rail = Curve.Fit(
2
+ [
3
+ [0, 0, 0],
4
+ [24, 10, 8],
5
+ [54, -8, 12],
6
+ [84, 0, 0],
7
+ ],
8
+ { degree: 3 },
9
+ );
10
+
11
+ const middle = Curve.Trim(rail, 0.2, 0.8);
12
+ const reversed = Curve.Reverse(middle);
13
+
14
+ const middleTube = sweep(circle2d(1.2), middle).color("#5f8cc0");
15
+ const reversedTube = sweep(circle2d(0.8), reversed).translate(0, 18, 0).color("#c06f5f");
16
+
17
+ const close3d = (a, b, tolerance = 1e-6) => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]) <= tolerance;
18
+
19
+ verify.that("Curve.Trim starts at the source subdomain", () => close3d(middle.pointAt(0), rail.pointAt(0.2)));
20
+ verify.that("Curve.Trim ends at the source subdomain", () => close3d(middle.pointAt(1), rail.pointAt(0.8)));
21
+ verify.that("Curve.Reverse preserves geometry with opposite parameter direction", () => close3d(reversed.pointAt(0), middle.pointAt(1)));
22
+ verify.greaterThan("Trimmed curves feed exact sweep rails", middleTube.boundingBox().max[0], 60);
23
+
24
+ return group(middleTube, reversedTube);
@@ -0,0 +1,36 @@
1
+ const lower = Curve.Arc({
2
+ start: [36, 0, 0],
3
+ end: [0, 36, 0],
4
+ tangent: [0, 1, 0],
5
+ });
6
+ const upper = Curve.Arc({
7
+ start: [36, 0, 10],
8
+ end: [0, 36, 10],
9
+ tangent: [0, 1, 0],
10
+ });
11
+ const half = Curve.Arc({
12
+ start: [12, 0, 18],
13
+ end: [-12, 0, 18],
14
+ tangent: [0, 1, 0],
15
+ });
16
+
17
+ const tube = sweep(circle2d(0.8), lower);
18
+ const upperTube = sweep(circle2d(0.5), upper).color("#5a8f7b");
19
+
20
+ const close3d = (a, b, tolerance = 1e-6) => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]) <= tolerance;
21
+
22
+ verify.that("Curve.Arc hits start, midpoint, and end exactly", () =>
23
+ close3d(lower.pointAt(0), [36, 0, 0]) &&
24
+ close3d(lower.pointAt(0.5), [36 * Math.SQRT1_2, 36 * Math.SQRT1_2, 0]) &&
25
+ close3d(lower.pointAt(1), [0, 36, 0]));
26
+
27
+ verify.that("Curve.Arc emits stable rational spans for half circles", () =>
28
+ half.controlPoints.length === 5 && close3d(half.pointAt(0.5), [0, 12, 18]));
29
+
30
+ verify.that("Curve.Arc feeds sweep as an exact NURBS rail", () =>
31
+ tube.geometryInfo().backend !== "unknown" && tube.boundingBox().max[0] > 30 && tube.boundingBox().max[1] > 30);
32
+
33
+ verify.that("Multiple Curve.Arc rails remain reusable sweep inputs", () =>
34
+ upperTube.boundingBox().max[2] > 10 && upperTube.boundingBox().max[0] > 30);
35
+
36
+ return group(tube, upperTube);
@@ -27,17 +27,14 @@ const body = plate.subtract(cutout);
27
27
  const bodyEdges = selectEdges(body);
28
28
  const raw = body.color('#7b8490');
29
29
  const chamfered = chamfer(body, 0.75, bodyEdges).color('#d3a33a');
30
- const shapes = [
30
+ // Native Truck fillet now produces analytic rolling-ball geometry (cylinders,
31
+ // spheres, and toroidal corner blends) that exports to STEP canonically
32
+ // identical to OpenCascade. See:
33
+ // forgecad export step examples/api/mixed-edge-finishes-proof.forge.js --backend truck
34
+ const filleted = fillet(body, 0.75, bodyEdges).color('#4e8fd6');
35
+
36
+ return [
31
37
  { name: 'Raw', shape: raw.translate(-80, 0, 0) },
32
38
  { name: 'Chamfered', shape: chamfered.translate(30, 0, 0) },
39
+ { name: 'Filleted', shape: filleted.translate(140, 0, 0) },
33
40
  ];
34
-
35
- try {
36
- const filleted = fillet(body, 0.75, bodyEdges).color('#4e8fd6');
37
- filleted.volume();
38
- shapes.push({ name: 'Filleted', shape: filleted.translate(140, 0, 0) });
39
- } catch (error) {
40
- console.log(`Filleted: unsupported in native Truck (${error instanceof Error ? error.message : String(error)})`);
41
- }
42
-
43
- return shapes;
@@ -0,0 +1,68 @@
1
+ // Curve.Route elbow - demonstrates virtual 3D route corners, named route ports,
2
+ // and sweeping an annular profile without hand-computing tangent points.
3
+
4
+ const route = Curve.Route.fromPolyline(
5
+ [
6
+ [0, 0, 0],
7
+ [0, 0, 203.2],
8
+ [203.2, 0, 203.2],
9
+ ],
10
+ { cornerRadius: 114.3, startPort: 'inlet', endPort: 'outlet' },
11
+ );
12
+
13
+ const outerRadius = 44.45;
14
+ const innerRadius = 38.96;
15
+ const flangeRadius = 89.0;
16
+ const boltCircleRadius = 72.3;
17
+ const boltRadius = 5.3;
18
+ const flangeThickness = 17.8;
19
+ const neckLength = 26.645;
20
+ const neckRadius = 55.6;
21
+
22
+ const tubeProfile = difference2d(circle2d(outerRadius, 80), circle2d(innerRadius, 80));
23
+ const pipe = sweep(tubeProfile, route, { samples: 72 });
24
+
25
+ function placeAtPort(shape, port, offset) {
26
+ return shape.pointAlong(port.axis).translate(
27
+ port.origin[0] + port.axis[0] * offset,
28
+ port.origin[1] + port.axis[1] * offset,
29
+ port.origin[2] + port.axis[2] * offset,
30
+ );
31
+ }
32
+
33
+ function flangePlate() {
34
+ const bore = cylinder(flangeThickness + 2, innerRadius, undefined, 80).translate(0, 0, -1);
35
+ const firstBolt = cylinder(flangeThickness + 2, boltRadius, undefined, 24).translate(boltCircleRadius, 0, -1);
36
+ const bolts = circularPattern(firstBolt, 5);
37
+ return cylinder(flangeThickness, flangeRadius, undefined, 96).subtract(bore, bolts);
38
+ }
39
+
40
+ function neck() {
41
+ const bore = cylinder(neckLength + 2, innerRadius, undefined, 80).translate(0, 0, -1);
42
+ return cylinder(neckLength, neckRadius, undefined, 80).subtract(bore);
43
+ }
44
+
45
+ const inlet = route.port('inlet');
46
+ const outlet = route.port('outlet');
47
+ const body = union(
48
+ pipe,
49
+ placeAtPort(neck(), inlet, -4.445),
50
+ placeAtPort(flangePlate(), inlet, 20.0),
51
+ placeAtPort(neck(), outlet, -4.445),
52
+ placeAtPort(flangePlate(), outlet, 20.0),
53
+ ).color('#b9c0c8');
54
+
55
+ const bbox = body.boundingBox();
56
+ const bboxSize = [bbox.max[0] - bbox.min[0], bbox.max[1] - bbox.min[1], bbox.max[2] - bbox.min[2]];
57
+
58
+ verify.equal('Curve.Route elbow keeps line-arc-line route intent', route.segments.length, 3);
59
+ verify.equal('Curve.Route elbow exposes inlet and outlet ports', Object.keys(route.ports).length, 2);
60
+ verify.boundingBoxSize('Curve.Route elbow preserves BenchCAD-scale envelope', body, [337, 178, 330], 18);
61
+ verify.that(
62
+ 'Curve.Route elbow bbox stays in expected quadrants',
63
+ () => bbox.min[0] < -40 && bbox.max[0] > 235 && bbox.min[2] < -35 && bbox.max[2] > 245 && bboxSize[1] > 175,
64
+ `bbox was ${JSON.stringify(bbox)}`,
65
+ );
66
+ verify.physicalComponentCount('Curve.Route elbow is one connected component', 1);
67
+
68
+ return body;
@@ -1,6 +1,5 @@
1
- // Transition Curves — smooth connections between edges
2
- // Demonstrates transitionCurve(), transitionSurface(), connectEdges(),
3
- // and weighted blending (G1 + G2 continuity).
1
+ // Curve blends — smooth connections between edges
2
+ // Demonstrates Curve.Blend(), sweep(), local edge recipes, and weighted blending.
4
3
 
5
4
  const weight = Param.number("Weight A", 1.0, { min: 0.1, max: 5.0, step: 0.1 });
6
5
  const weightB = Param.number("Weight B", 1.0, { min: 0.1, max: 5.0, step: 0.1 });
@@ -12,9 +11,43 @@ function anchor(pos) {
12
11
  return box(s, s, s).translate(pos[0], pos[1], pos[2]);
13
12
  }
14
13
 
14
+ function blendTube(edgeA, edgeB, options = {}) {
15
+ const curve = Curve.Blend(
16
+ { point: edgeA.point, tangent: edgeA.tangent, weight: options.weightA },
17
+ { point: edgeB.point, tangent: edgeB.tangent, weight: options.weightB },
18
+ );
19
+ const profile = options.profile ?? circle2d(options.radius ?? radius);
20
+ return sweep(profile, curve, { samples: options.samples, up: options.up });
21
+ }
22
+
23
+ function normalized(vec, fallback = [1, 0, 0]) {
24
+ const length = Math.hypot(vec[0], vec[1], vec[2]);
25
+ return length > 1e-9 ? [vec[0] / length, vec[1] / length, vec[2] / length] : fallback;
26
+ }
27
+
28
+ function edgePoint(edge, which = 'mid') {
29
+ if (which === 'start') return edge.start;
30
+ if (which === 'end') return edge.end;
31
+ return edge.midpoint;
32
+ }
33
+
34
+ function edgeOutward(edge) {
35
+ const a = edge.normalA ?? [0, 0, 0];
36
+ const b = edge.normalB ?? [0, 0, 0];
37
+ return normalized([a[0] + b[0], a[1] + b[1], a[2] + b[2]], edge.direction ?? [1, 0, 0]);
38
+ }
39
+
40
+ function edgeBlendTube(edgeA, edgeB, options = {}) {
41
+ return blendTube(
42
+ { point: edgePoint(edgeA, options.endA), tangent: edgeOutward(edgeA) },
43
+ { point: edgePoint(edgeB, options.endB), tangent: edgeOutward(edgeB) },
44
+ options,
45
+ );
46
+ }
47
+
15
48
  // ── 1. L-bend: 90-degree pipe turn ──────────────────────────────
16
49
  const pA1 = [0, 0, 0], pB1 = [30, 20, 0];
17
- const lBend = transitionSurface(
50
+ const lBend = blendTube(
18
51
  { point: pA1, tangent: [1, 0, 0] },
19
52
  { point: pB1, tangent: [0, 1, 0] },
20
53
  { radius, weightA: weight, weightB: weightB },
@@ -22,7 +55,7 @@ const lBend = transitionSurface(
22
55
 
23
56
  // ── 2. S-curve: opposing tangents ────────────────────────────────
24
57
  const pA2 = [0, 40, 0], pB2 = [30, 60, 0];
25
- const sCurve = transitionSurface(
58
+ const sCurve = blendTube(
26
59
  { point: pA2, tangent: [1, 0, 0] },
27
60
  { point: pB2, tangent: [-1, 0, 0] },
28
61
  { radius, weightA: weight, weightB: weightB },
@@ -30,7 +63,7 @@ const sCurve = transitionSurface(
30
63
 
31
64
  // ── 3. 3D transition: going up and around ────────────────────────
32
65
  const pA3 = [0, 0, 30], pB3 = [25, 15, 45];
33
- const transition3D = transitionSurface(
66
+ const transition3D = blendTube(
34
67
  { point: pA3, tangent: [1, 0, 0] },
35
68
  { point: pB3, tangent: [0, 0, 1] },
36
69
  { radius, weightA: weight, weightB: weightB, up: [0, 1, 0] },
@@ -38,7 +71,7 @@ const transition3D = transitionSurface(
38
71
 
39
72
  // ── 4. Asymmetric weight (3:0.5) ────────────────────────────────
40
73
  const pA4 = [55, 0, 0], pB4 = [85, 20, 0];
41
- const weighted = transitionSurface(
74
+ const weighted = blendTube(
42
75
  { point: pA4, tangent: [1, 0, 0] },
43
76
  { point: pB4, tangent: [0, 1, 0] },
44
77
  { radius, weightA: 3.0, weightB: 0.5 },
@@ -51,25 +84,21 @@ const boxB = box(10, 10, 10).translate(35, 15, -20);
51
84
  const topEdgeA = selectEdge(boxA, { atZ: -25, parallel: [1, 0, 0] });
52
85
  const bottomEdgeB = selectEdge(boxB, { atZ: -20, parallel: [1, 0, 0] });
53
86
 
54
- const edgeConnector = connectEdges(topEdgeA, bottomEdgeB, {
87
+ const edgeConnector = edgeBlendTube(topEdgeA, bottomEdgeB, {
55
88
  endA: 'mid',
56
89
  endB: 'mid',
57
- tangentModeA: 'outward',
58
- tangentModeB: 'outward',
59
90
  radius: 2,
60
91
  weightA: weight,
61
92
  weightB: weightB,
62
93
  });
63
94
 
64
- // ── 6. connectEdges shortcut ─────────────────────────────────────
95
+ // ── 6. Same local edge recipe on vertical side edges ─────────────
65
96
  const sideEdgeA = selectEdge(boxA, { near: [5, 0, -30], parallel: [0, 0, 1] });
66
97
  const sideEdgeB = selectEdge(boxB, { near: [30, 15, -15], parallel: [0, 0, 1] });
67
98
 
68
- const shortcutConnector = connectEdges(sideEdgeA, sideEdgeB, {
99
+ const shortcutConnector = edgeBlendTube(sideEdgeA, sideEdgeB, {
69
100
  endA: 'mid',
70
101
  endB: 'mid',
71
- tangentModeA: 'outward',
72
- tangentModeB: 'outward',
73
102
  radius: 1.5,
74
103
  weightA: weight,
75
104
  weightB: weightB,
@@ -85,7 +114,7 @@ const box2 = box(12, 12, 12).translate(25, -55, 25);
85
114
  // Cylinder rim at Y=-55: full radius available, so X=8 is on the rim.
86
115
  // Box left face at X=25, Y=-55 is on the face edge, Z=31 is mid-height.
87
116
  // End tangent [1,0,0] means the curve arrives going +X (into the face).
88
- const cylToBox = transitionSurface(
117
+ const cylToBox = blendTube(
89
118
  { point: [8, -55, 20], tangent: [1, 0, 0.65] },
90
119
  { point: [25, -55, 31], tangent: [1, 0, 0] },
91
120
  { radius: 1.5, weightA: weight, weightB: weightB },
@@ -1,5 +1,3 @@
1
- if (getActiveBackend() === 'manifold') setActiveBackend('truck');
2
-
3
1
  const width = param('Width', 104);
4
2
  const depth = param('Depth', 76);
5
3
  const height = param('Height', 42);
@@ -9,5 +9,5 @@ const coral = sdf.noise({ scale: 0.15, amplitude: 3, octaves: 4, seed: 7 });
9
9
  return vase
10
10
  .shell(3)
11
11
  .intersect(coral)
12
- .toShape({ edgeLength: 0.5 })
12
+ // .toShape({ edgeLength: 0.5 })
13
13
  .color('#e07856');
@@ -1,5 +1,5 @@
1
1
  // NURBS curve swept into a smooth tube
2
- const curve = nurbs3d(
2
+ const curve = Curve.Nurbs(
3
3
  [[0,0,0], [15,8,0], [25,-3,10], [40,5,15], [50,0,5]],
4
4
  { degree: 3 }
5
5
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgecad",
3
- "version": "0.9.14",
3
+ "version": "0.9.15",
4
4
  "description": "Code-first parametric CAD for JavaScript/TypeScript, in the browser and CLI.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://forgecad.io",
@@ -66,7 +66,9 @@
66
66
  },
67
67
  "files": [
68
68
  "dist-cli",
69
+ "!dist-cli/**/*.map",
69
70
  "dist",
71
+ "!dist/**/*.map",
70
72
  "dist-skill",
71
73
  "examples",
72
74
  "!examples/todo.md",
@@ -99,16 +101,15 @@
99
101
  "build:geometry:native:parallel": "node scripts/geometry-build.mjs --native --release --parallel",
100
102
  "bench:geometry:native": "cargo run --manifest-path geometry/Cargo.toml --release --features parallel --example server_parallel_bench -- --require-parallel",
101
103
  "bench:edge-finishes": "node scripts/truck-edge-finish-parity-benchmark.mjs",
102
- "build:benchmark-data": "node scripts/gen-benchmark-data.mjs",
103
104
  "test:solver": "node scripts/solver-test.mjs",
104
105
  "test:geometry": "node scripts/geometry-test.mjs",
105
106
  "build:sitemap": "node scripts/gen-sitemap.mjs",
106
- "build": "npm run build:solver && npm run build:geometry && npm run build:skill:forgecad && tsc && npm run build:sitemap && vite build && npm run build:cli",
107
- "build:hosted": "npm run build:solver && npm run build:geometry && npm run build:skill:forgecad && tsc && npm run build:sitemap && FORGE_HOSTED=true vite build",
107
+ "build": "npm run build:solver && npm run build:geometry && npm run build:skill:forgecad && tsc && npm run gen:public-docs && npm run build:docs && npm run build:sitemap && vite build && npm run build:cli",
108
+ "build:hosted": "npm run build:solver && npm run build:geometry && npm run build:skill:forgecad && tsc && npm run gen:public-docs && npm run build:docs && npm run build:sitemap && FORGE_HOSTED=true vite build",
108
109
  "dev:cli": "npm run build:solver:if-missing && npm run build:geometry:if-missing && tsup cli/forgecad.ts --format esm --platform node --target node20 --out-dir dist-cli --sourcemap --external typescript && node scripts/copy-cli-assets.mjs dist-cli",
109
- "build:cli": "npm run build:solver:if-missing && npm run build:geometry:if-missing && tsup cli/forgecad.ts --format esm --platform node --target node20 --out-dir dist-cli --clean --sourcemap --external typescript && node scripts/copy-cli-assets.mjs dist-cli",
110
- "internal": "node scripts/forgecad-internal.mjs",
111
- "build:backend": "npm run build:solver:if-missing && npm run build:geometry:if-missing && tsup apps/backend/src/server.ts --format esm --platform node --target node20 --out-dir dist-backend --clean --sourcemap && node scripts/copy-wasm-assets.mjs dist-backend",
110
+ "build:cli": "npm run build:solver:if-missing && npm run build:geometry:if-missing && tsup cli/forgecad.ts --format esm --platform node --target node20 --out-dir dist-cli --clean --external typescript && node scripts/copy-cli-assets.mjs dist-cli",
111
+ "build:native-occt": "node scripts/build-native-occt.mjs",
112
+ "build:backend": "npm run build:native-occt && tsup apps/backend/src/server.ts apps/backend/src/nativeOcctWorker.ts --format esm --platform node --target node20 --out-dir dist-backend --clean --sourcemap",
112
113
  "build:binary": "node scripts/build-binary.mjs",
113
114
  "build:binary:all": "node scripts/build-binary.mjs --all",
114
115
  "bundle:offline": "node scripts/build-install-bundle.mjs",
@@ -130,21 +131,18 @@
130
131
  "test:examples:smoke": "npm run test:prepare && FORGECAD_INTERNAL_CHECKS=1 node dist-cli/forgecad.js check examples --profile smoke",
131
132
  "test:examples:full": "npm run test:prepare && FORGECAD_INTERNAL_CHECKS=1 node dist-cli/forgecad.js check examples --profile full",
132
133
  "test:brep": "npm run test:prepare && FORGECAD_INTERNAL_CHECKS=1 node dist-cli/forgecad.js check brep",
134
+ "test:native-occt-ir": "npm run build:native-occt && vitest run test/nativeOcctIrCompute.test.ts test/computeRoutesAccess.test.ts",
133
135
  "test:api": "npm run test:prepare && FORGECAD_INTERNAL_CHECKS=1 node dist-cli/forgecad.js check api",
134
136
  "test:text": "npm run test:prepare && FORGECAD_INTERNAL_CHECKS=1 node dist-cli/forgecad.js check text",
135
137
  "verify:surface-member-render-evidence": "node scripts/verify-surface-member-render-evidence.mjs",
136
138
  "verify:global-install": "node scripts/verify-global-install-sandbox.mjs",
139
+ "verify:npm-artifacts": "node scripts/verify-npm-artifacts.mjs",
137
140
  "build:skill:forgecad": "node scripts/build-forgecad-skill.mjs",
138
141
  "sync:public-skills": "node scripts/sync-public-skills.mjs",
139
142
  "build:docs": "node scripts/build-docs-site.mjs",
140
- "benchmark:reconstruction": "node scripts/forgecad-internal.mjs benchmark reconstruction",
141
- "benchmark:reconstruction:list": "node scripts/forgecad-internal.mjs benchmark reconstruction list-tasks",
142
- "benchmark:reconstruction:import-harbor": "node scripts/forgecad-internal.mjs benchmark reconstruction import-harbor",
143
- "benchmark:reconstruction:leaderboard": "node scripts/forgecad-internal.mjs benchmark reconstruction leaderboard",
144
- "benchmark:reconstruction:report": "node scripts/forgecad-internal.mjs benchmark reconstruction report",
145
143
  "prepare": "npm run build:cli && npm run install-hooks",
146
144
  "install-hooks": "git config core.hooksPath scripts/git-hooks",
147
- "prepublishOnly": "npm run build",
145
+ "prepublishOnly": "npm run build && npm run verify:npm-artifacts",
148
146
  "release:pack": "node scripts/release-docker-check.mjs pack",
149
147
  "release:docker:create": "node scripts/release-docker-check.mjs container",
150
148
  "release:docker:copy": "node scripts/release-docker-check.mjs copy",
@@ -187,6 +185,8 @@
187
185
  "prod:promote-beta": "fish scripts/promote-beta-to-prod.fish",
188
186
  "prod:help": "bash scripts/prod.sh help",
189
187
  "paid-user-note": "node scripts/create-paid-user-note.mjs",
188
+ "gen:legal-docs": "tsx scripts/gen-legal-docs.ts",
189
+ "gen:public-docs": "tsx scripts/gen-public-docs.ts",
190
190
  "gen:types": "node scripts/gen-forge-types.mjs",
191
191
  "gen:docs": "node scripts/gen-api-docs.mjs",
192
192
  "gen:cli-docs": "node scripts/gen-cli-docs.mjs",
@@ -214,6 +214,7 @@
214
214
  "meshoptimizer": "^1.0.1",
215
215
  "mp4-muxer": "^5.2.1",
216
216
  "nanoid": "^5.1.7",
217
+ "node-addon-api": "^8.8.0",
217
218
  "opencascade.js": "2.0.0-beta.b5ff984",
218
219
  "opentype.js": "^1.3.4",
219
220
  "pino": "^10.3.1",