forgecad 0.1.1 → 0.1.3
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/{evalWorker-DuS4V-H5.js → evalWorker-1m873KWd.js} +107 -107
- package/dist/assets/{index-d60dJDhX.js → index-Dvz3nSDc.js} +342 -326
- package/dist/assets/{manifold-DEOPQqeC.js → manifold-C38sUiKu.js} +1 -1
- package/dist/assets/{manifold-cL7A7HeM.js → manifold-Dk2u-lhj.js} +1 -1
- package/dist/assets/{manifold-DbvY5u9x.js → manifold-rOWQW9fU.js} +1 -1
- package/dist/assets/{reportWorker-GZVKtf9S.js → reportWorker-Cj587shw.js} +129 -129
- package/dist/index.html +1 -1
- package/dist-cli/forgecad.js +204 -19
- package/dist-skill/SKILL.md +31 -4561
- package/dist-skill/docs/API/README.md +24 -0
- package/dist-skill/docs/API/guides/modeling-recipes.md +246 -0
- package/dist-skill/docs/API/internals/compiler.md +300 -0
- package/dist-skill/docs/API/internals/manifold.md +7 -0
- package/dist-skill/docs/API/model-building/README.md +31 -0
- package/dist-skill/docs/API/model-building/assembly.md +205 -0
- package/dist-skill/docs/API/model-building/coordinate-system.md +43 -0
- package/dist-skill/docs/API/model-building/entities.md +282 -0
- package/dist-skill/docs/API/model-building/geometry-conventions.md +104 -0
- package/dist-skill/docs/API/model-building/positioning.md +170 -0
- package/dist-skill/docs/API/model-building/reference.md +1936 -0
- package/dist-skill/docs/API/model-building/sheet-metal.md +180 -0
- package/dist-skill/docs/API/model-building/sketch-anchor.md +32 -0
- package/dist-skill/docs/API/model-building/sketch-booleans.md +101 -0
- package/dist-skill/docs/API/model-building/sketch-core.md +68 -0
- package/dist-skill/docs/API/model-building/sketch-extrude.md +57 -0
- package/dist-skill/docs/API/model-building/sketch-on-face.md +98 -0
- package/dist-skill/docs/API/model-building/sketch-operations.md +92 -0
- package/dist-skill/docs/API/model-building/sketch-path.md +70 -0
- package/dist-skill/docs/API/model-building/sketch-primitives.md +104 -0
- package/dist-skill/docs/API/model-building/sketch-transforms.md +60 -0
- package/dist-skill/docs/API/output/bom.md +53 -0
- package/dist-skill/docs/API/output/brep-export.md +82 -0
- package/dist-skill/docs/API/output/dimensions.md +62 -0
- package/dist-skill/docs/API/runtime/viewport.md +229 -0
- package/dist-skill/docs/CLI.md +672 -0
- package/dist-skill/docs/CODING.md +345 -0
- package/dist-skill/docs/PROGRAM-LEAD.md +180 -0
- package/dist-skill/docs/VISION.md +77 -0
- package/examples/api/import-group-assembly.forge.js +34 -0
- package/examples/api/import-group-source.forge.js +35 -0
- package/package.json +1 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# ForgeCAD Coding Guidelines
|
|
2
|
+
|
|
3
|
+
## Development Workflow
|
|
4
|
+
|
|
5
|
+
### Building & Running
|
|
6
|
+
```bash
|
|
7
|
+
npm install # Install dependencies
|
|
8
|
+
npm link # Install the local forgecad binary
|
|
9
|
+
forgecad studio # Start the browser studio (localhost:5173)
|
|
10
|
+
npm run build # Production build
|
|
11
|
+
npm run preview # Preview production build
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### CLI Tools
|
|
15
|
+
```bash
|
|
16
|
+
forgecad export svg examples/frame.sketch.js # Export sketch to SVG (Node, no browser)
|
|
17
|
+
forgecad render examples/cup.forge.js # Render to PNG (Puppeteer + Chrome)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
See [CLI.md](CLI.md) for full CLI documentation.
|
|
21
|
+
|
|
22
|
+
### Project Structure
|
|
23
|
+
```
|
|
24
|
+
src/
|
|
25
|
+
├── forge/ # Core geometry engine (shared by browser + CLI)
|
|
26
|
+
│ ├── kernel.ts # Manifold WASM wrapper, Shape class, primitives
|
|
27
|
+
│ ├── headless.ts # Single entry point for all contexts (browser + Node CLI)
|
|
28
|
+
│ ├── index.ts # Browser entry point (re-exports from headless.ts)
|
|
29
|
+
│ ├── runner.ts # Script sandbox — executes user scripts and resolves imported .svg assets
|
|
30
|
+
│ ├── params.ts # Parameter system (param() → UI sliders)
|
|
31
|
+
│ ├── library.ts # Part library (lib.boltHole, lib.pipe, etc.)
|
|
32
|
+
│ ├── section.ts # Plane intersection / projection
|
|
33
|
+
│ ├── meshToGeometry.ts # Manifold mesh → Three.js BufferGeometry
|
|
34
|
+
│ ├── sceneBuilder.ts # Three.js scene setup (shared with CLI renderer)
|
|
35
|
+
│ └── sketch/ # 2D sketch system
|
|
36
|
+
│ ├── core.ts # Sketch class
|
|
37
|
+
│ ├── primitives.ts # rect, circle2d, polygon, ngon, etc.
|
|
38
|
+
│ ├── transforms.ts # translate, rotate, scale, mirror
|
|
39
|
+
│ ├── booleans.ts # add, subtract, intersect, union2d, hull2d
|
|
40
|
+
│ ├── operations.ts # offset, hull, simplify, warp
|
|
41
|
+
│ ├── extrude.ts # extrude, revolve (2D → 3D)
|
|
42
|
+
│ ├── path.ts # PathBuilder, stroke
|
|
43
|
+
│ ├── anchor.ts # attachTo positioning
|
|
44
|
+
│ ├── constraints.ts # Constraint solver (18 types)
|
|
45
|
+
│ ├── entities.ts # Point2D, Line2D, Circle2D, Rectangle2D, Constraint helpers
|
|
46
|
+
│ ├── topology.ts # TrackedShape, face/edge naming
|
|
47
|
+
│ ├── patterns.ts # linearPattern, circularPattern, mirrorCopy
|
|
48
|
+
│ ├── fillets.ts # filletEdge, chamferEdge
|
|
49
|
+
│ ├── arcBridge.ts # arcBridgeBetweenRects
|
|
50
|
+
│ └── index.ts # Re-exports everything
|
|
51
|
+
├── components/ # React UI components
|
|
52
|
+
│ ├── Viewport.tsx # 3D viewport (Three.js + R3F)
|
|
53
|
+
│ ├── CodeEditor.tsx # Monaco editor with ForgeCAD types
|
|
54
|
+
│ ├── FileExplorer.tsx # Project file tree
|
|
55
|
+
│ ├── ViewPanel.tsx # Render mode, views, object settings
|
|
56
|
+
│ ├── ParamPanel.tsx # Parameter sliders
|
|
57
|
+
│ └── ExportPanel.tsx # STL export
|
|
58
|
+
├── store/
|
|
59
|
+
│ └── forgeStore.ts # Zustand global state
|
|
60
|
+
├── App.tsx # Main application shell
|
|
61
|
+
└── main.tsx # React entry point
|
|
62
|
+
|
|
63
|
+
cli/
|
|
64
|
+
├── forgecad.ts # Top-level CLI entrypoint and command routing
|
|
65
|
+
├── forge-svg.ts # SVG export (uses real engine via headless.ts)
|
|
66
|
+
├── forge-render.mjs # PNG render launcher (Puppeteer)
|
|
67
|
+
├── render.ts # Headless render entry (loaded in browser by Puppeteer)
|
|
68
|
+
└── render.html # HTML shell for headless render
|
|
69
|
+
|
|
70
|
+
examples/ # Example scripts
|
|
71
|
+
├── *.forge.js # 3D part examples
|
|
72
|
+
└── *.sketch.js # 2D sketch examples
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Coding Standards
|
|
76
|
+
|
|
77
|
+
### Minimal Implementation
|
|
78
|
+
Write only the code needed to solve the problem. No verbose implementations, no speculative features.
|
|
79
|
+
|
|
80
|
+
## Domain Localization Standard (Required)
|
|
81
|
+
|
|
82
|
+
This standard is package-wide for any new user-facing concept or API family.
|
|
83
|
+
|
|
84
|
+
### Contract
|
|
85
|
+
- Each concept family must have a clear primary home in both code and docs.
|
|
86
|
+
- Extend the module that already owns the mental model instead of scattering helpers across unrelated files.
|
|
87
|
+
- When a feature spans multiple layers, pick one domain owner and make the other layers mirror that owner.
|
|
88
|
+
- Keep related runtime code, examples, checks, and docs close to the same domain name whenever practical.
|
|
89
|
+
|
|
90
|
+
### Examples
|
|
91
|
+
- Assembly and kinematics live under `src/forge/assembly.ts` and `docs/permanent/API/model-building/assembly.md`.
|
|
92
|
+
- Sketch constraints live under `src/forge/sketch/constraints.ts` and the sketch/entity API docs.
|
|
93
|
+
- Transform/placement helpers should stay grouped with transform and positioning surfaces, not reappear as ad-hoc helpers in unrelated modules.
|
|
94
|
+
|
|
95
|
+
### Enforcement
|
|
96
|
+
- Before adding a new API, state which domain owns it.
|
|
97
|
+
- If a concept currently has no clean home, create one instead of spreading the first implementation across multiple files.
|
|
98
|
+
|
|
99
|
+
## Backend Compiler Standard (Required)
|
|
100
|
+
|
|
101
|
+
This standard is package-wide for any geometry feature that affects runtime lowering, exact export, or backend capability routing.
|
|
102
|
+
|
|
103
|
+
Read [API/internals/compiler.md](API/internals/compiler.md) before changing this area.
|
|
104
|
+
For large multi-agent migrations or architecture programs, also read [PROGRAM-LEAD.md](PROGRAM-LEAD.md).
|
|
105
|
+
|
|
106
|
+
### Contract
|
|
107
|
+
- Forge semantic intent comes first. Backends are lowerers, not the authoring model.
|
|
108
|
+
- Scene-level capability routing must stay centralized. Do not re-derive export/runtime policy ad hoc in unrelated modules.
|
|
109
|
+
- Public feature APIs must not hide backend-specific behavior directly in their callsites. Backend code belongs in the lowerers.
|
|
110
|
+
- New backend limitations must surface as diagnostics, not silent fallback or silent exactness loss.
|
|
111
|
+
|
|
112
|
+
### Enforcement
|
|
113
|
+
- If a feature is compile-covered, update the canonical compile graph and the scene compiler.
|
|
114
|
+
- If a feature is not yet dual-lowered, add explicit unsupported diagnostics for the missing backend rather than bypassing the compiler.
|
|
115
|
+
- Any geometry feature change must update invariant coverage and the living backend-compiler tracker.
|
|
116
|
+
|
|
117
|
+
## Multi-Agent Program Standard (Required For Large Migrations)
|
|
118
|
+
|
|
119
|
+
For work that spans multiple agent branches or staged dependency waves, the Program Lead role in [PROGRAM-LEAD.md](PROGRAM-LEAD.md) is the default operating model.
|
|
120
|
+
|
|
121
|
+
Use it when:
|
|
122
|
+
|
|
123
|
+
- one missing foundation blocks several feature lanes
|
|
124
|
+
- multiple agents need isolated tasks with dependency ordering
|
|
125
|
+
- the repo needs a living task graph and capability tracker to stay truthful
|
|
126
|
+
|
|
127
|
+
The key rule is simple:
|
|
128
|
+
|
|
129
|
+
- solve the deepest shared prerequisite first
|
|
130
|
+
- only then open the parallel wave that builds on top of it
|
|
131
|
+
|
|
132
|
+
### TypeScript
|
|
133
|
+
- Use explicit types for function parameters and return values
|
|
134
|
+
- Avoid `any` - use `unknown` or proper types
|
|
135
|
+
- Prefer interfaces for object shapes
|
|
136
|
+
|
|
137
|
+
### React Components
|
|
138
|
+
- Functional components only
|
|
139
|
+
- Inline styles for simplicity (no CSS files unless necessary)
|
|
140
|
+
- Extract reusable logic to custom hooks or store actions
|
|
141
|
+
|
|
142
|
+
### State Management
|
|
143
|
+
- All global state lives in `forgeStore.ts`
|
|
144
|
+
- Use Zustand selectors to prevent unnecessary re-renders
|
|
145
|
+
- Keep actions pure and synchronous where possible
|
|
146
|
+
|
|
147
|
+
## Frame Composition Standard (Required)
|
|
148
|
+
|
|
149
|
+
This standard is package-wide for any code that composes transforms (`Transform`, joints, assemblies, kinematic helpers).
|
|
150
|
+
|
|
151
|
+
### Contract
|
|
152
|
+
- `A.mul(B)` means **apply A, then B**
|
|
153
|
+
- Use `composeChain(...)` for 3+ composed transforms instead of manual `.mul()` chains
|
|
154
|
+
- In assembly/kinematics, always express composition in this canonical order:
|
|
155
|
+
- `local -> childBase -> jointMotion -> jointFrame -> parentWorld`
|
|
156
|
+
|
|
157
|
+
### Why this is mandatory
|
|
158
|
+
Transform order bugs can produce geometry that "looks valid" but is globally wrong (detached mechanism segments, drifting pivots, mirrored motion paths) and often pass casual visual checks.
|
|
159
|
+
|
|
160
|
+
### 5-Why (2026-02 Assembly disconnect incident)
|
|
161
|
+
1. Why were arm segments disconnected?
|
|
162
|
+
Because child world transforms were composed in the wrong order in `assembly.solve()`.
|
|
163
|
+
2. Why was order wrong?
|
|
164
|
+
Because `.mul()` chain semantics (apply self, then other) were interpreted inconsistently with matrix notation.
|
|
165
|
+
3. Why was that ambiguity possible?
|
|
166
|
+
Because there was no single canonical frame equation documented and enforced in code review.
|
|
167
|
+
4. Why didn’t tests catch it immediately?
|
|
168
|
+
Because there was no invariant test comparing assembly-solved frame origins against an analytic kinematic oracle.
|
|
169
|
+
5. Why no invariant test existed?
|
|
170
|
+
Because we had feature-level example checks, but no package-wide transform convention gate.
|
|
171
|
+
|
|
172
|
+
Root cause: **missing, enforced transform/frame composition contract across code + tests.**
|
|
173
|
+
|
|
174
|
+
### Enforcement
|
|
175
|
+
- Any change touching transforms, joints, or assembly solving must run:
|
|
176
|
+
- `forgecad check transforms`
|
|
177
|
+
- If the change affects user-facing geometry behavior, also run:
|
|
178
|
+
- `forgecad run <affected-example>`
|
|
179
|
+
|
|
180
|
+
## Editor Declaration Parity Standard (Required)
|
|
181
|
+
|
|
182
|
+
This standard is package-wide for any user-facing API exposed to scripts.
|
|
183
|
+
|
|
184
|
+
### Contract
|
|
185
|
+
- Runtime API and editor declarations must ship together:
|
|
186
|
+
- Runtime surface: `src/forge/*` exports + `src/forge/runner.ts` sandbox bindings
|
|
187
|
+
- Editor surface: `src/components/CodeEditor.tsx` `FORGE_TYPES`
|
|
188
|
+
- Docs surface: `docs/permanent/API/**/*.md`
|
|
189
|
+
- If an important feature is missing from editor declarations, you must either:
|
|
190
|
+
- implement declarations in the same change, or
|
|
191
|
+
- create a tracked task in `tasks/` that explicitly names the missing surface and scope.
|
|
192
|
+
|
|
193
|
+
### Enforcement
|
|
194
|
+
- Before merge, verify new/changed script APIs are present in all three surfaces above.
|
|
195
|
+
- Do not ship runtime-only features without either declaration parity or a tracking task.
|
|
196
|
+
|
|
197
|
+
## Script API Contract Standard (Required)
|
|
198
|
+
|
|
199
|
+
This standard is package-wide for any API exposed to user scripts.
|
|
200
|
+
|
|
201
|
+
### Contract
|
|
202
|
+
- Collection-shaped script APIs must accept the intuitive collection forms the docs advertise:
|
|
203
|
+
- variadic operands when the operation naturally works on many inputs
|
|
204
|
+
- a single array of operands when that keeps call sites composable
|
|
205
|
+
- Method syntax and function syntax must mirror each other for the same operation family.
|
|
206
|
+
- User-facing APIs must not silently ignore extra arguments. Unsupported arity or operand types must throw a direct runtime error with the API name in the message.
|
|
207
|
+
- If a future API needs configuration, do not smuggle it in as an ambiguous trailing object on an operand list. Use a distinct helper or a clearly named options-bearing API.
|
|
208
|
+
|
|
209
|
+
### Enforcement
|
|
210
|
+
- Any change to user-facing script APIs must run:
|
|
211
|
+
- `forgecad check api`
|
|
212
|
+
- If the change also affects transforms, dimensions, placement refs, or geometry semantics, run the relevant existing invariant checks too.
|
|
213
|
+
|
|
214
|
+
## Git Workflow
|
|
215
|
+
|
|
216
|
+
### Commit Every Major Change
|
|
217
|
+
Each logical unit of work should be a separate commit:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
git add <files>
|
|
221
|
+
git commit -m "Add file explorer panel"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Commit Message Format
|
|
225
|
+
```
|
|
226
|
+
<verb> <what>
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
- Add file explorer panel
|
|
230
|
+
- Fix measure mode toggle
|
|
231
|
+
- Update parameter slider styling
|
|
232
|
+
- Remove unused imports
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Use present tense verbs: Add, Fix, Update, Remove, Refactor
|
|
236
|
+
|
|
237
|
+
### What Counts as "Major"
|
|
238
|
+
- New feature or component
|
|
239
|
+
- Bug fix
|
|
240
|
+
- Refactoring that changes structure
|
|
241
|
+
- Performance improvement
|
|
242
|
+
- Breaking API change
|
|
243
|
+
|
|
244
|
+
### What to Commit Together
|
|
245
|
+
- Related files for a single feature
|
|
246
|
+
- Tests with the code they test
|
|
247
|
+
- Documentation with the feature it describes
|
|
248
|
+
|
|
249
|
+
### Example Workflow
|
|
250
|
+
```bash
|
|
251
|
+
# Feature: Add file explorer
|
|
252
|
+
git add src/components/FileExplorer.tsx
|
|
253
|
+
git add src/store/forgeStore.ts
|
|
254
|
+
git add src/App.tsx
|
|
255
|
+
git commit -m "Add file explorer panel"
|
|
256
|
+
|
|
257
|
+
# Next feature: Add keyboard shortcuts
|
|
258
|
+
git add src/hooks/useKeyboard.ts
|
|
259
|
+
git add src/App.tsx
|
|
260
|
+
git commit -m "Add keyboard shortcuts for file operations"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Testing
|
|
264
|
+
|
|
265
|
+
### Manual Testing Checklist
|
|
266
|
+
Before committing UI changes:
|
|
267
|
+
- [ ] Test in browser at localhost:5173
|
|
268
|
+
- [ ] Check console for errors
|
|
269
|
+
- [ ] Verify responsive behavior
|
|
270
|
+
- [ ] Test with example scripts
|
|
271
|
+
|
|
272
|
+
### Integration Testing
|
|
273
|
+
- Load example files and verify they render
|
|
274
|
+
- Test parameter sliders update geometry
|
|
275
|
+
- Verify STL export produces valid files
|
|
276
|
+
- Check measure mode calculates correctly
|
|
277
|
+
|
|
278
|
+
## Code Review
|
|
279
|
+
|
|
280
|
+
### Self-Review Before Commit
|
|
281
|
+
1. Remove console.logs and debug code
|
|
282
|
+
2. Check for unused imports
|
|
283
|
+
3. Verify TypeScript has no errors
|
|
284
|
+
4. Test the change works as intended
|
|
285
|
+
5. Read the diff - does it make sense?
|
|
286
|
+
|
|
287
|
+
### What to Look For
|
|
288
|
+
- Does this solve the problem with minimal code?
|
|
289
|
+
- Are there edge cases not handled?
|
|
290
|
+
- Is the code readable without comments?
|
|
291
|
+
- Does it follow existing patterns?
|
|
292
|
+
|
|
293
|
+
## Performance
|
|
294
|
+
|
|
295
|
+
### Geometry Operations
|
|
296
|
+
- Manifold operations are expensive - minimize boolean ops
|
|
297
|
+
- Cache geometry results when parameters don't change
|
|
298
|
+
- Use debouncing for real-time updates (already implemented)
|
|
299
|
+
|
|
300
|
+
### React Rendering
|
|
301
|
+
- Use Zustand selectors to prevent unnecessary re-renders
|
|
302
|
+
- Memoize expensive computations with `useMemo`
|
|
303
|
+
- Keep component tree shallow
|
|
304
|
+
|
|
305
|
+
## Common Patterns
|
|
306
|
+
|
|
307
|
+
### Adding a New Sketch Primitive
|
|
308
|
+
1. Add function to `src/forge/sketch/primitives.ts`
|
|
309
|
+
2. It's auto-exported via `sketch/index.ts` → `headless.ts` → `index.ts`
|
|
310
|
+
3. Add it to the sandbox in `src/forge/runner.ts` (both the `new Function()` args and the call)
|
|
311
|
+
4. Add TypeScript hints in `src/components/CodeEditor.tsx` (`FORGE_TYPES`)
|
|
312
|
+
5. Update `docs/permanent/API/model-building/sketch-primitives.md`
|
|
313
|
+
6. Commit: "Add [primitive] sketch primitive"
|
|
314
|
+
|
|
315
|
+
### Adding a New 3D Primitive
|
|
316
|
+
1. Add function to `src/forge/kernel.ts`
|
|
317
|
+
2. Export from `headless.ts`
|
|
318
|
+
3. Add to runner sandbox in `src/forge/runner.ts`
|
|
319
|
+
4. Add TypeScript hints in `src/components/CodeEditor.tsx`
|
|
320
|
+
5. Update `docs/permanent/API/model-building/reference.md`
|
|
321
|
+
6. Commit: "Add [primitive] 3D primitive"
|
|
322
|
+
|
|
323
|
+
### Adding a New CLI Command
|
|
324
|
+
1. Create `cli/your-command.ts`
|
|
325
|
+
2. Import from `../src/forge/headless`
|
|
326
|
+
3. Call `await init()` then use `runScript()`
|
|
327
|
+
4. Add script to `package.json`
|
|
328
|
+
5. Update `docs/permanent/CLI.md`
|
|
329
|
+
6. Commit: "Add [command] CLI command"
|
|
330
|
+
|
|
331
|
+
### Adding UI State
|
|
332
|
+
1. Add to `src/store/forgeStore.ts` interface
|
|
333
|
+
2. Add initial value and actions
|
|
334
|
+
3. Wire up to component
|
|
335
|
+
4. Commit: "Add [feature] UI state"
|
|
336
|
+
|
|
337
|
+
### Adding a Component
|
|
338
|
+
1. Create in `src/components/`
|
|
339
|
+
2. Import and use in `App.tsx` or parent
|
|
340
|
+
3. Commit: "Add [Component] component"
|
|
341
|
+
|
|
342
|
+
### Key Architecture Rule: Single Source of Truth
|
|
343
|
+
All geometry logic lives in `src/forge/`. CLI tools import from `src/forge/headless.ts`.
|
|
344
|
+
**Never** duplicate forge logic in CLI scripts. If you need something in CLI, make sure
|
|
345
|
+
it's exported from `headless.ts` and import it.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Program Lead Role
|
|
2
|
+
|
|
3
|
+
This document formalizes the reusable role Forge uses for large architectural projects that involve multiple agent branches and staged dependency waves.
|
|
4
|
+
|
|
5
|
+
Use this role when the work is too deep or too cross-cutting to split safely into ad hoc feature tickets.
|
|
6
|
+
|
|
7
|
+
## Role Name
|
|
8
|
+
|
|
9
|
+
Program Lead
|
|
10
|
+
|
|
11
|
+
Short version:
|
|
12
|
+
|
|
13
|
+
- owns the architectural through-line
|
|
14
|
+
- decides what must be solved before parallelization
|
|
15
|
+
- turns the program into explicit tasks, waves, and merge rules
|
|
16
|
+
- reviews landed work for truthfulness, scope, and regression safety
|
|
17
|
+
|
|
18
|
+
This is not a people-manager role. It is a technical integration and program-shaping role.
|
|
19
|
+
|
|
20
|
+
## Mission
|
|
21
|
+
|
|
22
|
+
Keep multi-agent technical work coherent.
|
|
23
|
+
|
|
24
|
+
The Program Lead protects three things:
|
|
25
|
+
|
|
26
|
+
1. one clear source of truth for architecture
|
|
27
|
+
2. honest task decomposition with real dependency boundaries
|
|
28
|
+
3. a repo state that tells the truth about what is landed, supported, blocked, and next
|
|
29
|
+
|
|
30
|
+
If those three drift apart, the program stops scaling.
|
|
31
|
+
|
|
32
|
+
## Responsibilities
|
|
33
|
+
|
|
34
|
+
### 1. Identify the deepest prerequisite
|
|
35
|
+
|
|
36
|
+
Before parallelizing, find the one core problem everything else depends on.
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
|
|
40
|
+
- shared query/reference backbone
|
|
41
|
+
- topology-rewrite propagation
|
|
42
|
+
- backend-neutral compile graph
|
|
43
|
+
|
|
44
|
+
The Program Lead should prefer foundation before breadth. If several features all feel blocked by the same missing layer, that missing layer becomes the next core lane.
|
|
45
|
+
|
|
46
|
+
### 2. Shape the work into waves
|
|
47
|
+
|
|
48
|
+
Every program should have:
|
|
49
|
+
|
|
50
|
+
- one current core lane
|
|
51
|
+
- one parallel wave that becomes safe after that lane lands
|
|
52
|
+
- one follow-on wave that depends on the first parallel wave
|
|
53
|
+
- one closeout lane for corpus, docs, and capability truthfulness
|
|
54
|
+
|
|
55
|
+
The Program Lead owns that wave plan and updates it as the repo changes.
|
|
56
|
+
|
|
57
|
+
### 3. Write explicit task contracts
|
|
58
|
+
|
|
59
|
+
Each task should define:
|
|
60
|
+
|
|
61
|
+
- problem definition
|
|
62
|
+
- description
|
|
63
|
+
- requirements
|
|
64
|
+
- isolation rule
|
|
65
|
+
- dependencies
|
|
66
|
+
- parallelization notes
|
|
67
|
+
- status log
|
|
68
|
+
|
|
69
|
+
The point is not bureaucracy. The point is merge safety and honest scope.
|
|
70
|
+
|
|
71
|
+
### 4. Own the integration seam
|
|
72
|
+
|
|
73
|
+
Agents should build feature logic in isolated modules first.
|
|
74
|
+
|
|
75
|
+
The Program Lead owns:
|
|
76
|
+
|
|
77
|
+
- the shared branch
|
|
78
|
+
- the thin shared-file integration seams
|
|
79
|
+
- the sequencing of merges when multiple tasks touch central compiler files
|
|
80
|
+
|
|
81
|
+
### 5. Review landed work before opening the next wave
|
|
82
|
+
|
|
83
|
+
Before the next wave starts, the Program Lead reviews:
|
|
84
|
+
|
|
85
|
+
- implementation against task scope
|
|
86
|
+
- tests and regression coverage
|
|
87
|
+
- docs and task/tracker truthfulness
|
|
88
|
+
- hidden capability inflation
|
|
89
|
+
|
|
90
|
+
The Program Lead should explicitly say whether the program should move forward or not.
|
|
91
|
+
|
|
92
|
+
### 6. Keep capability claims honest
|
|
93
|
+
|
|
94
|
+
The Program Lead is responsible for making sure docs do not overstate support.
|
|
95
|
+
|
|
96
|
+
If the implementation only supports a defended subset, the docs must say so.
|
|
97
|
+
|
|
98
|
+
### 7. Maintain the living docs
|
|
99
|
+
|
|
100
|
+
At minimum, the Program Lead keeps these current:
|
|
101
|
+
|
|
102
|
+
- temporary program README
|
|
103
|
+
- mission tracker
|
|
104
|
+
- task graph
|
|
105
|
+
- task files
|
|
106
|
+
- permanent architecture docs when contracts change
|
|
107
|
+
|
|
108
|
+
## Operating Rules
|
|
109
|
+
|
|
110
|
+
### One branch of truth
|
|
111
|
+
|
|
112
|
+
- Keep one program branch as the integration branch.
|
|
113
|
+
- Agent branches should merge into that branch, not bypass it.
|
|
114
|
+
- Reviews and go/no-go decisions should happen against that branch, not stale side worktrees.
|
|
115
|
+
|
|
116
|
+
### One architectural center
|
|
117
|
+
|
|
118
|
+
- Do not let each task invent its own local semantic model.
|
|
119
|
+
- If several tasks need the same concept, the Program Lead should create or demand a shared contract first.
|
|
120
|
+
|
|
121
|
+
### Explicit unsupported is good
|
|
122
|
+
|
|
123
|
+
- Unsupported or ambiguous cases should be recorded in diagnostics and docs.
|
|
124
|
+
- Silent fallback is program debt.
|
|
125
|
+
|
|
126
|
+
### Foundation before convenience
|
|
127
|
+
|
|
128
|
+
- Do not widen feature breadth by bypassing a missing architectural layer.
|
|
129
|
+
- If a feature needs a missing core layer, stop and create the layer task.
|
|
130
|
+
|
|
131
|
+
### Close each wave honestly
|
|
132
|
+
|
|
133
|
+
Before moving on:
|
|
134
|
+
|
|
135
|
+
- regression coverage must exist
|
|
136
|
+
- docs must match reality
|
|
137
|
+
- task graph must reflect the new queue
|
|
138
|
+
|
|
139
|
+
## Expected Outputs
|
|
140
|
+
|
|
141
|
+
For a healthy multi-agent program, the Program Lead should leave behind:
|
|
142
|
+
|
|
143
|
+
- a readable explainer
|
|
144
|
+
- a living mission tracker
|
|
145
|
+
- a dependency graph
|
|
146
|
+
- scoped task files
|
|
147
|
+
- regression expectations
|
|
148
|
+
- explicit next-step guidance after each review
|
|
149
|
+
|
|
150
|
+
## Anti-Patterns
|
|
151
|
+
|
|
152
|
+
These are warning signs that the Program Lead should stop and correct:
|
|
153
|
+
|
|
154
|
+
- "just start all the feature tasks"
|
|
155
|
+
- "we can clean the tracker later"
|
|
156
|
+
- "this branch probably has the latest state"
|
|
157
|
+
- "the snapshot changed, it is probably fine"
|
|
158
|
+
- "let's add one shortcut in this feature instead of solving the shared layer"
|
|
159
|
+
|
|
160
|
+
## Success Criteria
|
|
161
|
+
|
|
162
|
+
The role is working if:
|
|
163
|
+
|
|
164
|
+
- agents can work in parallel without constant semantic collisions
|
|
165
|
+
- merges are mostly thin and predictable
|
|
166
|
+
- tasks describe real isolated work instead of vague ambition
|
|
167
|
+
- docs tell a new contributor where the program really is
|
|
168
|
+
- the next wave opens only when the previous wave actually earned it
|
|
169
|
+
|
|
170
|
+
## Default Hand-off Pattern
|
|
171
|
+
|
|
172
|
+
For each review checkpoint, the Program Lead should answer:
|
|
173
|
+
|
|
174
|
+
1. What landed?
|
|
175
|
+
2. What is still missing?
|
|
176
|
+
3. Is there any blocker to moving forward?
|
|
177
|
+
4. Which tasks can start now?
|
|
178
|
+
5. Which tasks must still wait?
|
|
179
|
+
|
|
180
|
+
That hand-off pattern should be reusable across projects, not just ForgeCAD.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# ForgeCAD — What It Is and Where It's Going
|
|
2
|
+
|
|
3
|
+
## The Relationship with Manifold
|
|
4
|
+
|
|
5
|
+
[Manifold](https://github.com/elalish/manifold) is a geometry kernel. It does boolean operations on triangle meshes, extrusion, revolution, smoothing, and SDF level sets. It's fast, correct, and runs in WASM. Think of it as the engine block.
|
|
6
|
+
|
|
7
|
+
ForgeCAD is the car built around that engine. Manifold doesn't know what a "rectangle with named sides" is. It doesn't know what a "constraint" is. It doesn't have parameters, sliders, a code editor, or file imports. It gives you raw mesh operations — you give it polygons and get back polygons.
|
|
8
|
+
|
|
9
|
+
Every serious CAD system has this split:
|
|
10
|
+
- Fusion360 uses Parasolid/ACIS as its kernel
|
|
11
|
+
- FreeCAD uses OpenCascade
|
|
12
|
+
- ForgeCAD uses Manifold
|
|
13
|
+
|
|
14
|
+
The kernel is not the product. The modeling layer on top is.
|
|
15
|
+
|
|
16
|
+
## What ForgeCAD Adds Over Manifold
|
|
17
|
+
|
|
18
|
+
### Already built
|
|
19
|
+
- **Constraint solver** — 18 constraint types (coincident, parallel, perpendicular, tangent, equal, symmetric, concentric, collinear, distance, length, angle, radius, diameter, hDistance, vDistance, fixed, horizontal, vertical) with iterative relaxation solver. Detects under/over/fully-constrained states. Live constraint editing in the UI.
|
|
20
|
+
- **Named 2D entities** — `Rectangle2D`, `Circle2D`, `Line2D`, `Point2D` with semantic access (`.side('top')`, `.vertex('bottom-left')`, `.pointAtAngle(90)`)
|
|
21
|
+
- **Topology tracking** — `TrackedShape` preserves face/edge names through extrusion and translation. `shape.face('top')`, `shape.edge('vert-bl')`, `shape.rotateAroundEdge('top-bottom', 90)`.
|
|
22
|
+
- **Sketch primitives** — `roundedRect`, `slot`, `star`, `ngon`, `ellipse`, `polygon`, path builder with stroke
|
|
23
|
+
- **Patterns** — `linearPattern`, `circularPattern`, `mirrorCopy` for 3D shape arrays
|
|
24
|
+
- **Fillets & chamfers** — `filletCorners()` for selective 2D polygon corners, plus `filletEdge()` / `chamferEdge()` for vertical 3D edges using topology references
|
|
25
|
+
- **Arc bridge** — `arcBridgeBetweenRects()` for smooth arc surfaces between rectangular areas (e.g., laptop hinges)
|
|
26
|
+
- **Parameters** — `param()` creates live UI sliders, code re-executes on change
|
|
27
|
+
- **Multi-file** — `importSketch()`, `importPart()` with circular import detection, folder support
|
|
28
|
+
- **Code-as-format** — plain JS/TS files, version-controllable, LLM-writable
|
|
29
|
+
- **3D smoothing** — `smoothOut()` + `refine()` / `refineToLength()` / `refineToTolerance()` for edge rounding
|
|
30
|
+
- **3D advanced ops** — `hull3d()` (convex hull of shapes + points), `levelSet()` (SDF-based shapes), `warp()`, `split()`, `splitByPlane()`, `trimByPlane()`
|
|
31
|
+
- **Sketch on face** — `sketch.onFace(body, face, ...)` places a 2D sketch on canonical or tracked planar faces and extrudes from that face normal
|
|
32
|
+
- **Part library** — bolt holes, counterbores, tubes, pipes, hex nuts, rounded boxes, brackets, hole patterns, threaded bolts/nuts (real helical threads via SDF levelSet)
|
|
33
|
+
- **Colors** — `.color('#ff0000')` on both Shape and Sketch, preserved through transforms and booleans
|
|
34
|
+
- **CLI tools** — SVG export (pure Node), PNG render (Puppeteer), all sharing the same engine via `headless.ts`
|
|
35
|
+
- **Measurement tool** — Click-to-measure with vertex/edge/face snapping, draggable markers
|
|
36
|
+
- **File management** — File explorer with folders, drag-and-drop, rename, create/delete, unsaved change indicators
|
|
37
|
+
- **View controls** — Render modes (solid/wireframe/overlay), projection (perspective/orthographic), named views (front/back/left/right/top/bottom/iso), fit-to-view, zoom-to-selection
|
|
38
|
+
- **STL export** — Binary STL export from the browser UI
|
|
39
|
+
- **Cut planes** — `cutPlane()` defines named section planes for inspection. Viewport sectioning uses `trimByPlane()` for capped solids, with GPU clipping fallback on trim failures
|
|
40
|
+
|
|
41
|
+
### Gaps to close (Fusion360 parity)
|
|
42
|
+
|
|
43
|
+
| Feature | What it does | Why it matters | Difficulty |
|
|
44
|
+
|---------|-------------|----------------|------------|
|
|
45
|
+
| Arc entity | First-class arc in constraint system | Needed for fillet results to participate in constraints | Medium |
|
|
46
|
+
| Shell operation | Hollow a solid with wall thickness | Enclosures, cases, containers | Medium |
|
|
47
|
+
| Per-edge 3D fillet | Round specific edges by exact radius | The #1 most-used Fusion360 operation | Very Hard (mesh kernel) |
|
|
48
|
+
| Trim/extend | Cut or extend sketch entities at intersections | Complex sketch editing | Medium |
|
|
49
|
+
| Splines | B-spline curves in sketches | Organic shapes | Medium |
|
|
50
|
+
| Loft | Blend between multiple cross-section profiles | Transition shapes, aerodynamic forms | Hard |
|
|
51
|
+
| Thread/helix | Helical sweep for threads, springs | Mechanical fasteners | Medium (threads done via SDF, general helix sweep still missing) |
|
|
52
|
+
|
|
53
|
+
### What we deliberately skip
|
|
54
|
+
- **History tree / timeline** — code IS the history. You read it top to bottom. No need for a separate feature tree when the script is the tree.
|
|
55
|
+
- **Direct modeling** — push/pull faces interactively. Not relevant for code-first CAD.
|
|
56
|
+
- **Full GUI-style assembly mate solving** — Forge now supports code-level assembly graphs (`assembly()`, revolute/prismatic/fixed joints, collision checks, BOM metadata), but not full interactive face-mate workflows like Fusion's assembly workspace.
|
|
57
|
+
- **Photorealistic rendering** — not a rendering tool. Basic viewport materials are sufficient. Export to STL for slicing or external renderers.
|
|
58
|
+
|
|
59
|
+
## The Code-First Bet
|
|
60
|
+
|
|
61
|
+
The thesis: parametric CAD expressed as code is strictly more powerful than GUI-based CAD for certain workflows:
|
|
62
|
+
|
|
63
|
+
1. **LLM generation** — an AI can write and modify `.forge.js` files. It can't click buttons in Fusion360.
|
|
64
|
+
2. **Version control** — git diff on a `.forge.js` file shows exactly what changed. Fusion360 files are opaque blobs.
|
|
65
|
+
3. **Composition** — import a part, transform it, array it, subtract it. All in code. No manual assembly.
|
|
66
|
+
4. **Parametric by default** — every `param()` is a slider. No extra work to make something parametric.
|
|
67
|
+
5. **Extensibility** — if you need a new primitive, write a function. No plugin SDK needed.
|
|
68
|
+
|
|
69
|
+
This doesn't replace Fusion360 for everything. Interactive sketching, direct face manipulation, complex surfacing — those are better with a GUI. But for parametric parts, enclosures, mechanical components, and especially for AI-assisted design, code-first wins.
|
|
70
|
+
|
|
71
|
+
## Technical Direction
|
|
72
|
+
|
|
73
|
+
- **Keep Manifold as the kernel.** It's actively maintained, fast, and handles the hard geometry problems. Don't reimplement CSG.
|
|
74
|
+
- **Build the parametric layer.** Constraints, named entities, topology tracking, sketch operations — this is where ForgeCAD's value lives.
|
|
75
|
+
- **Expose Manifold's power.** Things like `smoothOut`, `refine`, `levelSet` (SDF), `warp` — make them accessible from user scripts with clean APIs.
|
|
76
|
+
- **Stay extensible.** Users should be able to define new primitives, new operations, new patterns inside their scripts. The API should be a toolkit, not a cage.
|
|
77
|
+
- **Make Forge semantics own the backends.** Manifold and CadQuery/OCCT should be lowerers for the same Forge modeling system, not competing authoring models. See [API/internals/compiler.md](API/internals/compiler.md).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// import-group-assembly.forge.js
|
|
2
|
+
// Demonstrates importGroup(): bring in a multipart component and work on
|
|
3
|
+
// the whole group or individual named children separately.
|
|
4
|
+
|
|
5
|
+
// --- Import the full assembly as a ShapeGroup ---
|
|
6
|
+
const bracketAssembly = importGroup("api/import-group-source.forge.js");
|
|
7
|
+
|
|
8
|
+
// Place it using a named reference (same API as importPart)
|
|
9
|
+
const placed = bracketAssembly.placeReference("mountCenter", [0, 0, 0]);
|
|
10
|
+
|
|
11
|
+
// --- Access individual children by name ---
|
|
12
|
+
// Each child is a Shape/TrackedShape/ShapeGroup you can manipulate independently.
|
|
13
|
+
const leftBracket = placed.child("Bracket Left");
|
|
14
|
+
const rightBracket = placed.child("Bracket Right");
|
|
15
|
+
const dowel = placed.child("Dowel");
|
|
16
|
+
|
|
17
|
+
// Make a highlight copy of the left bracket for visualisation
|
|
18
|
+
const highlight = leftBracket.color('#ff4444');
|
|
19
|
+
|
|
20
|
+
// --- A second instance, shifted and with overridden params ---
|
|
21
|
+
const secondAssembly = importGroup("api/import-group-source.forge.js", {
|
|
22
|
+
"Height": 60,
|
|
23
|
+
"Width": 80,
|
|
24
|
+
}).translate(150, 0, 0);
|
|
25
|
+
|
|
26
|
+
return [
|
|
27
|
+
// Show the first assembly as individual named parts
|
|
28
|
+
{ name: "Left Bracket (highlight)", shape: highlight },
|
|
29
|
+
{ name: "Right Bracket", shape: rightBracket },
|
|
30
|
+
{ name: "Dowel", shape: dowel },
|
|
31
|
+
|
|
32
|
+
// Show the second (translated) assembly as a group
|
|
33
|
+
{ name: "Second Assembly", shape: secondAssembly },
|
|
34
|
+
];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// import-group-source.forge.js
|
|
2
|
+
// A multipart bracket assembly exported as a named ShapeGroup.
|
|
3
|
+
// Import with: importGroup("api/import-group-source.forge.js")
|
|
4
|
+
|
|
5
|
+
const thickness = param("Thickness", 4, { min: 2, max: 8, unit: "mm" });
|
|
6
|
+
const height = param("Height", 40, { min: 20, max: 80, unit: "mm" });
|
|
7
|
+
const width = param("Width", 60, { min: 40, max: 120, unit: "mm" });
|
|
8
|
+
|
|
9
|
+
// Left bracket
|
|
10
|
+
const leftBracket = box(thickness, width, height)
|
|
11
|
+
.color('#5b7c8d');
|
|
12
|
+
|
|
13
|
+
// Right bracket — mirror of left
|
|
14
|
+
const rightBracket = box(thickness, width, height)
|
|
15
|
+
.translate(width + thickness, 0, 0)
|
|
16
|
+
.color('#5b7c8d');
|
|
17
|
+
|
|
18
|
+
// Connecting dowel — runs along Y axis between the two brackets
|
|
19
|
+
const dowel = cylinder(width, 3)
|
|
20
|
+
.rotate(90, 0, 0)
|
|
21
|
+
.translate(width / 2 + thickness, width, height / 2)
|
|
22
|
+
.color('#d38b4d');
|
|
23
|
+
|
|
24
|
+
return group(
|
|
25
|
+
{ name: "Bracket Left", shape: leftBracket },
|
|
26
|
+
{ name: "Bracket Right", shape: rightBracket },
|
|
27
|
+
{ name: "Dowel", shape: dowel },
|
|
28
|
+
).withReferences({
|
|
29
|
+
points: {
|
|
30
|
+
// Semantic mount point at the center of the left face
|
|
31
|
+
mountCenter: [0, width / 2, height / 2],
|
|
32
|
+
// Top-center of the full assembly
|
|
33
|
+
topCenter: [width / 2 + thickness, width / 2, height],
|
|
34
|
+
},
|
|
35
|
+
});
|