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
@@ -25,6 +25,8 @@ skill-order: 100
25
25
  - [SurfacePattern](#surfacepattern)
26
26
  - [Pattern2D](#pattern2d)
27
27
  - [Pattern2DBuilder](#pattern2dbuilder)
28
+ - [HermiteCurve3D](#hermitecurve3d)
29
+ - [QuinticHermiteCurve3D](#quintichermitecurve3d)
28
30
  - [ShapeRef](#shaperef)
29
31
  - [ANCHOR3D_NAMES](#anchor3d-names)
30
32
  - [verify](#verify)
@@ -364,9 +366,9 @@ selectEdges(shape: Shape, query?: EdgeQuery): EdgeSegment[]
364
366
  | `minLength?` | `number` | Filter: minimum edge length. |
365
367
  | `maxLength?` | `number` | Filter: maximum edge length. |
366
368
  | `within?` | `BoundingRegion` | Filter: edge midpoint must be within this bounding region. |
367
- | `atZ?` | `number` | Shorthand: edge midpoint Z this value (within `tolerance`). Equivalent to `within: { zMin: atZ - tol, zMax: atZ + tol }`. |
368
- | `tolerance?` | `number` | Position tolerance for approximate matches (default: `1.0`). Used by `atZ` and `near`. |
369
- | `angleTolerance?` | `number` | Angular tolerance in degrees for `parallel`/`perpendicular` filters (default: `10`). |
369
+ | `atZ?` | `number` | Shorthand: edge midpoint Z is approximately this value within `tolerance`. |
370
+ | `tolerance?` | `number` | Position tolerance for approximate matches. Used by `atZ` and `near`. Default: `1.0`. |
371
+ | `angleTolerance?` | `number` | Angular tolerance in degrees for `parallel`/`perpendicular` filters. Default: `10`. |
370
372
 
371
373
  `BoundingRegion`: `{ xMin?: number, xMax?: number, yMin?: number, yMax?: number, zMin?: number, zMax?: number }`
372
374
 
@@ -418,7 +420,16 @@ coalesceEdges(segments: EdgeSegment[], tolerance?: number): EdgeSegment[]
418
420
 
419
421
  #### `require()` — Import a module with optional ForgeCAD parameter overrides. Returns the module's exports.
420
422
 
421
- When importing a `.forge.js` file, the return value is what the script returns. If the script returns a metadata object (e.g. `{ shape: myShape, bolts: {...} }`), the caller receives the full object — renderable values and metadata together.
423
+ When importing a `.forge.js` file, most return values are passed through exactly as the script returns them. Assembly returns have one extra composition rule: an unsolved [`Assembly`](/docs/assembly#assembly) is wrapped as an [`ImportedAssembly`](/docs/assembly#importedassembly), preserving `solve(state)` and `mergeInto()` across file boundaries, while a returned [`SolvedAssembly`](/docs/assembly#solvedassembly) stays a [`SolvedAssembly`](/docs/assembly#solvedassembly). If the script returns a metadata object (e.g. `{ shape: myShape, bolts: {...} }`), the caller receives the full object — renderable values and metadata together.
424
+
425
+ **Assembly return contract**
426
+
427
+ | `.forge.js` return value | `require()` result |
428
+ |---|---|
429
+ | `Assembly` | `ImportedAssembly` |
430
+ | `SolvedAssembly` | `SolvedAssembly` |
431
+
432
+ [`ImportedAssembly`](/docs/assembly#importedassembly) exposes default-pose helpers such as `getPart()`, `collisionReport()`, and `minClearance()`. Use `solve(state)` first when inspecting a non-default pose.
422
433
 
423
434
  **Path rule:** Always include the file extension in relative imports: use `require("./part.forge.js")` for model files and `require("./helpers.js")` for plain helper modules. ForgeCAD does not apply Node-style extension inference, so `require("./part")` will not find `part.forge.js` or `part.js`.
424
435
 
@@ -449,6 +460,26 @@ mount.bolts.pos // access the metadata
449
460
  mount.shape // access the geometry
450
461
  ```
451
462
 
463
+ **Forge-aware builder module pattern** — use `.forge.js` modules for reusable sketch, profile, shape, or assembly builders that need ForgeCAD runtime APIs:
464
+
465
+ ```js
466
+ // profiles.forge.js — inspectable on its own, reusable through require()
467
+ function wheelProfile() {
468
+ return circle2d(40).subtract(circle2d(18));
469
+ }
470
+
471
+ return {
472
+ preview: [{ name: 'Wheel profile', sketch: wheelProfile() }],
473
+ make: { wheelProfile },
474
+ };
475
+
476
+ // main.forge.js
477
+ const profiles = require('./profiles.forge.js');
478
+ const wheel = profiles.make.wheelProfile().extrude(8);
479
+ ```
480
+
481
+ Keep exported builders pure over top-level constants, top-level `param()` values, or explicit function arguments. Do not declare new `param()` values inside an exported builder if callers need `require('./profiles.forge.js', { Width: 80 })` overrides: import overrides are validated while the module loads, before any exported builder is called. Use plain `.js` modules only for pure constants, tables, math helpers, and formatting code that does not construct ForgeCAD geometry.
482
+
452
483
  ```ts
453
484
  require(path: string, paramOverrides?: Record<string, number | string>): any
454
485
  ```
@@ -477,10 +508,18 @@ importSvgSketch(fileName: string, options?: SvgImportOptions): Sketch
477
508
  | `simplify?` | `number` | Simplification tolerance for final sketch cleanup. |
478
509
  | `invertY?` | `boolean` | Flip SVG Y-down coordinates to CAD Y-up. Enabled by default. |
479
510
 
480
- #### `importMesh()` — Import an external mesh file (STL, OBJ, 3MF) as a Shape.
511
+ #### `importMesh()` — Import an external mesh file (STL, OBJ, 3MF).
512
+
513
+ By default, 3MF build items are flattened into one Shape for compatibility. Use `separateObjects: true` to import 3MF build items/resource objects as a named ShapeGroup whose children are targetable by `forgecad ls`. Use `object` to import one item by the stable ref/name reported by `forgecad run`.
514
+
515
+ ```js
516
+ const all = importMesh("./assembly.3mf", { separateObjects: true });
517
+ const pin = all.child("Pin #001");
518
+ const plate = importMesh("./assembly.3mf", { object: "3mf:build:001:object:7" });
519
+ ```
481
520
 
482
521
  ```ts
483
- importMesh(fileName: string, options?: { scale?: number; center?: boolean; }): Shape
522
+ importMesh(fileName: string, options?: { scale?: number; center?: boolean; object?: string; separateObjects?: boolean; }): Shape | ShapeGroup
484
523
  ```
485
524
 
486
525
  #### `importStep()` — Import a STEP file (.step, .stp) as an exact OCCT-backed Shape. Preserves NURBS curves, B-spline surfaces, and exact topology. Requires running with the OCCT backend.
@@ -953,6 +992,25 @@ box(100, 100, 10).color('#gold').material({ metalness: 0.95, roughness: 0.05 }).
953
992
  material(props: ShapeMaterialProps): Shape
954
993
  ```
955
994
 
995
+ **`ShapeMaterialProps`**
996
+
997
+ | Option | Type | Description |
998
+ |--------|------|-------------|
999
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1000
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1001
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1002
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1003
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1004
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1005
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1006
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1007
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1008
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1009
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1010
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1011
+ | `specularColor?` | `string` | Specular highlight tint. |
1012
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1013
+
956
1014
  **Face Topology**
957
1015
 
958
1016
  #### `face()` — Resolve a face by user-authored label or compiler-owned name. Returns a `FaceRef` that can be passed to `.onFace()`, `projectToPlane()`, or used directly in placement.
@@ -1073,6 +1131,15 @@ body.edgesOf('top', { concave: true })
1073
1131
  edgesOf(faceLabel: string, options?: EdgesOfOptions): EdgeSegment[]
1074
1132
  ```
1075
1133
 
1134
+ **`EdgesOfOptions`**
1135
+
1136
+ | Option | Type | Description |
1137
+ |--------|------|-------------|
1138
+ | `exclude?` | `string \| string[]` | Exclude edges shared with these named faces. |
1139
+ | `convex?` | `boolean` | Additional geometric filter: only convex edges. |
1140
+ | `concave?` | `boolean` | Additional geometric filter: only concave edges. |
1141
+ | `minLength?` | `number` | Minimum edge length filter. |
1142
+
1076
1143
  #### `edgesBetween()` — Return edges shared between two named faces.
1077
1144
 
1078
1145
  An edge is "between" faces A and B when one of its adjacent mesh triangles belongs to A and the other belongs to B. This is the most precise topological edge selection — "fillet the edges where the top meets the wall."
@@ -1154,6 +1221,8 @@ rotateZ(angleDeg: number, options?: { pivot?: [ number, number, number ]; }): Sh
1154
1221
  rotateAroundTo(axis: [ number, number, number ], pivot: [ number, number, number ], movingPoint: RotationPointLike, targetPoint: RotationPointLike, options?: RotateAroundToOptions): Shape
1155
1222
  ```
1156
1223
 
1224
+ `RotateAroundToOptions`: `{ mode?: RotateAroundToMode }`
1225
+
1157
1226
  #### `transform()` — Apply a 4x4 affine transform matrix (column-major) or a Transform object.
1158
1227
 
1159
1228
  ```ts
@@ -1250,6 +1319,11 @@ box(100, 100, 20).pocket('top', 8, { scale: 0.8 })
1250
1319
  pocket(face: FaceSelector, depth: number, opts?: PocketOptions): Shape
1251
1320
  ```
1252
1321
 
1322
+ **`PocketOptions`**
1323
+ - `inset?: number` — Shrink the face boundary inward by this many mm before extruding. Produces angled walls when combined with depth. Default: 0 (full face).
1324
+ - `scale?: number` — Scale the face profile uniformly (e.g. 0.8 = 80% of the face area). Mutually exclusive with `inset`; `inset` takes precedence if both are set.
1325
+ - `join?: "Square" | "Round" | "Miter"` — Corner join style when using `inset`. Default: 'Round'.
1326
+
1253
1327
  #### `boss()` — Add a boss (protrusion) from the named face.
1254
1328
 
1255
1329
  ```js
@@ -1272,6 +1346,30 @@ box(50, 50, 20).hole('top', { diameter: 6, counterbore: { diameter: 12, depth: 3
1272
1346
  hole(faceOrRef: SketchFaceTarget | FaceRef, opts: ShapeHoleOptions): Shape
1273
1347
  ```
1274
1348
 
1349
+ **`FaceRef`**
1350
+
1351
+ | Option | Type | Description |
1352
+ |--------|------|-------------|
1353
+ | `normal` | `[ number, number, number ]` | Normal direction of the face |
1354
+ | `center` | `[ number, number, number ]` | Center point of the face |
1355
+ | `query?` | `FaceQueryRef` | Compiler-owned face query when available. |
1356
+ | `planar?` | `boolean` | True when the face can host a 2D sketch placement frame |
1357
+ | `uAxis?` | `[ number, number, number ]` | Face-local horizontal axis for planar faces |
1358
+ | `vAxis?` | `[ number, number, number ]` | Face-local vertical axis for planar faces |
1359
+ | `surface?` | `FaceSurface` | Analytic surface family when the backend can identify one. |
1360
+ | `descendant?` | `FaceDescendantMetadata` | Shared descendant-resolution metadata when this face is a semantic region/set. |
1361
+ | `name` | | — |
1362
+
1363
+ **`FaceDescendantMetadata`**: `kind: "single" | "face-set"`, `semantic: FaceDescendantSemantic`, `memberCount: number`, `memberNames: string[]`, `coplanar: boolean`
1364
+
1365
+ **`ShapeHoleOptions`**: `diameter: number`, `depth?: number`, `upToFace?: SketchFaceTarget | FaceRef`, `extent?: ShapeFeatureExtentOptions`, `u?: number`, `v?: number`, `counterbore?: { diameter: number; depth: number; }`, `countersink?: { diameter: number; angleDeg?: number; }`, `thread?: ShapeHoleThreadOptions`
1366
+
1367
+ `ShapeFeatureExtentOptions`: `{ forward: ShapeFeatureExtentSideOptions, reverse?: ShapeFeatureExtentSideOptions }`
1368
+
1369
+ `ShapeFeatureExtentSideOptions`: `{ depth?: number, upToFace?: SketchFaceTarget | FaceRef, through?: boolean }`
1370
+
1371
+ **`ShapeHoleThreadOptions`**: `designation?: string`, `pitch?: number`, `class?: string`, `handedness?: "right" | "left"`, `depth?: number`, `modeled?: boolean`
1372
+
1275
1373
  #### `cutout()` — Cut a profile-shaped pocket through a face using a placed sketch.
1276
1374
 
1277
1375
  The sketch must be placed on a face with `Sketch.onFace(...)`. The cut follows the sketch's 2D profile.
@@ -1285,6 +1383,8 @@ body.cutout(profile, { depth: 5 })
1285
1383
  cutout(sketch: Sketch, opts?: ShapeCutoutOptions): Shape
1286
1384
  ```
1287
1385
 
1386
+ **`ShapeCutoutOptions`**: `depth?: number`, `upToFace?: SketchFaceTarget | FaceRef`, `extent?: ShapeFeatureExtentOptions`, `taperScale?: number | [ number, number ]`
1387
+
1288
1388
  **Placement**
1289
1389
 
1290
1390
  #### `placeReference()` — Translate the shape so the given anchor or reference lands on the target coordinate.
@@ -1348,6 +1448,11 @@ mast.translate(0, station, radius + 50).seatInto(fuselage, 'mount', { depth: 'fl
1348
1448
  seatInto(target: Shape, surface: string, options?: SeatIntoOptions): Shape
1349
1449
  ```
1350
1450
 
1451
+ **`SeatIntoOptions`**
1452
+ - `along?: [ number, number, number ]` — Movement axis. Default: inverted face normal (points into target).
1453
+ - `depth?: "full" | "flush" | number` — How deep to embed. 'full' = entire face inside. 'flush' = nearest point touches. number = mm past flush. Default: 'full'.
1454
+ - `gap?: number` — Standoff gap in mm. Positive = gap between face and target. Negative = extra penetration. Default: 0.
1455
+
1351
1456
  #### `seatOver()` — Slide this shape until a target's labeled face is fully covered (inside this shape).
1352
1457
 
1353
1458
  The inverse of `seatInto`: instead of embedding *your* face into the target, you move until the *target's* face is embedded inside you.
@@ -1372,6 +1477,10 @@ seatOver(target: Shape, targetSurface: string, options?: SeatIntoOptions): Shape
1372
1477
  withConnectors(connectors: Record<string, ConnectorInput>): Shape
1373
1478
  ```
1374
1479
 
1480
+ **`PortInput`**: `origin?: [ number, number, number ]`, `axis?: [ number, number, number ]`, `start?: [ number, number, number ]`, `end?: [ number, number, number ]`, `up?: [ number, number, number ]`, `kind?: JointType`, `min?: number`, `max?: number`
1481
+
1482
+ `ConnectorInput`: `{ connectorType?: string, gender?: ConnectorGender, measurements?: Record<string, number | string> }`
1483
+
1375
1484
  #### `connectorNames()` — List all connector names on this shape.
1376
1485
 
1377
1486
  ```ts
@@ -1408,6 +1517,8 @@ Overloads:
1408
1517
  matchTo(targetOrPairs: Shape | MatchTarget | Array<[ Shape | MatchTarget, string, string ]>, selfConnOrDict?: string | Record<string, string>, targetConnOrOptions?: string | MatchToOptions, maybeOptions?: MatchToOptions): Shape
1409
1518
  ```
1410
1519
 
1520
+ `MatchToOptions`: `{ force?: boolean, angle?: number, distance?: number }`
1521
+
1411
1522
  **References**
1412
1523
 
1413
1524
  #### `withReferences()` — Attach named placement references that survive normal transforms and imports.
@@ -1416,6 +1527,12 @@ matchTo(targetOrPairs: Shape | MatchTarget | Array<[ Shape | MatchTarget, string
1416
1527
  withReferences(refs: PlacementReferenceInput): Shape
1417
1528
  ```
1418
1529
 
1530
+ **`PlacementReferenceInput`**: `points?: Record<string, [ number, number, number ]>`, `edges?: Record<string, PlacementEdgeRef>`, `surfaces?: Record<string, PlacementSurfaceRef>`, `objects?: Record<string, PlacementObjectInput>`
1531
+
1532
+ `PlacementEdgeRef`: `{ start: Vec3, end: Vec3 }`
1533
+
1534
+ `PlacementSurfaceRef`: `{ center: Vec3, normal: Vec3 }`
1535
+
1419
1536
  #### `referenceNames()` — List named placement references carried by this shape.
1420
1537
 
1421
1538
  ```ts
@@ -1577,6 +1694,24 @@ translate(x: number, y: number, z: number): Transform
1577
1694
  rotateAxis(axis: Vec3, angleDeg: number, pivot?: Vec3): Transform
1578
1695
  ```
1579
1696
 
1697
+ #### `rotateX()` — Rotate about the X axis after the current transform (parity with `Shape.rotateX`).
1698
+
1699
+ ```ts
1700
+ rotateX(angleDeg: number, pivot?: Vec3): Transform
1701
+ ```
1702
+
1703
+ #### `rotateY()` — Rotate about the Y axis after the current transform (parity with `Shape.rotateY`).
1704
+
1705
+ ```ts
1706
+ rotateY(angleDeg: number, pivot?: Vec3): Transform
1707
+ ```
1708
+
1709
+ #### `rotateZ()` — Rotate about the Z axis after the current transform (parity with `Shape.rotateZ`).
1710
+
1711
+ ```ts
1712
+ rotateZ(angleDeg: number, pivot?: Vec3): Transform
1713
+ ```
1714
+
1580
1715
  #### `inverse()` — Return the inverse transform.
1581
1716
 
1582
1717
  ```ts
@@ -1920,18 +2055,160 @@ constant(value?: number): Pattern2D
1920
2055
  sineWave(options: Pattern2DSineWaveOptions): Pattern2D
1921
2056
  ```
1922
2057
 
2058
+ **`Pattern2DSineWaveOptions`**
2059
+
2060
+ | Option | Type | Description |
2061
+ |--------|------|-------------|
2062
+ | `direction?` | `Vec2` | Direction the wave advances in UV space. Default: [1, 0]. |
2063
+ | `wavelength` | `number` | Distance between wave peaks in surface millimeters. |
2064
+ | `amplitude?` | `number` | Height amplitude in millimeters. Default: 1. |
2065
+ | `phase?` | `number` | Phase offset in radians. Default: 0. |
2066
+ | `bias?` | `number` | Constant height offset in millimeters. Default: 0. |
2067
+
1923
2068
  #### `stripes()` — Create recessed stripe bands in UV space.
1924
2069
 
1925
2070
  ```ts
1926
2071
  stripes(options: Pattern2DStripesOptions): Pattern2D
1927
2072
  ```
1928
2073
 
2074
+ **`Pattern2DStripesOptions`**
2075
+
2076
+ | Option | Type | Description |
2077
+ |--------|------|-------------|
2078
+ | `direction?` | `Vec2` | Direction perpendicular to the stripe bands in UV space. Default: [1, 0]. |
2079
+ | `spacing` | `number` | Center-to-center spacing in surface millimeters. |
2080
+ | `width` | `number` | Stripe width in surface millimeters. |
2081
+ | `depth?` | `number` | Stripe groove depth in millimeters. Default: 1. |
2082
+
1929
2083
  #### `overUnderWeave()` — Create an over-under woven relief pattern in UV space.
1930
2084
 
1931
2085
  ```ts
1932
2086
  overUnderWeave(options: Pattern2DOverUnderWeaveOptions): Pattern2D
1933
2087
  ```
1934
2088
 
2089
+ **`Pattern2DOverUnderWeaveOptions`**
2090
+
2091
+ | Option | Type | Description |
2092
+ |--------|------|-------------|
2093
+ | `spacing` | `number \| Vec2` | Thread center-to-center spacing. A number uses the same spacing for U and V. |
2094
+ | `threadWidth` | `number \| Vec2` | Thread width. A number uses the same width for U and V. |
2095
+ | `depth?` | `number` | Thread groove depth in millimeters. Default: 0.8. |
2096
+ | `underScale?` | `number` | Relative height of the under-crossing thread. Default: 0.15. |
2097
+
2098
+ ### `HermiteCurve3D`
2099
+
2100
+ **Properties:**
2101
+
2102
+ | Property | Type | Description |
2103
+ |----------|------|-------------|
2104
+ | `p0` | `Vec3` | Start position |
2105
+ | `p1` | `Vec3` | End position |
2106
+ | `t0` | `Vec3` | Scaled tangent at start (direction * weight * chordLength) |
2107
+ | `t1` | `Vec3` | Scaled tangent at end (direction * weight * chordLength) |
2108
+ | `chordLength` | `number` | Chord length (straight-line distance between endpoints) |
2109
+
2110
+ **Methods:**
2111
+
2112
+ #### `pointAt()` — Evaluate position at parameter t ∈ [0, 1]
2113
+
2114
+ ```ts
2115
+ pointAt(t: number): Vec3
2116
+ ```
2117
+
2118
+ #### `tangentAt()` — Evaluate tangent (first derivative) at parameter t ∈ [0, 1]
2119
+
2120
+ ```ts
2121
+ tangentAt(t: number): Vec3
2122
+ ```
2123
+
2124
+ #### `curvatureAt()` — Evaluate curvature vector (second derivative) at parameter t ∈ [0, 1]
2125
+
2126
+ ```ts
2127
+ curvatureAt(t: number): Vec3
2128
+ ```
2129
+
2130
+ #### `sample()` — Sample the curve as a polyline of evenly-spaced parameter values.
2131
+
2132
+ ```ts
2133
+ sample(count?: number): Vec3[]
2134
+ ```
2135
+
2136
+ #### `length()` — Approximate arc length by sampling.
2137
+
2138
+ ```ts
2139
+ length(samples?: number): number
2140
+ ```
2141
+
2142
+ #### `sampleAdaptive()` — Sample with adaptive density — more points where curvature is higher. Returns at least `minCount` points, up to `maxCount`.
2143
+
2144
+ ```ts
2145
+ sampleAdaptive(minCount?: number, maxCount?: number): Vec3[]
2146
+ ```
2147
+
2148
+ #### `toPolyline()` — Convert to a format compatible with sweep() path input.
2149
+
2150
+ ```ts
2151
+ toPolyline(samples?: number): Vec3[]
2152
+ ```
2153
+
2154
+ ### `QuinticHermiteCurve3D`
2155
+
2156
+ **Properties:**
2157
+
2158
+ | Property | Type | Description |
2159
+ |----------|------|-------------|
2160
+ | `p0` | `Vec3` | Start position |
2161
+ | `p1` | `Vec3` | End position |
2162
+ | `t0` | `Vec3` | Scaled tangent at start (direction * weight * chordLength) |
2163
+ | `t1` | `Vec3` | Scaled tangent at end (direction * weight * chordLength) |
2164
+ | `c0` | `Vec3` | Scaled second derivative at start (curvature * weight² * chordLength²) |
2165
+ | `c1` | `Vec3` | Scaled second derivative at end (curvature * weight² * chordLength²) |
2166
+ | `chordLength` | `number` | Chord length (straight-line distance between endpoints) |
2167
+
2168
+ **Methods:**
2169
+
2170
+ #### `pointAt()` — Evaluate position at parameter t ∈ [0, 1]
2171
+
2172
+ ```ts
2173
+ pointAt(t: number): Vec3
2174
+ ```
2175
+
2176
+ #### `tangentAt()` — Evaluate tangent (first derivative, normalized) at parameter t ∈ [0, 1]
2177
+
2178
+ ```ts
2179
+ tangentAt(t: number): Vec3
2180
+ ```
2181
+
2182
+ #### `curvatureAt()` — Evaluate curvature vector (second derivative) at parameter t ∈ [0, 1]
2183
+
2184
+ ```ts
2185
+ curvatureAt(t: number): Vec3
2186
+ ```
2187
+
2188
+ #### `sample()` — Sample the curve as a polyline of evenly-spaced parameter values.
2189
+
2190
+ ```ts
2191
+ sample(count?: number): Vec3[]
2192
+ ```
2193
+
2194
+ #### `length()` — Approximate arc length by sampling.
2195
+
2196
+ ```ts
2197
+ length(samples?: number): number
2198
+ ```
2199
+
2200
+ #### `sampleAdaptive()` — Sample with adaptive density — more points where curvature is higher. Returns at least `minCount` points, up to `maxCount`.
2201
+
2202
+ ```ts
2203
+ sampleAdaptive(minCount?: number, maxCount?: number): Vec3[]
2204
+ ```
2205
+
2206
+ #### `toPolyline()` — Convert to a format compatible with sweep() path input.
2207
+
2208
+ ```ts
2209
+ toPolyline(samples?: number): Vec3[]
2210
+ ```
2211
+
1935
2212
  ### `ShapeRef`
1936
2213
 
1937
2214
  A first-class reference path over a shape's semantic faces and face relationships.