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,374 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
# ForgeCAD Deployment & Environment
|
|
5
|
-
|
|
6
|
-
See also the **[Runbook](runbook.md)** for day-to-day operations, testing, troubleshooting, and API reference.
|
|
7
|
-
See **[Observability](platform/observability.md)** for the incident debugging workflow, dashboards, logs, metrics, and stack access.
|
|
8
|
-
|
|
9
|
-
ForgeCAD runs on a **Hetzner VPS** deployed via **[Kamal 2](https://kamal-deploy.org)**. Kamal handles zero-downtime rolling deploys, TLS, and container orchestration.
|
|
10
|
-
|
|
11
|
-
**Environments:**
|
|
12
|
-
|
|
13
|
-
| Env | URL | Config | Postgres accessory | Purpose |
|
|
14
|
-
|-----|-----|--------|--------------------|---------|
|
|
15
|
-
| **production** | https://forgecad.io | `config/deploy.yml` | `forgecad-postgres` | Real users |
|
|
16
|
-
| **beta** | https://beta.forgecad.io | `config/deploy.beta.yml` | `forgecad-postgres-beta` | Staging; every change lands here before prod |
|
|
17
|
-
|
|
18
|
-
Beta runs on the same VPS as prod, fully isolated at the process level —
|
|
19
|
-
separate containers, separate volumes, separate secrets, separate JWT keys.
|
|
20
|
-
See [beta-operations.md](beta-operations.md) for the full runbook.
|
|
21
|
-
|
|
22
|
-
**Kamal configs, Docker images:**
|
|
23
|
-
|
|
24
|
-
| Config | Dockerfile | Service | Image |
|
|
25
|
-
|--------|-----------|---------|-------|
|
|
26
|
-
| `config/deploy.yml` | `Dockerfile` | `forgecad` (web, prod) | `ghcr.io/kostard/forgecad-web` |
|
|
27
|
-
| `config/deploy.beta.yml` | `Dockerfile` | `forgecad-beta` (web, beta) | `ghcr.io/kostard/forgecad-web` |
|
|
28
|
-
| `config/deploy.backend.yml` | `Dockerfile.backend` | `forgecad-backend` (compute) | `ghcr.io/kostard/forgecad-backend` |
|
|
29
|
-
|
|
30
|
-
**Architecture:**
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
Cloudflare (TLS termination, "Full Strict" + Origin Certificate)
|
|
34
|
-
│
|
|
35
|
-
└─ kamal-proxy (:443/:80) ← TLS with Cloudflare Origin Cert
|
|
36
|
-
│
|
|
37
|
-
├─ forgecad web container ← Fastify app (Node.js) on :5173
|
|
38
|
-
│ │
|
|
39
|
-
│ ├─ Serves SPA (dist/) ← Vite-built React frontend
|
|
40
|
-
│ ├─ API routes (/api/*) ← Auth, projects, files
|
|
41
|
-
│ ├─ Metrics listener ← Internal-only Prometheus scrape on :9464
|
|
42
|
-
│ └─ connects to ──────────► postgresql accessory
|
|
43
|
-
│
|
|
44
|
-
└─ forgecad-backend container ← Compute server on :4510
|
|
45
|
-
└─ ForgeCAD kernel (Node.js + WASM)
|
|
46
|
-
|
|
47
|
-
Volume: forgecad-project-data ← User project files on disk
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
All containers share the `kamal` Docker network. The web container reaches the backend via the network alias `forgecad-backend`. Postgres is a Kamal accessory — never restarted on app deploys.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Deploying
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
# Deploy prod web app (zero-downtime rolling update)
|
|
58
|
-
npm run prod:deploy
|
|
59
|
-
|
|
60
|
-
# Deploy prod backend compute server
|
|
61
|
-
npm run prod:deploy:backend
|
|
62
|
-
|
|
63
|
-
# Deploy both prod services
|
|
64
|
-
npm run prod:deploy:all
|
|
65
|
-
|
|
66
|
-
# Deploy the same commit to beta (run BEFORE prod)
|
|
67
|
-
npm run beta:deploy
|
|
68
|
-
|
|
69
|
-
# Open the environment after a deploy
|
|
70
|
-
npm run beta:smoke
|
|
71
|
-
npm run prod:smoke
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Recommended flow for a change: merge to `mainline` → `npm run beta:deploy`
|
|
75
|
-
→ verify on `beta.forgecad.io` → `npm run prod:deploy`.
|
|
76
|
-
See [beta-operations.md](beta-operations.md) for the full beta runbook.
|
|
77
|
-
|
|
78
|
-
Kamal builds the Docker image on the server via SSH (`builder: remote:`), pushes to GHCR, pulls on the server, starts the new container, waits for healthcheck, switches traffic, stops old container. Zero downtime.
|
|
79
|
-
|
|
80
|
-
### Auto-deploy via CI
|
|
81
|
-
|
|
82
|
-
Push to `mainline` triggers `.github/workflows/deploy.yml` which runs `kamal deploy` (and optionally the backend). The GitHub Action SSHs into Hetzner and orchestrates the build there — no GitHub Actions compute used for building.
|
|
83
|
-
|
|
84
|
-
### Rollback
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
# Some Kamal installs require an explicit version argument.
|
|
88
|
-
# List recent prod web versions on Hetzner:
|
|
89
|
-
ssh hetzner 'docker ps -a --format "{{.Names}}\t{{.Status}}" | grep "^forgecad-web-" | sed -E "s/^forgecad-web-([a-f0-9]+)(_replaced_[^[:space:]]+)?\t/\1\t/"'
|
|
90
|
-
|
|
91
|
-
# Roll the web app back to the last known-good version:
|
|
92
|
-
npm run prod:rollback -- <VERSION>
|
|
93
|
-
|
|
94
|
-
# Backend rollback:
|
|
95
|
-
npm run prod:rollback:backend -- <VERSION>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Example:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm run prod:rollback -- db9c49b058aaa379d9d622456cb249f9b0ddc335
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
Use the most recent healthy version from the `docker ps -a` output above. The
|
|
105
|
-
version is the hex suffix in the Kamal container name, e.g.
|
|
106
|
-
`forgecad-web-<VERSION>`.
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## Configuration Files
|
|
111
|
-
|
|
112
|
-
| File | Purpose | Gitignored? |
|
|
113
|
-
|------|---------|-------------|
|
|
114
|
-
| `config/deploy.yml` | Kamal config for prod web app + postgres accessory | No |
|
|
115
|
-
| `config/deploy.beta.yml` | Kamal config for beta web app + its own postgres accessory | No |
|
|
116
|
-
| `config/deploy.backend.yml` | Kamal config for backend compute (prod) | No |
|
|
117
|
-
| `.kamal/secrets` | Production secrets (DB, JWT, OAuth, email, registry) | Yes |
|
|
118
|
-
| `.kamal/secrets.beta` | Beta secrets — must differ from prod | Yes |
|
|
119
|
-
| `.kamal/secrets.beta.example` | Template for `.kamal/secrets.beta` | No |
|
|
120
|
-
| `.kamal/certs/origin-cert.pem` | Cloudflare Origin Certificate (shared prod + beta, needs `*.forgecad.io` SAN) | Yes |
|
|
121
|
-
| `.kamal/certs/origin-key.pem` | Cloudflare Origin Private Key | Yes |
|
|
122
|
-
| `.github/workflows/deploy.yml` | CI deploy pipeline (prod only — beta is manual) | No |
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Operator Shortcuts
|
|
127
|
-
|
|
128
|
-
Routine production and beta admin work is wrapped by repo-local scripts so the
|
|
129
|
-
flow stays safe and memorable without changing the public ForgeCAD user CLI:
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
npm run prod:deploy
|
|
133
|
-
npm run prod:smoke
|
|
134
|
-
npm run prod:deploy:backend
|
|
135
|
-
npm run prod:deploy:all
|
|
136
|
-
npm run prod:rollback -- <VERSION>
|
|
137
|
-
npm run prod:logs
|
|
138
|
-
npm run prod:logs:backend
|
|
139
|
-
npm run prod:shell
|
|
140
|
-
npm run prod:db
|
|
141
|
-
npm run prod:health
|
|
142
|
-
npm run prod:errors -- web 1000
|
|
143
|
-
|
|
144
|
-
npm run beta:setup
|
|
145
|
-
npm run beta:deploy
|
|
146
|
-
npm run beta:smoke
|
|
147
|
-
npm run beta:logs
|
|
148
|
-
npm run beta:refresh
|
|
149
|
-
npm run beta:local
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
`beta:local` is the local-only smoke path: it launches a hosted frontend plus
|
|
153
|
-
`FORGE_ENVIRONMENT=beta` backend on localhost, so you can open the browser and
|
|
154
|
-
judge the UX without touching Cloudflare.
|
|
155
|
-
|
|
156
|
-
These package scripts are thin wrappers around `scripts/prod.sh`,
|
|
157
|
-
`scripts/beta.sh`, and Kamal. Use raw Kamal commands when debugging Kamal
|
|
158
|
-
itself; otherwise prefer the environment-prefixed shortcuts.
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Environment Variables
|
|
163
|
-
|
|
164
|
-
### Server Core
|
|
165
|
-
|
|
166
|
-
| Variable | Required | Default | Purpose |
|
|
167
|
-
|----------|----------|---------|---------|
|
|
168
|
-
| `NODE_ENV` | no | `development` | Set to `production` for deployed instances |
|
|
169
|
-
| `FORGE_ENVIRONMENT` | no | `production` | `production`, `beta`, or `development`. Drives the BETA banner in the UI and the `/api/health` response. Independent of `NODE_ENV`. |
|
|
170
|
-
| `FORGE_PORT` | no | `5173` | HTTP port the server listens on |
|
|
171
|
-
| `FORGE_HOST` | no | `127.0.0.1` | Bind address. Use `0.0.0.0` in Docker |
|
|
172
|
-
| `FORGE_METRICS_PORT` | no | `9464` | Internal Prometheus metrics listener port |
|
|
173
|
-
| `FORGE_METRICS_HOST` | no | `127.0.0.1` | Bind address for the internal metrics listener |
|
|
174
|
-
| `FORGE_DIST_DIR` | no | — | Path to Vite build output. In Docker: `/app/dist` |
|
|
175
|
-
|
|
176
|
-
### Database
|
|
177
|
-
|
|
178
|
-
ForgeCAD uses PostgreSQL 16 for users, projects, sessions, and audit logs. The database schema is managed by Drizzle ORM with auto-migrations on server startup.
|
|
179
|
-
|
|
180
|
-
| Variable | Required | Default | Purpose |
|
|
181
|
-
|----------|----------|---------|---------|
|
|
182
|
-
| `FORGE_DB_URL` | **yes** | — | PostgreSQL connection string |
|
|
183
|
-
| `FORGE_DB_SLOW_QUERY_MS` | no | `250` | Slow-query threshold for DB warning logs and metrics |
|
|
184
|
-
|
|
185
|
-
In Kamal, Postgres runs as an accessory with the hostname `forgecad-postgres` on the `kamal` Docker network:
|
|
186
|
-
```
|
|
187
|
-
FORGE_DB_URL=postgresql://<user>:<pass>@forgecad-postgres:5432/forgecad
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Authentication
|
|
191
|
-
|
|
192
|
-
| Variable | Required | Default | Purpose |
|
|
193
|
-
|----------|----------|---------|---------|
|
|
194
|
-
| `FORGE_JWT_SECRET` | **yes** | — | HMAC key for signing JWT tokens. Generate: `openssl rand -base64 32` |
|
|
195
|
-
| `FORGE_JWT_ACCESS_EXPIRES` | no | `15m` | Access token lifetime |
|
|
196
|
-
| `FORGE_JWT_REFRESH_EXPIRES` | no | `7d` | Refresh token lifetime |
|
|
197
|
-
|
|
198
|
-
### CORS & Public URL
|
|
199
|
-
|
|
200
|
-
| Variable | Required | Default | Purpose |
|
|
201
|
-
|----------|----------|---------|---------|
|
|
202
|
-
| `FORGE_ALLOWED_ORIGINS` | no | `http://localhost:5173` | Comma-separated CORS origins |
|
|
203
|
-
| `FORGE_APP_URL` | no | `http://localhost:5173` | Public base URL for email links |
|
|
204
|
-
|
|
205
|
-
### OAuth Providers
|
|
206
|
-
|
|
207
|
-
| Variable | Required | Default | Purpose |
|
|
208
|
-
|----------|----------|---------|---------|
|
|
209
|
-
| `GITHUB_CLIENT_ID` | no | — | GitHub OAuth app client ID |
|
|
210
|
-
| `GITHUB_CLIENT_SECRET` | no | — | GitHub OAuth app client secret |
|
|
211
|
-
| `GOOGLE_CLIENT_ID` | no | — | Google OAuth client ID |
|
|
212
|
-
| `GOOGLE_CLIENT_SECRET` | no | — | Google OAuth client secret |
|
|
213
|
-
|
|
214
|
-
### Email Delivery
|
|
215
|
-
|
|
216
|
-
| Variable | Required | Default | Purpose |
|
|
217
|
-
|----------|----------|---------|---------|
|
|
218
|
-
| `RESEND_API_KEY` | no | — | API key from resend.com. Without it, emails logged to stdout |
|
|
219
|
-
| `FORGE_EMAIL_FROM` | no | `ForgeCAD <noreply@forgecad.io>` | Sender address |
|
|
220
|
-
|
|
221
|
-
### File Storage
|
|
222
|
-
|
|
223
|
-
| Variable | Required | Default | Purpose |
|
|
224
|
-
|----------|----------|---------|---------|
|
|
225
|
-
| `FORGE_STORAGE_ROOT` | no | `/data/projects` | Root directory for user project files |
|
|
226
|
-
|
|
227
|
-
In Docker, this is backed by the `forgecad-project-data` volume.
|
|
228
|
-
|
|
229
|
-
### Backend Compute
|
|
230
|
-
|
|
231
|
-
| Variable | Required | Default | Purpose |
|
|
232
|
-
|----------|----------|---------|---------|
|
|
233
|
-
| `FORGE_COMPUTE_URL` | no | `http://localhost:4510` | Backend server address (from Fastify's perspective) |
|
|
234
|
-
| `FORGE_BACKEND_PORT` | no | `4510` | Backend server listen port |
|
|
235
|
-
|
|
236
|
-
In Kamal, the web app reaches the backend via `http://forgecad-backend:4510` (Docker network alias).
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
## Secrets Management
|
|
241
|
-
|
|
242
|
-
Secrets are stored in `.kamal/secrets` (gitignored). Kamal reads this file as a shell script — you can use `$(cat ...)` for multi-line values like TLS certificates:
|
|
243
|
-
|
|
244
|
-
```bash
|
|
245
|
-
FORGE_JWT_SECRET=your-secret-here
|
|
246
|
-
FORGE_DB_URL=postgresql://user:pass@forgecad-postgres:5432/forgecad
|
|
247
|
-
CLOUDFLARE_ORIGIN_CERT=$(cat .kamal/certs/origin-cert.pem)
|
|
248
|
-
CLOUDFLARE_ORIGIN_KEY=$(cat .kamal/certs/origin-key.pem)
|
|
249
|
-
KAMAL_REGISTRY_PASSWORD=ghp_your_github_pat
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
For CI deploys, secrets are passed as GitHub Actions secrets (see `.github/workflows/deploy.yml`).
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## TLS / SSL
|
|
257
|
-
|
|
258
|
-
TLS is handled by **Cloudflare** (edge termination) + **Cloudflare Origin Certificate** (origin authentication).
|
|
259
|
-
|
|
260
|
-
- Cloudflare SSL mode: **Full (Strict)**
|
|
261
|
-
- Origin cert stored in `.kamal/certs/` (gitignored, 15-year validity)
|
|
262
|
-
- kamal-proxy serves the Origin Certificate to Cloudflare
|
|
263
|
-
- `forward_headers: true` in proxy config passes `X-Forwarded-For` from Cloudflare
|
|
264
|
-
|
|
265
|
-
To regenerate the Origin Certificate: Cloudflare dashboard → SSL/TLS → Origin Server → Create Certificate (PEM format, hostnames: `*.forgecad.io` and `forgecad.io`).
|
|
266
|
-
|
|
267
|
-
---
|
|
268
|
-
|
|
269
|
-
## Database Migrations
|
|
270
|
-
|
|
271
|
-
Migrations run automatically on server startup (`server/db/migrate.ts`). No manual database setup needed — the ForgeCAD server creates all tables on first boot.
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## Debugging Production
|
|
276
|
-
|
|
277
|
-
Use the observability stack first for incidents:
|
|
278
|
-
|
|
279
|
-
- [runbook.md](runbook.md#observability-first-incident-workflow)
|
|
280
|
-
- [platform/observability.md](platform/observability.md)
|
|
281
|
-
|
|
282
|
-
SSH access: `ssh hetzner` (see `~/.ssh/config`).
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
# Kamal-backed commands (run from project root locally)
|
|
286
|
-
npm run prod:logs # web app logs
|
|
287
|
-
npm run prod:logs:backend # backend logs
|
|
288
|
-
npm run prod:shell # shell into web container
|
|
289
|
-
kamal proxy details # proxy routing info
|
|
290
|
-
|
|
291
|
-
# Direct SSH
|
|
292
|
-
ssh hetzner "docker ps --format 'table {{.Names}}\t{{.Status}}' | grep -E 'forgecad|kamal'"
|
|
293
|
-
ssh hetzner "df -h / && free -h"
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
### Production scripts
|
|
297
|
-
|
|
298
|
-
```bash
|
|
299
|
-
npm run prod:health # containers, disk, memory
|
|
300
|
-
npm run prod:errors -- web 1000 # error logs only
|
|
301
|
-
npm run prod:db # interactive psql via Kamal
|
|
302
|
-
bash scripts/prod/db.sh "SELECT ..." # one-shot SQL query
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Email not delivered
|
|
306
|
-
|
|
307
|
-
If `RESEND_API_KEY` is empty, emails are logged to stdout instead of sent. Check:
|
|
308
|
-
```bash
|
|
309
|
-
kamal app exec "env | grep RESEND"
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
---
|
|
313
|
-
|
|
314
|
-
## Local Development
|
|
315
|
-
|
|
316
|
-
### Quick start (editor only, no auth)
|
|
317
|
-
|
|
318
|
-
```bash
|
|
319
|
-
npm run dev
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
No database, no login. For geometry, sketches, viewer work.
|
|
323
|
-
|
|
324
|
-
### Full stack (auth, database, landing page, docs, blog)
|
|
325
|
-
|
|
326
|
-
```bash
|
|
327
|
-
# Terminal 1: start PostgreSQL
|
|
328
|
-
npm run dev:db
|
|
329
|
-
|
|
330
|
-
# Terminal 2: start Fastify API server (port 5174)
|
|
331
|
-
npm run dev:server
|
|
332
|
-
|
|
333
|
-
# Terminal 3: start Vite dev server (port 5173, proxies /api to 5174)
|
|
334
|
-
npm run dev:studio
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
To stop the database: `npm run dev:db:stop`
|
|
338
|
-
|
|
339
|
-
**Dev credentials** (hardcoded in `dev:server`, never used in production):
|
|
340
|
-
- Database: `forgecad:forgecad@localhost:5432/forgecad`
|
|
341
|
-
- JWT secret: `dev-secret-do-not-use-in-production`
|
|
342
|
-
|
|
343
|
-
### Production build locally
|
|
344
|
-
|
|
345
|
-
```bash
|
|
346
|
-
npm run dev:db # start PostgreSQL (once)
|
|
347
|
-
npm run dev:prod # tsc + vite build + run Fastify server
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
---
|
|
351
|
-
|
|
352
|
-
## Kamal Setup Notes
|
|
353
|
-
|
|
354
|
-
**Prerequisites for deploying from a new machine:**
|
|
355
|
-
1. Ruby (3.1+): `brew install ruby`
|
|
356
|
-
2. Kamal: `gem install kamal`
|
|
357
|
-
3. Docker + buildx: `brew install docker` + buildx plugin
|
|
358
|
-
4. Colima (macOS): `brew install colima && colima start`
|
|
359
|
-
5. SSH access to Hetzner: `ssh hetzner` must work
|
|
360
|
-
6. `.kamal/secrets` populated with production values
|
|
361
|
-
7. `.kamal/certs/` with Cloudflare Origin Certificate PEM files
|
|
362
|
-
|
|
363
|
-
**Kamal paths (Homebrew Ruby on macOS):**
|
|
364
|
-
```
|
|
365
|
-
/opt/homebrew/opt/ruby/bin
|
|
366
|
-
/opt/homebrew/lib/ruby/gems/4.0.0/bin/kamal
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
Add to fish: `fish_add_path /opt/homebrew/opt/ruby/bin /opt/homebrew/lib/ruby/gems/4.0.0/bin`
|
|
370
|
-
|
|
371
|
-
**Server requirements:**
|
|
372
|
-
- Docker installed
|
|
373
|
-
- Login shell must be bash (not fish): `sudo chsh -s /bin/bash <user>`
|
|
374
|
-
- Docker logged into GHCR: `docker login ghcr.io -u KoStard`
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-skill
|
|
3
|
-
skill-order: 1
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Skill System Maintenance
|
|
7
|
-
|
|
8
|
-
ForgeCAD ships an AI agent skill that teaches language models how to author `.forge.js` models. The skill has two variants:
|
|
9
|
-
|
|
10
|
-
- **Standard** (`forgecad skill install`) — model-authoring docs only. Shipped to users.
|
|
11
|
-
- **Dev** (`forgecad skill install --dev`) — everything above plus internals (compiler, solver, sketch pipeline, coding conventions, full CLI). For developers building ForgeCAD itself.
|
|
12
|
-
|
|
13
|
-
## Architecture
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
docs/permanent/ ← source of truth for all docs
|
|
17
|
-
scripts/build-forgecad-skill.mjs ← reads docs, emits skill artifacts
|
|
18
|
-
dist-skill/
|
|
19
|
-
SKILL.md ← standard skill ({{SKILL_DIR}} placeholders)
|
|
20
|
-
SKILL-dev.md ← dev skill (same, with extra sections)
|
|
21
|
-
CONTEXT.md ← one-file paste target for chat UIs
|
|
22
|
-
docs/ ← full docs tree, copied from docs/permanent/
|
|
23
|
-
library/ ← namespaced companion skills for `skill install`
|
|
24
|
-
docs/permanent/skills/ ← generated website pages for installable skills
|
|
25
|
-
src/pages/generatedSkillSections.ts ← generated docs sidebar/search manifest
|
|
26
|
-
skills/forgecad/SKILL.md ← in-repo dev SKILL.md (relative paths)
|
|
27
|
-
skills/*/SKILL.md ← companion workflow skills, tagged for public export
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
At install time (`forge-skill.ts`), the `{{SKILL_DIR}}` placeholder is replaced with the actual install directory (for example `~/.agents/skills/forgecad`), and the docs tree is copied alongside.
|
|
31
|
-
|
|
32
|
-
## Adding a New Doc to the Skill
|
|
33
|
-
|
|
34
|
-
1. Write the doc under `docs/permanent/` (e.g. `docs/permanent/API/core/my-feature.md`).
|
|
35
|
-
2. Add YAML frontmatter at the top declaring which skill group it belongs to:
|
|
36
|
-
```yaml
|
|
37
|
-
---
|
|
38
|
-
skill-group: core
|
|
39
|
-
skill-order: 5
|
|
40
|
-
---
|
|
41
|
-
```
|
|
42
|
-
3. Run `npm run refresh` — this rebuilds CLI, types, docs, and skill in the correct order.
|
|
43
|
-
4. Run `node dist-cli/forgecad.js skill install` (or `--dev`) to install locally.
|
|
44
|
-
|
|
45
|
-
`skill install` copies the already-built `dist-skill` artifacts. It does not rebuild them. If you are working from a checkout, run `npm run build:skill:forgecad` or `npm run refresh` before installing.
|
|
46
|
-
|
|
47
|
-
`forgecad skill flattened-files <output-folder>` also reads the already-built `dist-skill` artifacts. It writes `forgecad.md` plus one Markdown file per bundled companion skill, appending extra files under filename-prefixed sections so each skill can be moved around as a single file.
|
|
48
|
-
|
|
49
|
-
The build script discovers docs by scanning `docs/permanent/` for files with `skill-group` frontmatter. No hardcoded file lists to update.
|
|
50
|
-
|
|
51
|
-
### Frontmatter fields
|
|
52
|
-
|
|
53
|
-
| Field | Required | Default | Description |
|
|
54
|
-
|-------|----------|---------|-------------|
|
|
55
|
-
| `skill-group` | Yes | — | Group name (must match `GROUP_REGISTRY` in build script) |
|
|
56
|
-
| `skill-order` | No | 50 | Sort order within the group |
|
|
57
|
-
|
|
58
|
-
### Inclusion rules
|
|
59
|
-
|
|
60
|
-
- **`skill-group: <name>`** — included in SKILL.md (index) and CONTEXT.md (inlined).
|
|
61
|
-
- **`skill-group: dev-<name>`** — dev-only, appears in SKILL-dev.md only.
|
|
62
|
-
- **No `skill-group`** — not part of the skill at all.
|
|
63
|
-
|
|
64
|
-
### Adding a new group
|
|
65
|
-
|
|
66
|
-
If you need a new group, add it to `GROUP_REGISTRY` in `scripts/build-forgecad-skill.mjs` with a title, guidance, and order number.
|
|
67
|
-
|
|
68
|
-
## Companion Skill Public Export
|
|
69
|
-
|
|
70
|
-
ForgeCAD also keeps companion workflow skills under `skills/`. These are the prompts and operating procedures used around the core modeling skill: build-brief preparation, model authoring, render inspection, print-time optimization, public project workflows, and similar.
|
|
71
|
-
|
|
72
|
-
Each companion skill declares whether it can be mirrored to the public repository:
|
|
73
|
-
|
|
74
|
-
```yaml
|
|
75
|
-
---
|
|
76
|
-
name: forgecad-make-a-model
|
|
77
|
-
description: Create new ForgeCAD (.forge.js) models...
|
|
78
|
-
forgecad-public: true
|
|
79
|
-
---
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Use `forgecad-public: true` for skills that help people reproduce ForgeCAD modeling workflows. Use `forgecad-public: false` for operational, private, or personal-process skills.
|
|
83
|
-
|
|
84
|
-
To list the public set:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npm run sync:public-skills -- --list
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
To copy the public README source, rebuild the generated `forgecad` skill, build the installable companion library, and copy all public skills into the sibling public repo:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
npm run sync:public-skills
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
End users install the core skill and namespaced companion library from the npm package with:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
forgecad skill install
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Public companion skill folder names are the installed names. Use the `forgecad-*` prefix directly in `skills/` for public skills, for example `skills/forgecad-prepare-prompt/`, `skills/forgecad-make-a-model/`, and `skills/forgecad-lld/`. The build step copies these folders into `dist-skill/library/` without renaming them.
|
|
103
|
-
|
|
104
|
-
The sync script writes:
|
|
105
|
-
|
|
106
|
-
- `README.md` in the public repo from this repo's `public-kit/README.md`
|
|
107
|
-
- `skills/README.md` in this repo, listing public and private/internal skills
|
|
108
|
-
- `skills/README.md` in the public repo, listing only exported skills
|
|
109
|
-
- `skills/forgecad/` in the public repo from `dist-skill/`, so `forgecad skill install --core-only` remains available as the simple generated skill path
|
|
110
|
-
- every other public skill from `skills/<skill-name>/`
|
|
111
|
-
|
|
112
|
-
The skill build also writes the website-facing skill docs:
|
|
113
|
-
|
|
114
|
-
- `docs/permanent/skills/index.md`
|
|
115
|
-
- one page per installable skill under `docs/permanent/skills/<skill-name>.md`
|
|
116
|
-
- `src/pages/generatedSkillSections.ts`, which powers the React docs sidebar, index cards, keyboard navigation, and search list
|
|
117
|
-
|
|
118
|
-
Those pages are generated from the same `forgecad-public: true` skill set used for `dist-skill/library/`, so a public companion skill should never be installable without also appearing in the docs.
|
|
119
|
-
|
|
120
|
-
## Adding Dev-Only Docs
|
|
121
|
-
|
|
122
|
-
Use a `skill-group` with a `dev-` prefix (e.g. `dev-compiler`, `dev-solver`, `dev-conventions`). These appear in `SKILL-dev.md` but not in `SKILL.md` or `CONTEXT.md`. Use this for:
|
|
123
|
-
|
|
124
|
-
- Compiler/solver internals
|
|
125
|
-
- Coding conventions and PR guidelines
|
|
126
|
-
- Full CLI reference (vs the slim user-facing docs)
|
|
127
|
-
|
|
128
|
-
## Deciding Standard vs Dev
|
|
129
|
-
|
|
130
|
-
| Question | If yes → |
|
|
131
|
-
|----------|----------|
|
|
132
|
-
| Does a model author need this to build `.forge.js` files? | Standard |
|
|
133
|
-
| Does it describe internal architecture (compiler, solver, pipeline)? | Dev only |
|
|
134
|
-
| Does it cover team process (coding standards, releases, CI)? | Dev only |
|
|
135
|
-
| Is it repo-only developer tooling (`npm run check:suite`, `sdf`, debug flags)? | Dev only |
|
|
136
|
-
|
|
137
|
-
## Orphan files
|
|
138
|
-
|
|
139
|
-
Current `skill install` removes the installed `~/.agents/skills/forgecad/docs/` directory before copying the built docs tree, so normal installs should not leave doc orphans. If a machine used an older installer or files were edited manually, stale copies can still exist and should be deleted.
|
|
140
|
-
|
|
141
|
-
To check for orphans:
|
|
142
|
-
```bash
|
|
143
|
-
for f in $(find ~/.agents/skills/forgecad/docs -name '*.md'); do
|
|
144
|
-
echo "$f" | grep -q '/generated/' && continue
|
|
145
|
-
base=$(echo "$f" | sed "s|$HOME/.agents/skills/forgecad/docs/|docs/permanent/|")
|
|
146
|
-
[ -f "$base" ] || echo "ORPHAN: $f"
|
|
147
|
-
done
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Delete any orphans found. They're stale copies that can mislead agents with outdated information.
|
|
151
|
-
|
|
152
|
-
## Verifying
|
|
153
|
-
|
|
154
|
-
After changes, check that the build succeeds and the doc counts look right:
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
npm run refresh
|
|
158
|
-
node dist-cli/forgecad.js skill install --dev # verify dev install
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
The build script prints the number of indexed source files. Verify new docs are counted.
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# Surface Members: Straps, Inlays, Guards, And Structural Bands
|
|
2
|
-
|
|
3
|
-
Surface members are for physical material that follows a carrier surface: bottle-cage arms, razor grip inlays, brace ribs, prop guards, helmet vents, and similar curved product structures.
|
|
4
|
-
|
|
5
|
-
Use this layer when the model has:
|
|
6
|
-
|
|
7
|
-
- a carrier surface such as a cylinder, plane, or `ProductSkin`
|
|
8
|
-
- paths or bands that live in carrier-local coordinates
|
|
9
|
-
- member-local section thickness, edge radius, slots, cutouts, lips, cups, or ribs
|
|
10
|
-
- explicit joins between named members
|
|
11
|
-
|
|
12
|
-
Do not use it for ordinary boxes, simple extrusions, sheet-metal bends, exact machined faces, or free-floating assemblies with normal connector placement.
|
|
13
|
-
|
|
14
|
-
## Core Vocabulary
|
|
15
|
-
|
|
16
|
-
`Carrier` owns surface coordinates and frames. The first carriers are `Carrier.cylinder(name)`, `Carrier.plane(name)`, and `Carrier.productSkin(skin)`. `Carrier.mesh(name)` and `Carrier.scan(name)` are reserved stubs that fail with direct guidance until arbitrary mesh/scan parameterization exists.
|
|
17
|
-
|
|
18
|
-
`SurfaceBody(name)` is the main public builder for this layer. `SurfaceMembers.Body(name)` is the namespaced alias for the same builder; use the direct `SurfaceBody` form in examples where the model is mainly a surface-member graph. There is intentionally no lowercase `ribbonBody()` global in this primitive layer.
|
|
19
|
-
|
|
20
|
-
`SurfacePath` samples carrier-local coordinates into continuous 3D frames. Cylinder paths use degrees and handle seam wrapping without user trigonometry. ProductSkin paths stay on one side; use `Carrier.productSkin(skin).sideTransition(fromSide, toSide, { v, name })` for one adjacent side boundary, `sideTransitionChain([from, middle, to], { v, name })` for named boundary pairs, or `sideRoute({ sides, from, to, v, name })` to generate ready-to-use per-side segment endpoints. Transition `v` is normalized from 0 to 1; names must be non-empty when provided; returned boundary coordinates are verified as coincident. These helpers create matching side-local coordinates so you can split the detail into one member per side and join named transition anchors through `SurfaceBody.join(...)`.
|
|
21
|
-
|
|
22
|
-
`SurfaceBand` is a widened path footprint. It supports constant, station, eased, and function width profiles, records member-local hole/cut-region intent through `.withHole(name, { length, width, along, across })`, and exposes boundaries and cap intent before geometry lowering.
|
|
23
|
-
|
|
24
|
-
`SurfaceBody` owns named members and joins. Members can be `band()` or `plate()`. Features are attached to members before lowering, so a slot or cutout belongs to a member-local coordinate system instead of a global boolean recipe.
|
|
25
|
-
|
|
26
|
-
`buildWithDiagnostics()` returns a serializable member graph with endpoint, sampled landing, sampled band-boundary, named rounded slot/cutout feature-center, and explicit named surface-coordinate anchors from `.anchorAt(name, coordinateOrAnchor)`. Named anchors must be unique within a member. Diagnostics include a stable `code` field for agent repair loops; inspect `code` rather than matching prose. Joins must reference existing, distinct member names; invalid sources, targets, self-joins, raw wildcard joins, and conflicting duplicate radii fail directly. Join diagnostics report the nearest endpoint pair, landing candidate, or selected named anchor pair and distance, plus conflict warnings for too-small spans, too-large radii, insufficient overlap, and opposed normals. Close endpoint-to-endpoint joins and close `.join(a, b).betweenAnchors(fromAnchor, toAnchor)` joins lower into limited round connector geometry. Endpoint-to-band and endpoint-to-plate landing joins lower into surface-oriented pad connector geometry. `autoJoinAtSharedAnchors()` lowers only unambiguous shared endpoint pairs and warns when more than two members share a point. Farther, missing-anchor, or ambiguous joins remain diagnostic-only until topology-preserving trimming and blends exist.
|
|
27
|
-
|
|
28
|
-
`buildDebug()` returns the normal member shapes plus visible anchor markers, join connection/radius markers, band centerlines, band boundary rails, sampled frame axes, rounded slot/cutout feature outlines, rib-pattern crossbars, and lip/cup profile rails, alongside the same diagnostics and IR.
|
|
29
|
-
|
|
30
|
-
Bands report region diagnostics when center coordinates exceed carrier bounds, when ProductSkin side boundaries are crossed, when cylinder band width crosses z bounds, and when simple plane/cylinder boundary polylines self-intersect. These warnings use repair-oriented codes such as `region.centerOutOfBounds`, `region.productSkinBoundaryOutOfBounds`, `region.zBoundaryOutOfBounds`, and `region.boundarySelfIntersection` instead of forcing agents to parse English. The compiler reports these warnings instead of silently treating clipped or crossing geometry as valid.
|
|
31
|
-
|
|
32
|
-
`Product.ribbon()` and `Product.surface(...).ribbon(...)` remain the compatibility path for simple one-side conformal NURBS ribbons on a `ProductSkin`. Use `Carrier.productSkin(skin)` plus `SurfaceBody` when the same skin detail needs member-local features, repeated ribs, explicit joins, mirrored members, or the same primitive vocabulary as bottle cages and guards.
|
|
33
|
-
|
|
34
|
-
## Example
|
|
35
|
-
|
|
36
|
-
For a minimal guard, use a cylinder carrier, one authored strut, its mirror, and an explicit join to a front hoop:
|
|
37
|
-
|
|
38
|
-
```js
|
|
39
|
-
const envelope = Carrier.cylinder("guard-envelope").diameter(84).height(36).clearance(2);
|
|
40
|
-
|
|
41
|
-
const guard = SurfaceBody("simple-guard")
|
|
42
|
-
.carrier(envelope)
|
|
43
|
-
.member("left-strut")
|
|
44
|
-
.band()
|
|
45
|
-
.path(envelope.path().from({ angle: -132, z: 6 }).to({ angle: -58, z: 18 }))
|
|
46
|
-
.section({ width: 5.5, thickness: 2.8, edgeRadius: 0.6 })
|
|
47
|
-
.member("right-strut")
|
|
48
|
-
.mirrorOf("left-strut")
|
|
49
|
-
.member("front-hoop")
|
|
50
|
-
.band()
|
|
51
|
-
.path(envelope.path().around({ z: 18, fromAngle: -58, toAngle: 58 }))
|
|
52
|
-
.section({ width: 6.2, thickness: 3, edgeRadius: 0.7 })
|
|
53
|
-
.join("left-strut", "front-hoop").blend({ radius: 3.2 })
|
|
54
|
-
.join("right-strut", "front-hoop").blend({ radius: 3.2 })
|
|
55
|
-
.build();
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
```js
|
|
59
|
-
const bottle = Carrier.cylinder("bottle").diameter(74).height(170).clearance(1.5);
|
|
60
|
-
|
|
61
|
-
const cage = SurfaceBody("cage")
|
|
62
|
-
.carrier(bottle)
|
|
63
|
-
.member("left-arm")
|
|
64
|
-
.band()
|
|
65
|
-
.path(bottle.path()
|
|
66
|
-
.from({ angle: -145, z: 18 })
|
|
67
|
-
.through({ angle: -80, z: 72 })
|
|
68
|
-
.to({ angle: -34, z: 112 }))
|
|
69
|
-
.section({ width: 10, thickness: 5, edgeRadius: 1 })
|
|
70
|
-
.member("right-arm")
|
|
71
|
-
.mirrorOf("left-arm")
|
|
72
|
-
.join("left-arm", "right-arm").blend({ radius: 5, style: "structural" })
|
|
73
|
-
.build();
|
|
74
|
-
|
|
75
|
-
return cage;
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
The API is intentionally blueprint-first: common paths should not require `Math.sin`, `Math.cos`, raw matrices, or hand-built overlap solids.
|
|
79
|
-
|
|
80
|
-
## Current Limits
|
|
81
|
-
|
|
82
|
-
The first compiler lowers members as deterministic sampled mesh solids. Bands support square, rounded, and tapered end caps; extended-to-junction caps remain explicit join intent until the junction compiler can trim/extend members. Plate-local rounded slots/cutouts, plate counterbores, band-local rounded cutouts, band rib patterns, lip/cup profile rails, and cup cradle webs are lowered as real mesh features, including variable-width and variable-thickness band footprints. Close endpoint junctions, unambiguous auto shared-endpoint junctions, and selected named-anchor junctions are lowered as small round connector solids at actual anchors; sampled band/plate landing junctions lower as surface-oriented pad connector solids. More advanced cup retention shapes, member trimming, and topology-preserving junction blends are still graph/diagnostic intent, so unsupported high-order transitions should be decomposed or left as future work rather than hidden behind silent fallbacks.
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-compiler
|
|
3
|
-
skill-order: 0
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Backend Vocabulary
|
|
7
|
-
|
|
8
|
-
Use Forge terms first. Mention concrete backend implementations only at real implementation boundaries.
|
|
9
|
-
|
|
10
|
-
## Canonical Terms
|
|
11
|
-
|
|
12
|
-
- **Forge semantic intent**: the meaning of a modeling operation in Forge terms.
|
|
13
|
-
- **Compile plan**: the serializable Forge IR that preserves that intent for later lowering.
|
|
14
|
-
- **Backend**: a geometry engine with its own strengths, limits, and implementation details.
|
|
15
|
-
- **Capability**: something a backend can or cannot do for a given flow.
|
|
16
|
-
- **Route**: the centralized decision about which backend path or fallback a scene/object will use.
|
|
17
|
-
- **Implementation boundary**: the narrow place where a concrete backend or adapter is named directly.
|
|
18
|
-
|
|
19
|
-
## Naming Rules
|
|
20
|
-
|
|
21
|
-
- In shared IR, scene routing, and contributor docs, prefer Forge terms such as `compile plan`, `backend`, `capability`, and `route`.
|
|
22
|
-
- Use backend names like `manifold` or `occt` only when the code or doc is truly about that implementation boundary.
|
|
23
|
-
- Use `CadQuery` only when discussing the current Python export executor or other real CadQuery-specific behavior.
|
|
24
|
-
- Use `BREP` and `STEP` for file formats and interchange behavior, not as the primary architecture names for shared compiler layers.
|
|
25
|
-
- Avoid `exact` as a substitute for backend identity. If the real concern is capability, say which capability is required or missing.
|
|
26
|
-
|
|
27
|
-
## Practical Test
|
|
28
|
-
|
|
29
|
-
When naming a shared type or document section, ask:
|
|
30
|
-
|
|
31
|
-
1. Is this describing Forge's meaning?
|
|
32
|
-
2. Is this describing a backend capability?
|
|
33
|
-
3. Or is this describing one backend implementation detail?
|
|
34
|
-
|
|
35
|
-
If the answer is 1 or 2, do not name it after a historical implementation.
|