forgecad 0.9.4 → 0.9.5

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 (82) hide show
  1. package/dist/assets/{AdminPage-jwoEgwE_.js → AdminPage-uTtcSXtn.js} +1 -1
  2. package/dist/assets/{BlogPage-Ck7g3ue2.js → BlogPage-DYJMjWx3.js} +1 -1
  3. package/dist/assets/{DocsPage-9WaRC14b.js → DocsPage-C58f0K5v.js} +1 -6
  4. package/dist/assets/{EditorApp-Dja2jMmW.js → EditorApp-DNH1TEz1.js} +282 -62
  5. package/dist/assets/{EmbedViewer-37_PfMwv.js → EmbedViewer-CMXWA2LX.js} +2 -2
  6. package/dist/assets/{LandingPageProofDriven-CO8WL0CY.js → LandingPageProofDriven-CAu2OZFn.js} +1 -1
  7. package/dist/assets/{PricingPage-DADKGuOa.js → PricingPage-BIgW7m3X.js} +1 -1
  8. package/dist/assets/{SettingsPage-DKKI4W49.js → SettingsPage-N1l1tMXO.js} +1 -1
  9. package/dist/assets/{app-CwI02pTA.js → app-CFy7g5WP.js} +74 -12
  10. package/dist/assets/cli/{render-Kw5hLEcL.js → render-BrVVdj_T.js} +453 -41
  11. package/dist/assets/{evalWorker-D6ub3kfS.js → evalWorker-c_SB9gg3.js} +2057 -446
  12. package/dist/assets/{manifold-lru0jwVw.js → manifold-CRoBhJKH.js} +2 -2
  13. package/dist/assets/{manifold-CwDdMKyc.js → manifold-Cjk7WhRs.js} +1 -1
  14. package/dist/assets/{manifold-DTvmxSDf.js → manifold-Dp6pvFr6.js} +1 -1
  15. package/dist/assets/{renderSceneState-tvtNKNRi.js → renderSceneState-3DfsSASX.js} +1 -1
  16. package/dist/assets/{reportWorker-DeqktDGt.js → reportWorker-BLkuIoS8.js} +2052 -443
  17. package/dist/assets/{sectionPlaneMath-C8N0w8o3.js → sectionPlaneMath-CykEnkvQ.js} +2258 -518
  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/generated/assembly.md +8 -3
  24. package/dist/docs-raw/generated/concepts.md +44 -41
  25. package/dist/docs-raw/generated/core.md +97 -47
  26. package/dist/docs-raw/generated/curves.md +6 -580
  27. package/dist/docs-raw/generated/lib.md +40 -3
  28. package/dist/docs-raw/generated/output.md +6 -1
  29. package/dist/docs-raw/generated/sdf.md +50 -4
  30. package/dist/docs-raw/generated/viewport.md +1 -9
  31. package/dist/docs-raw/guides/inspection-bundles.md +31 -6
  32. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -0
  33. package/dist/docs-raw/skills/forgecad-image-replicator.md +3 -1
  34. package/dist/docs-raw/skills/forgecad-make-a-model.md +48 -4
  35. package/dist/docs-raw/skills/forgecad-render-inspect.md +3 -1
  36. package/dist/docs-raw/skills/forgecad-visual-spec.md +2 -0
  37. package/dist/docs-raw/skills/forgecad.md +2 -1
  38. package/dist/docs-raw/skills/index.md +0 -1
  39. package/dist/index.html +1 -1
  40. package/dist/sitemap.xml +6 -6
  41. package/dist-cli/blender/render.py +43 -8
  42. package/dist-cli/forgecad.js +4941 -1758
  43. package/dist-cli/forgecad.js.map +1 -1
  44. package/dist-skill/CONTEXT.md +255 -656
  45. package/dist-skill/SKILL-dev.md +2 -1
  46. package/dist-skill/SKILL.md +2 -1
  47. package/dist-skill/docs/API/core/concepts.md +11 -1
  48. package/dist-skill/docs/CLI.md +64 -13
  49. package/dist-skill/docs/generated/assembly.md +8 -3
  50. package/dist-skill/docs/generated/core.md +97 -47
  51. package/dist-skill/docs/generated/curves.md +6 -580
  52. package/dist-skill/docs/generated/lib.md +40 -3
  53. package/dist-skill/docs/generated/output.md +6 -1
  54. package/dist-skill/docs/generated/sdf.md +50 -4
  55. package/dist-skill/docs/generated/viewport.md +1 -9
  56. package/dist-skill/docs/guides/inspection-bundles.md +31 -6
  57. package/dist-skill/docs-dev/API/core/concepts.md +11 -1
  58. package/dist-skill/docs-dev/CLI.md +64 -13
  59. package/dist-skill/docs-dev/generated/assembly.md +8 -3
  60. package/dist-skill/docs-dev/generated/core.md +97 -47
  61. package/dist-skill/docs-dev/generated/curves.md +6 -580
  62. package/dist-skill/docs-dev/generated/lib.md +40 -3
  63. package/dist-skill/docs-dev/generated/output.md +6 -1
  64. package/dist-skill/docs-dev/generated/sdf.md +50 -4
  65. package/dist-skill/docs-dev/generated/viewport.md +1 -9
  66. package/dist-skill/docs-dev/guides/inspection-bundles.md +31 -6
  67. package/dist-skill/library/README.md +0 -1
  68. package/dist-skill/library/forgecad-blockout-model/SKILL.md +1 -0
  69. package/dist-skill/library/forgecad-image-replicator/SKILL.md +3 -1
  70. package/dist-skill/library/forgecad-make-a-model/SKILL.md +48 -4
  71. package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
  72. package/dist-skill/library/forgecad-visual-spec/SKILL.md +2 -0
  73. package/examples/api/drive-wheel-regions.forge.js +43 -0
  74. package/examples/api/sdf-circular-array-knurling.forge.js +19 -0
  75. package/examples/api/sdf-pattern2d-ceramic-ripple-set.forge.js +83 -0
  76. package/examples/api/sdf-pattern2d-grip-tread.forge.js +72 -0
  77. package/examples/api/sdf-pattern2d-orbital-jewelry.forge.js +62 -0
  78. package/examples/api/sdf-surface-basket-weave.forge.js +67 -0
  79. package/examples/api/sector-gear-body.forge.js +34 -0
  80. package/package.json +1 -1
  81. package/dist/docs-raw/skills/forgecad-api-dogfood.md +0 -130
  82. package/dist-skill/library/forgecad-api-dogfood/SKILL.md +0 -125
