forgecad 0.9.4 → 0.9.6

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 (90) hide show
  1. package/dist/assets/{AdminPage-jwoEgwE_.js → AdminPage-Da6hhpJx.js} +1 -1
  2. package/dist/assets/{BlogPage-Ck7g3ue2.js → BlogPage-Bl_sKeWb.js} +1 -1
  3. package/dist/assets/{DocsPage-9WaRC14b.js → DocsPage-Blz3Tp4j.js} +1 -6
  4. package/dist/assets/EditorApp-CuiPbtn5.js +12754 -0
  5. package/dist/assets/{EmbedViewer-37_PfMwv.js → EmbedViewer-BFG6-Ufm.js} +2 -2
  6. package/dist/assets/{LandingPageProofDriven-CO8WL0CY.js → LandingPageProofDriven-DB9fQd5P.js} +1 -1
  7. package/dist/assets/{PricingPage-DADKGuOa.js → PricingPage-BMxYT_F0.js} +1 -1
  8. package/dist/assets/{SettingsPage-DKKI4W49.js → SettingsPage-VVQNrCAg.js} +1 -1
  9. package/dist/assets/{app-CwI02pTA.js → app-Dl9ymBWC.js} +355 -36
  10. package/dist/assets/cli/{render-Kw5hLEcL.js → render-CFtwKCCY.js} +203 -862
  11. package/dist/assets/{sectionPlaneMath-C8N0w8o3.js → distance-BEC2RjJi.js} +4150 -801
  12. package/dist/assets/{evalWorker-D6ub3kfS.js → evalWorker-CRvbzTXm.js} +2611 -528
  13. package/dist/assets/{manifold-CwDdMKyc.js → manifold-B9QSr-qP.js} +1 -1
  14. package/dist/assets/{manifold-DTvmxSDf.js → manifold-DpBXFS2K.js} +1 -1
  15. package/dist/assets/{manifold-lru0jwVw.js → manifold-DzZ4VRPs.js} +2 -2
  16. package/dist/assets/{renderSceneState-tvtNKNRi.js → renderSceneState-BuAXF2jh.js} +1 -1
  17. package/dist/assets/{reportWorker-DeqktDGt.js → reportWorker-BNWEnRg1.js} +2606 -525
  18. package/dist/cli/render.html +1 -1
  19. package/dist/docs/index.html +2 -2
  20. package/dist/docs-raw/AI/usage.md +0 -1
  21. package/dist/docs-raw/API/core/concepts.md +11 -1
  22. package/dist/docs-raw/CLI.md +64 -13
  23. package/dist/docs-raw/beta-operations.md +4 -0
  24. package/dist/docs-raw/deployment.md +38 -23
  25. package/dist/docs-raw/generated/assembly.md +8 -3
  26. package/dist/docs-raw/generated/concepts.md +126 -46
  27. package/dist/docs-raw/generated/core.md +97 -47
  28. package/dist/docs-raw/generated/curves.md +113 -595
  29. package/dist/docs-raw/generated/lib.md +40 -3
  30. package/dist/docs-raw/generated/output.md +6 -1
  31. package/dist/docs-raw/generated/sdf.md +50 -4
  32. package/dist/docs-raw/generated/sketch.md +9 -1
  33. package/dist/docs-raw/generated/viewport.md +1 -9
  34. package/dist/docs-raw/guides/inspection-bundles.md +40 -9
  35. package/dist/docs-raw/runbook.md +3 -3
  36. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -0
  37. package/dist/docs-raw/skills/forgecad-image-replicator.md +3 -1
  38. package/dist/docs-raw/skills/forgecad-make-a-model.md +48 -4
  39. package/dist/docs-raw/skills/forgecad-render-inspect.md +3 -1
  40. package/dist/docs-raw/skills/forgecad-visual-spec.md +2 -0
  41. package/dist/docs-raw/skills/forgecad.md +2 -1
  42. package/dist/docs-raw/skills/index.md +0 -1
  43. package/dist/index.html +1 -1
  44. package/dist/sitemap.xml +6 -6
  45. package/dist-cli/blender/render.py +43 -8
  46. package/dist-cli/forgecad.js +5729 -2015
  47. package/dist-cli/forgecad.js.map +1 -1
  48. package/dist-skill/CONTEXT.md +372 -667
  49. package/dist-skill/SKILL-dev.md +2 -1
  50. package/dist-skill/SKILL.md +2 -1
  51. package/dist-skill/docs/API/core/concepts.md +11 -1
  52. package/dist-skill/docs/CLI.md +64 -13
  53. package/dist-skill/docs/generated/assembly.md +8 -3
  54. package/dist-skill/docs/generated/core.md +97 -47
  55. package/dist-skill/docs/generated/curves.md +113 -595
  56. package/dist-skill/docs/generated/lib.md +40 -3
  57. package/dist-skill/docs/generated/output.md +6 -1
  58. package/dist-skill/docs/generated/sdf.md +50 -4
  59. package/dist-skill/docs/generated/sketch.md +9 -1
  60. package/dist-skill/docs/generated/viewport.md +1 -9
  61. package/dist-skill/docs/guides/inspection-bundles.md +40 -9
  62. package/dist-skill/docs-dev/API/core/concepts.md +11 -1
  63. package/dist-skill/docs-dev/CLI.md +64 -13
  64. package/dist-skill/docs-dev/generated/assembly.md +8 -3
  65. package/dist-skill/docs-dev/generated/core.md +97 -47
  66. package/dist-skill/docs-dev/generated/curves.md +113 -595
  67. package/dist-skill/docs-dev/generated/lib.md +40 -3
  68. package/dist-skill/docs-dev/generated/output.md +6 -1
  69. package/dist-skill/docs-dev/generated/sdf.md +50 -4
  70. package/dist-skill/docs-dev/generated/sketch.md +9 -1
  71. package/dist-skill/docs-dev/generated/viewport.md +1 -9
  72. package/dist-skill/docs-dev/guides/inspection-bundles.md +40 -9
  73. package/dist-skill/library/README.md +0 -1
  74. package/dist-skill/library/forgecad-blockout-model/SKILL.md +1 -0
  75. package/dist-skill/library/forgecad-image-replicator/SKILL.md +3 -1
  76. package/dist-skill/library/forgecad-make-a-model/SKILL.md +48 -4
  77. package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
  78. package/dist-skill/library/forgecad-visual-spec/SKILL.md +2 -0
  79. package/examples/api/drive-wheel-regions.forge.js +43 -0
  80. package/examples/api/guided-loft-olive-oil-bottle.forge.js +135 -0
  81. package/examples/api/sdf-circular-array-knurling.forge.js +19 -0
  82. package/examples/api/sdf-pattern2d-ceramic-ripple-set.forge.js +83 -0
  83. package/examples/api/sdf-pattern2d-grip-tread.forge.js +72 -0
  84. package/examples/api/sdf-pattern2d-orbital-jewelry.forge.js +62 -0
  85. package/examples/api/sdf-surface-basket-weave.forge.js +67 -0
  86. package/examples/api/sector-gear-body.forge.js +34 -0
  87. package/package.json +20 -2
  88. package/dist/assets/EditorApp-Dja2jMmW.js +0 -12509
  89. package/dist/docs-raw/skills/forgecad-api-dogfood.md +0 -130
  90. package/dist-skill/library/forgecad-api-dogfood/SKILL.md +0 -125
