forgecad 0.6.3 → 0.8.0

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 (234) hide show
  1. package/README.md +3 -12
  2. package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-D4bocK4E.js} +250 -151
  3. package/dist/assets/{BlogPage-P_AJP0v9.js → BlogPage-CJEXL_zJ.js} +94 -70
  4. package/dist/assets/{DocsPage-CKRV2iq2.js → DocsPage-D3A_g8V3.js} +329 -163
  5. package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-BWYUSpUN.css} +590 -136
  6. package/dist/assets/EditorApp-Cihhqcsq.js +11692 -0
  7. package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-kWjKaC_t.js} +2 -4
  8. package/dist/assets/LandingPageProofDriven-Bg2IUc3l.css +856 -0
  9. package/dist/assets/LandingPageProofDriven-DXkKlyhI.js +601 -0
  10. package/dist/assets/PricingPage-BsU5vzEx.js +232 -0
  11. package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-PqvpAKIs.js} +129 -5
  12. package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-C-hzNUMy.js} +8949 -3161
  13. package/dist/assets/{Viewport-CoB46f5R.js → index-Pz321YAt.js} +38382 -7501
  14. package/dist/assets/{index-2hfs_ub0.css → index-ay13WNfa.css} +726 -53
  15. package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
  16. package/dist/assets/{manifold-CqNMHHKO.js → manifold-BcbjWLIo.js} +4 -3
  17. package/dist/assets/{manifold-Cce9wRFz.js → manifold-DBckbFgx.js} +1 -1
  18. package/dist/assets/{manifold-D6BeHIOo.js → manifold-O2AAGXyj.js} +1 -1
  19. package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-Dxr-5A7w.js} +8760 -3559
  20. package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
  21. package/dist/docs/index.html +2 -2
  22. package/dist/docs-raw/CLI.md +341 -718
  23. package/dist/docs-raw/generated/assembly.md +699 -112
  24. package/dist/docs-raw/generated/concepts.md +1834 -1346
  25. package/dist/docs-raw/generated/core.md +1012 -1059
  26. package/dist/docs-raw/generated/curves.md +759 -116
  27. package/dist/docs-raw/generated/lib.md +43 -748
  28. package/dist/docs-raw/generated/output.md +139 -245
  29. package/dist/docs-raw/generated/sdf.md +208 -0
  30. package/dist/docs-raw/generated/sheet-metal.md +473 -21
  31. package/dist/docs-raw/generated/sketch.md +1518 -362
  32. package/dist/docs-raw/generated/viewport.md +368 -299
  33. package/dist/docs-raw/generated/wood.md +104 -0
  34. package/dist/index.html +2 -2
  35. package/dist/landing/proof-ams-adapter.png +0 -0
  36. package/dist/landing/proof-bolt-and-nut.png +0 -0
  37. package/dist/landing/proof-fillet-enclosure.png +0 -0
  38. package/dist/landing/proof-glasses.png +0 -0
  39. package/dist/landing/proof-gyroid.png +0 -0
  40. package/dist/sitemap.xml +6 -6
  41. package/dist-cli/forgecad.js +12321 -5700
  42. package/dist-cli/forgecad.js.map +1 -0
  43. package/dist-cli/solver-46FFSK2U.js +363 -0
  44. package/dist-cli/solver-46FFSK2U.js.map +1 -0
  45. package/dist-skill/CONTEXT.md +4890 -6302
  46. package/dist-skill/SKILL-dev.md +22 -66
  47. package/dist-skill/SKILL.md +20 -59
  48. package/dist-skill/docs/API/core/concepts.md +37 -92
  49. package/dist-skill/docs/CLI.md +341 -718
  50. package/dist-skill/docs/generated/assembly.md +699 -112
  51. package/dist-skill/docs/generated/core.md +1012 -1059
  52. package/dist-skill/docs/generated/curves.md +759 -116
  53. package/dist-skill/docs/generated/lib.md +43 -748
  54. package/dist-skill/docs/generated/output.md +139 -245
  55. package/dist-skill/docs/generated/sdf.md +208 -0
  56. package/dist-skill/docs/generated/sheet-metal.md +473 -21
  57. package/dist-skill/docs/generated/sketch.md +1518 -362
  58. package/dist-skill/docs/generated/viewport.md +368 -299
  59. package/dist-skill/docs/generated/wood.md +104 -0
  60. package/dist-skill/docs/guides/coordinate-system.md +11 -17
  61. package/dist-skill/docs/guides/geometry-conventions.md +13 -70
  62. package/dist-skill/docs/guides/joint-design.md +78 -0
  63. package/dist-skill/docs/guides/modeling-recipes.md +22 -195
  64. package/dist-skill/docs/guides/positioning.md +88 -147
  65. package/dist-skill/docs-dev/API/core/concepts.md +78 -0
  66. package/dist-skill/docs-dev/CLI.md +488 -0
  67. package/dist-skill/{docs → docs-dev}/blueprint-first.md +5 -0
  68. package/dist-skill/{docs → docs-dev}/coding-best-practices.md +6 -8
  69. package/dist-skill/{docs → docs-dev}/coding.md +2 -4
  70. package/dist-skill/docs-dev/component-model.md +164 -0
  71. package/dist-skill/docs-dev/generated/assembly.md +779 -0
  72. package/dist-skill/docs-dev/generated/core.md +1676 -0
  73. package/dist-skill/docs-dev/generated/curves.md +855 -0
  74. package/dist-skill/docs-dev/generated/lib.md +55 -0
  75. package/dist-skill/docs-dev/generated/output.md +234 -0
  76. package/dist-skill/docs-dev/generated/sdf.md +208 -0
  77. package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
  78. package/dist-skill/docs-dev/generated/sketch.md +1753 -0
  79. package/dist-skill/docs-dev/generated/viewport.md +513 -0
  80. package/dist-skill/docs-dev/generated/wood.md +104 -0
  81. package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
  82. package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
  83. package/dist-skill/docs-dev/guides/joint-design.md +78 -0
  84. package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
  85. package/dist-skill/docs-dev/guides/positioning.md +151 -0
  86. package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
  87. package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
  88. package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
  89. package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
  90. package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
  91. package/examples/api/attachTo-basics.forge.js +8 -8
  92. package/examples/api/bill-of-materials.forge.js +9 -9
  93. package/examples/api/bolt-pattern.forge.js +5 -5
  94. package/examples/api/boolean-operations.forge.js +5 -5
  95. package/examples/api/bounding-box-visualizer.forge.js +3 -3
  96. package/examples/api/clone-duplicate.forge.js +2 -2
  97. package/examples/api/colors-union-vs-array.forge.js +6 -6
  98. package/examples/api/connector-assembly.forge.js +8 -6
  99. package/examples/api/connector-basics.forge.js +7 -7
  100. package/examples/api/constrained-sketch-mechanical.forge.js +4 -4
  101. package/examples/api/elbow-test.forge.js +3 -3
  102. package/examples/api/extrude-options.forge.js +8 -14
  103. package/examples/api/feature-created-faces.forge.js +6 -10
  104. package/examples/api/fillet-showcase.forge.js +2 -2
  105. package/examples/api/folded-service-panel-cover.forge.js +2 -2
  106. package/examples/api/gears-tier1.forge.js +5 -5
  107. package/examples/api/group-test.forge.js +3 -3
  108. package/examples/api/group-vs-union.forge.js +1 -1
  109. package/examples/api/highlight-debug.forge.js +4 -0
  110. package/examples/api/js-module-pillars.js +1 -1
  111. package/examples/api/js-module-scene.js +2 -2
  112. package/examples/api/mesh-import-slats.forge.js +4 -4
  113. package/examples/api/patterns.forge.js +3 -3
  114. package/examples/api/pointAlong-orientation.forge.js +3 -3
  115. package/examples/api/profile-2020-b-slot6.forge.js +4 -5
  116. package/examples/api/route-perimeter-flange.forge.js +1 -1
  117. package/examples/api/sdf-rover-demo.forge.js +10 -10
  118. package/examples/api/sketch-on-face-demo.forge.js +2 -2
  119. package/examples/api/sketch-regions.forge.js +4 -4
  120. package/examples/api/sketch-rounding-strategies.forge.js +1 -1
  121. package/examples/api/smooth-curve-connections.forge.js +1 -1
  122. package/examples/api/transition-curves.forge.js +4 -4
  123. package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
  124. package/examples/api/variable-sweep-test.forge.js +2 -2
  125. package/examples/api/wood-joinery.forge.js +60 -0
  126. package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
  127. package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
  128. package/examples/constraints/01-fully-constrained-rect.forge.js +2 -2
  129. package/examples/constraints/02-underconstrained-triangle.forge.js +1 -1
  130. package/examples/constraints/03-redundant-constraints.forge.js +2 -2
  131. package/examples/constraints/05-parallel-with-linedistance.forge.js +2 -2
  132. package/examples/constraints/06-complex-spectrogram.forge.js +1 -1
  133. package/examples/constraints/07-perpendicular-chain.forge.js +4 -4
  134. package/examples/constraints/08-symmetric-bracket.forge.js +4 -4
  135. package/examples/constraints/09-stress-spiral.forge.js +1 -1
  136. package/examples/constraints/10-stress-honeycomb.forge.js +1 -1
  137. package/examples/constraints/11-surface-grid.forge.js +2 -2
  138. package/examples/constraints/12-surface-nested.forge.js +4 -4
  139. package/examples/constraints/13-surface-complex.forge.js +1 -1
  140. package/examples/exact-arc-housing.forge.js +12 -0
  141. package/examples/experiments/drone-arm.forge.js +53 -0
  142. package/examples/furniture/adjustable-table.forge.js +15 -15
  143. package/examples/furniture/bathroom.forge.js +26 -26
  144. package/examples/furniture/chair.forge.js +13 -13
  145. package/examples/furniture/picture-frame.forge.js +6 -6
  146. package/examples/furniture/shoe-rack-doors.forge.js +8 -8
  147. package/examples/furniture/shoe-rack.forge.js +7 -7
  148. package/examples/furniture/table-lamp.forge.js +8 -8
  149. package/examples/gcode/lissajous-vase.forge.js +4 -4
  150. package/examples/gcode/math-surface.forge.js +3 -3
  151. package/examples/gcode/parametric-vase.forge.js +4 -4
  152. package/examples/gcode/spiral-tower.forge.js +4 -4
  153. package/examples/generative/crystal-growth.forge.js +9 -9
  154. package/examples/generative/frost-spires.forge.js +9 -9
  155. package/examples/generative/golden-spiral-tower.forge.js +11 -11
  156. package/examples/generative/molten-forge.forge.js +6 -6
  157. package/examples/generative/neon-coral.forge.js +7 -7
  158. package/examples/mechanical/3d-printer.forge.js +37 -37
  159. package/examples/mechanical/5-finger-robot-hand.forge.js +19 -19
  160. package/examples/mechanical/airplane-propeller.forge.js +9 -9
  161. package/examples/mechanical/bolt-and-nut.forge.js +10 -10
  162. package/examples/mechanical/door-with-hinges.forge.js +7 -7
  163. package/examples/mechanical/fillet-enclosure.forge.js +15 -11
  164. package/examples/mechanical/headphone-hanger-v2.forge.js +11 -11
  165. package/examples/mechanical/robot_hand.forge.js +24 -24
  166. package/examples/mechanical/robot_hand_2.forge.js +26 -26
  167. package/examples/nurbs-surface.forge.js +8 -0
  168. package/examples/nurbs-tube.forge.js +7 -0
  169. package/examples/products/bottle.forge.js +8 -8
  170. package/examples/products/chess-set.forge.js +25 -25
  171. package/examples/products/classical-piano.forge.js +20 -20
  172. package/examples/products/clock.forge.js +33 -33
  173. package/examples/products/cup.forge.js +5 -5
  174. package/examples/products/iphone.forge.js +20 -20
  175. package/examples/products/laptop.forge.js +24 -24
  176. package/examples/products/laser-cut-box.forge.js +6 -6
  177. package/examples/products/laser-cut-tray.forge.js +6 -6
  178. package/examples/products/liquid-soap-dispenser.forge.js +23 -23
  179. package/examples/products/origami-fish.forge.js +14 -12
  180. package/examples/products/spiderman-cake.forge.js +6 -6
  181. package/examples/shelf/container.forge.js +5 -5
  182. package/examples/shelf/shelf-unit.forge.js +6 -6
  183. package/examples/toolbox/bolted-joint.forge.js +7 -7
  184. package/package.json +9 -4
  185. package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
  186. package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
  187. package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
  188. package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
  189. package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
  190. package/dist/assets/index-1CYp3zUp.js +0 -1455
  191. package/dist-skill/docs/API/API.md +0 -1666
  192. package/dist-skill/docs/API/README.md +0 -37
  193. package/dist-skill/docs/API/assembly/assembly.md +0 -617
  194. package/dist-skill/docs/API/core/edge-queries.md +0 -130
  195. package/dist-skill/docs/API/core/parameters.md +0 -122
  196. package/dist-skill/docs/API/core/reserved-terms.md +0 -137
  197. package/dist-skill/docs/API/core/sdf.md +0 -326
  198. package/dist-skill/docs/API/core/skill-cli.md +0 -194
  199. package/dist-skill/docs/API/core/skill-guide.md +0 -205
  200. package/dist-skill/docs/API/core/specs.md +0 -186
  201. package/dist-skill/docs/API/core/topology.md +0 -372
  202. package/dist-skill/docs/API/entities.md +0 -268
  203. package/dist-skill/docs/API/output/bom.md +0 -58
  204. package/dist-skill/docs/API/output/brep-export.md +0 -87
  205. package/dist-skill/docs/API/output/dimensions.md +0 -67
  206. package/dist-skill/docs/API/output/export.md +0 -110
  207. package/dist-skill/docs/API/output/gcode.md +0 -195
  208. package/dist-skill/docs/API/runtime/viewport.md +0 -420
  209. package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
  210. package/dist-skill/docs/API/sketch/anchor.md +0 -37
  211. package/dist-skill/docs/API/sketch/booleans.md +0 -91
  212. package/dist-skill/docs/API/sketch/core.md +0 -73
  213. package/dist-skill/docs/API/sketch/extrude.md +0 -62
  214. package/dist-skill/docs/API/sketch/on-face.md +0 -104
  215. package/dist-skill/docs/API/sketch/operations.md +0 -78
  216. package/dist-skill/docs/API/sketch/path.md +0 -75
  217. package/dist-skill/docs/API/sketch/primitives.md +0 -146
  218. package/dist-skill/docs/API/sketch/regions.md +0 -80
  219. package/dist-skill/docs/API/sketch/text.md +0 -108
  220. package/dist-skill/docs/API/sketch/transforms.md +0 -65
  221. package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
  222. package/dist-skill/docs/INDEX.md +0 -94
  223. package/dist-skill/docs/RELEASING.md +0 -55
  224. package/dist-skill/docs/cli-monetization.md +0 -111
  225. package/dist-skill/docs/deployment.md +0 -281
  226. package/dist-skill/docs/generated/concepts.md +0 -2112
  227. package/dist-skill/docs/internals/shape-from-slices.md +0 -152
  228. package/dist-skill/docs/platform/admin.md +0 -45
  229. package/dist-skill/docs/platform/architecture.md +0 -79
  230. package/dist-skill/docs/platform/auth.md +0 -110
  231. package/dist-skill/docs/platform/email.md +0 -67
  232. package/dist-skill/docs/platform/projects.md +0 -111
  233. package/dist-skill/docs/platform/sharing.md +0 -90
  234. package/dist-skill/docs/runbook.md +0 -345