@@ -213,7 +213,6 @@ For the full command reference, see [ForgeCAD CLI](../CLI.md).
213
213
  | `forgecad-blockout-model` | Making rough concept geometry to explore proportions, layout, motion envelope, or spatial intuition before detailed modeling. |
214
214
  | `forgecad-image-replicator` | Recreating an object from reference images as real ForgeCAD geometry through camera-calibrated render/compare/iterate loops. |
215
215
  | `forgecad-render-inspect` | Generating and interpreting `forgecad render inspect` bundles for collision, wall thickness, connectivity, masks, depth, normals, and sections. |
216
- | `forgecad-api-dogfood` | Building a real model while recording API friction and concrete improvement proposals. |
217
216
  | `forgecad-visual-spec` | Producing builder-honest image prompts from a concrete model, HLD, LLD, or build brief. |
218
217
  | `forgecad-project` | Managing forgecad.io projects from the CLI: init, clone, pull, push, file commands, members, publish, and shares. |
219
218
 
@@ -34,7 +34,7 @@ Top-level declarations such as `const bom = ...`, `let scene = ...`, or `class S
34
34
 
35
35
  - Scripts re-execute on every parameter change (400ms debounce)
36
36
  - Geometry operations are **immutable** — shapes, sketches, groups, imported assemblies, and wood boards return new values instead of modifying in place
37
- - Must return one of: `Shape`, `Sketch`, `ShapeGroup`, `Assembly`, `SolvedAssembly`, `SdfShape`, `Array` of renderables, `Array` of `{ name, shape?, sketch?, group?, color? }`, or a **metadata object** (see below)
37
+ - Must return one of: `Shape`, `Sketch`, `ShapeGroup`, `Assembly`, `SolvedAssembly`, `SdfShape`, `Array` of renderables, `Array` of `{ name, tags?, shape?, sketch?, group?, color? }`, or a **metadata object** (see below)
38
38
 
39
39
  Top-level assembly scripts can return an unsolved `Assembly` directly; ForgeCAD solves it at default joint values for display. Return `assembly.solve(state)` when you want a specific pose. Do not call `.toGroup()` just to make an assembly render — use `.toGroup()` only when you specifically need `ShapeGroup` composition, group-style transforms, or named-child lookup.
40
40
 
@@ -67,6 +67,16 @@ return {
67
67
  };
68
68
  ```
69
69
 
70
+ Named return objects and named `group(...)` children can include `tags`. Tags are viewport metadata: they do not affect geometry, exports, face labels, or BOM rows, but the command palette can hide, show only, or focus every object with a selected tag.
71
+
72
+ ```javascript
73
+ return [
74
+ { name: 'Base Plate', tags: ['printed', 'structural'], shape: base },
75
+ { name: 'M4 Bolt A', tags: 'fastener', shape: boltA },
76
+ { name: 'M4 Bolt B', tags: 'fastener', shape: boltB },
77
+ ];
78
+ ```
79
+
70
80
  ## Coordinate System
71
81
 
72
82
  Z-up right-handed: X = left/right, Y = forward/back, Z = up/down.
@@ -113,12 +113,14 @@ forgecad run examples/constraints/06-complex-spectrogram.forge.js --solver-debug
113
113
 
114
114
  ### `forgecad render`
115
115
 
116
- Render a Forge scene. Use a subcommand — `3d`, `inspect`, `section`, `wireframe`, `sketch`, or `hq`.
116
+ Render a Forge scene. Use a subcommand — `3d`, `inspect`, `views`, `section`, `wireframe`, `sketch`, or `hq`.
117
117
 
118
118
  `forgecad render` is a group of rendering subcommands. Pick one based on what you want:
119
119
 
120
120
  - `render 3d` — standard viewport PNG, the usual way to visually verify geometry
121
121
  - `render inspect` — machine-readable inspection bundle with geometry channels and a manifest
122
+ - `render inspect channels` — list supported inspection channels
123
+ - `render views` — list named cameras declared with `scene({ views })`
122
124
  - `render wireframe` — edges only, no shading
123
125
  - `render section` — 2D cross-section cut by a plane (SVG or PNG)
124
126
  - `render sketch` — 2D sketch script to PNG
@@ -127,6 +129,8 @@ Render a Forge scene. Use a subcommand — `3d`, `inspect`, `section`, `wirefram
127
129
  ```bash
128
130
  forgecad render 3d examples/cup.forge.js
129
131
  forgecad render inspect examples/api/static-assembly-connectors.forge.js --channels rgb,mask
132
+ forgecad render inspect channels
133
+ forgecad render views examples/cup.forge.js
130
134
  forgecad render wireframe examples/cup.forge.js
131
135
  forgecad render section examples/furniture/01-table.forge.js --plane XZ
132
136
  forgecad render hq examples/cup.forge.js --preset dramatic
@@ -138,7 +142,7 @@ Render a Forge scene to PNG using the real viewport renderer.
138
142
 
139
143
  Launches a headless Chrome instance, renders the scene with the same WebGL viewport as the editor, and saves a PNG. The output path defaults to `<script-name>.png` next to the input file.
140
144
 
141
- Use `--focus` to isolate specific parts (hides everything else) or `--hide` to remove clutter like mock objects. The `--view` flag selects a named camera declared in `scene({ views })`. The `--camera` flag accepts built-in views (`front`, `top`, `iso`), `azimuth:elevation` angles, or an exact `proj/pos/target/up/fov` camera spec — pass `--camera` multiple times to render several viewpoints in one run.
145
+ Use `--focus` to isolate specific parts (hides everything else) or `--hide` to remove clutter like mock objects. The `--view` flag selects a named camera declared in `scene({ views })`. The `--camera` flag accepts built-in views (`front`, `top`, `iso`), `azimuth:elevation` angles, or an exact `proj/pos/target/up/fov` camera spec — pass `--camera` multiple times to render several viewpoints in one run. Use `--camera-json <file>` or `--scene <file>` for exact reproducible viewport cameras without shell escaping.
142
146
 
