forgecad 0.9.16 → 0.10.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.
- package/dist/assets/{AdminPage-CXvls4-J.js → AdminPage-DwYHz72L.js} +1 -1
- package/dist/assets/{BenchmarkPage-B27zk8xL.js → BenchmarkPage-a9_f-1US.js} +1 -1
- package/dist/assets/{BlogPage-CMAVvgQL.js → BlogPage-DodHpvmf.js} +1 -1
- package/dist/assets/{DocsPage-knf4I4h7.js → DocsPage-B5LePEuj.js} +8 -858
- package/dist/assets/EditorApp-QXsAISLR.js +16307 -0
- package/dist/assets/{EmbedViewer-D7ZGlFjx.js → EmbedViewer-DdEHGUMU.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-CnevhTE8.js → LandingPageProofDriven-yhhOodbf.js} +1 -1
- package/dist/assets/{LegalPage-BPTUmqeg.js → LegalPage-5RbKRGYK.js} +1 -1
- package/dist/assets/{PricingPage-B0D4goG_.js → PricingPage-E3Rma7aV.js} +1 -1
- package/dist/assets/{SettingsPage-CFF-UgjI.js → SettingsPage-BJZcM97j.js} +1 -1
- package/dist/assets/{app-T0pDcSX4.js → app-DSYrDg0V.js} +733 -205
- package/dist/assets/cli/{render-C5pcIISc.js → render-ZMHR9HkV.js} +19 -46
- package/dist/assets/{constructionHistoryWorker-Ba2Hm58b.js → constructionHistoryWorker-AwMMWSxg.js} +1103 -349
- package/dist/assets/{evalWorker-vkx310U2.js → evalWorker-DbNs7Dkp.js} +3798 -1622
- package/dist/assets/{inspectWorker-BuTJDVX6.js → inspectWorker-CZsCFtQT.js} +1163 -409
- package/dist/assets/{jointPose-B_Cgedn9.js → jointPose-DO6mnXn_.js} +1 -1
- package/dist/assets/{manifold-BWgsjmAM.js → manifold-BGlQBBH9.js} +1 -1
- package/dist/assets/{manifold-rZexZI0G.js → manifold-BU-tJwQh.js} +1 -1
- package/dist/assets/{manifold-D6IFSkhH.js → manifold-fy2MV7K1.js} +2 -2
- package/dist/assets/{reportWorker-0AGij1Ru.js → reportWorker-DO6hcQbh.js} +7155 -2437
- package/dist/assets/{scalar-sampling-budget-J5cuzxT1.js → scalar-sampling-budget-o90NSNmF.js} +3940 -1742
- package/dist/assets/{scanProxyWorker-Vl4Wxa1y.js → scanProxyWorker-2GtDLk-R.js} +1 -1
- package/dist/assets/{javascript-1kQXfVaz.js → typescript-DBQ6RN5l.js} +874 -22
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +3 -3
- package/dist/docs-raw/AI/usage.md +1 -1
- package/dist/docs-raw/CLI.md +63 -241
- package/dist/docs-raw/README.md +6 -0
- package/dist/docs-raw/component-model.md +17 -150
- package/dist/docs-raw/generated/assembly.md +139 -598
- package/dist/docs-raw/generated/concepts.md +245 -3501
- package/dist/docs-raw/generated/core.md +277 -1251
- package/dist/docs-raw/generated/curves.md +387 -1608
- package/dist/docs-raw/generated/legacy.md +162 -0
- package/dist/docs-raw/generated/lib.md +227 -85
- package/dist/docs-raw/generated/output.md +38 -73
- package/dist/docs-raw/generated/runtime-names.md +23 -23
- package/dist/docs-raw/generated/sdf.md +68 -284
- package/dist/docs-raw/generated/sheet-metal.md +68 -335
- package/dist/docs-raw/generated/sketch.md +240 -1161
- package/dist/docs-raw/generated/viewport.md +75 -316
- package/dist/docs-raw/generated/wood.md +21 -49
- package/dist/docs-raw/guides/coordinate-system.md +4 -42
- package/dist/docs-raw/guides/inspection-bundles.md +44 -442
- package/dist/docs-raw/guides/joint-design.md +18 -79
- package/dist/docs-raw/guides/positioning.md +21 -143
- package/dist/docs-raw/guides/scene-presentation.md +89 -0
- package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +25 -111
- package/dist/docs-raw/skills/forgecad-blockout-model.md +20 -117
- package/dist/docs-raw/skills/forgecad-component-model.md +23 -107
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +47 -155
- package/dist/docs-raw/skills/forgecad-image-replicator.md +26 -143
- package/dist/docs-raw/skills/forgecad-lld.md +19 -113
- package/dist/docs-raw/skills/forgecad-make-a-model.md +112 -532
- package/dist/docs-raw/skills/forgecad-model-grader.md +38 -108
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +24 -211
- package/dist/docs-raw/skills/forgecad-project.md +13 -131
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +42 -134
- package/dist/docs-raw/skills/forgecad-render-inspect.md +27 -174
- package/dist/docs-raw/skills/forgecad-visual-spec.md +32 -112
- package/dist/docs-raw/skills/forgecad.md +19 -18
- package/dist/docs-raw/skills/index.md +2 -0
- package/dist/docs-raw/welcome.md +2 -2
- package/dist/index.html +1 -1
- package/dist/llms.txt +1 -2
- package/dist/sitemap.xml +13 -13
- package/dist-cli/{check-compiler-SYQ2PWOB.js → check-compiler-JTVBITCR.js} +1 -1
- package/dist-cli/{check-query-propagation-HIAGV62W.js → check-query-propagation-3FFLSMVN.js} +1 -1
- package/dist-cli/{chunk-SPZE3DUY.js → chunk-OAN5T4XD.js} +4412 -2212
- package/dist-cli/forgecad.js +507 -179
- package/dist-skill/CONTEXT.md +2172 -8377
- package/dist-skill/SKILL.md +15 -15
- package/dist-skill/docs/API/core/concepts.md +27 -157
- package/dist-skill/docs/CLI.md +63 -241
- package/dist-skill/docs/generated/assembly.md +138 -549
- package/dist-skill/docs/generated/core.md +277 -1251
- package/dist-skill/docs/generated/curves.md +387 -1609
- package/dist-skill/docs/generated/lib.md +227 -85
- package/dist-skill/docs/generated/output.md +38 -73
- package/dist-skill/docs/generated/runtime-names.md +16 -21
- package/dist-skill/docs/generated/sdf.md +68 -284
- package/dist-skill/docs/generated/sheet-metal.md +68 -335
- package/dist-skill/docs/generated/sketch.md +240 -1160
- package/dist-skill/docs/generated/viewport.md +75 -223
- package/dist-skill/docs/generated/wood.md +21 -49
- package/dist-skill/docs/guides/coordinate-system.md +4 -42
- package/dist-skill/docs/guides/inspection-bundles.md +44 -442
- package/dist-skill/docs/guides/joint-design.md +18 -79
- package/dist-skill/docs/guides/positioning.md +21 -143
- package/dist-skill/docs/guides/scene-presentation.md +89 -0
- package/dist-skill/docs/guides/surface-members.md +26 -0
- package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +23 -111
- package/dist-skill/library/forgecad-blockout-model/SKILL.md +18 -117
- package/dist-skill/library/forgecad-component-model/SKILL.md +21 -107
- package/dist-skill/library/forgecad-high-level-spec/SKILL.md +45 -155
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +24 -143
- package/dist-skill/library/forgecad-lld/SKILL.md +17 -113
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +110 -532
- package/dist-skill/library/forgecad-model-grader/SKILL.md +36 -108
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +35 -224
- package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +43 -271
- package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +30 -99
- package/dist-skill/library/forgecad-project/SKILL.md +13 -133
- package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +29 -123
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +25 -174
- package/dist-skill/library/forgecad-visual-spec/SKILL.md +30 -111
- package/dist-skill/website/skills/forgecad-3d-reconstruction.md +58 -0
- package/dist-skill/website/skills/forgecad-blockout-model.md +49 -0
- package/dist-skill/website/skills/forgecad-component-model.md +53 -0
- package/dist-skill/website/skills/forgecad-high-level-spec.md +101 -0
- package/dist-skill/website/skills/forgecad-image-replicator.md +63 -0
- package/dist-skill/website/skills/forgecad-lld.md +41 -0
- package/dist-skill/website/skills/forgecad-make-a-model.md +186 -0
- package/dist-skill/website/skills/forgecad-model-grader.md +82 -0
- package/dist-skill/website/skills/forgecad-prepare-prompt.md +63 -0
- package/dist-skill/website/skills/forgecad-project.md +26 -0
- package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +60 -0
- package/dist-skill/website/skills/forgecad-render-inspect.md +80 -0
- package/dist-skill/website/skills/forgecad-visual-spec.md +71 -0
- package/dist-skill/website/skills/forgecad.md +122 -0
- package/dist-skill/website/skills/index.md +26 -0
- package/examples/api/comparison-imported-sphere-candidate.forge.js +1 -1
- package/examples/api/conformal-product-ribbon.forge.js +1 -1
- package/examples/api/exact-sheet-shell-assembly.forge.js +1 -1
- package/examples/api/extrude-options.forge.js +4 -2
- package/examples/api/field-loft-drive-tip.forge.js +40 -0
- package/examples/api/guided-loft-olive-oil-bottle.forge.js +1 -1
- package/examples/api/highlight-debug.forge.js +10 -10
- package/examples/api/mesh-import-slats.forge.js +1 -1
- package/examples/api/real-product-curves.forge.js +1 -1
- package/examples/api/sculpt-box-circle-booleans.forge.js +1 -1
- package/examples/api/sdf-shapes.forge.js +2 -5
- package/examples/api/sketch-rounding-strategies.forge.js +6 -6
- package/examples/api/surface-member-bottle-cage.forge.js +3 -3
- package/examples/api/surface-member-conformal-product-ribbon.forge.js +3 -3
- package/examples/api/surface-member-razor-inlay.forge.js +1 -1
- package/examples/api/variable-sweep-test.forge.js +3 -3
- package/examples/mechanical/airplane-propeller.forge.js +74 -39
- package/examples/nurbs-surface.forge.js +1 -1
- package/examples/products/iphone.forge.js +1 -1
- package/package.json +1 -1
- package/dist/assets/EditorApp-BHMQlJ-D.js +0 -14686
- package/dist/docs-raw/guides/geometry-conventions.md +0 -52
- package/dist/docs-raw/guides/modeling-recipes.md +0 -78
- package/dist-skill/docs/guides/geometry-conventions.md +0 -52
- package/dist-skill/docs/guides/modeling-recipes.md +0 -78
- package/dist-skill/library/forgecad-visual-spec/references/prompt-template.md +0 -79
|
@@ -5,176 +5,43 @@ skill-order: 4
|
|
|
5
5
|
|
|
6
6
|
# The Component Model
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Long-form rationale for ForgeCAD's multi-part architecture. The enforceable rule sheet — anti-patterns, design gate, file-structure rules — lives in the `forgecad-component-model` skill (`agent-skill-library/forgecad-component-model/SKILL.md`). Connector and joint mechanics (frame semantics, mating, mirrored-revolute handedness) live in the assembly JSDoc, surfaced in `docs/permanent/generated/assembly.md`.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## The Principle
|
|
11
11
|
|
|
12
|
-
> **A part is a function from props to shape + connectors. It knows nothing about where it sits in the world. The assembly decides.**
|
|
12
|
+
> **A part is a function from props to shape + connectors + metadata. It knows nothing about where it sits in the world. The assembly decides.**
|
|
13
13
|
|
|
14
|
-
This is how React changed UI: components render content, the layout system positions them. Components don't know their screen coordinates. Before React, jQuery code positioned elements in page-space
|
|
14
|
+
This is how React changed UI: components render content, the layout system positions them. Components don't know their screen coordinates. Before React, jQuery code positioned elements in page-space; after React, components are local and composable.
|
|
15
15
|
|
|
16
|
-
ForgeCAD applies the same principle to mechanical design. Before: parts compute their assembly-space coordinates (translate to the right X, Y, Z,
|
|
17
|
-
|
|
18
|
-
## The Three Rules
|
|
19
|
-
|
|
20
|
-
### Rule 1: Parts Build at Origin
|
|
21
|
-
|
|
22
|
-
A part is built in its own local coordinate system. Origin at `[0, 0, 0]`. No knowledge of the assembly. No imports of sibling part files. No global coordinate offsets.
|
|
23
|
-
|
|
24
|
-
```js
|
|
25
|
-
// WRONG — part positions itself in assembly space
|
|
26
|
-
const rackPlaced = rack.translate(pinionPitchR, 0, layout.pinionZ);
|
|
27
|
-
|
|
28
|
-
// RIGHT — part builds at origin, connector declares the interface
|
|
29
|
-
const rack = lib.rackGear({ ... }).rotateZ(90);
|
|
30
|
-
// pitch line at X=0, teeth face -X, local coordinates only
|
|
31
|
-
return rack.withConnectors({
|
|
32
|
-
teeth: connector("rack-slide", { origin: [0, 0, faceWidth/2], axis: [0, 1, 0] }),
|
|
33
|
-
});
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Rule 2: Connectors Are the Interface
|
|
37
|
-
|
|
38
|
-
Every part that participates in an assembly declares connectors. A connector says: "here's where I connect, what direction I face, and what roll I consider upright." It's the part's public interface — the only thing the assembly needs to know.
|
|
39
|
-
|
|
40
|
-
```js
|
|
41
|
-
return mount.withConnectors({
|
|
42
|
-
flange: connector("bolt-face", {
|
|
43
|
-
origin: [0, 0, 0], // where the mating surface is
|
|
44
|
-
axis: [0, 0, 1], // direction it faces (outward from part)
|
|
45
|
-
up: [1, 0, 0], // roll reference when orientation matters
|
|
46
|
-
}),
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
A connector is a small local frame:
|
|
51
|
-
|
|
52
|
-
- `origin` is the pivot, contact point, socket center, or mating-face point.
|
|
53
|
-
- `axis` is the primary direction: face normal, hinge line, or slide direction.
|
|
54
|
-
- `up` is the secondary direction that fixes roll around `axis`.
|
|
55
|
-
|
|
56
|
-
`up` is not world up. It is the connector's local roll reference and must not be parallel to `axis`. If `up` is omitted, ForgeCAD picks a deterministic perpendicular vector. That is fine when roll does not matter, but hinges, wheels, levers, and keyed parts should author `up` explicitly.
|
|
57
|
-
|
|
58
|
-
Connectors meet **face-to-face**. Both axes point outward from their respective parts. The system brings them together from opposite sides, then uses `up` to pin the rest orientation — like plugging in a keyed connector instead of a round peg.
|
|
59
|
-
|
|
60
|
-
### Rule 3: The Assembly Is Pure Composition
|
|
61
|
-
|
|
62
|
-
The assembly file does three things: instantiate parts with props, connect them, and define motion. Zero coordinate math. Zero translate calls. Zero shared-dims imports.
|
|
63
|
-
|
|
64
|
-
```js
|
|
65
|
-
assembly("Gripper")
|
|
66
|
-
.addPart("Base", base)
|
|
67
|
-
.addPart("Mount", mount)
|
|
68
|
-
.connect("Base.mount_face", "Mount.flange", { as: "mount-fix" })
|
|
69
|
-
.addPart("Pinion", pinion)
|
|
70
|
-
.connect("Base.pinion_seat", "Pinion.bore", { as: "spin" })
|
|
71
|
-
// ...
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
If you're writing `translate()` in an assembly file, something is wrong. Either the part should have a connector, or the prop should carry the dimension.
|
|
16
|
+
ForgeCAD applies the same principle to mechanical design. Before: parts compute their assembly-space coordinates (translate to the right X, Y, Z, fed by a shared-dims file). After: parts build at origin in local space, declare connectors as their public interface, and the assembly uses `connect()` to position everything. The assembly file becomes pure composition — instantiate parts with props, connect them, define motion — with zero coordinate math.
|
|
75
17
|
|
|
76
18
|
## Data Flow: Props Down, Metadata Up
|
|
77
19
|
|
|
78
|
-
Data flows in one direction
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
Assembly (root)
|
|
82
|
-
├── passes { servo, wall, clearance } → Motor Mount
|
|
83
|
-
│ └── returns { shape, boltPattern, flange connector }
|
|
84
|
-
├── passes { gears, boltPattern } → Base Body
|
|
85
|
-
│ └── returns { shape, pinionZ, rack connectors }
|
|
86
|
-
├── passes { gears, rackZ, armSpan } → Jaw Unit
|
|
87
|
-
│ └── returns { shape, armWidth, rack connector }
|
|
88
|
-
└── passes { boltPattern, armSlot } → Cover Plate
|
|
89
|
-
└── returns { shape, seat connector }
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
**Props flow down:** The assembly knows the cross-cutting decisions (base height, wall thickness, servo model) and passes them to parts as `require()` param overrides.
|
|
93
|
-
|
|
94
|
-
**Metadata flows up:** Parts return their shape + connectors + any computed data that siblings need. The assembly reads this metadata and passes relevant pieces to other parts.
|
|
20
|
+
Data flows in one direction, from parent (assembly) to children (parts):
|
|
95
21
|
|
|
96
|
-
**
|
|
22
|
+
- **Props flow down.** The assembly owns the cross-cutting decisions (base height, wall thickness, servo model) and passes them to parts as `require()` param overrides.
|
|
23
|
+
- **Metadata flows up.** Parts return shape + connectors + any computed data siblings need (`return { shape, boltPattern, pinionZ }`).
|
|
24
|
+
- **Siblings never import each other.** The cover plate doesn't import the motor mount to read bolt positions; the assembly reads the mount's bolt pattern and passes it to the cover plate. The parent mediates all sibling communication.
|
|
97
25
|
|
|
98
26
|
```js
|
|
99
|
-
// Assembly mediates sibling data flow
|
|
100
27
|
const mount = require('./motor-mount.forge.js', { Wall: wall });
|
|
101
|
-
const base = require('./base-body.forge.js', {
|
|
102
|
-
Height: baseH,
|
|
103
|
-
BoltPattern: mount.boltPattern, // parent passes mount's data to base
|
|
104
|
-
});
|
|
105
28
|
const cover = require('./cover-plate.forge.js', {
|
|
106
|
-
BoltPattern: mount.boltPattern, //
|
|
107
|
-
ArmSlot: jaw.armProfile, // jaw's data to cover
|
|
29
|
+
BoltPattern: mount.boltPattern, // parent routes mount's data to a sibling
|
|
108
30
|
});
|
|
109
31
|
```
|
|
110
32
|
|
|
111
33
|
## Why This Matters
|
|
112
34
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Each part file tells a complete story. You open `motor-mount.forge.js` and see everything: its geometry, its connectors, its parameters, its verifications. No chasing imports across 8 files. No 266-line shared-dims.js to understand.
|
|
116
|
-
|
|
117
|
-
Modifying one part doesn't break siblings — connectors are the contract. Change the mount's internal cavity dimensions and nothing else changes, as long as the flange connector stays at the same position.
|
|
118
|
-
|
|
119
|
-
### For AIs
|
|
120
|
-
|
|
121
|
-
Each part file is self-contained context. An AI generates `base-body.forge.js` without reading `jaw-unit.forge.js`. The assembly file is a high-level plan — generate it from a natural language description. Props are the interface contract — the AI knows exactly what each part needs and provides.
|
|
122
|
-
|
|
123
|
-
### For Swap-ability
|
|
124
|
-
|
|
125
|
-
Change the servo model → the mount rebuilds with new cavity dimensions → its bolt pattern updates → the assembly passes the new pattern to base and cover → everything adapts. One change, cascading update, zero manual re-derivation.
|
|
126
|
-
|
|
127
|
-
## The Connector Convention
|
|
128
|
-
|
|
129
|
-
Connectors follow one convention: **face-to-face connector frames**.
|
|
130
|
-
|
|
131
|
-
Each connector's axis points **outward** from its part — the direction the connection faces. When two connectors mate, the system makes their origins coincide and, for fixed/revolute joints, negates one axis so they approach from opposite sides. The `up` vectors define the roll reference that makes the rest pose deterministic.
|
|
132
|
-
|
|
133
|
-
- **Fixed joints** (bolt flange): both faces point outward, system brings them together
|
|
134
|
-
- **Revolute joints** (hinge): both parts point outward along the hinge line, system opposes them, and `up` pins zero angle
|
|
135
|
-
- **Prismatic joints** (slider): both connectors point along the slide direction (co-directional exception — the slide axis IS the shared direction), while `up` still pins roll around the rail
|
|
136
|
-
|
|
137
|
-
Revolute joint values are still signed by the physical hinge axis. If a bilateral
|
|
138
|
-
mechanism mirrors a hinge axis, the mirrored pose uses the negated physical value
|
|
139
|
-
(`Right: +theta`, `Left: -theta`), and physical limits mirror as
|
|
140
|
-
`[min, max] -> [-max, -min]`. Prismatic joints do not have this angle-handedness
|
|
141
|
-
flip. Use a side-neutral link graph or explicit state mapping when equal semantic
|
|
142
|
-
pose values should drive both sides.
|
|
143
|
-
|
|
144
|
-
```js
|
|
145
|
-
// Base bottom face points down, mount flange points up → meet in the middle
|
|
146
|
-
base.withConnectors({ mount_face: connector("bolt-face", { origin: [0,0,0], axis: [0,0,-1], up: [1,0,0] }) });
|
|
147
|
-
mount.withConnectors({ flange: connector("bolt-face", { origin: [0,0,0], axis: [0,0,1], up: [1,0,0] }) });
|
|
148
|
-
|
|
149
|
-
// Hinge: axes oppose along the pin, up pins the closed/rest roll
|
|
150
|
-
frame.withConnectors({ hinge: connector("hinge", { origin: [0,0,40], axis: [0,0,1], up: [1,0,0] }) });
|
|
151
|
-
door.withConnectors({ hinge: connector("hinge", { origin: [0,0,40], axis: [0,0,-1], up: [1,0,0] }) });
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## One File vs. Many Files
|
|
155
|
-
|
|
156
|
-
**Default: one file per assembly.** For a project-specific assembly (robot gripper, drone frame), put everything in one file. Parts are sections separated by comments. Shared data is just variables. This maximizes locality — you see the whole design by scrolling.
|
|
157
|
-
|
|
158
|
-
**Split when:** A part is reusable across projects (standard servo cradle, parametric gear pair), or the file exceeds ~300 lines. Split parts into separate `.forge.js` files that export component functions.
|
|
159
|
-
|
|
160
|
-
**Never split for "organization."** Eight files with 40 lines each is worse than one file with 300 lines. The context-switching cost of 8 files destroys locality.
|
|
161
|
-
|
|
162
|
-
## What This Forbids
|
|
163
|
-
|
|
164
|
-
1. **No shared-dims files.** If you're writing a file whose only job is to compute derived dimensions from component specs, the assembly should be doing that work (or the parts should derive their own internal dimensions from props).
|
|
165
|
-
|
|
166
|
-
2. **No sibling imports.** A part file never `require()`s another part file. Data flows through the parent.
|
|
167
|
-
|
|
168
|
-
3. **No assembly-space coordinates in parts.** A part doesn't know `pinionZ = 14`. It receives `rackZ: 14` as a prop, or it computes its own internal Z from its own props.
|
|
35
|
+
**For humans.** Each part file tells a complete story: geometry, connectors, parameters, verifications — no chasing imports across eight files, no 266-line shared-dims.js to internalize. Modifying one part doesn't break siblings, because connectors are the contract: change the mount's internal cavity and nothing else moves, as long as the flange connector stays put.
|
|
169
36
|
|
|
170
|
-
|
|
37
|
+
**For AIs.** Each part file is self-contained context. An agent generates `base-body.forge.js` without reading `jaw-unit.forge.js`. The assembly file is a high-level plan generatable from a natural-language description, and props are an explicit interface contract — the agent knows exactly what each part needs and provides.
|
|
171
38
|
|
|
172
|
-
|
|
39
|
+
**For swap-ability.** Change the servo model → the mount rebuilds with new cavity dimensions → its bolt pattern updates → the assembly passes the new pattern to base and cover → everything adapts. One change, cascading update, zero manual re-derivation.
|
|
173
40
|
|
|
174
|
-
##
|
|
41
|
+
## File Granularity
|
|
175
42
|
|
|
176
|
-
|
|
43
|
+
One file per project-specific assembly is the default because it maximizes locality: parts as comment-separated sections, shared data as plain variables, the whole design visible by scrolling. Eight 40-line files are worse than one 300-line file — the context-switching cost destroys exactly the locality this model exists to create. Split only for genuine cross-project reuse or when a file outgrows ~300 lines (the binding rule is in the skill).
|
|
177
44
|
|
|
178
|
-
|
|
45
|
+
## Enforcement
|
|
179
46
|
|
|
180
|
-
|
|
47
|
+
The anti-pattern list and the three-question design gate live in the `forgecad-component-model` skill; every multi-part example and agent-built assembly must pass that gate.
|