@@ -9,8 +9,8 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
9
9
 
10
10
  ## Contents
11
11
 
12
- - [Curves & Surfacing](#curves-surfacing) — `hermiteTransitionG2`, `nurbs3d`, `spline2d`, `spline3d`, `loft`, `loftAlongSpine`, `sweep`, `variableSweep`, `nurbsSurface`, `surfacePatch`, `transitionCurve`, `transitionSurface`, `connectEdges`
13
- - [Surface Members](#surface-members) — `surfaceBand`, `compileSurfaceMember`, `SurfaceBody`
12
+ - [Curves & Surfacing](#curves-surfacing) — `Loft.station`, `Loft.leftRail`, `Loft.rightRail`, `Loft.frontRail`, `Loft.backRail`, `Loft.centerRail`, `Loft.pathOnXz`, `Loft.pathOnYz`, `Loft.pathOnXy`, `Loft.withGuideRails`, `hermiteTransitionG2`, `nurbs3d`, `spline2d`, `spline3d`, `loft`, `loftAlongSpine`, `sweep`, `variableSweep`, `nurbsSurface`, `surfacePatch`, `transitionCurve`, `transitionSurface`, `connectEdges`
13
+ - [Surface Members](#surface-members) — `surfaceBand`, `SurfaceBody`
14
14
  - [Curve3D](#curve3d)
15
15
  - [NurbsCurve3D](#nurbscurve3d)
16
16
  - [NurbsSurface](#nurbssurface)
@@ -27,7 +27,6 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
27
27
  - [ProductSpoutBuilder](#productspoutbuilder)
28
28
  - [ProductHandleBuilder](#producthandlebuilder)
29
29
  - [ProductHandleFeature](#producthandlefeature)
30
- - [ProductRibbonBuilder](#productribbonbuilder)
31
30
  - [CylinderCarrier](#cylindercarrier)
32
31
  - [PlaneCarrier](#planecarrier)
33
32
  - [ProductSkinCarrier](#productskincarrier)
@@ -53,6 +52,87 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
53
52
 
54
53
  ### Curves & Surfacing
55
54
 
55
+ #### `Loft.station()` — Create a loft station from a 2D profile and an axis position.
56
+
57
+ ```ts
58
+ Loft.station(profile: Sketch, position: number): LoftStation
59
+ ```
60
+
61
+ `LoftStation`: `{ profile: Sketch, position: number }`
62
+
63
+ #### `Loft.leftRail()` — Create a guide rail that constrains the section-local negative-X side.
64
+
65
+ ```ts
66
+ Loft.leftRail(path: LoftGuideRailPath): LoftGuideRail
67
+ ```
68
+
69
+ `LoftGuideRail`: `{ side: LoftGuideRailSide, path: LoftGuideRailPath }`
70
+
71
+ #### `Loft.rightRail()` — Create a guide rail that constrains the section-local positive-X side.
72
+
73
+ ```ts
74
+ Loft.rightRail(path: LoftGuideRailPath): LoftGuideRail
75
+ ```
76
+
77
+ #### `Loft.frontRail()` — Create a guide rail that constrains the section-local positive-Y side.
78
+
79
+ ```ts
80
+ Loft.frontRail(path: LoftGuideRailPath): LoftGuideRail
81
+ ```
82
+
83
+ #### `Loft.backRail()` — Create a guide rail that constrains the section-local negative-Y side.
84
+
85
+ ```ts
86
+ Loft.backRail(path: LoftGuideRailPath): LoftGuideRail
87
+ ```
88
+
89
+ #### `Loft.centerRail()` — Create a guide rail that moves section centers along the loft.
90
+
91
+ ```ts
92
+ Loft.centerRail(path: LoftGuideRailPath): LoftGuideRail
93
+ ```
94
+
95
+ #### `Loft.pathOnXz()` — Place a 2D guide path onto the XZ plane.
96
+
97
+ The path's first coordinate becomes X and its second coordinate becomes Z. Use this for left/right silhouette rails authored with [`path()`](/docs/sketch#path) or [`constrainedSketch()`](/docs/sketch#constrainedsketch).
98
+
99
+ ```ts
100
+ Loft.pathOnXz(path: LoftPath2D, y?: number): Vec3[]
101
+ ```
102
+
103
+ #### `Loft.pathOnYz()` — Place a 2D guide path onto the YZ plane.
104
+
105
+ The path's first coordinate becomes Y and its second coordinate becomes Z. Use this for front/back crown rails authored with [`path()`](/docs/sketch#path) or [`constrainedSketch()`](/docs/sketch#constrainedsketch).
106
+
107
+ ```ts
108
+ Loft.pathOnYz(path: LoftPath2D, x?: number): Vec3[]
109
+ ```
110
+
111
+ #### `Loft.pathOnXy()` — Place a 2D guide path onto the XY plane.
112
+
113
+ The path's first coordinate becomes X and its second coordinate becomes Y. Use this when lofting along X or Y and a rail lives in a horizontal sketch plane.
114
+
115
+ ```ts
116
+ Loft.pathOnXy(path: LoftPath2D, z?: number): Vec3[]
117
+ ```
118
+
119
+ #### `Loft.withGuideRails()` — Loft through profile stations while forcing generated sections to follow guide rails.
120
+
121
+ Stations define the cross-section family. Guide rails define the side or center paths the loft must pass through. With opposite side rails, the section is scaled to touch both rails. With one side rail, the section keeps its interpolated size unless a center rail is also present.
122
+
123
+ ```ts
124
+ Loft.withGuideRails(stations: LoftStation[], rails: LoftGuideRail[], options?: LoftWithGuideRailsOptions): Shape
125
+ ```
126
+
127
+ **`LoftOptions`**
128
+ - `edgeLength?: number` — Marching-grid edge length for level-set meshing. Smaller = finer.
129
+ - `boundsPadding?: number` — Optional extra bounds padding.
130
+
131
+ **`LoftWithGuideRailsOptions`** extends LoftOptions
132
+ - `axis?: LoftAxis` — Primary station axis. Default Z.
133
+ - `samples?: number` — Number of generated loft stations including ends. Default scales with station count.
134
+ - `railSamples?: number` — Number of points sampled from curve-backed rails before axis interpolation. Default 64.
135
+
56
136
  #### `hermiteTransitionG2()` — Create a quintic Hermite transition curve between two edge endpoints (G2 continuity).
57
137
 
58
138
  The curve starts at `a.point` tangent to `a.tangent` with curvature `a.curvature`, and ends at `b.point` tangent to `b.tangent` with curvature `b.curvature`, with smooth G2-continuous interpolation matching position, tangent, and curvature.
@@ -141,10 +221,6 @@ Performance note: loft is significantly heavier than primitive/extrude/revolve.
141
221
  loft(profiles: Sketch[], heights: number[], options?: LoftOptions): Shape
142
222
  ```
143
223
 
144
- **`LoftOptions`**
145
- - `edgeLength?: number` — Marching-grid edge length for level-set meshing. Smaller = finer.
146
- - `boundsPadding?: number` — Optional extra bounds padding.
147
-
148
224
  #### `loftAlongSpine()` — Loft between multiple profiles positioned along an arbitrary 3D spine curve.
149
225
 
150
226
  Unlike loft() which only supports Z heights, loftAlongSpine() places each profile at a position along a 3D spine, oriented perpendicular to the spine tangent. This enables lofting along curved paths — e.g., a wing root-to-tip transition that follows a swept-back leading edge.
@@ -375,11 +451,8 @@ connectEdges(edgeA: EdgeSegment, edgeB: EdgeSegment, options?: ConnectEdgesOptio
375
451
  | `normalA` | `Vec3` | Normal of first adjacent face. |
376
452
  | `normalB` | `Vec3` | Normal of second adjacent face (same as normalA for boundary edges). |
377
453
  | `boundary` | `boolean` | true if this is a boundary (unmatched) edge — unusual for closed solids. |
378
- | `nativeTopology?` | `EdgeNativeTopologyRef` | Native kernel topology identity when the active backend can provide one. |
379
454
  | `start`, `end`, `midpoint`, `length` | | — |
380
455
 
381
- `EdgeNativeTopologyRef`: `{ backend: "truck", edge: number }`
382
-
383
456
 
384
457
  **`ConnectEdgesOptions`** extends TransitionSurfaceOptions
385
458
 
@@ -402,63 +475,6 @@ connectEdges(edgeA: EdgeSegment, edgeB: EdgeSegment, options?: ConnectEdgesOptio
402
475
  surfaceBand<C extends SurfaceCoordinate>(path: SurfacePath<C> | SurfacePathBuilder<C>, width: WidthProfile, cap?: SurfaceBandCap): SurfaceBand<C>
403
476
  ```
404
477
 
405
- #### `compileSurfaceMember()`
406
-
407
- ```ts
408
- compileSurfaceMember<C extends SurfaceCoordinate>(input: Omit<SurfaceMemberSpec<C>, "section"> & { section: MemberSection | MemberSectionInput; }): CompiledSurfaceMember
409
- ```
410
-
411
- **`SurfaceMemberSpec`**: `name: string`, `kind: SurfaceMemberKind`, `path?: SurfacePath<C> | SurfacePathBuilder<C>`, `anchor?: SurfaceAnchor<C>`, `size?: { width: number; height: number; }`, `section: MemberSection`, `features: MemberFeature[]`, `capStyle?: SurfaceBandCap`, `explicitAnchors?: SurfaceMemberExplicitAnchor<C>[]`
412
-
413
- `SurfaceAnchor`: `{ carrier: CarrierSurface<C>, coordinate: C }`
414
-
415
- `CarrierSurface`: `{ name: string, kind: SurfaceCarrierKind }`
416
-
417
- **`MemberSection`**: `width?: number`, `thickness: number`, `edgeRadius: number`, `direction: MemberOutwardDirection`, `material?: ProductMaterial`, `stations: MemberSectionStation[]`
418
-
419
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
420
-
421
- **`ShapeMaterialProps`**
422
-
423
- | Option | Type | Description |
424
- |--------|------|-------------|
425
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
426
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
427
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
428
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
429
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
430
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
431
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
432
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
433
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
434
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
435
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
436
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
437
- | `specularColor?` | `string` | Specular highlight tint. |
438
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
439
-
440
- `MemberSectionStation`: `{ t: number, width?: number, thickness?: number }`
441
-
442
- **`MemberFeature`**: `type: MemberFeatureType`, `name?: string`, `length?: number`, `width?: number`, `diameter?: number`, `counterboreDiameter?: number`, `clearanceDiameter?: number`, `height?: number`, `depth?: number`, `count?: number`, `along?: number`, `across?: number`, `verticalTravel?: number`
443
-
444
- `SurfaceMemberExplicitAnchor`: `{ name: string, coordinate: C, carrierName?: string }`
445
-
446
- **`MemberSectionInput`**: `width?: number`, `thickness: number`, `edgeRadius?: number`, `direction?: MemberOutwardDirection`, `material?: ProductMaterial`, `stations?: MemberSectionStation[]`
447
-
448
- **`CompiledSurfaceMember`**: `name: string`, `shape: Shape`, `mesh: MemberMesh`, `diagnostics: SurfaceDiagnostic[]`, `anchors: { start?: CompiledSurfaceMemberAnchor; end?: CompiledSurfaceMemberAnchor; center: CompiledSurfaceMemberAnchor; landings?: CompiledSurfaceMemberAnchor[]; boundaries?: CompiledSurfaceMemberAnchor[]; features?: CompiledSurfaceMemberAnchor[]; explicit?: CompiledSurfaceMemberAnchor[]; }`
449
-
450
- `MemberMesh`: `{ vertices: Vec3[], triangles: Array<[ number, number, number ]> }`
451
-
452
- **`SurfaceDiagnostic`**
453
- - `code?: SurfaceDiagnosticCode` — Stable machine-readable repair hook. Messages may change; codes should not.
454
- - Also: `category: "carrier" | "path" | "region" | "member" | "feature" | "join" | "compiler", level: "info" | "warning" | "error", message: string, subject?: string`
455
-
456
- **`SurfaceMemberAnchorIR`**: `role: SurfaceMemberAnchorRole`, `kind: "member-end" | "member-center" | "member-landing" | "member-boundary" | "plate-edge" | "plate-center" | "plate-landing" | "feature-center" | "surface-coordinate"`, `name?: string`, `point: Vec3`, `normal?: Vec3`
457
-
458
- `CompiledSurfaceMemberAnchor`: `{ frame?: SurfaceFrame }`
459
-
460
- **`SurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentAlong: Vec3`, `tangentAcross: Vec3`, `matrix: Mat4`, `carrier: string`, `representation: SurfaceCarrierKind | string`, `coordinate: SurfaceCoordinate`
461
-
462
478
  #### `SurfaceBody()` — Start a surface-member body builder for straps, inlays, guards, braces, cuffs, and similar physical members that live on a carrier surface.
463
479
 
464
480
  ```js
@@ -882,6 +898,21 @@ path().moveTo(0,0).lineTo(10,0).lineTo(10,5).mirror('x').close()
882
898
  mirror(axis: "x" | "y" | [ number, number ]): this
883
899
  ```
884
900
 
901
+ #### `toPolyline()` — Return the open path as a sampled 2D polyline.
902
+
903
+ This is for construction geometry such as guide rails, measured centerlines, and curve-driven helpers where the authored path should stay open instead of becoming a filled sketch or stroked profile.
904
+
905
+ ```ts
906
+ const rail = path()
907
+ .moveTo(24, 0)
908
+ .bezierTo(32, 44, 28, 92, 18, 120)
909
+ .toPolyline();
910
+ ```
911
+
912
+ ```ts
913
+ toPolyline(): [ number, number ][]
914
+ ```
915
+
885
916
  #### `closeOffset()` — Close the path and return an offset version of the filled Sketch. Positive delta expands outward, negative shrinks inward.
886
917
 
887
918
  ```ts
@@ -1034,18 +1065,6 @@ with(...children: GroupInput[]): ShapeGroup
1034
1065
  integrate(...details: Shape[]): Shape
1035
1066
  ```
1036
1067
 
1037
- #### `diagnostics()` — Return lowering representation, station names, rail names, and warnings.
1038
-
1039
- ```ts
1040
- diagnostics(): ProductSkinDiagnostics
1041
- ```
1042
-
1043
- **`ProductSkinDiagnostics`**: `representation: ProductSkinRepresentation`, `lowering: string[]`, `warnings: string[]`, `stationNames: string[]`, `railNames: string[]`
1044
-
1045
- **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
1046
-
1047
- `"exact" | "sampled" | "mixed" | "fallback"`
1048
-
1049
1068
  #### `uv()` — Create a side/u/v surface-ref query on this skin.
1050
1069
 
1051
1070
  ```ts
@@ -1101,7 +1120,7 @@ stationAt(vOrAxis: number): { ... }
1101
1120
  frame(query: ProductSkinRefQuery): ProductSurfaceFrame
1102
1121
  ```
1103
1122
 
1104
- **`ProductSurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentU: Vec3`, `tangentV: Vec3`, `matrix: Mat4`, `skin: string`, `representation: ProductSkinRepresentation`
1123
+ `ProductSurfaceFrame`: `{ point: Vec3, normal: Vec3, tangentU: Vec3, tangentV: Vec3, matrix: Mat4, skin: string }`
1105
1124
 
1106
1125
  ### `ProductSurfaceRef`
1107
1126
 
@@ -1119,25 +1138,6 @@ frame(query: ProductSkinRefQuery): ProductSurfaceFrame
1119
1138
  frame(overrides?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame
1120
1139
  ```
1121
1140
 
1122
- **`ProductSkinRefQuery`**
1123
-
1124
- | Option | Type | Description |
1125
- |--------|------|-------------|
1126
- | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1127
- | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1128
- | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1129
- | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1130
-
1131
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1132
-
1133
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1134
-
1135
- **`ProductSurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentU: Vec3`, `tangentV: Vec3`, `matrix: Mat4`, `skin: string`, `representation: ProductSkinRepresentation`
1136
-
1137
- **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
1138
-
1139
- `"exact" | "sampled" | "mixed" | "fallback"`
1140
-
1141
1141
  #### `with()` — Return a copy of this ref with side/u/v/offset overrides.
1142
1142
 
1143
1143
  ```ts
@@ -1182,31 +1182,12 @@ ref(u?: number, v?: number, offset?: number): ProductSurfaceRef
1182
1182
  uv(u?: number, v?: number, offset?: number): ProductSkinRefQuery
1183
1183
  ```
1184
1184
 
1185
- **`ProductSkinRefQuery`**
1186
-
1187
- | Option | Type | Description |
1188
- |--------|------|-------------|
1189
- | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1190
- | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1191
- | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1192
- | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1193
-
1194
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1195
-
1196
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1197
-
1198
1185
  #### `frame()` — Resolve a point/frame on this surface using the builder's side.
1199
1186
 
1200
1187
  ```ts
1201
1188
  frame(query?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame
1202
1189
  ```
1203
1190
 
1204
- **`ProductSurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentU: Vec3`, `tangentV: Vec3`, `matrix: Mat4`, `skin: string`, `representation: ProductSkinRepresentation`
1205
-
1206
- **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
1207
-
1208
- `"exact" | "sampled" | "mixed" | "fallback"`
1209
-
1210
1191
  #### `ribbon()` — Start a conformal ribbon on this skin side.
1211
1192
 
1212
1193
  Path points use side-local `u`/`v` coordinates; this builder supplies the side. The returned ProductRibbonBuilder is already bound to the source skin and can be further configured before build(). Use `widthSamples` >= 3 when the ribbon must visibly wrap over curved product sections instead of behaving like a flat strip.
@@ -1284,11 +1265,7 @@ stations(stations: Array<ProductStationBuilder | ProductStationSpec>): this
1284
1265
 
1285
1266
  `ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
1286
1267
 
1287
- **`ProductProfileKind`**
1288
-
1289
- `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
1290
-
1291
- #### `rails()` — Attach guide rails as ProductSkin IR metadata and diagnostics.
1268
+ #### `rails()` — Attach named guide rails for product-skin construction and downstream surface references.
1292
1269
 
1293
1270
  ```ts
1294
1271
  rails(rails: Record<string, ProductRailSpec>): this
@@ -1306,19 +1283,6 @@ rails(rails: Record<string, ProductRailSpec>): this
1306
1283
  ref(name: string, query: ProductSkinRefQuery): this
1307
1284
  ```
1308
1285
 
1309
- **`ProductSkinRefQuery`**
1310
-
1311
- | Option | Type | Description |
1312
- |--------|------|-------------|
1313
- | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1314
- | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1315
- | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1316
- | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1317
-
1318
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1319
-
1320
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1321
-
1322
1286
  #### `refs()` — Publish multiple named semantic surface refs on the skin.
1323
1287
 
1324
1288
  ```ts
@@ -1337,27 +1301,6 @@ uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery
1337
1301
  material(material: ProductMaterial): this
1338
1302
  ```
1339
1303
 
1340
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1341
-
1342
- **`ShapeMaterialProps`**
1343
-
1344
- | Option | Type | Description |
1345
- |--------|------|-------------|
1346
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1347
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1348
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1349
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1350
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1351
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1352
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1353
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1354
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1355
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1356
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1357
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1358
- | `specularColor?` | `string` | Specular highlight tint. |
1359
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1360
-
1361
1304
  #### `color()` — Apply a simple color override to the lowered skin.
1362
1305
 
1363
1306
  ```ts
@@ -1370,7 +1313,7 @@ color(color: string): this
1370
1313
  edgeLength(value: number): this
1371
1314
  ```
1372
1315
 
1373
- #### `wall()` — Records a target wall thickness; v1 keeps exterior skin lowering sampled and reports wall as a diagnostic.
1316
+ #### `wall()` — Record intended wall thickness for product design metadata. Use explicit shelling when the model needs real inner-wall geometry.
1374
1317
 
1375
1318
  ```ts
1376
1319
  wall(thickness: number): this
@@ -1448,7 +1391,7 @@ circle(diameter: number, options?: { segments?: number; }): this
1448
1391
  custom(sketch: Sketch, width: number, depth: number): this
1449
1392
  ```
1450
1393
 
1451
- #### `crown()` — Stores a semantic crown amount for diagnostics and future rail solving.
1394
+ #### `crown()` — Set the station crown amount for soft product-section intent.
1452
1395
 
1453
1396
  ```ts
1454
1397
  crown(amount: number): this
@@ -1460,14 +1403,6 @@ crown(amount: number): this
1460
1403
  toSpec(): ProductStationSpec
1461
1404
  ```
1462
1405
 
1463
- `ProductStationSpec`: `{ name: string, center: Vec3, profile: ProductStationProfile, crown?: number }`
1464
-
1465
- `ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
1466
-
1467
- **`ProductProfileKind`**
1468
-
1469
- `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
1470
-
1471
1406
  ### `ProductPanelBuilder`
1472
1407
 
1473
1408
  **Properties:**
@@ -1508,27 +1443,6 @@ thickness(thickness: number): this
1508
1443
  material(material: ProductMaterial): this
1509
1444
  ```
1510
1445
 
1511
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1512
-
1513
- **`ShapeMaterialProps`**
1514
-
1515
- | Option | Type | Description |
1516
- |--------|------|-------------|
1517
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1518
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1519
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1520
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1521
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1522
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1523
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1524
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1525
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1526
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1527
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1528
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1529
- | `specularColor?` | `string` | Specular highlight tint. |
1530
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1531
-
1532
1446
  #### `color()` — Apply a simple color override to the panel.
1533
1447
 
1534
1448
  ```ts
@@ -1551,23 +1465,9 @@ attachTo(ref: ProductRefInput, options?: ProductPanelAttachOptions): Shape
1551
1465
 
1552
1466
  `ProductSurfaceRef`
1553
1467
 
1554
- `ProductAttachOptions`: `{ offset?: number, inset?: number }`
1555
1468
 
1556
1469
  `ProductPanelAttachOptions`: `{ at?: Partial<ProductSkinRefQuery>, thickness?: number, material?: ProductMaterial, color?: string }`
1557
1470
 
1558
- **`ProductSkinRefQuery`**
1559
-
1560
- | Option | Type | Description |
1561
- |--------|------|-------------|
1562
- | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1563
- | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1564
- | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1565
- | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1566
-
1567
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1568
-
1569
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1570
-
1571
1471
  ### `ProductRibbonBuilder`
1572
1472
 
1573
1473
  Builder for thin trim, label, grip, and split-line features that bend with a ProductSkin surface.
@@ -1592,68 +1492,21 @@ on(skin: ProductSkin, points: ProductRibbonPathPoint[], options?: ProductRibbonB
1592
1492
 
1593
1493
  `ProductSkinRefQuery | ProductSurfaceRef`
1594
1494
 
1595
- **`ProductSkinRefQuery`**
1495
+ #### `fromRefs()` — Follow explicit surface refs.
1596
1496
 
1597
- | Option | Type | Description |
1598
- |--------|------|-------------|
1599
- | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1600
- | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1601
- | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1602
- | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1497
+ Useful for named refs or paths assembled elsewhere. The builder resolves each ref frame and interpolates between those frames; use on(skin, points) when you need full skin-side sampling between sparse control points.
1603
1498
 
1604
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1499
+ ```ts
1500
+ fromRefs(points: ProductSurfaceRef[], options?: ProductRibbonBuildOptions): this
1501
+ ```
1605
1502
 
1606
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1503
+ #### `width()` Set ribbon width in millimeters.
1607
1504
 
1608
- **`ProductRibbonBuildOptions`** — Options shared by Product.ribbon() builders and Product.surface(...).ribbon(...).
1505
+ ```ts
1506
+ width(width: number): this
1507
+ ```
1609
1508
 
1610
- | Option | Type | Description |
1611
- |--------|------|-------------|
1612
- | `width?` | `number` | Width across the surface in millimeters. |
1613
- | `thickness?` | `number` | Solid thickness outward from the source surface in millimeters. |
1614
- | `offset?` | `number` | Positive clearance between the source surface and the ribbon's inner face. |
1615
- | `samples?` | `number` | Samples along the ribbon path. Higher values bend more smoothly. |
1616
- | `widthSamples?` | `number` | Samples across the ribbon width. Use 3+ to visibly wrap over curved cross-sections. |
1617
- | `resolution?` | `number` | Tessellation resolution passed to the lowered NURBS surface. |
1618
- | `material?` | `ProductMaterial` | Apply a product material preset to the ribbon. |
1619
- | `color?` | `string` | Apply a simple color override. |
1620
-
1621
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1622
-
1623
- **`ShapeMaterialProps`**
1624
-
1625
- | Option | Type | Description |
1626
- |--------|------|-------------|
1627
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1628
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1629
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1630
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1631
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1632
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1633
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1634
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1635
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1636
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1637
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1638
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1639
- | `specularColor?` | `string` | Specular highlight tint. |
1640
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1641
-
1642
- #### `fromRefs()` — Follow explicit surface refs.
1643
-
1644
- Useful for named refs or paths assembled elsewhere. The builder resolves each ref frame and interpolates between those frames; use on(skin, points) when you need full skin-side sampling between sparse control points.
1645
-
1646
- ```ts
1647
- fromRefs(points: ProductSurfaceRef[], options?: ProductRibbonBuildOptions): this
1648
- ```
1649
-
1650
- #### `width()` — Set ribbon width in millimeters.
1651
-
1652
- ```ts
1653
- width(width: number): this
1654
- ```
1655
-
1656
- #### `thickness()` — Set solid thickness outward from the source surface in millimeters.
1509
+ #### `thickness()` Set solid thickness outward from the source surface in millimeters.
1657
1510
 
1658
1511
  ```ts
1659
1512
  thickness(thickness: number): this
@@ -1701,48 +1554,6 @@ color(color: string): this
1701
1554
  build(options?: ProductRibbonBuildOptions): Shape
1702
1555
  ```
1703
1556
 
1704
- #### `buildWithDiagnostics()` — Build a conformal ribbon and return surface-feature diagnostics.
1705
-
1706
- Use this while validating API usage or model fidelity; diagnostics report sampling counts, side-span clamping, lowering mode, and warnings that should be visible in reviews.
1707
-
1708
- ```ts
1709
- buildWithDiagnostics(options?: ProductRibbonBuildOptions): ProductRibbonResult
1710
- ```
1711
-
1712
- **`ProductRibbonResult`** — Shape plus diagnostics returned by ProductRibbonBuilder.buildWithDiagnostics().
1713
- - `shape: Shape` — Lowered conformal ribbon shape.
1714
- - `diagnostics: ProductRibbonDiagnostics` — Sampling and lowering diagnostics for the returned shape.
1715
-
1716
- **`ProductRibbonDiagnostics`** — Diagnostics describing how a conformal ribbon was sampled and lowered.
1717
-
1718
- | Option | Type | Description |
1719
- |--------|------|-------------|
1720
- | `name` | `string` | Ribbon shape name. |
1721
- | `skin?` | `string` | Source skin name when the ribbon follows a ProductSkin directly. |
1722
- | `side?` | `ProductSkinSide` | Source skin side when all path points are on one semantic side. |
1723
- | `pathPointCount` | `number` | Number of control path points supplied before interpolation. |
1724
- | `width` | `number` | Final ribbon width in millimeters. |
1725
- | `thickness` | `number` | Final ribbon solid thickness in millimeters. |
1726
- | `offset` | `number` | Final normal offset from the source surface in millimeters. |
1727
- | `samples` | `number` | Final sample count along the ribbon path. |
1728
- | `widthSamples` | `number` | Final sample count across the ribbon width. |
1729
- | `resolution` | `number` | NURBS tessellation resolution used for the lowered surface. |
1730
- | `lowering` | `"nurbsSurface"` | Lowering primitive used for the ribbon shape. |
1731
- | `expectedFidelity` | `ProductSkinRepresentation` | Expected fidelity inherited from the source skin/ref sampling mode. |
1732
- | `clampedUCount` | `number` | Number of generated width samples clamped to the valid side span. |
1733
- | `maxUClampDistance` | `number` | Largest absolute u-distance lost to side-span clamping. |
1734
- | `warnings` | `string[]` | Non-fatal sampling and lowering warnings. |
1735
-
1736
- **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
1737
-
1738
- `"exact" | "sampled" | "mixed" | "fallback"`
1739
-
1740
- #### `diagnostics()` — Return diagnostics from the most recent build, if this builder has been built.
1741
-
1742
- ```ts
1743
- diagnostics(): ProductRibbonDiagnostics | undefined
1744
- ```
1745
-
1746
1557
  ### `ProductSpoutBuilder`
1747
1558
 
1748
1559
  **Properties:**
@@ -1765,14 +1576,6 @@ from(ref: ProductSurfaceRef): this
1765
1576
  sections(sections: Array<Sketch | ProductStationBuilder | ProductStationSpec>): this
1766
1577
  ```
1767
1578
 
1768
- `ProductStationSpec`: `{ name: string, center: Vec3, profile: ProductStationProfile, crown?: number }`
1769
-
1770
- `ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
1771
-
1772
- **`ProductProfileKind`**
1773
-
1774
- `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
1775
-
1776
1579
  #### `projection()` — Set the projection length along the source ref normal.
1777
1580
 
1778
1581
  ```ts
@@ -1791,27 +1594,6 @@ edgeLength(value: number): this
1791
1594
  material(material: ProductMaterial): this
1792
1595
  ```
1793
1596
 
1794
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1795
-
1796
- **`ShapeMaterialProps`**
1797
-
1798
- | Option | Type | Description |
1799
- |--------|------|-------------|
1800
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1801
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1802
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1803
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1804
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1805
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1806
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1807
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1808
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1809
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1810
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1811
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1812
- | `specularColor?` | `string` | Specular highlight tint. |
1813
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1814
-
1815
1597
  #### `color()` — Apply a simple color override to the spout.
1816
1598
 
1817
1599
  ```ts
@@ -1830,8 +1612,6 @@ build(): Shape
1830
1612
  attach(options?: ProductAttachOptions): Shape
1831
1613
  ```
1832
1614
 
1833
- `ProductAttachOptions`: `{ offset?: number, inset?: number }`
1834
-
1835
1615
  ### `ProductHandleBuilder`
1836
1616
 
1837
1617
  **Properties:**
@@ -1854,12 +1634,6 @@ between(upper: ProductSurfaceRef, lower: Vec3): this
1854
1634
  spine(points: Vec3[] | ProductRailSpec): this
1855
1635
  ```
1856
1636
 
1857
- `ProductRailSpec`: `{ kind: ProductRailKind, points: Vec3[], degree?: number, name?: string }`
1858
-
1859
- **`ProductRailKind`**
1860
-
1861
- `"bezier" | "nurbs" | "polyline"`
1862
-
1863
1637
  #### `grip()` — Set the grip cross-section profile.
1864
1638
 
1865
1639
  ```ts
@@ -1872,27 +1646,6 @@ grip(profile: Sketch): this
1872
1646
  material(material: ProductMaterial): this
1873
1647
  ```
1874
1648
 
1875
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1876
-
1877
- **`ShapeMaterialProps`**
1878
-
1879
- | Option | Type | Description |
1880
- |--------|------|-------------|
1881
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1882
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1883
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1884
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1885
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1886
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1887
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1888
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1889
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1890
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1891
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1892
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1893
- | `specularColor?` | `string` | Specular highlight tint. |
1894
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1895
-
1896
1649
  #### `padMaterial()` — Apply a product material preset to handle landing pads.
1897
1650
 
1898
1651
  ```ts
@@ -1941,181 +1694,6 @@ toShape(): Shape
1941
1694
  toGroup(): ShapeGroup
1942
1695
  ```
1943
1696
 
1944
- ### `ProductRibbonBuilder`
1945
-
1946
- Builder for thin trim, label, grip, and split-line features that bend with a ProductSkin surface.
1947
-
1948
- **Properties:**
1949
-
1950
- | Property | Type | Description |
1951
- |----------|------|-------------|
1952
- | `name` | `string` | — |
1953
-
1954
- **Methods:**
1955
-
1956
- #### `on()` — Follow a ProductSkin with side/u/v path queries or refs.
1957
-
1958
- This is the highest-fidelity mode because every interpolated sample is resolved through ProductSkin.frame(), so the ribbon bends along the selected side as station width/depth changes. All query path points must stay on one side; split side transitions into separate ribbons.
1959
-
1960
- ```ts
1961
- on(skin: ProductSkin, points: ProductRibbonPathPoint[], options?: ProductRibbonBuildOptions): this
1962
- ```
1963
-
1964
- **`ProductRibbonPathPoint`** — Path point for Product.ribbon().on(...): either a side/u/v query or a resolved surface ref.
1965
-
1966
- `ProductSkinRefQuery | ProductSurfaceRef`
1967
-
1968
- **`ProductSkinRefQuery`**
1969
-
1970
- | Option | Type | Description |
1971
- |--------|------|-------------|
1972
- | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1973
- | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1974
- | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1975
- | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1976
-
1977
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1978
-
1979
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1980
-
1981
- **`ProductRibbonBuildOptions`** — Options shared by Product.ribbon() builders and Product.surface(...).ribbon(...).
1982
-
1983
- | Option | Type | Description |
1984
- |--------|------|-------------|
1985
- | `width?` | `number` | Width across the surface in millimeters. |
1986
- | `thickness?` | `number` | Solid thickness outward from the source surface in millimeters. |
1987
- | `offset?` | `number` | Positive clearance between the source surface and the ribbon's inner face. |
1988
- | `samples?` | `number` | Samples along the ribbon path. Higher values bend more smoothly. |
1989
- | `widthSamples?` | `number` | Samples across the ribbon width. Use 3+ to visibly wrap over curved cross-sections. |
1990
- | `resolution?` | `number` | Tessellation resolution passed to the lowered NURBS surface. |
1991
- | `material?` | `ProductMaterial` | Apply a product material preset to the ribbon. |
1992
- | `color?` | `string` | Apply a simple color override. |
1993
-
1994
- `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1995
-
1996
- **`ShapeMaterialProps`**
1997
-
1998
- | Option | Type | Description |
1999
- |--------|------|-------------|
2000
- | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
2001
- | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
2002
- | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
2003
- | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
2004
- | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
2005
- | `wireframe?` | `boolean` | Render as wireframe. Default: false |
2006
- | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
2007
- | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
2008
- | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
2009
- | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
2010
- | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
2011
- | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
2012
- | `specularColor?` | `string` | Specular highlight tint. |
2013
- | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
2014
-
2015
- #### `fromRefs()` — Follow explicit surface refs.
2016
-
2017
- Useful for named refs or paths assembled elsewhere. The builder resolves each ref frame and interpolates between those frames; use on(skin, points) when you need full skin-side sampling between sparse control points.
2018
-
2019
- ```ts
2020
- fromRefs(points: ProductSurfaceRef[], options?: ProductRibbonBuildOptions): this
2021
- ```
2022
-
2023
- #### `width()` — Set ribbon width in millimeters.
2024
-
2025
- ```ts
2026
- width(width: number): this
2027
- ```
2028
-
2029
- #### `thickness()` — Set solid thickness outward from the source surface in millimeters.
2030
-
2031
- ```ts
2032
- thickness(thickness: number): this
2033
- ```
2034
-
2035
- #### `offset()` — Set positive clearance between the source surface and the ribbon's inner face.
2036
-
2037
- ```ts
2038
- offset(offset: number): this
2039
- ```
2040
-
2041
- #### `samples()` — Set samples along the path.
2042
-
2043
- ```ts
2044
- samples(samples: number): this
2045
- ```
2046
-
2047
- #### `widthSamples()` — Set samples across the width. Use 3+ to bend over curved cross-sections.
2048
-
2049
- ```ts
2050
- widthSamples(samples: number): this
2051
- ```
2052
-
2053
- #### `resolution()` — Set NURBS tessellation resolution.
2054
-
2055
- ```ts
2056
- resolution(resolution: number): this
2057
- ```
2058
-
2059
- #### `material()` — Apply a product material preset.
2060
-
2061
- ```ts
2062
- material(material: ProductMaterial): this
2063
- ```
2064
-
2065
- #### `color()` — Apply a simple color override.
2066
-
2067
- ```ts
2068
- color(color: string): this
2069
- ```
2070
-
2071
- #### `build()` — Build a conformal ribbon as a thin NURBS surface solid.
2072
-
2073
- ```ts
2074
- build(options?: ProductRibbonBuildOptions): Shape
2075
- ```
2076
-
2077
- #### `buildWithDiagnostics()` — Build a conformal ribbon and return surface-feature diagnostics.
2078
-
2079
- Use this while validating API usage or model fidelity; diagnostics report sampling counts, side-span clamping, lowering mode, and warnings that should be visible in reviews.
2080
-
2081
- ```ts
2082
- buildWithDiagnostics(options?: ProductRibbonBuildOptions): ProductRibbonResult
2083
- ```
2084
-
2085
- **`ProductRibbonResult`** — Shape plus diagnostics returned by ProductRibbonBuilder.buildWithDiagnostics().
2086
- - `shape: Shape` — Lowered conformal ribbon shape.
2087
- - `diagnostics: ProductRibbonDiagnostics` — Sampling and lowering diagnostics for the returned shape.
2088
-
2089
- **`ProductRibbonDiagnostics`** — Diagnostics describing how a conformal ribbon was sampled and lowered.
2090
-
2091
- | Option | Type | Description |
2092
- |--------|------|-------------|
2093
- | `name` | `string` | Ribbon shape name. |
2094
- | `skin?` | `string` | Source skin name when the ribbon follows a ProductSkin directly. |
2095
- | `side?` | `ProductSkinSide` | Source skin side when all path points are on one semantic side. |
2096
- | `pathPointCount` | `number` | Number of control path points supplied before interpolation. |
2097
- | `width` | `number` | Final ribbon width in millimeters. |
2098
- | `thickness` | `number` | Final ribbon solid thickness in millimeters. |
2099
- | `offset` | `number` | Final normal offset from the source surface in millimeters. |
2100
- | `samples` | `number` | Final sample count along the ribbon path. |
2101
- | `widthSamples` | `number` | Final sample count across the ribbon width. |
2102
- | `resolution` | `number` | NURBS tessellation resolution used for the lowered surface. |
2103
- | `lowering` | `"nurbsSurface"` | Lowering primitive used for the ribbon shape. |
2104
- | `expectedFidelity` | `ProductSkinRepresentation` | Expected fidelity inherited from the source skin/ref sampling mode. |
2105
- | `clampedUCount` | `number` | Number of generated width samples clamped to the valid side span. |
2106
- | `maxUClampDistance` | `number` | Largest absolute u-distance lost to side-span clamping. |
2107
- | `warnings` | `string[]` | Non-fatal sampling and lowering warnings. |
2108
-
2109
- **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
2110
-
2111
- `"exact" | "sampled" | "mixed" | "fallback"`
2112
-
2113
- #### `diagnostics()` — Return diagnostics from the most recent build, if this builder has been built.
2114
-
2115
- ```ts
2116
- diagnostics(): ProductRibbonDiagnostics | undefined
2117
- ```
2118
-
2119
1697
  ### `CylinderCarrier`
2120
1698
 
2121
1699
  **Properties:**
@@ -2247,12 +1825,6 @@ bounds(): SurfaceBounds
2247
1825
  offset(distance: number): CylinderCarrier
2248
1826
  ```
2249
1827
 
2250
- #### `diagnostics()`
2251
-
2252
- ```ts
2253
- diagnostics(): SurfaceDiagnostic[]
2254
- ```
2255
-
2256
1828
  #### `mirrorCoordinate()`
2257
1829
 
2258
1830
  ```ts
@@ -2372,12 +1944,6 @@ bounds(): SurfaceBounds
2372
1944
  offset(distance: number): PlaneCarrier
2373
1945
  ```
2374
1946
 
2375
- #### `diagnostics()`
2376
-
2377
- ```ts
2378
- diagnostics(): SurfaceDiagnostic[]
2379
- ```
2380
-
2381
1947
  #### `mirrorCoordinate()`
2382
1948
 
2383
1949
  ```ts
@@ -2402,10 +1968,6 @@ mirrorCoordinate(coordinate: PlaneSurfaceCoordinate): PlaneSurfaceCoordinate
2402
1968
  surface(side: ProductSkinSide): ProductSkinCarrier
2403
1969
  ```
2404
1970
 
2405
- **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
2406
-
2407
- `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
2408
-
2409
1971
  #### [`path()`](/docs/sketch#path)
2410
1972
 
2411
1973
  ```ts
@@ -2494,16 +2056,6 @@ bounds(): SurfaceBounds
2494
2056
  offset(distance: number): ProductSkinCarrier
2495
2057
  ```
2496
2058
 
2497
- #### `diagnostics()`
2498
-
2499
- ```ts
2500
- diagnostics(): SurfaceDiagnostic[]
2501
- ```
2502
-
2503
- **`SurfaceDiagnostic`**
2504
- - `code?: SurfaceDiagnosticCode` — Stable machine-readable repair hook. Messages may change; codes should not.
2505
- - Also: `category: "carrier" | "path" | "region" | "member" | "feature" | "join" | "compiler", level: "info" | "warning" | "error", message: string, subject?: string`
2506
-
2507
2059
  #### `mirrorCoordinate()`
2508
2060
 
2509
2061
  ```ts
@@ -2646,12 +2198,6 @@ withHole(name: string, input: SurfaceBandHoleInput): SurfaceBand<C>
2646
2198
  holes(): SurfaceBandHoleRegion[]
2647
2199
  ```
2648
2200
 
2649
- #### `diagnostics()`
2650
-
2651
- ```ts
2652
- diagnostics(samples?: number): SurfaceDiagnostic[]
2653
- ```
2654
-
2655
2201
  ### `SurfaceBodyBuilder`
2656
2202
 
2657
2203
  **Properties:**
@@ -2692,18 +2238,6 @@ autoJoinAtSharedAnchors(): this
2692
2238
  build(): Shape | ShapeGroup
2693
2239
  ```
2694
2240
 
2695
- #### `buildWithDiagnostics()`
2696
-
2697
- ```ts
2698
- buildWithDiagnostics(): SurfaceBodyBuildResult
2699
- ```
2700
-
2701
- #### `buildDebug()`
2702
-
2703
- ```ts
2704
- buildDebug(): SurfaceBodyBuildResult
2705
- ```
2706
-
2707
2241
  ### `SurfaceMemberBuilder`
2708
2242
 
2709
2243
  #### `plate()`
@@ -2766,7 +2300,7 @@ cutout(name: string, feature: MemberFeature | RoundedSlotBuilder): this
2766
2300
  counterbore(name: string, feature: MemberFeature | CounterboreBuilder): this
2767
2301
  ```
2768
2302
 
2769
- #### `anchorAt()` — Add a named anchor at a carrier surface coordinate for diagnostics, debug views, and future named-anchor joins.
2303
+ #### `anchorAt()` — Add a named anchor at a carrier surface coordinate for explicit member joins.
2770
2304
 
2771
2305
  ```ts
2772
2306
  anchorAt(name: string, coordinate: C | SurfaceAnchor<C>): this
@@ -2814,18 +2348,6 @@ autoJoinAtSharedAnchors(): SurfaceBodyBuilder
2814
2348
  build(): Shape | ShapeGroup
2815
2349
  ```
2816
2350
 
2817
- #### `buildWithDiagnostics()`
2818
-
2819
- ```ts
2820
- buildWithDiagnostics(): SurfaceBodyBuildResult
2821
- ```
2822
-
2823
- #### `buildDebug()`
2824
-
2825
- ```ts
2826
- buildDebug(): SurfaceBodyBuildResult
2827
- ```
2828
-
2829
2351
  ### `SurfaceJoinBuilder`
2830
2352
 
2831
2353
  #### `betweenAnchors()` — Select named anchors on the source and target members before lowering this join.
@@ -2908,7 +2430,6 @@ toFeature(name?: string): MemberFeature
2908
2430
 
2909
2431
  - `Edge(options: BlendEdgeOptions): Shape`
2910
2432
  - `Surface(options: BlendSurfaceOptions): Shape`
2911
- - `CornerY(options: BlendCornerYOptions): Shape` — Current implementation uses continuity-controlled edge fillets on solid edges. It does not yet provide a dedicated open-sheet or multi-patch Y-corner solver. Follow progress: https://github.com/KoStard/forgecad-private/issues/162
2912
2433
 
2913
2434
  ### `Analysis`
2914
2435
 
@@ -2947,15 +2468,12 @@ toFeature(name?: string): MemberFeature
2947
2468
  - `cylinder(name: string): CylinderCarrier` — Create an analytic cylinder carrier for bottles, limbs, tubes, guards, and cuffs.
2948
2469
  - `plane(name: string): PlaneCarrier` — Create an analytic plane carrier for plates and local flat construction surfaces.
2949
2470
  - `productSkin(skin: ProductSkin): ProductSkinCarrier` — Adapt an existing ProductSkin into the general surface-member carrier protocol.
2950
- - `mesh(name: string): never` — Reserved stub for future parameterized mesh carriers; arbitrary mesh parameterization is not implemented yet.
2951
- - `scan(name: string): never` — Reserved stub for future scan/body-fit carriers; arbitrary scan parameterization is not implemented yet.
2952
2471
 
2953
2472
  ### `SurfaceMembers`
2954
2473
 
2955
2474
  - `Body(name: string): SurfaceBodyBuilder` — Start a surface-member body builder for straps, inlays, guards, braces, cuffs, and similar physical members that live on a carrier surface.
2956
2475
  - `Band: typeof SurfaceBand`
2957
2476
  - `band<C extends SurfaceCoordinate>(path: SurfacePath<C> | SurfacePathBuilder<C>, width: WidthProfile, cap?: SurfaceBandCap): SurfaceBand<C>`
2958
- - `compileMember<C extends SurfaceCoordinate>(input: Omit<SurfaceMemberSpec<C>, "section"> & { section: MemberSection | MemberSectionInput; }): CompiledSurfaceMember`
2959
2477
 
2960
2478
  ### `Slot`
2961
2479