143
147
  Use `--edges=<off|thin|bold>` to control the edge overlay. For a pure wireframe look, use `render wireframe` instead.
144
148
 
@@ -152,16 +156,29 @@ forgecad render 3d examples/cup.forge.js --hide "wall,bolt"
152
156
  forgecad render 3d model.forge.js --view hero
153
157
  forgecad render 3d model.forge.js --camera 45:30
154
158
  forgecad render 3d model.forge.js --camera "proj=perspective;pos=200,-160,120;target=0,0,20;up=0,0,1;fov=38"
159
+ forgecad render 3d model.forge.js --camera-json camera.json
160
+ forgecad render 3d model.forge.js --scene scene.json
155
161
  forgecad render 3d model.forge.js --camera front --camera side
156
162
  forgecad render 3d model.forge.js --edges bold
157
163
  forgecad render 3d model.forge.js --edges off
158
164
  ```
159
165
 
166
+ ### `forgecad render views`
167
+
168
+ List named camera views declared by a model with `scene({ views })`.
169
+
170
+ Runs the script headlessly and prints every named render view with an exact camera spec that can be passed back to `render 3d`, `render hq`, or `capture`.
171
+
172
+ ```bash
173
+ forgecad render views model.forge.js
174
+ forgecad render views model.forge.js --json
175
+ ```
176
+
160
177
  ### `forgecad render inspect`
161
178
 
162
179
  Render a machine-readable inspection bundle with geometry channels and a manifest.
163
180
 
164
- Launches the headless viewport renderer and writes a directory bundle for agent and automation workflows. Every channel is opt-in with `--channels`; there is no default bundle. Selected channels emit canonical `front`, `right`, `top`, and `iso` views for RGB, depth, normals, object masks, physical connectivity, rooted component distance, collisions, and wall thickness, or a principal-plane section atlas, plus a root `manifest.json` with scene metadata, filters, object visibility, and relative file paths.
181
+ Launches the headless viewport renderer and writes a directory bundle for agent and automation workflows. Every channel is opt-in with `--channels`; there is no default bundle. Selected channels emit canonical `front`, `right`, `top`, and `iso` views for RGB, depth, normals, surface roughness, object masks, physical connectivity, rooted component distance, collisions, and wall thickness, or a principal-plane section atlas, plus a root `manifest.json` with scene metadata, filters, object visibility, and relative file paths.
165
182
 
166
183
  Use `--focus` to isolate specific parts or hide mocks, and `--hide` to remove named clutter. Output defaults to `<script-name>-inspect/` next to the input file.
167
184
 
@@ -173,6 +190,15 @@ forgecad render inspect examples/api/static-assembly-connectors.forge.js out/ben
173
190
  forgecad render inspect examples/api/static-assembly-connectors.forge.js --channels rgb,mask,collisions --hide "Bench.Slat0" --force
174
191
  ```
175
192
 
193
+ ### `forgecad render inspect channels`
194
+
195
+ List supported inspection bundle channels.
196
+
197
+ ```bash
198
+ forgecad render inspect channels
199
+ forgecad render inspect channels --json
200
+ ```
201
+
176
202
  ### `forgecad render wireframe`
177
203
 
178
204
  Render a Forge scene as a wireframe (edges only, no shading).
@@ -190,13 +216,15 @@ High-quality render via Blender Cycles — path-traced, HDRI, material presets.
190
216
 
191
217
  Exports the scene to Blender and renders with Cycles (path tracer). Requires Blender installed and on PATH.
192
218
 
193
- Choose a `--preset` for the look: `studio` (neutral product shot), `dramatic` (high-contrast), `clay` (matte, no color), `glass`, `metallic`, `toon`, `xray`, `normals`, `silhouette`, and more. Control quality vs speed with `--samples` (default 256). Use `--transparent` for a transparent background (compositing-ready).
219
+ Choose a `--preset` for the look: `studio` (neutral product shot), `dramatic` (high-contrast), `clay` (matte, no color), `glass`, `metallic`, `toon`, `xray`, `normals`, `silhouette`, and more. Control quality vs speed with `--samples` (default 256). Use `--view`, `--camera`, `--camera-json`, or `--scene <file>` for still camera control, matching `render 3d`. Use `--transparent` for a transparent background (compositing-ready).
194
220
 
195
221
  Output defaults to `<script-name>-hq.png`. Great for documentation, marketing renders, and social media.
196
222
 
197
223
  ```bash
198
224
  forgecad render hq examples/cup.forge.js
199
225
  forgecad render hq examples/cup.forge.js hero.png --preset dramatic --samples 1024
226
+ forgecad render hq examples/cup.forge.js hero.png --view hero
227
+ forgecad render hq examples/cup.forge.js hero.png --camera-json camera.json
200
228
  forgecad render hq examples/cup.forge.js --preset clay --size 2048
201
229
  forgecad render hq examples/cup.forge.js --transparent --preset glass
202
230
  ```
@@ -205,16 +233,20 @@ forgecad render hq examples/cup.forge.js --transparent --preset glass
205
233
 
206
234
  Animated orbit or joint playback.
207
235
 
208
- Renders an animated sequence by either orbiting the camera around the model or playing back a `jointsView` animation. Use `--capture orbit` (default) for a turntable rotation, `--capture animation --animation <name>` to play a named joints clip, or `--capture section-sweep` to move a clipping plane through the model. Supports `--cut-plane` to animate with a static cross-section visible.
236
+ Renders an animated sequence by either orbiting the camera around the model or playing back a `jointsView` animation. Use `--capture orbit` (default) for a turntable rotation, `--capture animation --animation <name>` to play a named joints clip, or `--capture section-sweep` to move a clipping plane through the model. Supports `--cut-plane` to animate with a static cross-section visible. Use `--view`, `--camera`, `--camera-json`, or `--scene <file>` to choose the orbit base camera or the fixed camera for animations and section sweeps.
209
237
 