@@ -1,205 +0,0 @@
1
- ---
2
- skill-group: core
3
- skill-order: 0
4
- skill-tiers: [one-file]
5
- ---
6
-
7
- # ForgeCAD Skill Guide — Concepts & Patterns
8
-
9
- Conceptual knowledge that complements the auto-generated API index. The API index covers every function signature; this file covers the patterns, gotchas, and composition strategies that signatures alone cannot convey.
10
-
11
- ## Core Concepts
12
-
13
- ForgeCAD scripts are JavaScript code that returns geometry. The forge API is globally available — no imports needed.
14
-
15
- ### Basic Structure
16
- ```javascript
17
- const width = param("Width", 50, { min: 20, max: 100, unit: "mm" });
18
- const shape = box(width, 30, 10);
19
- return shape;
20
- ```
21
-
22
- ### Execution Model
23
- - Scripts execute on every parameter change (400ms debounce)
24
- - All operations are **immutable** — they return new shapes, never modify in place
25
- - Must return one of:
26
- - A `Shape` (3D solid)
27
- - A `Sketch` (2D profile — rendered flat on XY plane)
28
- - A `TrackedShape` (3D solid with named faces/edges — auto-unwrapped)
29
- - A `ShapeGroup` (multiple shapes/sketches grouped for joint transforms)
30
- - An `Array` of shapes/sketches/groups (multi-object scene)
31
- - An `Array` of `{ name, shape?, sketch?, color? }` objects (named multi-object scene)
32
-
33
- ### Unions Remove Colors
34
-
35
- `union()` merges into a single solid — individual colors are lost. Return an array of named objects instead:
36
-
37
- ```javascript
38
- // BAD: colors lost after union
39
- return union(red, blue);
40
-
41
- // GOOD: each object keeps its color
42
- return [
43
- { name: "Red Box", shape: red, color: '#ff0000' },
44
- { name: "Blue Box", shape: blue, color: '#0066ff' },
45
- ];
46
- ```
47
-
48
- ### Coordinate System
49
- Z-up right-handed: X = left/right, Y = forward/back, Z = up/down.
50
-
51
- ## Returning Multiple Objects
52
-
53
- ```javascript
54
- return [
55
- { name: "Base", shape: box(100, 100, 5), color: "#888888" },
56
- { name: "Column", shape: cylinder(50, 10).translate(50, 50, 5), color: "#4488cc" },
57
- ];
58
- ```
59
-
60
- Each object must have `name` (string) and `shape` or `sketch`. Optional `color` sets display color.
61
-
62
- ## Positioning & Connectors
63
-
64
- ### Connectors + `.matchTo()` — Primary positioning method
65
-
66
- Define named connectors on parts, then use `matchTo()` for automatic alignment. Connectors are stable (don't shift with geometry changes), semantic (typed and gendered), and oriented (full coordinate frame).
67
-
68
- ```javascript
69
- const bracket = box(40, 10, 60, true).withConnectors({
70
- mount: connector.male("bolt", { origin: [0, -5, 0], axis: [0, -1, 0] }),
71
- });
72
- const wall = box(200, 5, 200, true).withConnectors({
73
- slot: connector.female("bolt", { origin: [50, 2.5, 30], axis: [0, 1, 0] }),
74
- });
75
- const placed = bracket.matchTo(wall, "mount", "slot");
76
- ```
77
-
78
- Query connector distances to derive dimensions:
79
- ```javascript
80
- const pipeLen = frame.connectorDistance('inlet', 'outlet');
81
- ```
82
-
83
- ### `.attachTo()` — Quick bounding-box positioning
84
-
85
- For simple stacking where connectors aren't needed. Uses bounding-box anchors — fast but fragile.
86
-
87
- ```javascript
88
- const column = cylinder(50, 8).attachTo(base, 'top', 'bottom');
89
- ```
90
-
91
- ### `.onFace(parent, face, opts?)`
92
-
93
- Place a shape on a specific face of a parent. Face-local coordinates: `u`/`v` offset from center, `protrude` outward.
94
-
95
- ```javascript
96
- const vent = box(80, 2, 12, true)
97
- .onFace(body, 'front', { v: -15, protrude: 2 });
98
- ```
99
-
100
- **When to use:** `onFace()` for surface details (vents, displays). Connectors for assembly interfaces. `attachTo()` for quick prototyping.
101
-
102
- ## Multi-File Projects
103
-
104
- ### File Types
105
- - `.forge.js` — parametric part/assembly script
106
- - `.forge-notebook.json` — multi-cell notebook
107
- - `.svg` — vector artwork, imported as sketch geometry
108
-
109
- ### Import Function
110
-
111
- Use `require(path, paramOverrides?)` to import any `.forge.js` file. The second argument is optional param overrides.
112
-
113
- ```javascript
114
- const bracket = require("./bracket.forge.js");
115
- const bracket2 = require("./bracket.forge.js", { Width: 100, Thickness: 3 });
116
- ```
117
-
118
- The return value matches what the imported file exports:
119
- - File `return`s a `Shape` → you get a `Shape`
120
- - File `return`s an `Assembly` → you get an `ImportedAssembly`
121
- - File `return`s a `ShapeGroup` → you get a `ShapeGroup`
122
- - File uses `exports.name = value` → you get an object with named properties
123
-
124
- Use `importSvgSketch()` for SVG files (separate function — SVG is a file format loader, not a module import).
125
-
126
- ### Import Rules
127
- - Paths: `./file.forge.js` resolves relative to caller; bare paths resolve from project root
128
- - Param overrides only affect that import call
129
- - Circular imports throw an error
130
- - Each import call is a fresh execution
131
-
132
- ### Placement References
133
-
134
- Attach named reference points/edges/surfaces to shapes for precise cross-file positioning:
135
-
136
- ```javascript
137
- // In part file:
138
- return union(base, post).withReferences({
139
- points: { mount: [0, -16, -4] },
140
- surfaces: { mountingFace: { center: [0, -16, 0], normal: [0, -1, 0] } },
141
- objects: { base, post },
142
- });
143
-
144
- // In assembly file:
145
- const widget = require("./widget.forge.js")
146
- .placeReference("mount", [120, 40, 0]);
147
- const cap = box(18, 18, 8, true)
148
- .attachTo(widget, "objects.post.top", "bottom");
149
- ```
150
-
151
- References survive transforms and import round-trips.
152
-
153
- ### Plain JS Module Imports
154
-
155
- Regular `import`/`require()` works for utility modules. Don't mix explicit exports with top-level `return` in the same module.
156
-
157
- ### Typical Project Structure
158
- ```
159
- my-project/
160
- ├── base-profile.forge.js ← 2D cross-section (returns Sketch)
161
- ├── bracket.forge.js ← extrudes the sketch, adds holes
162
- └── assembly.forge.js ← imports multiple parts, positions them
163
- ```
164
-
165
- ## Compiler-Owned Operations
166
-
167
- ### `shape.shell(thickness, options?)`
168
- Hollows out a solid. Supports `box()`, `cylinder()`, straight `extrude()`. Optional `openFaces: ['top' | 'bottom']`.
169
-
170
- ```javascript
171
- const cup = roundedRect(80, 50, 6, true)
172
- .extrude(30).shell(2.5, { openFaces: ['top'] });
173
- ```
174
-
175
- ### `shape.hole(face, options)`
176
- Circular hole anchored to a face. `depth` omitted = through-hole. Supports `counterbore`/`countersink`, `upToFace`, two-sided `extent`.
177
-
178
- ```javascript
179
- const body = block
180
- .hole('front', { diameter: 8, u: 0, v: 2 })
181
- .hole('top', { diameter: 6, u: -18, v: 10, depth: 10 })
182
- .hole('top', { diameter: 5, u: 18, v: 10, upToFace: exitFace,
183
- counterbore: { diameter: 9, depth: 4 } });
184
- ```
185
-
186
- ### `shape.cutout(sketch, options?)`
187
- Cut-extrude using a sketch placed with `Sketch.onFace(...)`. Same extent options as `hole()`. Supports `taperScale` on circle/rect/roundedRect profiles.
188
-
189
- ### `sheetMetal(options)`
190
- Sheet-metal builder: base panel → `.flange()` → `.cutout()` → `.folded()` or `.flatPattern()`.
191
-
192
- ## Group Patterns
193
-
194
- `group()` combines shapes without merging — colors and identities preserved.
195
-
196
- ```javascript
197
- const housing = group(
198
- { name: 'Shell', shape: shell },
199
- { name: 'Lid', shape: lid },
200
- ).withReferences({
201
- points: { mountCenter: [0, 30, 20] },
202
- });
203
- ```
204
-
205
- ShapeGroup supports all transforms, placement references, and child access (`.child("Name")`).
@@ -1,186 +0,0 @@
1
- # Specs — Named Requirement Bundles
2
-
3
- A **Spec** is a named, reusable group of `verify.*` checks. When you call `spec.check(shape)`, every `verify` call inside the check function is tagged with the spec name and displayed as a collapsible section in the Checks panel.
4
-
5
- ## Why Specs
6
-
7
- Bare `verify.*` calls produce a flat list. With 15 checks across 3 different concerns, the panel becomes hard to scan. Specs add structure:
8
-
9
- - **Grouping** — related checks appear under a named, collapsible header
10
- - **Reusability** — one spec, applied to many shapes: `printable.check(bracket); printable.check(standoff);`
11
- - **Composability** — combine independent specs: check fit, strength, and printability separately
12
- - **Separation** — define what "good" looks like before building geometry (spec-first / TDD workflow)
13
-
14
- ## Quick Start
15
-
16
- ```javascript
17
- // Define a spec
18
- const printable = spec("Fits printer bed", (shape) => {
19
- verify.notEmpty("Has geometry", shape);
20
- const bb = shape.boundingBox();
21
- const size = [bb.max[0] - bb.min[0], bb.max[1] - bb.min[1], bb.max[2] - bb.min[2]];
22
- verify.lessThan("Width < 220mm", size[0], 220);
23
- verify.lessThan("Depth < 220mm", size[1], 220);
24
- verify.lessThan("Height < 250mm", size[2], 250);
25
- });
26
-
27
- // Build something
28
- const part = box(100, 80, 40);
29
-
30
- // Check it
31
- printable.check(part);
32
-
33
- return part;
34
- ```
35
-
36
- The Checks panel shows:
37
-
38
- ```
39
- ▼ ✓ Fits printer bed — 4/4
40
- ✓ Has geometry
41
- ✓ Width < 220mm
42
- ✓ Depth < 220mm
43
- ✓ Height < 250mm
44
- ```
45
-
46
- ## API
47
-
48
- ### `spec(name, checkFn)`
49
-
50
- Create a named spec.
51
-
52
- | Parameter | Type | Description |
53
- |-----------|------|-------------|
54
- | `name` | `string` | Display name in the Checks panel |
55
- | `checkFn` | `(...args) => void` | Function that calls `verify.*` methods |
56
-
57
- Returns a `Spec` object with a `.check()` method.
58
-
59
- ### `Spec.check(...args)`
60
-
61
- Run the spec's check function. Any `verify.*` calls inside are grouped under the spec name.
62
-
63
- Returns a `SpecResult`:
64
-
65
- ```typescript
66
- interface SpecResult {
67
- name: string; // Spec name
68
- passed: number; // Checks that passed
69
- total: number; // Total checks
70
- results: VerificationResult[];
71
- }
72
- ```
73
-
74
- The return value is optional — you can ignore it and just let the Checks panel show the results.
75
-
76
- ## Patterns
77
-
78
- ### Reusable Spec — Apply to Multiple Shapes
79
-
80
- ```javascript
81
- const structural = spec("Structural", (shape) => {
82
- verify.greaterThan("Min volume", shape.volume(), 500);
83
- verify.notEmpty("Not degenerate", shape);
84
- });
85
-
86
- structural.check(bracket);
87
- structural.check(plate);
88
- structural.check(standoff);
89
- // Each call adds a "Structural" group to the panel
90
- ```
91
-
92
- ### Multi-Shape Spec — Check Relationships
93
-
94
- Specs can accept multiple arguments for checking relationships between parts:
95
-
96
- ```javascript
97
- const fitSpec = spec("Assembly fit", (partA, partB) => {
98
- verify.notColliding("No interference", partA, partB, 10);
99
- verify.minClearance("Min gap 0.3mm", partA, partB, 0.3, 10);
100
- verify.parallel("Mating faces aligned",
101
- partA.face('top'), partB.face('bottom'));
102
- });
103
-
104
- fitSpec.check(bracket, standoff);
105
- ```
106
-
107
- ### Importable Spec Library
108
-
109
- Specs can live in separate `.forge.js` files and be imported via `require()`:
110
-
111
- ```javascript
112
- // specs/printers.forge.js
113
- const prusaMK3S = spec("Prusa MK3S", (shape) => {
114
- const bb = shape.boundingBox();
115
- const size = [bb.max[0]-bb.min[0], bb.max[1]-bb.min[1], bb.max[2]-bb.min[2]];
116
- verify.lessThan("X", size[0], 220);
117
- verify.lessThan("Y", size[1], 220);
118
- verify.lessThan("Z", size[2], 250);
119
- });
120
-
121
- return { prusaMK3S };
122
- ```
123
-
124
- ```javascript
125
- // my-part.forge.js
126
- const { prusaMK3S } = require("./specs/printers.forge.js");
127
- const part = box(100, 80, 40);
128
- prusaMK3S.check(part);
129
- return part;
130
- ```
131
-
132
- ### Reference Geometry in Specs
133
-
134
- Specs can create shapes internally as test fixtures — these are used only for checking and never rendered:
135
-
136
- ```javascript
137
- const fitsInEnclosure = spec("Fits in enclosure", (shape) => {
138
- // Reference geometry — not returned, not rendered
139
- const enclosure = box(200, 150, 100);
140
- const overlap = shape.intersect(enclosure);
141
-
142
- verify.that("Fully contained", () =>
143
- Math.abs(overlap.volume() - shape.volume()) < 1
144
- );
145
- verify.minClearance("2mm clearance", shape, enclosure, 2.0, 20);
146
- });
147
- ```
148
-
149
- ### Spec-First Workflow (TDD for CAD)
150
-
151
- Write specs before geometry. Watch checks go from red to green as you build:
152
-
153
- ```javascript
154
- // Step 1: Define what we need
155
- const caseSpec = spec("Phone case", (shape) => {
156
- verify.notEmpty("Has geometry", shape);
157
- verify.that("Is hollow (< 40% fill)", () => {
158
- const bb = shape.boundingBox();
159
- const bboxVol = (bb.max[0]-bb.min[0]) * (bb.max[1]-bb.min[1]) * (bb.max[2]-bb.min[2]);
160
- return shape.volume() < bboxVol * 0.4;
161
- });
162
- verify.greaterThan("Weighs under 30g (PLA)", 30, shape.volume() * 0.00124);
163
- });
164
-
165
- // Step 2: Build iteratively — specs tell you when you're done
166
- const myCase = box(75, 150, 12).shell(2, { openFaces: ['top'] });
167
- caseSpec.check(myCase);
168
- return myCase;
169
- ```
170
-
171
- ## Mixing Specs and Plain Verify Calls
172
-
173
- Plain `verify.*` calls (outside any spec) still work. They appear ungrouped below the spec sections:
174
-
175
- ```javascript
176
- // Grouped under spec name
177
- printable.check(part);
178
-
179
- // Ungrouped — shown separately
180
- verify.greaterThan("Custom check", someValue, 10);
181
- ```
182
-
183
- ## See Also
184
-
185
- - **[Verification demo](../../../examples/api/verification-demo.forge.js)** — all `verify.*` methods
186
- - **[Spec demo](../../../examples/api/spec-demo.forge.js)** — `spec()` in action