forgecad 0.9.13 → 0.9.15
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/LICENSE +6 -4
- package/README.md +8 -4
- package/dist/assets/{AdminPage-DramHHDf.js → AdminPage-CDyGUinA.js} +2 -2
- package/dist/assets/{BenchmarkPage-Bjgkh5m9.js → BenchmarkPage-DfPMY_-d.js} +4 -15
- package/dist/assets/{BlogPage-n_HGP3Qm.js → BlogPage-kF0fkdJT.js} +2 -2
- package/dist/assets/{DocsPage-WCIkPmzC.js → DocsPage-B954L3YN.js} +9 -3
- package/dist/assets/EditorApp-Beb-IZ0y.js +14014 -0
- package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-CuDLxKqL.css} +698 -0
- package/dist/assets/{EmbedViewer-DEZKqdfW.js → EmbedViewer-C77B-TrF.js} +3 -3
- package/dist/assets/{LandingPageProofDriven-CeRIctuj.js → LandingPageProofDriven-Cr6fXMDj.js} +35 -37
- package/dist/assets/LegalPage-BRlScr9A.css +91 -0
- package/dist/assets/LegalPage-Dzklqmmg.js +39 -0
- package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
- package/dist/assets/{PricingPage-rIRa8p4Y.js → PricingPage-zWXkvlwl.js} +19 -19
- package/dist/assets/{SettingsPage-BqCUvEXM.js → SettingsPage-Bz0of4KQ.js} +2 -2
- package/dist/assets/app-CE3sYcV7.css +3890 -0
- package/dist/assets/{app-BUZqJvSO.js → app-D3kDkggg.js} +2305 -960
- package/dist/assets/cli/{render-lhGxj50Y.js → render-DSY3mMQa.js} +423 -30
- package/dist/assets/{constructionHistoryWorker-ipD1jcIv.js → constructionHistoryWorker-gpDo-uH2.js} +927 -243
- package/dist/assets/{evalWorker-CHXSe_-u.js → evalWorker-CU0Ke6DP.js} +7799 -4163
- package/dist/assets/{forgecad_geometry-BVnIeXMG.js → forgecad_geometry-Dgceylq9.js} +43 -1
- package/dist/assets/{forgecad_geometry_bg-DufhhCBV.wasm → forgecad_geometry_bg-dD4RNQF1.wasm} +0 -0
- package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-COyp8XXA.js} +927 -243
- package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
- package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
- package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
- package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
- package/dist/assets/{manifold-D1LZIHqn.js → manifold-BRI5prcH.js} +1 -1
- package/dist/assets/{manifold-C2fwoTgd.js → manifold-C-3h2M7p.js} +2 -2
- package/dist/assets/{manifold-BTkzxi9V.js → manifold-DNkrUWpA.js} +1 -1
- package/dist/assets/{reportWorker-Cq1qGmg0.js → reportWorker-CdBz5bNg.js} +7537 -10856
- package/dist/assets/{scalar-sampling-budget-D9Qv_UlJ.js → scalar-sampling-budget-wJF98aY9.js} +6943 -4345
- package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-B-9VbLIs.js} +32 -1
- package/dist/assets/{renderSceneState-Dr0xPq1A.js → targets-B9sGB5nB.js} +27 -1
- package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/ai-native-cad.md +50 -0
- package/dist/docs-raw/AI/usage.md +9 -17
- package/dist/docs-raw/CLI.md +71 -21
- package/dist/docs-raw/component-model.md +27 -11
- package/dist/docs-raw/generated/assembly.md +301 -212
- package/dist/docs-raw/generated/concepts.md +238 -240
- package/dist/docs-raw/generated/core.md +283 -6
- package/dist/docs-raw/generated/curves.md +274 -361
- package/dist/docs-raw/generated/lib.md +7 -1
- package/dist/docs-raw/generated/output.md +19 -4
- package/dist/docs-raw/generated/runtime-names.md +41 -0
- package/dist/docs-raw/generated/sdf.md +31 -0
- package/dist/docs-raw/generated/sheet-metal.md +9 -0
- package/dist/docs-raw/generated/sketch.md +44 -1
- package/dist/docs-raw/generated/viewport.md +14 -6
- package/dist/docs-raw/guides/coordinate-system.md +20 -16
- package/dist/docs-raw/guides/geometry-conventions.md +2 -2
- package/dist/docs-raw/guides/inspection-bundles.md +2 -1
- package/dist/docs-raw/guides/joint-design.md +24 -0
- package/dist/docs-raw/guides/positioning.md +13 -3
- package/dist/docs-raw/legal/privacy.md +63 -0
- package/dist/docs-raw/legal/software-license.md +55 -0
- package/dist/docs-raw/legal/terms.md +87 -0
- package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +3 -3
- package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
- package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
- package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
- package/dist/docs-raw/skills/forgecad-lld.md +1 -1
- package/dist/docs-raw/skills/forgecad-make-a-model.md +4 -4
- package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
- package/dist/docs-raw/skills/forgecad-project.md +1 -1
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +4 -4
- package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
- package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
- package/dist/docs-raw/skills/forgecad.md +4 -3
- package/dist/index.html +40 -12
- package/dist/llms.txt +8 -0
- package/dist/site.webmanifest +1 -1
- package/dist/sitemap.xml +49 -13
- package/dist-cli/{check-compiler-LOXCPEOI.js → check-compiler-SDX5QIXI.js} +1 -2
- package/dist-cli/{check-query-propagation-BAKNVWXR.js → check-query-propagation-EAYEFT77.js} +1 -2
- package/dist-cli/{chunk-RY43WF46.js → chunk-N4O47JLF.js} +13772 -9938
- package/dist-cli/forgecad.js +2387 -899
- package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
- package/dist-cli/forgecad_geometry_bg.wasm +0 -0
- package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
- package/dist-skill/CONTEXT.md +1120 -724
- package/dist-skill/SKILL.md +3 -2
- package/dist-skill/docs/API/core/concepts.md +64 -1
- package/dist-skill/docs/CLI.md +71 -21
- package/dist-skill/docs/generated/assembly.md +277 -229
- package/dist-skill/docs/generated/core.md +283 -6
- package/dist-skill/docs/generated/curves.md +272 -362
- package/dist-skill/docs/generated/lib.md +7 -1
- package/dist-skill/docs/generated/output.md +19 -4
- package/dist-skill/docs/generated/runtime-names.md +41 -0
- package/dist-skill/docs/generated/sdf.md +31 -0
- package/dist-skill/docs/generated/sheet-metal.md +9 -0
- package/dist-skill/docs/generated/sketch.md +44 -2
- package/dist-skill/docs/generated/viewport.md +5 -90
- package/dist-skill/docs/guides/coordinate-system.md +20 -16
- package/dist-skill/docs/guides/geometry-conventions.md +2 -2
- package/dist-skill/docs/guides/inspection-bundles.md +2 -1
- package/dist-skill/docs/guides/joint-design.md +24 -0
- package/dist-skill/docs/guides/positioning.md +13 -3
- package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +2 -2
- package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
- package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +3 -3
- package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
- package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +3 -3
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
- package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
- package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
- package/examples/api/assembly-kinematics-limb.forge.js +116 -0
- package/examples/api/connector-frame-rig-chain.forge.js +102 -0
- package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
- package/examples/api/exact-surface-studio.forge.js +6 -8
- package/examples/api/helix-basics.forge.js +6 -6
- package/examples/api/lean-foundations/README.md +12 -0
- package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
- package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
- package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
- package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
- package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
- package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
- package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
- package/examples/api/route3d-elbow.forge.js +68 -0
- package/examples/api/transition-curves.forge.js +44 -15
- package/examples/api/y-blend-corner-showcase.forge.js +0 -2
- package/examples/generative/coral-vase.forge.js +1 -1
- package/examples/nurbs-tube.forge.js +1 -1
- package/package.json +14 -18
- package/dist/assets/EditorApp-CP9Za6tm.js +0 -13630
- package/dist/assets/app-CsHnaBWt.css +0 -1789
- package/dist/docs-raw/API/README.md +0 -16
- package/dist/docs-raw/API/core/concepts.md +0 -118
- package/dist/docs-raw/INDEX.md +0 -138
- package/dist/docs-raw/RELEASING.md +0 -87
- package/dist/docs-raw/agent-native-api.md +0 -27
- package/dist/docs-raw/beta-deployment.md +0 -304
- package/dist/docs-raw/beta-operations.md +0 -325
- package/dist/docs-raw/blueprint-first.md +0 -145
- package/dist/docs-raw/cli-monetization.md +0 -112
- package/dist/docs-raw/coding-best-practices.md +0 -120
- package/dist/docs-raw/coding.md +0 -340
- package/dist/docs-raw/deployment.md +0 -374
- package/dist/docs-raw/guides/skill-maintenance.md +0 -161
- package/dist/docs-raw/guides/surface-members.md +0 -82
- package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
- package/dist/docs-raw/internals/compiler.md +0 -307
- package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
- package/dist/docs-raw/internals/constraint-solver.md +0 -176
- package/dist/docs-raw/internals/shape-from-slices.md +0 -152
- package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
- package/dist/docs-raw/platform/admin.md +0 -45
- package/dist/docs-raw/platform/architecture.md +0 -82
- package/dist/docs-raw/platform/auth.md +0 -139
- package/dist/docs-raw/platform/email.md +0 -67
- package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
- package/dist/docs-raw/platform/observability.md +0 -197
- package/dist/docs-raw/platform/projects.md +0 -111
- package/dist/docs-raw/platform/sharing.md +0 -90
- package/dist/docs-raw/product/README.md +0 -39
- package/dist/docs-raw/product/api-as-product-language.md +0 -13
- package/dist/docs-raw/product/business-model.md +0 -15
- package/dist/docs-raw/product/competitive-positioning.md +0 -17
- package/dist/docs-raw/product/creative-manufacturing.md +0 -15
- package/dist/docs-raw/product/founder-story.md +0 -11
- package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
- package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
- package/dist/docs-raw/product/product-loop.md +0 -17
- package/dist/docs-raw/product/strategic-decisions.md +0 -22
- package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
- package/dist/docs-raw/product/user-segments.md +0 -15
- package/dist/docs-raw/product/vision.md +0 -26
- package/dist/docs-raw/rl-environments.md +0 -508
- package/dist/docs-raw/runbook.md +0 -611
- package/dist-cli/check-compiler-LOXCPEOI.js.map +0 -1
- package/dist-cli/check-query-propagation-BAKNVWXR.js.map +0 -1
- package/dist-cli/chunk-RY43WF46.js.map +0 -1
- package/dist-cli/forgecad.js.map +0 -1
- package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
- package/dist-cli/solver-46FFSK2U.js.map +0 -1
- package/dist-skill/SKILL-dev.md +0 -145
- package/dist-skill/docs-dev/API/core/concepts.md +0 -118
- package/dist-skill/docs-dev/CLI.md +0 -647
- package/dist-skill/docs-dev/agent-native-api.md +0 -27
- package/dist-skill/docs-dev/blueprint-first.md +0 -145
- package/dist-skill/docs-dev/coding-best-practices.md +0 -120
- package/dist-skill/docs-dev/coding.md +0 -340
- package/dist-skill/docs-dev/component-model.md +0 -164
- package/dist-skill/docs-dev/generated/assembly.md +0 -794
- package/dist-skill/docs-dev/generated/core.md +0 -2117
- package/dist-skill/docs-dev/generated/curves.md +0 -2583
- package/dist-skill/docs-dev/generated/lib.md +0 -169
- package/dist-skill/docs-dev/generated/output.md +0 -247
- package/dist-skill/docs-dev/generated/sdf.md +0 -446
- package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
- package/dist-skill/docs-dev/generated/sketch.md +0 -1811
- package/dist-skill/docs-dev/generated/viewport.md +0 -585
- package/dist-skill/docs-dev/generated/wood.md +0 -108
- package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
- package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
- package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
- package/dist-skill/docs-dev/guides/joint-design.md +0 -78
- package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
- package/dist-skill/docs-dev/guides/positioning.md +0 -161
- package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
- package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
- package/dist-skill/docs-dev/internals/compiler.md +0 -307
- package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
- package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
- package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
- package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-conventions
|
|
3
|
-
skill-order: 3
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Agent-Native API Design
|
|
7
|
-
|
|
8
|
-
ForgeCAD assumes that much of its model code will be written by AI coding agents. That is a strength of code-first CAD: the artifact is plain source, the API is documented, and the CLI gives the agent a feedback loop. A strong agent can read domain documentation and temporarily become useful in almost any specialty.
|
|
9
|
-
|
|
10
|
-
But "make the agent more specialized through documentation" is not the core problem ForgeCAD should solve. If the agent needs pages of instructions to hand-derive standard mechanical behavior, manually tune magic numbers, compute trigonometry, or reconstruct common CAD operations from primitives, the missing capability belongs in the API. Documentation can teach the vocabulary, but it should not compensate for a weak vocabulary.
|
|
11
|
-
|
|
12
|
-
The goal is an API specific and powerful enough to cover most serious modeling needs directly. Instead of asking agents to become gear experts, sheet-metal experts, fixture experts, or assembly-kinematics experts from scratch on every task, ForgeCAD should give them first-class concepts with names, contracts, diagnostics, and examples. The agent should read the docs to discover `lib.spurGear()`, `SheetMetal.flange()`, connector-based assemblies, inspection bundles, and exact export workflows, then compose those concepts with confidence.
|
|
13
|
-
|
|
14
|
-
Docs are leverage, not product substitute. They should explain what exists, when to use it, what guarantees it provides, what limitations remain, and how to validate the result. They should not become long recipes for reimplementing missing algorithms in user code. When a doc repeatedly explains how to work around an API gap, that is a design signal: promote the intent into the API, add diagnostics, and keep the recipe as orientation rather than obligation.
|
|
15
|
-
|
|
16
|
-
This is also why API specificity matters. Generic geometry escape hatches are valuable for unusual work, but the common path should preserve domain intent. A belt drive is not just a loop of tangent lines. A countersunk hole is not just three boolean cylinders. A multi-part assembly is not just a collection of translates. When ForgeCAD encodes those concepts directly, AI agents produce code that is shorter, more inspectable, easier to repair, and closer to what a mechanical designer meant.
|
|
17
|
-
|
|
18
|
-
## Design Gate
|
|
19
|
-
|
|
20
|
-
When improving docs or adding API surface, ask:
|
|
21
|
-
|
|
22
|
-
- Are we teaching the agent an existing ForgeCAD concept, or teaching it to reimplement a concept ForgeCAD should own?
|
|
23
|
-
- Would three different agents likely write three different fragile versions of this from the same docs?
|
|
24
|
-
- Does the current solution require hand-tuned constants, manual trigonometry, raw coordinate derivation, or silent fallback behavior?
|
|
25
|
-
- Could a domain-specific function, builder, namespace, diagnostic, or verification primitive make the intended model obvious?
|
|
26
|
-
|
|
27
|
-
If the answer points to missing vocabulary, prefer an API improvement over longer instructions. Let documentation make agents fluent in ForgeCAD; do not make documentation carry the weight of the CAD system.
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-conventions
|
|
3
|
-
skill-order: 3
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Blueprint-First Philosophy
|
|
7
|
-
|
|
8
|
-
## Code Should Read Like a Mechanical Blueprint
|
|
9
|
-
|
|
10
|
-
ForgeCAD is a **mechanical compiler**. The user inputs design intent — dimensions, constraints, relationships — and the engine handles the geometry. If a mechanical feature can be dimensioned on a 2D drawing without explicit X/Y coordinates, a user should be able to model it in ForgeCAD without calculating those coordinates.
|
|
11
|
-
|
|
12
|
-
We are building a geometry engine, not a math test.
|
|
13
|
-
|
|
14
|
-
## The Trigonometry Tax
|
|
15
|
-
|
|
16
|
-
Every time a user writes `Math.sin()` or `Math.cos()` to place a bolt hole, position a circular pattern, or compute a tangent point, our API has failed them. This is the **Trigonometry Tax** — the cost of translating declarative engineering intent into imperative Cartesian math.
|
|
17
|
-
|
|
18
|
-
The tax is real and measurable. In our own example library, ~40 of 250+ files contain manual trig. The same patterns repeat: circular positioning, polygon vertex layout, rotation result computation, polar-to-cartesian conversion. Each one is a place where the API should have provided an abstraction but didn't.
|
|
19
|
-
|
|
20
|
-
## The Core Pillars
|
|
21
|
-
|
|
22
|
-
### Pillar I: Intent-Driven Constraints over Explicit Coordinates
|
|
23
|
-
|
|
24
|
-
Traditional CAD-as-code requires calculating exact center points and intersections. ForgeCAD uses **constraint-driven pathing** — users define the knowns (radii, angles, distances), and the solver calculates the implicit intersections.
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
// The old way — calculating tangent arc intercepts by hand
|
|
28
|
-
const cx = r1 * Math.cos(angle) + offset * Math.sin(angle);
|
|
29
|
-
const cy = r1 * Math.sin(angle) - offset * Math.cos(angle);
|
|
30
|
-
|
|
31
|
-
// The ForgeCAD way — declare intent, solver handles geometry
|
|
32
|
-
sketch.route([
|
|
33
|
-
{ tangent: circleA },
|
|
34
|
-
{ fillet: 17 },
|
|
35
|
-
{ tangent: circleB },
|
|
36
|
-
]);
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Pillar II: Topological Selection
|
|
40
|
-
|
|
41
|
-
Hardcoding vertex indices or exact 3D coordinates to apply fillets makes models brittle. If a base dimension changes, the coordinates change, and the build breaks. ForgeCAD borrows from the DOM: **select geometry via topological queries, not hardcoded indices.**
|
|
42
|
-
|
|
43
|
-
```javascript
|
|
44
|
-
// Brittle — breaks if topology changes
|
|
45
|
-
body.fillet(5, edgeIndex[14]);
|
|
46
|
-
|
|
47
|
-
// ForgeCAD — semantic edge selection
|
|
48
|
-
fillet(body, 5, { parallel: [0, 0, 1], convex: true });
|
|
49
|
-
fillet(body, 3, selectEdges(body, { atZ: 0 }));
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Pillar III: Mechanical First-Class Citizens
|
|
53
|
-
|
|
54
|
-
Primitives should not be limited to circles, rectangles, and polygons. Mechanical engineering relies on standard features that are tedious to build from scratch. If a machinist has a specific tool bit for it, the API should have a specific primitive for it.
|
|
55
|
-
|
|
56
|
-
```javascript
|
|
57
|
-
// Holes with real mechanical features — not raw boolean subtraction
|
|
58
|
-
shape.hole('top', { diameter: 11, depth: 20,
|
|
59
|
-
counterbore: { diameter: 18, depth: 5 },
|
|
60
|
-
thread: { designation: 'M10' },
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Standard mechanical profiles
|
|
64
|
-
slot(30, 10);
|
|
65
|
-
arcSlot({ pitchRadius: 50, sweep: 60, width: 12 });
|
|
66
|
-
lib.spurGear({ module: 2, teeth: 24 });
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Pillar IV: Relative Workplanes
|
|
70
|
-
|
|
71
|
-
Everything in mechanical design is relative. You don't drill a hole at `[15.5, 30.2, 100.0]` in global space. You drill a hole on the top face of the flange, centered on the lug. The API must support dynamic coordinate systems that attach to existing geometry.
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
// Global coordinates — fragile, unreadable
|
|
75
|
-
const hole = circle2d(5).extrude(20).translate(15.5, 30.2, 100.0);
|
|
76
|
-
|
|
77
|
-
// Relative to geometry — moves with the parent
|
|
78
|
-
circle2d(5).onFace(flange, 'top', { u: 10, v: 0 }).extrude(-20);
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Pillar V: No Manual Math for Standard Layout
|
|
82
|
-
|
|
83
|
-
If a user has to import `Math.sin` to place elements in a circle, compute `Math.sqrt(3)` for an equilateral triangle, or manually convert degrees to radians, our API has a gap. Standard layout operations are first-class:
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
// Circular layout — no trig
|
|
87
|
-
const positions = circularLayout(12, radius);
|
|
88
|
-
|
|
89
|
-
// Polygon vertex positions — no sqrt(3)
|
|
90
|
-
const vertices = polygonVertices(3, radius);
|
|
91
|
-
|
|
92
|
-
// Polar positioning — no sin/cos
|
|
93
|
-
shape.translatePolar(radius, angleDeg);
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## The Anti-Patterns
|
|
97
|
-
|
|
98
|
-
### 1. No sin/cos in user code for standard layout
|
|
99
|
-
If a user imports `Math.sin` to place a bolt hole, we have a missing abstraction. We provide polar coordinates, patterns, and layout helpers natively.
|
|
100
|
-
|
|
101
|
-
### 2. No magic shrinkwraps without explicit control
|
|
102
|
-
Connections between shapes must be explicit. "Connect Shape A to Shape B with a tangent arc of R15" — not a black-box convex hull that guesses intent.
|
|
103
|
-
|
|
104
|
-
### 3. No silent failures
|
|
105
|
-
If a fillet radius is too large, or a tangent route can't be solved, the API throws a descriptive mechanical error — not a generic engine crash. (See also: CLAUDE.md "No Silent Fallbacks" rule.)
|
|
106
|
-
|
|
107
|
-
### 4. No coordinate math for relative positioning
|
|
108
|
-
If a feature is defined relative to another feature (a hole on a face, a boss centered on a lug), the API must express that relationship directly — not force the user to compute the absolute position.
|
|
109
|
-
|
|
110
|
-
## Design Gate
|
|
111
|
-
|
|
112
|
-
**Every new public API method must pass this test:**
|
|
113
|
-
|
|
114
|
-
> Can the user accomplish this without `Math.sin`, `Math.cos`, `Math.atan2`, manual degree-to-radian conversion, or computing intermediate Cartesian coordinates from polar/angular intent?
|
|
115
|
-
|
|
116
|
-
If the answer is no, the API needs a higher-level alternative. The raw math path can still exist for power users, but the common case must be trig-free.
|
|
117
|
-
|
|
118
|
-
## Ergonomics in JavaScript
|
|
119
|
-
|
|
120
|
-
JavaScript lacks Python's `with` statement, so ForgeCAD relies on **method chaining** and **callback scopes** for clean, fluid modeling:
|
|
121
|
-
|
|
122
|
-
```javascript
|
|
123
|
-
// Fluid chaining — sketch to solid to features
|
|
124
|
-
const part = circle2d(50)
|
|
125
|
-
.extrude(15)
|
|
126
|
-
.fillet(5, { atZ: 0 });
|
|
127
|
-
|
|
128
|
-
// Callback workplane — scoped 2D ops on a 3D face
|
|
129
|
-
shape.onFace('top', (face) => {
|
|
130
|
-
face.subtract(
|
|
131
|
-
circularPattern(circle2d(5.5), 6, { radius: 32.5 })
|
|
132
|
-
);
|
|
133
|
-
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## Architecture Constraints
|
|
137
|
-
|
|
138
|
-
- **TypeScript native.** Autocomplete and compile-time checking for mechanical parameters are mandatory.
|
|
139
|
-
- **B-Rep capable.** Topological naming and precise filleting require a real CAD kernel (Manifold for mesh, OCCT for B-Rep).
|
|
140
|
-
- **Immutable geometry, mutable builders.** Underlying geometry is immutable for predictable undo/redo. Builder classes maintain state for ergonomic chaining.
|
|
141
|
-
- **Degrees at the API boundary.** All user-facing angles are in degrees. Radians are an internal implementation detail.
|
|
142
|
-
|
|
143
|
-
## Summary
|
|
144
|
-
|
|
145
|
-
We are not building a 3D drawing tool. We are building a **mechanical compiler**. The user inputs the blueprint's design intent, and our API handles the geometry.
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-conventions
|
|
3
|
-
skill-order: 1
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Coding Best Practices
|
|
7
|
-
|
|
8
|
-
## Minimal Implementation
|
|
9
|
-
|
|
10
|
-
Write only the code needed to solve the problem. No verbose implementations, no speculative features.
|
|
11
|
-
|
|
12
|
-
## TypeScript
|
|
13
|
-
|
|
14
|
-
- Use explicit types for function parameters and return values
|
|
15
|
-
- Avoid `any` — use `unknown` or proper types
|
|
16
|
-
- Prefer interfaces for object shapes
|
|
17
|
-
|
|
18
|
-
## React Components
|
|
19
|
-
|
|
20
|
-
- Functional components only
|
|
21
|
-
- Inline styles for simplicity (no CSS files unless necessary)
|
|
22
|
-
- Extract reusable logic to custom hooks or store actions
|
|
23
|
-
|
|
24
|
-
### Stable References in Render Bodies
|
|
25
|
-
|
|
26
|
-
Never use `?? []`, `?? {}`, or inline fallback literals in a component render body if the value flows (directly or transitively) into a `useMemo`/`useCallback`/`useEffect` dependency array. Each render creates a new reference, which silently invalidates every downstream memo.
|
|
27
|
-
|
|
28
|
-
```tsx
|
|
29
|
-
// BAD — new [] every render, breaks every useMemo that depends on `items`
|
|
30
|
-
const items = config?.items ?? [];
|
|
31
|
-
|
|
32
|
-
// GOOD — stable reference across renders
|
|
33
|
-
const items = useMemo(() => config?.items ?? [], [config]);
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Use `useMemo` for any derived-with-fallback value that feeds into other hooks.
|
|
37
|
-
|
|
38
|
-
## State Management
|
|
39
|
-
|
|
40
|
-
- All global state lives in `forgeStore.ts`
|
|
41
|
-
- Use Zustand selectors to prevent unnecessary re-renders
|
|
42
|
-
- Keep actions pure and synchronous where possible
|
|
43
|
-
|
|
44
|
-
## Performance
|
|
45
|
-
|
|
46
|
-
### Geometry Operations
|
|
47
|
-
|
|
48
|
-
- Manifold operations are expensive — minimize boolean ops
|
|
49
|
-
- Cache geometry results when parameters don't change
|
|
50
|
-
- Use debouncing for real-time updates
|
|
51
|
-
|
|
52
|
-
### React Rendering
|
|
53
|
-
|
|
54
|
-
- Use Zustand selectors to prevent unnecessary re-renders
|
|
55
|
-
- Memoize expensive computations with `useMemo`
|
|
56
|
-
- Keep component tree shallow
|
|
57
|
-
|
|
58
|
-
## Linting & Formatting
|
|
59
|
-
|
|
60
|
-
[Biome](https://biomejs.dev/) handles both linting and formatting for all TS/JS code.
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
npm run lint # check for lint issues (no changes)
|
|
64
|
-
npm run lint:fix # auto-fix lint issues
|
|
65
|
-
npm run format # auto-format all files
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Biome runs as part of `npm run check:suite`. Configuration lives in `biome.json` at the repo root.
|
|
69
|
-
|
|
70
|
-
## Self-Review Before Commit
|
|
71
|
-
|
|
72
|
-
1. Remove console.logs and debug code
|
|
73
|
-
2. Check for unused imports
|
|
74
|
-
3. Verify TypeScript has no errors
|
|
75
|
-
4. Test the change works as intended
|
|
76
|
-
5. Read the diff — does it make sense?
|
|
77
|
-
|
|
78
|
-
### What to Look For
|
|
79
|
-
|
|
80
|
-
- Does this solve the problem with minimal code?
|
|
81
|
-
- Are there edge cases not handled?
|
|
82
|
-
- Is the code readable without comments?
|
|
83
|
-
- Does it follow existing patterns?
|
|
84
|
-
|
|
85
|
-
## API Naming: Methods Read Like Sentences
|
|
86
|
-
|
|
87
|
-
Public API method names must read like natural English. Prefer verbose, intuitive names over short, ambiguous ones. The method name alone should tell you exactly what it does — no options objects or magic strings needed to disambiguate.
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
// BAD — technical jargon, not a sentence
|
|
91
|
-
shape.rotateAxisAngle([0,1,0], 45)
|
|
92
|
-
|
|
93
|
-
// GOOD — reads like a sentence
|
|
94
|
-
shape.rotateX(45) // "rotate X 45 degrees"
|
|
95
|
-
shape.rotateY(45) // "rotate Y 45 degrees"
|
|
96
|
-
shape.rotateZ(45) // "rotate Z 45 degrees"
|
|
97
|
-
shape.rotate([0, 1, 0], 45) // "rotate around axis"
|
|
98
|
-
shape.rotateZ(45, { pivot: [10, 0, 0] }) // "rotate Z at pivot"
|
|
99
|
-
|
|
100
|
-
shape.scale(2) // "scale by 2" (from center)
|
|
101
|
-
shape.scaleAround(pivot, 2) // "scale around pivot"
|
|
102
|
-
|
|
103
|
-
shape.mirror([1,0,0]) // "mirror along X" (through center)
|
|
104
|
-
shape.mirrorThrough(point, [1,0,0]) // "mirror through point"
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Rules:
|
|
108
|
-
- The **bare method** (`rotate`, `scale`, `mirror`) does the common-sense default (operates relative to the shape's own center)
|
|
109
|
-
- **Longer names** make the reference point explicit — no ambiguity
|
|
110
|
-
- **No string literals** as behavior selectors (`'center'`, `'origin'`)
|
|
111
|
-
- **No options objects** to disambiguate what should be separate methods
|
|
112
|
-
|
|
113
|
-
## Runtime Global Namespace
|
|
114
|
-
|
|
115
|
-
Do not add new lowercase injected globals to `.forge.js` scripts. Existing lowercase globals such as `box`, `union`, and `loft` are established core vocabulary; new domain helpers must live under a PascalCase namespace or class such as `Product.materials`, `Product.profiles`, or `Shape.fromSlices`.
|
|
116
|
-
|
|
117
|
-
The repo enforces this in `npm run check:suite -- --profile smoke`. If a lowercase global truly must be added for compatibility, it needs an explicit API review and an allowlist update in `cli/check-runtime-globals.ts`.
|
|
118
|
-
|
|
119
|
-
## File length
|
|
120
|
-
Keep files under 200 lines. If a file grows beyond that, consider splitting it into smaller, focused files.
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-conventions
|
|
3
|
-
skill-order: 2
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# ForgeCAD Coding Guidelines
|
|
7
|
-
|
|
8
|
-
## Development Workflow
|
|
9
|
-
|
|
10
|
-
### Building & Running
|
|
11
|
-
```bash
|
|
12
|
-
npm install # Install dependencies
|
|
13
|
-
npm link # Install the local forgecad binary
|
|
14
|
-
forgecad studio examples # Start the browser studio (localhost:5173)
|
|
15
|
-
npm run build # Production build
|
|
16
|
-
npm run preview # Preview production build
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### CLI Tools
|
|
20
|
-
```bash
|
|
21
|
-
forgecad export svg examples/constraints/01-fully-constrained-rect.forge.js # Export sketch to SVG
|
|
22
|
-
forgecad render 3d examples/products/cup.forge.js # Render to PNG (Puppeteer + Chrome)
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
See [CLI.md](../CLI.md) for full CLI documentation.
|
|
26
|
-
|
|
27
|
-
### Project Structure
|
|
28
|
-
```
|
|
29
|
-
src/
|
|
30
|
-
├── forge/ # Core geometry engine (shared by browser + CLI)
|
|
31
|
-
│ ├── kernel.ts # Manifold WASM wrapper, Shape class, primitives
|
|
32
|
-
│ ├── headless.ts # Single entry point for all contexts (browser + Node CLI)
|
|
33
|
-
│ ├── index.ts # Browser entry point (re-exports from headless.ts)
|
|
34
|
-
│ ├── runner.ts # Script sandbox — executes user scripts and resolves imported .svg assets
|
|
35
|
-
│ ├── params.ts # Parameter system (param() → UI sliders)
|
|
36
|
-
│ ├── library.ts # Part library (lib.boltHole, lib.pipe, etc.)
|
|
37
|
-
│ ├── section.ts # Plane intersection / projection
|
|
38
|
-
│ ├── meshToGeometry.ts # Manifold mesh → Three.js BufferGeometry
|
|
39
|
-
│ ├── sceneBuilder.ts # Three.js scene setup (shared with CLI renderer)
|
|
40
|
-
│ └── sketch/ # 2D sketch system
|
|
41
|
-
│ ├── core.ts # Sketch class
|
|
42
|
-
│ ├── primitives.ts # rect, circle2d, polygon, ngon, etc.
|
|
43
|
-
│ ├── transforms.ts # translate, rotate, scale, mirror
|
|
44
|
-
│ ├── booleans.ts # add, subtract, intersect, union2d
|
|
45
|
-
│ ├── operations.ts # offset, simplify, warp
|
|
46
|
-
│ ├── extrude.ts # extrude, revolve (2D → 3D)
|
|
47
|
-
│ ├── path.ts # PathBuilder, stroke
|
|
48
|
-
│ ├── anchor.ts # attachTo/matchTo positioning
|
|
49
|
-
│ ├── constraints.ts # Constraint solver (18 types)
|
|
50
|
-
│ ├── entities.ts # Point2D, Line2D, Circle2D, Rectangle2D, Constraint helpers
|
|
51
|
-
│ ├── topology.ts # TrackedShape, face/edge naming
|
|
52
|
-
│ ├── patterns.ts # linearPattern, circularPattern, mirrorCopy
|
|
53
|
-
│ ├── fillets.ts # filletEdge, chamferEdge
|
|
54
|
-
│ ├── arcBridge.ts # arcBridgeBetweenRects
|
|
55
|
-
│ └── index.ts # Re-exports everything
|
|
56
|
-
├── components/ # React UI components
|
|
57
|
-
│ ├── Viewport.tsx # 3D viewport (Three.js + R3F)
|
|
58
|
-
│ ├── CodeEditor.tsx # Monaco editor with ForgeCAD types
|
|
59
|
-
│ ├── FileExplorer.tsx # Project file tree
|
|
60
|
-
│ ├── ViewPanel.tsx # Render mode, views, object settings
|
|
61
|
-
│ ├── ParamPanel.tsx # Parameter sliders
|
|
62
|
-
│ └── ExportPanel.tsx # STL export
|
|
63
|
-
├── store/
|
|
64
|
-
│ └── forgeStore.ts # Zustand global state
|
|
65
|
-
├── App.tsx # Main application shell
|
|
66
|
-
└── main.tsx # React entry point
|
|
67
|
-
|
|
68
|
-
cli/
|
|
69
|
-
├── forgecad.ts # Top-level CLI entrypoint and command routing
|
|
70
|
-
├── forge-svg.ts # SVG export (uses real engine via headless.ts)
|
|
71
|
-
├── forge-render.mjs # PNG render launcher (Puppeteer)
|
|
72
|
-
├── render.ts # Headless render entry (loaded in browser by Puppeteer)
|
|
73
|
-
└── render.html # HTML shell for headless render
|
|
74
|
-
|
|
75
|
-
examples/ # Example scripts
|
|
76
|
-
├── *.forge.js # 3D part and 2D sketch examples
|
|
77
|
-
└── constraints/ # Constrained sketch examples
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Coding Standards
|
|
81
|
-
|
|
82
|
-
See [coding-best-practices.md](coding-best-practices.md) for TypeScript, React, state management, and performance best practices.
|
|
83
|
-
|
|
84
|
-
## Agent-Native API Design Standard (Required)
|
|
85
|
-
|
|
86
|
-
ForgeCAD expects AI agents to author serious `.forge.js` models, but agent specialization through documentation is not a substitute for API design. Read [agent-native-api.md](agent-native-api.md) before treating a modeling difficulty as "just a docs problem."
|
|
87
|
-
|
|
88
|
-
If a common modeling task requires agents to reimplement a known CAD concept from recipes, trigonometry, magic numbers, or raw boolean construction, prefer a domain-specific API improvement with clear docs and diagnostics. Documentation should make agents fluent in ForgeCAD's vocabulary; it should not carry missing vocabulary.
|
|
89
|
-
|
|
90
|
-
## Domain Localization Standard (Required)
|
|
91
|
-
|
|
92
|
-
This standard is package-wide for any new user-facing concept or API family.
|
|
93
|
-
|
|
94
|
-
### Contract
|
|
95
|
-
- Each concept family must have a clear primary home in both code and docs.
|
|
96
|
-
- Extend the module that already owns the mental model instead of scattering helpers across unrelated files.
|
|
97
|
-
- When a feature spans multiple layers, pick one domain owner and make the other layers mirror that owner.
|
|
98
|
-
- Keep related runtime code, examples, checks, and docs close to the same domain name whenever practical.
|
|
99
|
-
|
|
100
|
-
### Examples
|
|
101
|
-
- Assembly and kinematics live under `src/forge/assembly.ts` and `docs/permanent/API/assembly/assembly.md`.
|
|
102
|
-
- Sketch constraints live under `src/forge/sketch/constraints.ts` and the sketch/entity API docs.
|
|
103
|
-
- Transform/placement helpers should stay grouped with transform and positioning surfaces, not reappear as ad-hoc helpers in unrelated modules.
|
|
104
|
-
|
|
105
|
-
### Enforcement
|
|
106
|
-
- Before adding a new API, state which domain owns it.
|
|
107
|
-
- If a concept currently has no clean home, create one instead of spreading the first implementation across multiple files.
|
|
108
|
-
|
|
109
|
-
## Backend Compiler Standard (Required)
|
|
110
|
-
|
|
111
|
-
This standard is package-wide for any geometry feature that affects runtime lowering, export-backend coverage, or backend capability routing.
|
|
112
|
-
|
|
113
|
-
Read [compiler.md](../internals/compiler.md) before changing this area.
|
|
114
|
-
For large multi-agent migrations or architecture programs, also read [PROGRAM-LEAD.md](../../processes/PROGRAM-LEAD.md).
|
|
115
|
-
|
|
116
|
-
### Contract
|
|
117
|
-
- Forge semantic intent comes first. Backends are lowerers, not the authoring model.
|
|
118
|
-
- Scene-level capability routing must stay centralized. Do not re-derive export/runtime policy ad hoc in unrelated modules.
|
|
119
|
-
- Public feature APIs must not hide backend-specific behavior directly in their callsites. Backend code belongs in the lowerers.
|
|
120
|
-
- New backend limitations must surface as diagnostics, not silent fallback or silent exactness loss.
|
|
121
|
-
|
|
122
|
-
### Enforcement
|
|
123
|
-
- If a feature is compile-covered, update the canonical compile graph and the scene compiler.
|
|
124
|
-
- If a feature is not yet dual-lowered, add explicit unsupported diagnostics for the missing backend rather than bypassing the compiler.
|
|
125
|
-
- Any geometry feature change must update invariant coverage and the living backend-compiler tracker.
|
|
126
|
-
|
|
127
|
-
## Multi-Agent Program Standard (Required For Large Migrations)
|
|
128
|
-
|
|
129
|
-
For work that spans multiple agent branches or staged dependency waves, the Program Lead role in [PROGRAM-LEAD.md](../../processes/PROGRAM-LEAD.md) is the default operating model.
|
|
130
|
-
|
|
131
|
-
Use it when:
|
|
132
|
-
|
|
133
|
-
- one missing foundation blocks several feature lanes
|
|
134
|
-
- multiple agents need isolated tasks with dependency ordering
|
|
135
|
-
- the repo needs a living task graph and capability tracker to stay truthful
|
|
136
|
-
|
|
137
|
-
The key rule is simple:
|
|
138
|
-
|
|
139
|
-
- solve the deepest shared prerequisite first
|
|
140
|
-
- only then open the parallel wave that builds on top of it
|
|
141
|
-
|
|
142
|
-
## Frame Composition Standard (Required)
|
|
143
|
-
|
|
144
|
-
This standard is package-wide for any code that composes transforms (`Transform`, joints, assemblies, kinematic helpers).
|
|
145
|
-
|
|
146
|
-
### Contract
|
|
147
|
-
- `A.mul(B)` means **apply A, then B**
|
|
148
|
-
- Use `composeChain(...)` for 3+ composed transforms instead of manual `.mul()` chains
|
|
149
|
-
- In assembly/kinematics, always express composition in this canonical order:
|
|
150
|
-
- `local -> childBase -> jointMotion -> jointFrame -> parentWorld`
|
|
151
|
-
|
|
152
|
-
### Why this is mandatory
|
|
153
|
-
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.
|
|
154
|
-
|
|
155
|
-
### 5-Why (2026-02 Assembly disconnect incident)
|
|
156
|
-
1. Why were arm segments disconnected?
|
|
157
|
-
Because child world transforms were composed in the wrong order in `assembly.solve()`.
|
|
158
|
-
2. Why was order wrong?
|
|
159
|
-
Because `.mul()` chain semantics (apply self, then other) were interpreted inconsistently with matrix notation.
|
|
160
|
-
3. Why was that ambiguity possible?
|
|
161
|
-
Because there was no single canonical frame equation documented and enforced in code review.
|
|
162
|
-
4. Why didn’t tests catch it immediately?
|
|
163
|
-
Because there was no invariant test comparing assembly-solved frame origins against an analytic kinematic oracle.
|
|
164
|
-
5. Why no invariant test existed?
|
|
165
|
-
Because we had feature-level example checks, but no package-wide transform convention gate.
|
|
166
|
-
|
|
167
|
-
Root cause: **missing, enforced transform/frame composition contract across code + tests.**
|
|
168
|
-
|
|
169
|
-
### Enforcement
|
|
170
|
-
- Any change touching transforms, joints, or assembly solving must run:
|
|
171
|
-
- `npm run check:suite -- --profile smoke`
|
|
172
|
-
- If the change affects user-facing geometry behavior, also run:
|
|
173
|
-
- `forgecad run <affected-example>`
|
|
174
|
-
|
|
175
|
-
## Editor Declaration Parity Standard (Required)
|
|
176
|
-
|
|
177
|
-
This standard is package-wide for any user-facing API exposed to scripts.
|
|
178
|
-
|
|
179
|
-
### Contract
|
|
180
|
-
- Runtime API and editor declarations must ship together:
|
|
181
|
-
- Runtime surface: `src/forge/*` exports + `src/forge/runner.ts` sandbox bindings
|
|
182
|
-
- Editor surface: `src/components/CodeEditor.tsx` `FORGE_TYPES`
|
|
183
|
-
- Docs surface: `docs/permanent/API/**/*.md`
|
|
184
|
-
- If an important feature is missing from editor declarations, you must either:
|
|
185
|
-
- implement declarations in the same change, or
|
|
186
|
-
- create a tracked task in `tasks/` that explicitly names the missing surface and scope.
|
|
187
|
-
|
|
188
|
-
### Enforcement
|
|
189
|
-
- Before merge, verify new/changed script APIs are present in all three surfaces above.
|
|
190
|
-
- Do not ship runtime-only features without either declaration parity or a tracking task.
|
|
191
|
-
|
|
192
|
-
## Multi-File Native Standard (Required)
|
|
193
|
-
|
|
194
|
-
ForgeCAD projects must scale cleanly across multiple files. Complex models should be **expressible as a composition of separate, independently-authored files** — not as a single growing script.
|
|
195
|
-
|
|
196
|
-
### Tenet
|
|
197
|
-
|
|
198
|
-
Every user-facing import mechanism must make multi-file composition a first-class path, not an afterthought:
|
|
199
|
-
|
|
200
|
-
- Any `.forge.js` file (returning a `Shape`, `ShapeGroup`, `Assembly`, or other type) can be imported with `require("./file.forge.js")`.
|
|
201
|
-
- `require()` accepts an optional second argument for parameter overrides: `require("./part.forge.js", { Width: 100 })`.
|
|
202
|
-
- Files can also use `exports.name = value` alongside or instead of `return` for named multi-export.
|
|
203
|
-
- Plain JS helpers and constants belong in regular `.js` modules imported via `require()` or standard `import`.
|
|
204
|
-
|
|
205
|
-
No user should have to choose between "clean file structure" and "full API access". If a new return type or authoring primitive appears, **its import path must ship at the same time or in the same milestone**.
|
|
206
|
-
|
|
207
|
-
### Consequences for API design
|
|
208
|
-
|
|
209
|
-
- New authoring primitives (anything a user might `return` from a `.forge.js` file) are automatically importable via `require()`.
|
|
210
|
-
- Imported objects must expose the same child-access and placement-reference ergonomics that inline objects do.
|
|
211
|
-
- Parameter overrides must be supported via the second argument to `require()` so multi-instance use is natural.
|
|
212
|
-
- If a sub-file feature cannot yet be fully composed (e.g. kinematic merge across file boundaries), document the limitation explicitly and create a tracked task — do not silently downgrade.
|
|
213
|
-
|
|
214
|
-
### Enforcement
|
|
215
|
-
|
|
216
|
-
- When adding a new return-type contract, check: is there an `import*()` function for it?
|
|
217
|
-
- When adding placement-reference or child-access APIs to an object type, check: do imported versions of that type also expose those APIs?
|
|
218
|
-
- Verify with `forgecad run` that a multi-file example using the new feature works end-to-end before merge.
|
|
219
|
-
|
|
220
|
-
## Script API Contract Standard (Required)
|
|
221
|
-
|
|
222
|
-
This standard is package-wide for any API exposed to user scripts.
|
|
223
|
-
|
|
224
|
-
### Contract
|
|
225
|
-
- Collection-shaped script APIs must accept the intuitive collection forms the docs advertise:
|
|
226
|
-
- variadic operands when the operation naturally works on many inputs
|
|
227
|
-
- a single array of operands when that keeps call sites composable
|
|
228
|
-
- Method syntax and function syntax must mirror each other for the same operation family.
|
|
229
|
-
- 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.
|
|
230
|
-
- 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.
|
|
231
|
-
|
|
232
|
-
### Enforcement
|
|
233
|
-
- Any change to user-facing script APIs must run:
|
|
234
|
-
- `npm run check:suite`
|
|
235
|
-
- If the change also affects transforms, dimensions, placement refs, or geometry semantics, run the relevant existing invariant checks too.
|
|
236
|
-
|
|
237
|
-
## Git Workflow
|
|
238
|
-
|
|
239
|
-
### Commit Every Major Change
|
|
240
|
-
Each logical unit of work should be a separate commit:
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
git add <files>
|
|
244
|
-
git commit -m "Add file explorer panel"
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### Commit Message Format
|
|
248
|
-
```
|
|
249
|
-
<verb> <what>
|
|
250
|
-
|
|
251
|
-
Examples:
|
|
252
|
-
- Add file explorer panel
|
|
253
|
-
- Fix measure mode toggle
|
|
254
|
-
- Update parameter slider styling
|
|
255
|
-
- Remove unused imports
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
Use present tense verbs: Add, Fix, Update, Remove, Refactor
|
|
259
|
-
|
|
260
|
-
### What Counts as "Major"
|
|
261
|
-
- New feature or component
|
|
262
|
-
- Bug fix
|
|
263
|
-
- Refactoring that changes structure
|
|
264
|
-
- Performance improvement
|
|
265
|
-
- Breaking API change
|
|
266
|
-
|
|
267
|
-
### What to Commit Together
|
|
268
|
-
- Related files for a single feature
|
|
269
|
-
- Tests with the code they test
|
|
270
|
-
- Documentation with the feature it describes
|
|
271
|
-
|
|
272
|
-
### Example Workflow
|
|
273
|
-
```bash
|
|
274
|
-
# Feature: Add file explorer
|
|
275
|
-
git add src/components/FileExplorer.tsx
|
|
276
|
-
git add src/store/forgeStore.ts
|
|
277
|
-
git add src/App.tsx
|
|
278
|
-
git commit -m "Add file explorer panel"
|
|
279
|
-
|
|
280
|
-
# Next feature: Add keyboard shortcuts
|
|
281
|
-
git add src/hooks/useKeyboard.ts
|
|
282
|
-
git add src/App.tsx
|
|
283
|
-
git commit -m "Add keyboard shortcuts for file operations"
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
## Testing
|
|
287
|
-
|
|
288
|
-
### Manual Testing Checklist
|
|
289
|
-
Before committing UI changes:
|
|
290
|
-
- [ ] Test in browser at localhost:5173
|
|
291
|
-
- [ ] Check console for errors
|
|
292
|
-
- [ ] Verify responsive behavior
|
|
293
|
-
- [ ] Test with example scripts
|
|
294
|
-
|
|
295
|
-
### Integration Testing
|
|
296
|
-
- Load example files and verify they render
|
|
297
|
-
- Test parameter sliders update geometry
|
|
298
|
-
- Verify STL export produces valid files
|
|
299
|
-
- Check measure mode calculates correctly
|
|
300
|
-
|
|
301
|
-
## Common Patterns
|
|
302
|
-
|
|
303
|
-
### Adding a New Sketch Primitive
|
|
304
|
-
1. Add function to `src/forge/sketch/primitives.ts`
|
|
305
|
-
2. It's auto-exported via `sketch/index.ts` → `headless.ts` → `index.ts`
|
|
306
|
-
3. Add it to the sandbox in `src/forge/runner.ts` (both the `new Function()` args and the call)
|
|
307
|
-
4. Add TypeScript hints in `src/components/CodeEditor.tsx` (`FORGE_TYPES`)
|
|
308
|
-
5. Update `docs/permanent/API/sketch/primitives.md`
|
|
309
|
-
6. Commit: "Add [primitive] sketch primitive"
|
|
310
|
-
|
|
311
|
-
### Adding a New 3D Primitive
|
|
312
|
-
1. Add function to `src/forge/kernel.ts`
|
|
313
|
-
2. Export from `headless.ts`
|
|
314
|
-
3. Add to runner sandbox in `src/forge/runner.ts`
|
|
315
|
-
4. Add TypeScript hints in `src/components/CodeEditor.tsx`
|
|
316
|
-
5. Commit: "Add [primitive] 3D primitive"
|
|
317
|
-
|
|
318
|
-
### Adding a New CLI Command
|
|
319
|
-
1. Create `cli/your-command.ts`
|
|
320
|
-
2. Import from `../src/forge/headless`
|
|
321
|
-
3. Call `await init()` then use `runScript()`
|
|
322
|
-
4. Add script to `package.json`
|
|
323
|
-
5. Update `docs/permanent/CLI.md`
|
|
324
|
-
6. Commit: "Add [command] CLI command"
|
|
325
|
-
|
|
326
|
-
### Adding UI State
|
|
327
|
-
1. Add to `src/store/forgeStore.ts` interface
|
|
328
|
-
2. Add initial value and actions
|
|
329
|
-
3. Wire up to component
|
|
330
|
-
4. Commit: "Add [feature] UI state"
|
|
331
|
-
|
|
332
|
-
### Adding a Component
|
|
333
|
-
1. Create in `src/components/`
|
|
334
|
-
2. Import and use in `App.tsx` or parent
|
|
335
|
-
3. Commit: "Add [Component] component"
|
|
336
|
-
|
|
337
|
-
### Key Architecture Rule: Single Source of Truth
|
|
338
|
-
All geometry logic lives in `src/forge/`. CLI tools import from `src/forge/headless.ts`.
|
|
339
|
-
**Never** duplicate forge logic in CLI scripts. If you need something in CLI, make sure
|
|
340
|
-
it's exported from `headless.ts` and import it.
|