210
238
  ```bash
211
239
  forgecad capture gif examples/cup.forge.js
212
240
  forgecad capture gif examples/3d-printer.forge.js out/section.gif --cut-plane "Front Section"
213
241
  forgecad capture gif model.forge.js out/raw.gif --param "Output=raw-sdf"
242
+ forgecad capture gif model.forge.js out/front.gif --camera front
243
+ forgecad capture gif model.forge.js out/hero.gif --view hero
214
244
  forgecad capture gif examples/3d-printer.forge.js out/sweep.gif --capture section-sweep --sweep-plane YZ
215
245
  forgecad capture mp4 examples/cup.forge.js
216
246
  forgecad capture mp4 examples/api/runtime-joints-view.forge.js out/step.mp4 --capture animation --animation Step
217
247
  forgecad capture mp4 model.forge.js out/raw.mp4 --param "Output=raw-sdf"
248
+ forgecad capture mp4 model.forge.js out/front.mp4 --camera front
249
+ forgecad capture mp4 model.forge.js out/hero.mp4 --view hero
218
250
  forgecad capture mp4 examples/3d-printer.forge.js out/sweep.mp4 --capture section-sweep --sweep-plane YZ --sweep-frames 180
219
251
  ```
220
252
 
@@ -247,18 +279,22 @@ forgecad render section examples/furniture/01-table.forge.js out/bold.svg --edge
247
279
  | `--focus <names>` | Focus: no arg hides mocks; comma-separated names shows only those |
248
280
  | `--hide <names>` | Hide comma-separated object names |
249
281
  | `--camera <front\|back\|side\|right\|top\|iso\|az:el\|az:el:dist\|spec>` | Camera preset, spherical (az:el), or full spec such as `proj=perspective;pos=x,y,z;target=x,y,z;up=x,y,z;fov=45`. Repeatable. |
282
+ | `--camera-json <file>` | Exact viewport camera JSON file |
250
283
  | `--view <name>` | Named camera view declared by the model with scene({ views }) |
251
284
  | `--size <px>` | Image size in pixels |
252
- | `--scene <json>` | Viewport scene state JSON |
285
+ | `--scene <json\|file>` | Viewport scene state JSON or JSON file |
253
286
  | `--background <color>` | Canvas background override |
254
287
  | `--render-mode <solid\|wireframe>` | Shaded solid (default) or wireframe only |
255
- | `--edges <off\|thin\|bold>` | Edge overlay preset in solid mode (default: thin) |
288
+ | `--edges <off\|thin\|bold>` | Edge overlay preset in solid mode (default: off) |
256
289
  | `--render-style <classic\|studio\|fast\|glass>` | Visual render style (default: classic) |
257
290
  | `--port <n>` | Vite dev server port |
291
+ | `--fresh-server` | Start a fresh renderer instead of reusing an existing one |
258
292
  | `--chrome-path <path>` | Chrome or Chromium executable path |
259
293
  | `--output <path>` | Output file path |
260
- | `--channels <rgb,depth,normals,mask,connectivity,distance,collisions,thickness,section>` | Required inspection channels to emit; no default |
261
- | `--quality <default\|live\|high>` | Mesh/render quality |
294
+ | `--json` | Print machine-readable JSON |
295
+ | `--quality <default\|live\|high>` | Mesh quality preset |
296
+ | `--backend <manifold\|occt\|truck>` | Geometry backend |
297
+ | `--channels <rgb,depth,normals,roughness,mask,connectivity,distance,collisions,thickness,section>` | Required inspection channels to emit; no default |
262
298
  | `--force` | Replace an existing bundle directory |
263
299
  | `--min-thickness <mm>` | Critical thickness threshold in model units |
264
300
  | `--warn-thickness <mm>` | Warning thickness threshold in model units |
@@ -276,7 +312,6 @@ forgecad render section examples/furniture/01-table.forge.js out/bold.svg --edge
276
312
  | `--frames <n>` | Video frames per revolution |
277
313
  | `--fps <n>` | Video frame rate |
278
314
  | `--pitch <deg>` | Camera pitch angle in degrees |
279
- | `--backend <manifold\|occt\|truck>` | Geometry backend |
280
315
  | `--format <gif\|mp4>` | Output format |
281
316
  | `--capture <orbit\|animation\|section-sweep>` | Capture preset |
282
317
  | `--animation <name>` | Named jointsView animation clip |
@@ -330,6 +365,7 @@ forgecad cut-list examples/api/sheet-stock-cut-list.forge.js
330
365
  forgecad export cutting-layout examples/api/sheet-stock-cut-list.forge.js --sheet-width 420 --sheet-height 594 --kerf 3
331
366
 
332
367
  # 3D printing
368
+ forgecad check print bracket.forge.js
333
369
  forgecad export stl bracket.forge.js
334
370
  forgecad export 3mf bracket.forge.js --quality high
335
371
 
@@ -494,11 +530,26 @@ forgecad skill one-file ~/Desktop/forgecad-context.md
494
530
  forgecad skill flattened-files ~/Desktop/forgecad-skills
495
531
  ```
496
532
 
497
- > **Workflow:** Agent writes the model -> `forgecad run` validates it -> `forgecad render inspect` produces evidence -> `forgecad check params` sweeps the parameter range -> export ships the result. All in the terminal.
533
+ > **Workflow:** Agent writes the model -> `forgecad run` validates it -> `forgecad check print` catches printability risks -> `forgecad render inspect` produces visual evidence -> `forgecad check params` sweeps parameter robustness -> export ships the result. All in the terminal.
498
534
 
499
535
  ## Validation
500
536
 
501
- Test parameter ranges and run invariant suites.
537
+ Check printability, test parameter ranges, and run invariant suites.
538
+
539
+ ### `forgecad check print`
540
+
541
+ Run fast 3D-print readiness checks for collisions, mesh health, walls, overhangs, and bed contact.
542
+
543
+ Runs a Forge script with the headless kernel and emits a slicer-adjacent printability report without launching a browser. The check is designed for agents: JSON is stable, failures name the specific print risk, and the default profile is conservative for FDM PLA on a 0.4mm nozzle.
544
+
545
+ Checks include script `verify.*` results, exact positive-volume object collisions, physical component count, mesh topology, sampled wall thickness, unsupported overhang budget, and bed-contact area. Use `--json` for automation and `--output` to save the full report while keeping the readable terminal summary.
546
+
547
+ ```bash
548
+ forgecad check print examples/api/attachTo-basics.forge.js
549
+ forgecad check print examples/api/verification-demo.forge.js --json
550
+ forgecad check print model.forge.js --min-wall 1.2 --warn-wall 2
551
+ forgecad check print model.forge.js --expect-components 1 -p "Wall Thickness=3"
552
+ ```
502
553
 
503
554
  ### `forgecad check params`
504
555
 
@@ -566,7 +617,7 @@ The CLI is free for core workflows and exports. Production outputs are free to r
566
617
 
567
618
  | Free | Production outputs | Pro |
568
619
  |------|--------------------|-----|
569
- | `run`, `dev`, `studio`, `render 3d`, `export stl`, `export 3mf`, `export svg`, `check params`, `check suite` | `cut-list`, `export sketch-pdf`, `export step`, `export brep`, `export gcode`, `export sdf`, `export urdf`, `export report`, `export cutting-layout` are free to run; Pro covers commercial use. | `render hq`, `capture gif`, `capture mp4` |
620
+ | `run`, `dev`, `studio`, `render 3d`, `export stl`, `export 3mf`, `export svg`, `check print`, `check params`, `check suite` | `cut-list`, `export sketch-pdf`, `export step`, `export brep`, `export gcode`, `export sdf`, `export urdf`, `export report`, `export cutting-layout` are free to run; Pro covers commercial use. | `render hq`, `capture gif`, `capture mp4` |
570
621
 
571
622
  ```bash
572
623
  forgecad license # Check signed-in account status
@@ -29,7 +29,12 @@ bomToCsv(rows: BomRow[]): string
29
29
 
30
30
  **`BomRow`**: `part: string`, `qty: number`, `material?: string`, `process?: string`, `tolerance?: string`, `notes?: string`, `metadata?: PartMetadata`
31
31
 
32
- **`PartMetadata`**: `material?: string`, `process?: string`, `tolerance?: string`, `qty?: number`, `notes?: string`, `densityKgM3?: number`, `massKg?: number`
32
+ **`PartMetadata`**
33
+
34
+ | Option | Type | Description |
35
+ |--------|------|-------------|
36
+ | `tags?` | `string \| readonly string[]` | Viewport organization tags applied to scene objects produced from this part. |
37
+ | `material?`, `process?`, `tolerance?`, `qty?`, `notes?`, `densityKgM3?`, `massKg?` | | — |
33
38
 
34
39
  #### `assembly()` — Create an assembly container with named parts and joints for kinematic mechanisms.
35
40
 
@@ -670,13 +675,13 @@ toGroup(): ShapeGroup
670
675
  Each part becomes `{ name, shape }` or `{ name, group: [...] }` if the part is a [`ShapeGroup`](/docs/core#shapegroup). Top-level scripts should normally return the `SolvedAssembly` directly. Use `toGroup()` when you need [`ShapeGroup`](/docs/core#shapegroup) behavior; use this method only for advanced scene-graph control where you need access to the flat per-part array with metadata.
671
676
 
672
677
  ```ts
673
- toSceneObjects(): Array<{ name: string; shape?: Shape; group?: Array<{ name: string; shape: Shape; }>; metadata?: PartMetadata; }>
678
+ toSceneObjects(): Array<{ name: string; shape?: Shape; group?: Array<{ name: string; shape: Shape; tags?: string[]; }>; metadata?: PartMetadata; }>
674
679
  ```
675
680
 
676
681
  #### `toScene()` — Backward-compatible alias for `toSceneObjects()`.
677
682
 
678
683
  ```ts
679
- toScene(): Array<{ name: string; shape?: Shape; group?: Array<{ name: string; shape: Shape; }>; metadata?: PartMetadata; }>
684
+ toScene(): Array<{ name: string; shape?: Shape; group?: Array<{ name: string; shape: Shape; tags?: string[]; }>; metadata?: PartMetadata; }>
680
685
  ```
681
686
 
682
687
  #### [`bom()`](/docs/output#bom) — Generate a bill of materials for all parts in the solved assembly.
@@ -4,7 +4,7 @@ Every public API function belongs to one of 16 fundamental concepts. This docume
4
4
 
5
5
  ## Concepts
6
6
 
7
- - **[C1: Primitive Construction](#c1-primitive-construction)** — Create geometry from parameters — no input geometry required. *(74 functions)*
7
+ - **[C1: Primitive Construction](#c1-primitive-construction)** — Create geometry from parameters — no input geometry required. *(76 functions)*
8
8
  - **[C2: Boolean Combination](#c2-boolean-combination)** — Combine same-dimension geometry using CSG set operations. *(6 functions)*
9
9
  - **[C3: Rigid Transform](#c3-rigid-transform)** — Reposition or reorient geometry without changing its shape. *(3 functions)*
10
10
  - **[C4: Dimensional Promotion](#c4-dimensional-promotion)** — Convert a 2D profile into a 3D solid (extrude, revolve, loft, sweep). *(30 functions)*
@@ -259,6 +259,12 @@ sdf.basketWeave(options?: BasketWeaveOptions): SurfacePattern
259
259
  - `threadWidth?: number` — Thread width in mm. Default: 1.5
260
260
  - `depth?: number` — Thread protrusion depth in mm. Default: 0.8
261
261
 
262
+ #### `sdf.pattern2d()` — Create typed, composable 2D surface patterns for `.surfaceDisplace()`.
263
+
264
+ ```ts
265
+ sdf.pattern2d(): Pattern2DBuilder
266
+ ```
267
+
262
268
  #### `sdf.twist()` — Twist an SDF shape around the Z axis.
263
269
 
264
270
  ```ts
@@ -277,6 +283,12 @@ sdf.bend(shape: SdfShape, radius: number): SdfShape
277
283
  sdf.repeat(shape: SdfShape, spacing: Vec3, count?: Vec3): SdfShape
278
284
  ```
279
285
 
286
+ #### `sdf.circularArray()` — Arrange an SDF shape in a circular array around the Z axis with O(1) folded-domain evaluation.
287
+
288
+ ```ts
289
+ sdf.circularArray(shape: SdfShape, count: number, offset?: number): SdfShape
290
+ ```
291
+
280
292
  #### `sdf.SurfacePattern()` — A 2D surface pattern — a heightmap function for use with `.surfaceDisplace()`.
281
293
 
282
294
  ```ts
@@ -362,7 +374,6 @@ sdf.Sculpt: { sphere: (radius: number) => SdfShape; box: (x: number, y: number,
362
374
  | `behavior?` | `"opt-in" \| "auto"` | Whether the viewer should offer or auto-open the journey. First slice supports opt-in. |
363
375
  | `steps` | `SceneJourneyStepConfig[]` | Ordered journey spine. Branches can be added later without changing this core contract. |
364
376
  | `valid?` | `boolean` | True unless any journey or step diagnostic has level "error". |
365
- | `diagnostics?` | `SceneJourneyDiagnostic[]` | Whole-journey diagnostics, including unresolved startsAt and step target diagnostics. |
366
377
 
367
378
  **`SceneJourneyStepConfig`**
368
379
 
@@ -375,9 +386,6 @@ sdf.Sculpt: { sphere: (radius: number) => SdfShape; box: (x: number, y: number,
375
386
  | `camera?` | `SceneViewCameraConfig` | Optional explicit camera for this step. When omitted, the viewer fits `focus`. |
376
387
  | `resolvedFocusId?` | `string \| null` | Resolved object id after script execution, when `focus` matched exactly one object. |
377
388
  | `resolvedFocusPath?` | `string \| null` | Resolved object tree path or name after script execution. |
378
- | `diagnostics?` | `SceneJourneyDiagnostic[]` | Resolution diagnostics for this step. |
379
-
380
- `SceneJourneyDiagnostic`: `{ level: SceneJourneyDiagnosticLevel, message: string, stepId?: string, suggestions?: string[] }`
381
389
 
382
390
  **`SceneLightConfig`**
383
391
 
@@ -1059,14 +1067,6 @@ Blend.Surface(options: BlendSurfaceOptions): Shape
1059
1067
 
1060
1068
  `SurfaceMatchConstraintInput`: `{ target: EdgeRef, continuity?: SurfaceContinuity }`
1061
1069
 
1062
- #### `Blend.CornerY()` — 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
1063
-
1064
- ```ts
1065
- Blend.CornerY(options: BlendCornerYOptions): Shape
1066
- ```
1067
-
1068
- `BlendCornerYOptions`: `{ edges: EdgeRef[], cornerTolerance?: number, minBranchAngleDeg?: number }`
1069
-
1070
1070
  #### `Surface.Nurbs()`
1071
1071
 
1072
1072
  ```ts
@@ -1254,11 +1254,8 @@ connectEdges(edgeA: EdgeSegment, edgeB: EdgeSegment, options?: ConnectEdgesOptio
1254
1254
  | `normalA` | `Vec3` | Normal of first adjacent face. |
1255
1255
  | `normalB` | `Vec3` | Normal of second adjacent face (same as normalA for boundary edges). |
1256
1256
  | `boundary` | `boolean` | true if this is a boundary (unmatched) edge — unusual for closed solids. |
1257
- | `nativeTopology?` | `EdgeNativeTopologyRef` | Native kernel topology identity when the active backend can provide one. |
1258
1257
  | `start`, `end`, `midpoint`, `length` | | — |
1259
1258
 
1260
- `EdgeNativeTopologyRef`: `{ backend: "truck", edge: number }`
1261
-
1262
1259
  **`TransitionCurveOptions`**
1263
1260
  - `weightA?: number` — Weight for the start edge. Controls tangent magnitude at the start. - 1.0 (default): balanced transition - > 1.0: curve follows start edge longer before turning - < 1.0: curve turns sooner at the start
1264
1261
  - `weightB?: number` — Weight for the end edge. Controls tangent magnitude at the end. - 1.0 (default): balanced transition - > 1.0: curve follows end edge longer before turning - < 1.0: curve turns sooner at the end
@@ -1495,11 +1492,8 @@ coalesceEdges(segments: EdgeSegment[], tolerance?: number): EdgeSegment[]
1495
1492
  | `normalA` | `Vec3` | Normal of first adjacent face. |
1496
1493
  | `normalB` | `Vec3` | Normal of second adjacent face (same as normalA for boundary edges). |
1497
1494
  | `boundary` | `boolean` | true if this is a boundary (unmatched) edge — unusual for closed solids. |
1498
- | `nativeTopology?` | `EdgeNativeTopologyRef` | Native kernel topology identity when the active backend can provide one. |
1499
1495
  | `start`, `end`, `midpoint`, `length` | | — |
1500
1496
 
1501
- `EdgeNativeTopologyRef`: `{ backend: "truck", edge: number }`
1502
-
1503
1497
  #### `selectEdge()` — Select the single best-matching edge from a shape.
1504
1498
 
1505
1499
  When `near` is specified, returns the edge whose midpoint is closest to that point. Otherwise returns the first matching edge in mesh order. Throws if no edges match the query — useful as a guard when you expect exactly one result.
@@ -1559,9 +1553,11 @@ selectEdges(shape: Shape, query?: EdgeQuery): EdgeSegment[]
1559
1553
 
1560
1554
  Modify edges of a solid — fillets, chamfers, draft, offset.
1561
1555
 
1562
- #### `chamfer()` — Apply chamfers (beveled edges) to one or more edges of a shape.
1556
+ #### `chamfer()` — Apply experimental chamfers (beveled edges) to one or more edges of a shape.
1557
+
1558
+ **Experimental**: chamfers are still backend-sensitive. The Manifold backend is known to produce incorrect results for some edge-finish cases, and the OCCT backend can be very slow, especially with broad edge selections. Prefer targeted edge selectors and inspect the result before treating it as production-ready geometry.
1563
1559
 
1564
- Produces a 45° bevel at the specified `size` (distance from edge). Works on edge selections from any active backend. Truck and OCCT route chamfers through native kernel operations; unsupported selections fail as explicit kernel gaps instead of using TypeScript geometry fallbacks.
1560
+ Produces a 45° bevel at the specified `size` (distance from edge). Edge selections compile into backend operations; unsupported selections fail as explicit kernel gaps instead of using TypeScript geometry fallbacks.
1565
1561
 
1566
1562
  The `edges` parameter accepts the same options as `fillet()`: inline `EdgeQuery`, pre-selected `EdgeSegment`/`EdgeSegment[]`, or `undefined` (all sharp edges).
1567
1563
 
@@ -1595,9 +1591,11 @@ draft(myShape, 2, [0, 0, 1], 10)
1595
1591
  draft(shape: Shape, angleDeg: number, pullDirection?: [ number, number, number ], neutralPlaneOffset?: number): Shape
1596
1592
  ```
1597
1593
 
1598
- #### `fillet()` — Apply fillets (rounded edges) to one or more edges of a shape.
1594
+ #### `fillet()` — Apply experimental fillets (rounded edges) to one or more edges of a shape.
1599
1595
 
1600
- Works on edge selections from any active backend. Truck and OCCT route edge finishes through native kernel operations; unsupported selections fail as explicit kernel gaps instead of using TypeScript geometry fallbacks.
1596
+ **Experimental**: fillets are still backend-sensitive. The Manifold backend is known to produce incorrect results for some edge-finish cases, and the OCCT backend can be very slow, especially with broad edge selections. Prefer targeted edge selectors and inspect the result before treating it as production-ready geometry.
1597
+
1598
+ Edge selections compile into backend operations; unsupported selections fail as explicit kernel gaps instead of using TypeScript geometry fallbacks.
1601
1599
 
1602
1600
  The `edges` parameter is flexible:
1603
1601
 
@@ -2165,7 +2163,12 @@ bomToCsv(rows: BomRow[]): string
2165
2163
 
2166
2164
  **`BomRow`**: `part: string`, `qty: number`, `material?: string`, `process?: string`, `tolerance?: string`, `notes?: string`, `metadata?: PartMetadata`
2167
2165
 
2168
- **`PartMetadata`**: `material?: string`, `process?: string`, `tolerance?: string`, `qty?: number`, `notes?: string`, `densityKgM3?: number`, `massKg?: number`
2166
+ **`PartMetadata`**
2167
+
2168
+ | Option | Type | Description |
2169
+ |--------|------|-------------|
2170
+ | `tags?` | `string \| readonly string[]` | Viewport organization tags applied to scene objects produced from this part. |
2171
+ | `material?`, `process?`, `tolerance?`, `qty?`, `notes?`, `densityKgM3?`, `massKg?` | | — |
2169
2172
 
2170
2173
  #### `joint()` — Create a revolute joint that auto-generates a parameter slider and rotates the shape.
2171
2174
 
@@ -2599,7 +2602,12 @@ robotExport(options: RobotExportOptions): CollectedRobotExport
2599
2602
 
2600
2603
  `AssemblyPartDef`: `{ name: string, part: AssemblyPart, base: Transform, metadata?: PartMetadata }`
2601
2604
 
2602
- **`PartMetadata`**: `material?: string`, `process?: string`, `tolerance?: string`, `qty?: number`, `notes?: string`, `densityKgM3?: number`, `massKg?: number`
2605
+ **`PartMetadata`**
2606
+
2607
+ | Option | Type | Description |
2608
+ |--------|------|-------------|
2609
+ | `tags?` | `string \| readonly string[]` | Viewport organization tags applied to scene objects produced from this part. |
2610
+ | `material?`, `process?`, `tolerance?`, `qty?`, `notes?`, `densityKgM3?`, `massKg?` | | — |
2603
2611
 
2604
2612
  **`AssemblyJointDef`**: `name: string`, `type: JointType`, `parent: string`, `child: string`, `frame: Transform`, `axis: Vec3`, `min?: number`, `max?: number`, `defaultValue: number`, `unit?: string`, `effort?: number`, `velocity?: number`, `damping?: number`, `friction?: number`, `connectorRefs?: JointConnectorRefs`
2605
2613
 
@@ -2978,7 +2986,7 @@ When `lights` is specified, **all** default lights are removed. You must include
2978
2986
 
2979
2987
  Setting `camera.position` overrides auto-framing — the viewport will no longer auto-fit the geometry on script reload.
2980
2988
 
2981
- Named render views let scripts check in repeatable cameras next to the model code. The canonical shape is `{ camera: { position, target } }`, and a direct camera shorthand `{ position, target }` is also accepted. Use the canonical shape when you may add view metadata later. Use it from the CLI with `forgecad render 3d model.forge.js --view hero`.
2989
+ Named render views let scripts check in repeatable cameras next to the model code. The canonical shape is `{ camera: { position, target } }`, and a direct camera shorthand `{ position, target }` is also accepted. Use the canonical shape when you may add view metadata later. Use it from the CLI with `--view hero` on `forgecad render 3d`, `forgecad render hq`, or `forgecad capture`.
2982
2990
 
2983
2991
  Model journeys let scripts check in a compact guided path through named objects. Each journey has ordered `steps`; each step can name a `focus` target by object name/tree path, provide a caption, and optionally provide an explicit camera. In the viewer, journeys are opt-in: they appear as a small Explore control and do not move the camera until the user starts them. Use `forgecad run model.forge.js --journeys` or `--journeys-json` to inspect resolved targets.
2984
2992
 
@@ -3047,7 +3055,6 @@ scene(options: SceneOptions): void
3047
3055
  | `behavior?` | `"opt-in" \| "auto"` | Whether the viewer should offer or auto-open the journey. First slice supports opt-in. |
3048
3056
  | `steps` | `SceneJourneyStepConfig[]` | Ordered journey spine. Branches can be added later without changing this core contract. |
3049
3057
  | `valid?` | `boolean` | True unless any journey or step diagnostic has level "error". |
3050
- | `diagnostics?` | `SceneJourneyDiagnostic[]` | Whole-journey diagnostics, including unresolved startsAt and step target diagnostics. |
3051
3058
 
3052
3059
  **`SceneJourneyStepConfig`**
3053
3060
 
@@ -3060,9 +3067,6 @@ scene(options: SceneOptions): void
3060
3067
  | `camera?` | `SceneViewCameraConfig` | Optional explicit camera for this step. When omitted, the viewer fits `focus`. |
3061
3068
  | `resolvedFocusId?` | `string \| null` | Resolved object id after script execution, when `focus` matched exactly one object. |
3062
3069
  | `resolvedFocusPath?` | `string \| null` | Resolved object tree path or name after script execution. |
3063
- | `diagnostics?` | `SceneJourneyDiagnostic[]` | Resolution diagnostics for this step. |
3064
-
3065
- `SceneJourneyDiagnostic`: `{ level: SceneJourneyDiagnosticLevel, message: string, stepId?: string, suggestions?: string[] }`
3066
3070
 
3067
3071
  **`SceneLightConfig`**
3068
3072
 
@@ -3146,10 +3150,6 @@ viewConfig({
3146
3150
  viewConfig(options?: ViewConfigOptions): void
3147
3151
  ```
3148
3152
 
3149
- `ViewConfigOptions`: `{ jointOverlay?: JointOverlayViewConfigOptions }`
3150
-
3151
- **`JointOverlayViewConfigOptions`**: `enabled?: boolean`, `axisColor?: string`, `axisCoreColor?: string`, `arcColor?: string`, `zeroColor?: string`, `arcVisualLimitDeg?: number`, `axisLengthScale?: number`, `axisLengthMin?: number`, `axisLineRadiusScale?: number`, `axisLineRadiusMin?: number`, `axisLineRadiusMax?: number`, `spokeLineRadiusScale?: number`, `spokeLineRadiusMin?: number`, `spokeLineRadiusMax?: number`, `arcLineRadiusScale?: number`, `arcLineRadiusMin?: number`, `arcLineRadiusMax?: number`, `axisDotRadiusScale?: number`, `axisDotRadiusMin?: number`, `axisArrowRadiusScale?: number`, `axisArrowRadiusMin?: number`, `axisArrowLengthScale?: number`, `axisArrowLengthMin?: number`, `axisArrowOffsetFactor?: number`, `arcRadiusScale?: number`, `arcRadiusMin?: number`, `arcDotRadiusScale?: number`, `arcDotRadiusMin?: number`, `arcArrowRadiusScale?: number`, `arcArrowRadiusMin?: number`, `arcArrowLengthScale?: number`, `arcArrowLengthMin?: number`, `arcArrowOffsetFactor?: number`, `arcStepDeg?: number`, `arcMinSteps?: number`, `arcTubeSegmentsMin?: number`, `arcTubeSegmentsFactor?: number`, `arcTubeRadialSegments?: number`
3152
-
3153
3153
  #### `spec()` — Create a named, reusable bundle of verification checks.
3154
3154
 
3155
3155
  A spec groups related `verify.*` calls under a collapsible header in the Checks panel. This makes large check suites scannable. Specs can be applied to multiple shapes and can check relationships between parts.
@@ -3197,18 +3197,21 @@ Bring external geometry or other ForgeCAD modules into the current script.
3197
3197
 
3198
3198
  Unlike union(), child colors and individual identities are preserved. Children can be plain shapes, named descriptors ({ name, shape/sketch/group }), or nested groups. The returned ShapeGroup supports all Shape transforms (translate, rotate, etc.).
3199
3199
 
3200
+ Named descriptors can include `tags` for viewport organization. Tags do not affect geometry; they let the command palette hide, show only, or focus all objects with the same tag.
3201
+
3200
3202
  **Local coordinate pattern:** Build child parts at the origin (local coordinates), then group and translate once to place the whole assembly. This eliminates the error-prone pattern of manually adding parent offsets to every sub-part.
3201
3203
 
3202
3204
  ```js
3203
- // BAD every sub-part repeats the parent's global offset
3204
- const unitX = 0, unitY = -18, unitZ = 70;
3205
- const body = roundedBox(100, 20, 32, 4).translate(unitX, unitY, unitZ);
3206
- const panel = box(98, 2, 18).translate(unitX, unitY - 12, unitZ + 4);
3207
- const louver = box(88, 2, 6).translate(unitX, unitY - 14, unitZ - 11);
3205
+ const body = roundedBox(100, 20, 32, 4);
3206
+ const panel = box(98, 2, 18).translate(0, -12, 4);
3207
+ const louver = box(88, 2, 6).translate(0, -14, -11);
3208
+ const indoorUnit = group(
3209
+ { name: 'Body', shape: body },
3210
+ { name: 'Panel', tags: 'cover', shape: panel },
3211
+ { name: 'Louver', tags: ['cover', 'moving'], shape: louver },
3212
+ ).translate(0, -18, 70);
3208
3213
  ```
3209
3214
 
3210
- // GOOD — build at origin, group, translate once const body = roundedBox(100, 20, 32, 4); const panel = box(98, 2, 18).translate(0, -12, 4); const louver = box(88, 2, 6).translate(0, -14, -11); const indoorUnit = group( { name: 'Body', shape: body }, { name: 'Panel', shape: panel }, { name: 'Louver', shape: louver }, ).translate(0, -18, 70);
3211
-
3212
3215
  ```ts
3213
3216
  group(...items: GroupInput[]): ShapeGroup
3214
3217
  ```