forgecad 0.9.5 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/assets/{AdminPage-uTtcSXtn.js → AdminPage-DX0mpSZT.js} +1 -1
  2. package/dist/assets/{BlogPage-DYJMjWx3.js → BlogPage-CI_P0_Pf.js} +1 -1
  3. package/dist/assets/{DocsPage-C58f0K5v.js → DocsPage-DLhIIZyJ.js} +3 -3
  4. package/dist/assets/EditorApp-BujZvuwX.js +12874 -0
  5. package/dist/assets/{EditorApp-DS0AIUrZ.css → EditorApp-DfFT2Dn8.css} +1 -0
  6. package/dist/assets/{EmbedViewer-CMXWA2LX.js → EmbedViewer-0S0qXKog.js} +2 -2
  7. package/dist/assets/{LandingPageProofDriven-CAu2OZFn.js → LandingPageProofDriven-O_yMtAri.js} +1 -1
  8. package/dist/assets/{PricingPage-BIgW7m3X.js → PricingPage-DGkX3Ahr.js} +1 -1
  9. package/dist/assets/{SettingsPage-N1l1tMXO.js → SettingsPage-DBsqTB_y.js} +82 -22
  10. package/dist/assets/{app-CFy7g5WP.js → app-BE2nD6Yz.js} +1246 -191
  11. package/dist/assets/cli/{render-BrVVdj_T.js → render-iP9qh475.js} +841 -586
  12. package/dist/assets/{evalWorker-c_SB9gg3.js → evalWorker-Ds5U4xtN.js} +2732 -112
  13. package/dist/assets/inspectWorker-Dll4eVyD.js +12620 -0
  14. package/dist/assets/{manifold-Dp6pvFr6.js → manifold-Bk26ViCr.js} +1 -1
  15. package/dist/assets/{manifold-CRoBhJKH.js → manifold-DjYsd7A_.js} +2 -2
  16. package/dist/assets/{manifold-Cjk7WhRs.js → manifold-sJ-axdXM.js} +1 -1
  17. package/dist/assets/{renderSceneState-3DfsSASX.js → renderSceneState-Bngp5MrQ.js} +1 -1
  18. package/dist/assets/{reportWorker-BLkuIoS8.js → reportWorker-CU8RZ4O0.js} +2715 -112
  19. package/dist/assets/{sectionPlaneMath-CykEnkvQ.js → sectionPlaneMath-BdTjyVfs.js} +3213 -252
  20. package/dist/cli/render.html +1 -1
  21. package/dist/docs/index.html +1 -1
  22. package/dist/docs-raw/AI/usage.md +7 -2
  23. package/dist/docs-raw/CLI.md +82 -53
  24. package/dist/docs-raw/beta-operations.md +9 -0
  25. package/dist/docs-raw/coding.md +1 -1
  26. package/dist/docs-raw/deployment.md +38 -23
  27. package/dist/docs-raw/generated/concepts.md +141 -7
  28. package/dist/docs-raw/generated/core.md +206 -1
  29. package/dist/docs-raw/generated/curves.md +97 -5
  30. package/dist/docs-raw/generated/lib.md +17 -1
  31. package/dist/docs-raw/generated/sketch.md +9 -1
  32. package/dist/docs-raw/generated/viewport.md +1 -1
  33. package/dist/docs-raw/guides/inspection-bundles.md +45 -16
  34. package/dist/docs-raw/platform/auth.md +2 -0
  35. package/dist/docs-raw/platform/google-oauth-setup.md +4 -0
  36. package/dist/docs-raw/runbook.md +3 -3
  37. package/dist/docs-raw/skills/forgecad-make-a-model.md +87 -8
  38. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +14 -6
  39. package/dist/docs-raw/skills/forgecad-render-inspect.md +1 -1
  40. package/dist/docs-raw/skills/index.md +2 -2
  41. package/dist/index.html +1 -1
  42. package/dist/sitemap.xml +6 -6
  43. package/dist-cli/forgecad.js +8725 -4747
  44. package/dist-cli/forgecad.js.map +1 -1
  45. package/dist-skill/CONTEXT.md +375 -25
  46. package/dist-skill/docs/CLI.md +82 -53
  47. package/dist-skill/docs/generated/core.md +206 -1
  48. package/dist-skill/docs/generated/curves.md +97 -5
  49. package/dist-skill/docs/generated/lib.md +17 -1
  50. package/dist-skill/docs/generated/sketch.md +9 -1
  51. package/dist-skill/docs/generated/viewport.md +1 -1
  52. package/dist-skill/docs/guides/inspection-bundles.md +45 -16
  53. package/dist-skill/docs-dev/CLI.md +82 -53
  54. package/dist-skill/docs-dev/coding.md +1 -1
  55. package/dist-skill/docs-dev/generated/core.md +206 -1
  56. package/dist-skill/docs-dev/generated/curves.md +97 -5
  57. package/dist-skill/docs-dev/generated/lib.md +17 -1
  58. package/dist-skill/docs-dev/generated/sketch.md +9 -1
  59. package/dist-skill/docs-dev/generated/viewport.md +1 -1
  60. package/dist-skill/docs-dev/guides/inspection-bundles.md +45 -16
  61. package/dist-skill/library/forgecad-make-a-model/SKILL.md +87 -8
  62. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +14 -6
  63. package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +5 -3
  64. package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +7 -5
  65. package/dist-skill/library/forgecad-render-inspect/SKILL.md +1 -1
  66. package/examples/api/bolted-service-cover.forge.js +17 -0
  67. package/examples/api/cable-gland-anchor.forge.js +14 -0
  68. package/examples/api/captured-cartridge-guide.forge.js +14 -0
  69. package/examples/api/captured-linear-slide.forge.js +13 -0
  70. package/examples/api/clevis-pin-joint.forge.js +13 -0
  71. package/examples/api/datum-enclosure.forge.js +16 -0
  72. package/examples/api/guided-loft-olive-oil-bottle.forge.js +135 -0
  73. package/examples/api/hose-barb-port.forge.js +14 -0
  74. package/examples/api/intentional-overlap-overmold.forge.js +16 -0
  75. package/examples/api/knuckled-hinge-assembly.forge.js +15 -0
  76. package/examples/api/living-hinge-cover.forge.js +14 -0
  77. package/examples/api/pcb-terminal-block.forge.js +22 -0
  78. package/examples/api/pinned-lever-pivot-stack.forge.js +14 -0
  79. package/examples/api/retained-shaft-knob-stack.forge.js +15 -0
  80. package/examples/api/routed-tube-clip.forge.js +15 -0
  81. package/examples/api/seated-bearing-stack.forge.js +30 -0
  82. package/examples/api/snap-latch-cover.forge.js +14 -0
  83. package/examples/api/static-assembly-connectors.forge.js +14 -16
  84. package/examples/api/thumb-screw-clamp.forge.js +15 -0
  85. package/package.json +20 -2
  86. package/dist/assets/EditorApp-DNH1TEz1.js +0 -12729
@@ -87,7 +87,7 @@ Pre-built parametric parts available in user scripts as `lib.*`.
87
87
 
88
88
  Every key in this object becomes a method or namespace on the `lib` object exposed to `.forge.js` scripts. The catalog includes:
89
89
 
90
- **Fasteners:** `bolt`, `nut`, `washer`, `fastenerSet`, `fastenerHole`, `boltHole`, `counterbore`, `hexNut`, `holePattern`
90
+ **Fasteners and hardware patterns:** `bolt`, `nut`, `washer`, `fastenerSet`, `boltedServiceCover`, `datumEnclosureAssembly`, `snapLatchCoverAssembly`, `pinnedLeverAssembly`, `retainedShaftAssembly`, `capturedLinearSlide`, `capturedCartridgeGuideAssembly`, `livingHingeCoverAssembly`, `knuckledHingeAssembly`, `clevisPinJointAssembly`, `seatedBearingAssembly`, `cableGlandAnchorAssembly`, `hoseBarbPortAssembly`, `routedTubeClipAssembly`, `pcbTerminalBlockAssembly`, `thumbScrewClampAssembly`, `fastenerHole`, `boltHole`, `counterbore`, `hexNut`, `holePattern`
91
91
 
92
92
  **Structure:** `tube`, `pipe`, `bracket`, `pipeRoute`, `elbow`, `tSlotProfile`, `tSlotExtrusion`, `profile2020BSlot6Profile`, `profile2020BSlot6`
93
93
 
@@ -121,6 +121,22 @@ Sizes outside the supported ranges will throw at runtime with a descriptive erro
121
121
  - `nut(diameter: number, options?: { pitch?: number; height?: number; acrossFlats?: number; segments?: number; }): Shape` — ISO-style hex nut with a threaded bore. **Details** Constructed from the intersection of three rotated slabs with a cylindrical bore subtracted. The nut is centered at the origin, height along Z. Default proportions follow ISO 4032 loosely: height ≈ 0.8×diameter, across-flats ≈ 1.6×diameter. The bore is a clearance bore (not modelled with helical threads) for rendering efficiency. For standard M-size nuts pre-configured for a complete joint, use { **Example** ```ts const n = lib.nut(5); // M5 nut ```
122
122
  - `washer(size: MetricSize, options?: { standard?: WasherStandard; segments?: number; }): Shape` — ISO metric flat washer (DIN 125-A). **Details** Returns a flat ring centered at the origin, thickness along Z. Dimensions are taken from { **Example** ```ts const w = lib.washer('M5'); // DIN 125-A M5 washer ```
123
123
  - `fastenerSet(size: MetricSize, boltLength: number, options?: FastenerSetOptions): FastenerSetResult` — Complete ISO metric fastener set — bolt, nut, optional washers, and matching hole cutters. **Details** Returns all geometry for one bolted joint: the bolt, nut, up to two washers, a clearance-hole cutter, and a tap-drill cutter. All shapes are returned **un-positioned** (each on the Z-axis). Place them with `.translate()`. Sizes outside M4–M10 are supported for the washer (M2–M10); unsupported combinations will throw. **Example** ```ts const hw = lib.fastenerSet('M5', 20); const topPlate = box(60, 40, 8).translate(0, 0, 12) .subtract(hw.clearanceHole.translate(15, 10, 12)); const botPlate = box(60, 40, 8) .subtract(hw.clearanceHole.translate(15, 10, 0)); return [ { name: 'Top Plate', shape: topPlate }, { name: 'Bot Plate', shape: botPlate }, { name: 'Bolt', shape: hw.bolt.translate(15, 10, 20) }, { name: 'Nut', shape: hw.nut.translate(15, 10, -4) }, ]; ```
124
+ - `boltedServiceCover(options: BoltedServiceCoverOptions): BoltedServiceCoverResult` — Bolted service-cover interface with real seats, aligned holes, gasket, fused pull tabs, and installed screws. **Details** This is a higher-level mechanical pattern for the common "removable service cover" failure mode. It creates the parent ledge, cover, gasket, and screws from one shared bolt pattern so agents do not place decorative screw heads or floating pull tabs by eye. Coordinate convention: the parent frame sits from `z=0` to `parentThickness`, the gasket sits on the ledge, the cover sits above the gasket, and screw shafts run downward through the cover into the parent. All parts are centered on the XY origin. **Example** ```ts const cover = lib.boltedServiceCover({ width: 90, depth: 56, screwSize: 'M4', ledgeWidth: 10, boltInset: [6, 6], }); verify.equal('four retained cover screws', cover.screws.length, 4); return cover.parts; ```
125
+ - `datumEnclosureAssembly(options: DatumEnclosureAssemblyOptions): DatumEnclosureAssemblyResult` — Datum-driven enclosure tray with shared wall, ledge, standoff, cover, gasket, port, and screw geometry. **Details** This pattern is for electronics boxes, thermostat backplates, service-stack housings, camera housings, and small fixtures where generated models often place panels, ribs, bosses, ports, and covers by eye. The tray, internal ledges, standoffs, ribs, service port, gasket, cover holes, and installed screws all come from one datum system. This keeps screw axes, boss locations, wall thickness, and service openings aligned instead of relying on independent magic numbers. Coordinate convention: X/Y are the enclosure footprint, Z is up. The base tray starts at `z=0` and rises to `height`; the gasket and cover sit above the top ledge with small explicit face clearances. **Example** ```ts const enclosure = lib.datumEnclosureAssembly({ width: 96, depth: 64, height: 18, }); verify.notColliding('cover clears enclosure gasket', enclosure.cover, enclosure.gasket); verify.inRange('cover stack has small seating clearance', enclosure.dims.faceClearance, 0.01, 0.08); return enclosure.parts; ```
126
+ - `snapLatchCoverAssembly(options: SnapLatchCoverAssemblyOptions): SnapLatchCoverAssemblyResult` — Snap-retained cover with a receiver frame, latch windows, underside catch lands, and fused snap hooks. **Details** This pattern is for covers, cartridges, clasps, and small housings where agents often add decorative tabs without a catch. The receiver has a real service opening plus two clearance latch windows. The cover is one fused part with two flexible-looking snap fingers that pass through the windows and barb under the receiver underside. Nothing intersects in the final assembly; the hook geometry sits close enough to the catch lands to prove retention intent. Coordinate convention: the receiver frame sits from `z=0` to `parentThickness`; the cover is seated just above the receiver on +Z. Two snap hooks sit on the +/-Y ledges and tuck under the receiver. **Example** ```ts const snapCover = lib.snapLatchCoverAssembly({ width: 72, depth: 44, }); verify.notColliding('snap hooks clear receiver windows', snapCover.cover, snapCover.parent); verify.inRange('snap cover has small seating clearance', snapCover.dims.faceClearance, 0.01, 0.08); return snapCover.parts; ```
127
+ - `pinnedLeverAssembly(options: PinnedLeverAssemblyOptions): PinnedLeverAssemblyResult` — Retained pinned lever stack with a fused hub/arm/grip, low stop land, pivot pin, bore cutters, and thrust washers. **Details** This pattern is for the common handle/lever failure mode where a visual arm, hub, washer, and pin are placed near each other but never form a credible mechanism. The lever body is one fused part, the pin runs through aligned bores, washers sit on both sides of the lever, and the support includes a bearing land plus an optional low stop land beside the lever path. Coordinate convention: pivot axis is +Z at the XY origin. The support starts at `z=0`, the lower washer sits on top of the support, the lever sits on the lower washer, the upper washer sits on the lever, and the retained pin spans the full stack. **Example** ```ts const lever = lib.pinnedLeverAssembly({ armLength: 54, armWidth: 10, pinDiameter: 5, }); verify.equal('lever stack has five retained parts', lever.parts.length, 5); return lever.parts; ```
128
+ - `retainedShaftAssembly(options: RetainedShaftAssemblyOptions): RetainedShaftAssemblyResult` — Retained shaft, washer, knob, and support-cheek stack for trunnions, pivots, and adjustable clamps. **Details** This pattern replaces the common "pin, washers, and knob are near each other" visual shortcut with a mechanically accountable shaft stack. The two support cheeks get matching clearance bores, the through shaft spans the whole stack, washers and knobs share the same axis, and retaining heads keep the knobs from reading as loose floating cylinders. Coordinate convention: the shaft axis is +X through the world origin. Support cheeks are centered at `x = +/- supportSpacing / 2`. The supports are bored for clearance, so collision inspection should report no support/shaft overlap while the connectivity audit still sees one retained stack. **Example** ```ts const trunnion = lib.retainedShaftAssembly({ supportSpacing: 96, shaftDiameter: 8, supportHeight: 42, }); verify.equal('retained shaft stack has seven parts', trunnion.parts.length, 7); return trunnion.parts; ```
129
+ - `capturedLinearSlide(options: CapturedLinearSlideOptions): CapturedLinearSlideResult` — Captured linear slide with a U-channel rail, return lips, end stops, and a carriage posed inside the guide. **Details** This pattern is for drawer-slide, quick-release plate, and guided-carriage models where agents often place rail details and a moving block near each other without a capture relationship. The rail is one fused part with side walls, inward lips, and end stops; the carriage is wider than the lip throat but narrower than the inner rail width, so it is mechanically captured while retaining explicit clearance. Coordinate convention: rail length is along X, width is along Y, and Z is up. The rail base starts at `z=0`; the carriage sits above the base and below the return lips. `travel=0` places the carriage at the negative-X end of travel, and `travel=maxTravel` places it at the positive-X end. **Example** ```ts const slide = lib.capturedLinearSlide({ length: 160, carriageLength: 52, travel: 42, }); verify.greaterThan('carriage is captured by return lips', slide.dims.carriageWidth, slide.dims.throatWidth); return slide.parts; ```
130
+ - `capturedCartridgeGuideAssembly(options: CapturedCartridgeGuideAssemblyOptions): CapturedCartridgeGuideAssemblyResult` — Captured removable cartridge guide with return lips, rear stop, wide cartridge flange, and pull tab. **Details** This pattern is for pump cartridges, filter cassettes, skeg cassettes, battery cartridges, and slide-in service modules where generated models often place a tray and a loose block near each other. The guide is one fused part with side walls, inward return lips, and a rear stop. The cartridge has a wide lower flange captured under the lips and a narrower body that passes through the throat, so the model has a real retention contract without manual coordinate tuning. Coordinate convention: insertion travel is along +X. The open entry is at −X, the rear stop is at +X, the guide base starts at `z=0`, and `insertion=0` places the cartridge at the front travel limit. **Example** ```ts const cassette = lib.capturedCartridgeGuideAssembly({ length: 150, cartridgeLength: 72, }); verify.notColliding('cartridge clears guide rails', cassette.cartridge, cassette.guide); verify.greaterThan('cartridge flange is captured by lips', cassette.dims.cartridgeWidth, cassette.dims.throatWidth); return cassette.parts; ```
131
+ - `livingHingeCoverAssembly(options: LivingHingeCoverAssemblyOptions): LivingHingeCoverAssemblyResult` — One-piece molded living-hinge cover strip with a fixed leaf, thin flexible web, cover leaf, pull lip, snap barb, and catch land. **Details** This pattern is for small polypropylene-style lids, battery doors, sample covers, blister latches, and molded service flaps where generated models often draw a decorative hinge strip between two disconnected plates. It returns one fused molded part in its as-molded flat state: fixed mounting leaf, thin hinge web, moving cover leaf, pull lip, raised snap barb, and catch land. The flexible web is intentionally much thinner than the rigid leaves and shares material with both leaves. Coordinate convention: X is hinge length/part width, Y runs from fixed leaf through hinge web to cover leaf, and Z is thickness. The hinge web is centered on `y=0`; the fixed leaf lies at −Y and the cover leaf at +Y. **Example** ```ts const livingCover = lib.livingHingeCoverAssembly({ width: 64, coverDepth: 42, }); verify.greaterThan('living hinge is much thinner than rigid leaves', livingCover.dims.flexRatio, 3); return livingCover.parts; ```
132
+ - `knuckledHingeAssembly(options: KnuckledHingeAssemblyOptions): KnuckledHingeAssemblyResult` — Alternating knuckle hinge with two fused leaves and a retained pin. **Details** This pattern replaces hand-placed hinge barrels and pin ghosts with a mechanically accountable hinge. The fixed leaf owns every other knuckle, the moving leaf owns the alternating knuckles, all knuckles share one bore size, and the retained pin spans the full stack with heads outside the barrels. Coordinate convention: the hinge pin axis is +X through the world origin. The fixed leaf extends toward +Y. The moving leaf extends toward -Y and rotates about +X by `openAngleDeg`. **Example** ```ts const hinge = lib.knuckledHingeAssembly({ length: 70, leafLength: 28, openAngleDeg: 45, }); verify.equal('hinge has two leaves and one retained pin', hinge.parts.length, 3); return hinge.parts; ```
133
+ - `clevisPinJointAssembly(options?: ClevisPinJointAssemblyOptions): ClevisPinJointAssemblyResult` — Clevis-style pin joint with bored yoke ears, a center link eye, and a retained pin. **Details** This pattern is for crank links, damper rod ends, pump crossheads, capo/cam pivots, and small mechanism joints where agents often place an eyelet and a pin near a bracket without modeling the captured load path. The clevis is one fused part with two bored ears and a rear bridge, the center link has a real eye and arm, and the retained pin spans the full stack with heads outside the ears. Coordinate convention: the pin axis is +Y through the world origin. The center link arm extends toward +X. The clevis bridge sits behind the eye on -X, leaving the link eye clear inside the yoke. **Example** ```ts const clevis = lib.clevisPinJointAssembly({ pinDiameter: 4, linkArmLength: 38, }); verify.equal('clevis joint has three retained parts', clevis.parts.length, 3); return clevis.parts; ```
134
+ - `seatedBearingAssembly(options: SeatedBearingAssemblyOptions): SeatedBearingAssemblyResult` — Seated radial-bearing support with a real counterbore, shoulder, through shaft, and retaining collars. **Details** This pattern is for purchased bearings, rollers, burr-cartridge shafts, and small spindle supports where agents often place a ring and a shaft near a block without modelling the pocket that locates the bearing. The housing includes a through-bore and a larger counterbore that leaves a shoulder for the bearing outer race. The shaft is smaller than the bearing bore and carries collars outside the housing, so collision checks can distinguish intended clearance from impossible overlap. Coordinate convention: the shaft axis is +Z through the world origin. The housing block starts at `z=0`, the raised boss is on top of the block, the bearing is seated from the top counterbore, and the shaft extends above and below the housing. **Example** ```ts const bearingStack = lib.seatedBearingAssembly({ bearingOuterDiameter: 22, bearingInnerDiameter: 8, bearingWidth: 7, }); verify.greaterThan('housing has wall around bearing pocket', bearingStack.dims.bossOuterDiameter - bearingStack.dims.pocketDiameter, 4); return bearingStack.parts; ```
135
+ - `cableGlandAnchorAssembly(options: CableGlandAnchorAssemblyOptions): CableGlandAnchorAssemblyResult` — Cable, wire, or tube gland anchor with a real panel hole, hollow gland body, compression nut, and routed cable. **Details** This pattern is for pumps, filters, electronics boxes, vents, monitors, and fixtures where generated models often leave hoses or cables terminating in space. It creates the receiving panel hole, a hollow gland body with a panel-side flange seated in a shallow pocket, a hollow compression nut, and a cable/tube that runs through the gland bore with explicit clearance. Coordinate convention: the cable axis is +X through the world origin. The panel is centered around `x=0` with thickness along X; the flange sits on the +X side of the panel and the compression nut sits on the −X side. The cable spans the full anchor. **Example** ```ts const anchor = lib.cableGlandAnchorAssembly({ cableDiameter: 6, panelThickness: 3, }); verify.notColliding('cable clears gland bore', anchor.cable, anchor.gland); verify.clearanceBetween('gland flange is seated at panel pocket', anchor.gland, anchor.panel, 0.01, 0.2); return anchor.parts; ```
136
+ - `hoseBarbPortAssembly(options: HoseBarbPortAssemblyOptions): HoseBarbPortAssemblyResult` — Hose-barb pump/filter port with a bored receiver, shoulder, barb ridges, installed hose, and clamp band. **Details** This pattern is for pump heads, filters, vents, lab cartridges, and fluid fittings where generated models often leave tubes ending near a block. The receiver has a real through-port and raised boss, the fitting is hollow with a shoulder and multiple barb ridges, and the hose is modeled as an installed tube over the barb envelope with a clamp band. The hose bore is sized for the deformed installed hose, so collision checks distinguish the retained interface from impossible solid overlap. Coordinate convention: the fluid axis is +X through the world origin. The receiver block is centered around `x=0`; the raised boss and hose are on the +X side. **Example** ```ts const hosePort = lib.hoseBarbPortAssembly({ hoseInnerDiameter: 6, hoseOuterDiameter: 10, }); verify.notColliding('hose clears barb peaks', hosePort.hose, hosePort.fitting); verify.inRange('fitting shoulder seats near boss face', hosePort.dims.faceClearance, 0.01, 0.08); return hosePort.parts; ```
137
+ - `routedTubeClipAssembly(options: RoutedTubeClipAssemblyOptions): RoutedTubeClipAssemblyResult` — Routed tube or cable retained by saddle clips with real bores, screw holes, and installed screws. **Details** This pattern is for hoses, wires, pump tubes, sensor leads, and appliance cable runs where generated models often draw a cylinder near a wall without clips or strain relief. The base panel has receiving screw envelopes, each saddle clip has a real through-bore around the tube and vertical screw clearances, and the installed screws share those positions. Coordinate convention: the routed tube runs along +X through the world origin. The base panel starts at `z=0`; clips sit on top of the panel, and the tube passes through their bores. **Example** ```ts const route = lib.routedTubeClipAssembly({ tubeDiameter: 6, clipCount: 3, }); verify.notColliding('tube clears clip bores', route.tube, union(...route.clips)); verify.notColliding('clip screws clear retained stack', union(...route.screws), union(route.panel, ...route.clips)); return route.parts; ```
138
+ - `pcbTerminalBlockAssembly(options?: PcbTerminalBlockAssemblyOptions): PcbTerminalBlockAssemblyResult` — PCB terminal-block stack with a backplate, standoffs, mounting screws, pin holes, and a seated terminal block. **Details** This pattern is for thermostat backplates, appliance control panels, sensor boards, and small electronics where generated models often place a terminal block, screw heads, and holes as independent decorations. The PCB mounting holes, fused standoffs, installed screws, terminal pins, and PCB pin clearances all come from one shared datum system so the purchased block is mechanically seated and the board is actually mounted. Coordinate convention: X/Y are the board footprint, Z is up. The backplate starts at `z=0`, standoffs rise from the plate, the PCB rests on the standoffs, and the terminal block sits on top of the PCB near the front edge. **Example** ```ts const terminalStack = lib.pcbTerminalBlockAssembly({ terminalCount: 5, screwSize: 'M3', }); verify.notColliding('terminal pins clear PCB holes', terminalStack.terminalBlock, terminalStack.pcb); verify.notColliding('mounting screws clear PCB and standoff holes', union(...terminalStack.screws), union(terminalStack.pcb, terminalStack.backplate)); return terminalStack.parts; ```
139
+ - `thumbScrewClampAssembly(options?: ThumbScrewClampAssemblyOptions): ThumbScrewClampAssemblyResult` — Thumb-screw clamp with a C-frame, threaded boss, captive pressure pad, knob, and clamped workpiece. **Details** This pattern is for bench clamps, monitor-arm desk clamps, small vise screws, capo pressure screws, fixture hold-downs, and service brackets where generated models often place a loose screw, knob, or pressure pad near a bracket. The helper creates a one-piece clamp frame with a fixed anvil pad, a bored threaded support and boss, an installed screw with a captive pressure pad and hand knob, and a representative clamped workpiece seated between the pads. Coordinate convention: the clamp screw runs along +X. The fixed anvil is on the -X side, the threaded support and knob are on the +X side, and Z is up from the base bridge. **Example** ```ts const clamp = lib.thumbScrewClampAssembly({ screwSize: 'M6', workpieceThickness: 20, }); verify.notColliding('thumb screw clears threaded boss', clamp.clampScrew, clamp.frame); verify.clearanceBetween('pressure pad is seated on workpiece', clamp.clampScrew, clamp.workpiece, -0.01, 0.05); return clamp.parts; ```
124
140
  - `pipeRoute(points: [ number, number, number ][], radius: number, options?: { bendRadius?: number; wall?: number; segments?: number; }): Shape` — Route a pipe (solid or hollow) through 3D waypoints with smooth bends. Each interior waypoint gets a torus-section bend. Straight segments connect them. Returns a single unioned Shape.
125
141
  - `elbow(pipeRadius: number, bendRadius: number, angle?: number | { ... }, options?: { ... }): Shape` — Pipe elbow — a curved pipe section (torus arc) for connecting two pipe directions. By default creates a bend in the XZ plane: incoming along +Z, outgoing rotated by `angle`. The bend starts at the origin, curving away from it.
126
142
  - `beltDrive(options: BeltDriveOptions): BeltDriveResult` — Create a flat open-belt body around two pulley pitch circles. The belt is generated as a tangent loop in the XY plane and extruded along +Z by `beltWidth`. The result includes the solid belt, the 2D belt profile, a thin pitch-path sketch for visualization, total belt length, tangent spans, and wrap metadata for each pulley. For more than two pulleys, the API intentionally asks for route intent before geometry is created. Use `route: "outer"` for the future outside-envelope mode, or an ordered route for future serpentine/idler layouts. ```ts const drive = lib.beltDrive({ pulleys: [ { name: "motor", center: [0, 0], pitchRadius: 12 }, { name: "output", center: [80, 0], pitchRadius: 28 }, ], beltWidth: 8, beltThickness: 2, }); return drive.belt; ```
@@ -1457,7 +1457,15 @@ detectArrangement(): Sketch[]
1457
1457
  #### `detectArrangementRegion()` — Select the single arrangement region that contains the given seed point. Throws if no region contains the seed.
1458
1458
 
1459
1459
  ```ts
1460
- detectArrangementRegion(seed: [ number, number ]): Sketch
1460
+ detectArrangementRegion(_seed: [ number, number ]): Sketch
1461
+ ```
1462
+
1463
+ #### `toPolyline()` — Return the solved constrained path as a sampled 2D polyline.
1464
+
1465
+ Use this when a construction rail was authored with `constrainedSketch()` and should feed another operation such as `Loft.pathOnXz(...)`. The sketch must contain exactly one profile path.
1466
+
1467
+ ```ts
1468
+ toPolyline(samples?: number): [ number, number ][]
1461
1469
  ```
1462
1470
 
1463
1471
  #### `withUpdatedConstraint()` — Re-solve the sketch after changing the value of one existing constraint.
@@ -366,7 +366,7 @@ Mock objects appear in the viewport and spatial analysis when you run a file dir
366
366
 
367
367
  The shape is returned unchanged, so you can reference it for alignment, dimensioning, and `verify` checks.
368
368
 
369
- Mock objects participate in `forgecad run` collision detection and spatial analysis. Their names appear with a `(mock)` suffix in reports.
369
+ Mock objects participate in `forgecad run --spatial bounded|exact` collision detection and spatial analysis. Their names appear with a `(mock)` suffix in reports.
370
370
 
371
371
  In the viewport, mock objects render at reduced opacity so they are visually distinct from real geometry.
372
372
 
@@ -26,7 +26,7 @@ cross-sections.
26
26
  forgecad render inspect examples/api/static-assembly-connectors.forge.js --channels rgb,mask
27
27
  forgecad render inspect model.forge.js out/model-inspect --channels rgb,section --force
28
28
  forgecad render inspect model.forge.js --channels rgb,mask,section
29
- forgecad render inspect model.forge.js --channels collisions --focus Bench
29
+ forgecad render inspect model.forge.js --channels collisions --focus "Bench.*"
30
30
  forgecad render inspect model.forge.js --channels rgb,mask --hide "Bench.Slat0,Bench.Slat1"
31
31
  forgecad render inspect model.forge.js --channels thickness --min-thickness 1.2 --warn-thickness 2.0
32
32
  forgecad render inspect channels
@@ -43,7 +43,9 @@ question so heavy analyses do not run unnecessarily.
43
43
  `--focus` and `--hide` use the same object-name filtering semantics as
44
44
  `forgecad run` and `forgecad render 3d`. A bare `--focus` hides mock objects;
45
45
  `--focus name1,name2` emits only matching objects; `--hide name1,name2` removes
46
- matching objects from an otherwise visible scene.
46
+ matching objects from an otherwise visible scene. Matching is case-insensitive
47
+ and supports `*` / `?` globs, so grouped child objects are usually best matched
48
+ with patterns such as `Bench.*`.
47
49
 
48
50
  ## Bundle Layout
49
51
 
@@ -148,6 +150,12 @@ defects. Use this channel to spot spiky tessellation, accidental faceting,
148
150
  jagged boolean residue, and dense sharp-corner regions without losing the
149
151
  silhouette of otherwise smooth surfaces.
150
152
 
153
+ The channel also writes `channels/roughness/point-cloud.json`. Each point sample
154
+ stores object identity, object-local position, normal, dihedral angle, class,
155
+ RGB color, and represented surface area. The PNG renders those samples over
156
+ muted source geometry so the visual evidence stays point-level instead of
157
+ painting a whole object.
158
+
151
159
  `mask` emits one object-color image per view. Black is background. Non-black
152
160
  pixels resolve through `manifest.channels.mask.objects`, which includes object
153
161
  index, RGB color, object id, name, group, tree path, and mock flag. Edge pixels
@@ -161,9 +169,9 @@ background. Non-black pixels resolve through
161
169
  Connectivity is computed from visible scene objects:
162
170
 
163
171
  ```text
164
- bbox overlap edge = bbox interiors overlap
165
- touching edge = bbox contact gap <= 0.05 model units
166
- component = transitive closure over overlap/touching edges
172
+ bbox candidate = bbox interiors overlap or bbox contact gap <= 0.05 model units
173
+ overlap edge = exact boolean intersection volume > 0.1 model units^3
174
+ component = transitive closure over exact overlap edges
167
175
  ```
168
176
 
169
177
  The manifest stores the edge list, component list, per-object body counts, and
@@ -172,8 +180,11 @@ multiple disconnected kernel bodies and the caller supplied a body count, the
172
180
  manifest reports `bodyCount > 1` but the PNG cannot color those internal bodies
173
181
  separately yet.
174
182
 
175
- Connectivity is a fast bbox-neighborhood graph. Use the `collisions` channel
176
- when you need exact positive-volume boolean overlap evidence.
183
+ Connectivity uses bbox only as a broadphase. Bbox contact is not enough to merge
184
+ separate scene objects, which keeps concave assemblies such as cages and captive
185
+ balls from being falsely colored as one component. Use the `collisions` channel
186
+ when you need positive-volume overlap evidence as a defect report rather than a
187
+ component grouping.
177
188
 
178
189
  `distance` emits one rooted physical-component-distance heatmap per view. Black
179
190
  is background. Non-black pixels resolve through
@@ -190,9 +201,15 @@ root = largest component by body count, object count, then bbox volume
190
201
  rootDistance = shortest accumulated gap distance from root component
191
202
  ```
192
203
 
204
+ For large scenes the manifest does not materialize the complete component gap
205
+ graph, because that graph is quadratic in the number of components. The
206
+ `gapEdgeCount` field reports the logical complete-graph edge count used by the
207
+ analysis. `gapEdges` stores a compact evidence subset containing nearest-gap
208
+ and root-parent edges.
209
+
193
210
  The PNG colors components from green at the root/near distances through yellow to
194
211
  red at the farthest rooted component. The manifest stores the root component,
195
- maximum rooted distance, complete component gap edge list, nearest-gap data, and
212
+ maximum rooted distance, compact gap edge evidence, nearest-gap data, and
196
213
  shortest-path parent fields. The current v1 metric is bbox-based: it measures air
197
214
  gaps between component bounding boxes, not exact closest mesh-surface distance.
198
215
 
@@ -209,16 +226,17 @@ collision = boolean intersection volume > 0.1mm^3
209
226
  ```
210
227
 
211
228
  The manifest stores the inspected objects, collision pair names/ids, overlap
212
- volume, warnings, render style, and each collision finding's `groupIndex`,
213
- `color`, and `hex`. Exact interior pixels can be matched against
229
+ volume, broadphase counters, warnings, render style, and each collision finding's
230
+ `groupIndex`, `color`, and `hex`. Exact interior pixels can be matched against
214
231
  `manifest.channels.collisions.collisions[].color`; antialiased edges may blend
215
232
  with the ghosted source geometry. If `--focus PartA,PartB` is used, everything
216
233
  except those objects is hidden, `PartA` and `PartB` are ghosted, and their
217
234
  overlap volume is highlighted if present.
218
235
 
219
- `thickness` emits one local wall-thickness heatmap per view. The renderer
220
- samples visible mesh triangles, casts through the object along each triangle
221
- normal, and colors the surface by the first opposite-surface distance:
236
+ `thickness` emits one local wall-thickness heatmap per view. The renderer places
237
+ deterministic area-weighted point samples across visible mesh surfaces, casts
238
+ through the object along each sample normal, and colors each point by the first
239
+ opposite-surface distance:
222
240
 
223
241
  ```text
224
242
  red = thickness <= minThickness
@@ -231,7 +249,7 @@ gray = unresolved sample
231
249
  The default thresholds are `minThickness=1.2`, `warnThickness=2.0`, and
232
250
  `maxThickness=6.0` model units. Override them with `--min-thickness`,
233
251
  `--warn-thickness`, and `--max-thickness`. Use `--thickness-samples` to raise or
234
- lower the maximum sampled triangles per object.
252
+ lower the maximum thickness point samples per object.
235
253
 
236
254
  The manifest stores the method, thresholds, palette, object list, per-object
237
255
  triangle counts, sampled-triangle counts, minimum, p05, median, mean, maximum,
@@ -239,6 +257,17 @@ critical-area percentage, warning-area percentage, below-warning percentage, and
239
257
  unresolved-area percentage. This makes the PNG useful for visual debugging while
240
258
  the manifest remains the machine-readable source of truth.
241
259
 
260
+ The channel also writes `channels/thickness/point-cloud.json`. Each point sample
261
+ stores object identity, object-local position, normal, measured thickness,
262
+ class, RGB color, and represented surface area. The PNG renders those samples
263
+ over muted source geometry, so local evidence survives even when neighboring
264
+ triangles have very different values.
265
+
266
+ `roughness` uses the same area-weighted point placement. Point colors are local
267
+ to nearby physical feature edges: smooth tessellation diagonals do not become
268
+ visible roughness lines. Use `--roughness-samples` to raise or lower the maximum
269
+ roughness point samples per object.
270
+
242
271
  `section` emits five interior slices per principal plane. The current slicing
243
272
  policy is:
244
273
 
@@ -276,8 +305,8 @@ per-view depth ranges, and object-mask mappings live.
276
305
  not infer identity from object order alone.
277
306
  - Connectivity is object-level. It reports disconnected kernel bodies in the
278
307
  manifest, but the PNG does not split a single scene object into per-body colors.
279
- - Bbox contact is intentionally simple and may over-connect concave shapes whose
280
- bounding boxes touch while surfaces do not. Boolean-overlap edges are exact.
308
+ - Bbox contact is only broadphase evidence and does not merge separate scene
309
+ objects by default. Boolean-overlap edges are exact.
281
310
  - Distance is a physical-component bbox-gap metric in v1, not exact nearest
282
311
  mesh-surface distance. Concave components and loose bounding boxes can make the
283
312
  reported gap smaller than the real closest-surface distance.
@@ -67,50 +67,63 @@ Execute scripts and produce images headless — no browser window. Renders use C
67
67
 
68
68
  ### `forgecad run`
69
69
 
70
- Execute a Forge script and print full geometry diagnostics — object summary, collision detection, spatial analysis, verification results, and solver profiling.
70
+ Execute a Forge script quickly and print the inner-loop build summary: returned objects, verification results, parameters, and timing.
71
71
 
72
- The primary validation command. Runs your script with the real geometry kernel (no browser needed) and prints a comprehensive report:
72
+ The fast validation command. Runs your script with the real geometry kernel (no browser needed) and reports whether it built, which objects came back, any `verify.*` results, parameter values, script logs, and elapsed script time. This is the command agents should run frequently while editing a model.
73
73
 
74
- **Object summary** — lists every named shape with its volume, bounding box, and body count. For constrained sketches, shows solver status (FULLY / UNDER / OVER constrained), DOF, and error residuals. Problematic constraints (conflicting, redundant, or high-residual) are flagged individually.
74
+ **Fast by default** — a bare `forgecad run model.forge.js` does not compute per-object volumes, bounding boxes, construction history, feature tallies, spatial relationships, collision intersections, or solver profiles. Those diagnostics are useful, but they are no longer part of the hot path.
75
75
 
76
- **Construction history** — shows the build sequence for each shape (primitives, operations, modifications) so you can verify the modeling intent.
76
+ **Opt-in diagnostics** — use `--details` for volume/bounding-box/object geometry summaries, `--history` for the construction tree, `--features` for feature tallies, `--solver-profile` for constraint solver timing, or `--full` for the legacy rich report. Use `--spatial bounded|exact` only when you want directional relationships and collision intersections from the run command itself.
77
77
 
78
- **Feature summary** — tallies geometry features across all objects (e.g. `3 extrude, 2 fillet, 1 chamfer`).
78
+ **Verification results** — runs any `verify.*` checks in the script and reports pass/fail with expected vs actual values. Verification failures remain non-fatal so the model can still render and be inspected.
79
79
 
80
- **Verification results** — runs any `verify.*` checks in the script and reports pass/fail with expected vs actual values.
80
+ **Physical connectivity** — pass `--connectivity` to list physically connected components across visible objects. Overlapping bbox candidates are checked with exact geometry by default, while bbox-only contact is treated as evidence rather than proof of one connected component. This helps answer whether the model is one continuous assembly or several separate islands.
81
81
 
82
- **Automatic collision detection** — performs an all-pairs collision check on every named shape. For each pair whose bounding boxes overlap, computes the boolean intersection and reports overlap above 0.1 mm³:
83
-
84
- ```
85
- ⚠ COLLISION: bolt ∩ base (shared vol: 42.3mm³)
86
- ```
87
-
88
- Intra-group pairs (same assembly group) and mock-to-mock pairs are skipped. If a part passes through a boolean-subtracted hole, no collision is reported — the material is gone.
82
+ **Quality preset** — pass `--quality live|default|high` to select the same geometry quality profile used by the editor and export tools. `live` is the fastest preset for large audit models.
89
83
 
90
- **Spatial analysis** reports directional relationships and gap distances between nearby objects (e.g. `bracket is ABOVE base (gap: 5mm)`). Exact pairwise collision intersections run by default only for bounded scenes; use `--spatial exact` for exhaustive collision checks or `--spatial off` to skip this section.
84
+ For deeper confidence gates, prefer `forgecad inspect mechanical-integrity`, `forgecad check print`, `forgecad check params`, or `forgecad render inspect` instead of turning `run` back into a catch-all audit command.
91
85
 
92
- **Physical connectivity** — pass `--connectivity` to list physically connected components across visible objects. Overlapping or touching bboxes are joined within `--connectivity-tolerance` (default `0.05` model units); use collision inspection for exact positive-volume overlaps. This helps answer whether the model is one continuous assembly or several separate islands.
86
+ ```bash
87
+ forgecad run examples/api/static-assembly-connectors.forge.js
88
+ forgecad run examples/api/static-assembly-connectors.forge.js --focus
89
+ forgecad run examples/api/static-assembly-connectors.forge.js --focus "Bench.Slat*"
90
+ forgecad run examples/api/static-assembly-connectors.forge.js --hide "Bench.Slat0,Bench.Slat1"
91
+ forgecad run examples/api/static-assembly-connectors.forge.js --details --history
92
+ forgecad run examples/api/static-assembly-connectors.forge.js --spatial bounded
93
+ forgecad run examples/api/static-assembly-connectors.forge.js --full
94
+ forgecad run examples/products/cup.forge.js --connectivity
95
+ forgecad run examples/products/cup.forge.js --journeys
96
+ forgecad run examples/products/cup.forge.js --backend occt
97
+ forgecad run examples/products/cup.forge.js --backend truck --quality live
98
+ forgecad run examples/products/cup.forge.js --debug-imports
99
+ forgecad run examples/products/cup.forge.js -p "Wall Thickness=3" -p "Body Height=200"
100
+ forgecad run examples/constraints/06-complex-spectrogram.forge.js --solver-debug-out tmp/spectrogram-debug
101
+ ```
93
102
 
94
- **Quality preset** pass `--quality live|default|high` to select the same geometry quality profile used by the editor and export tools. `live` is the fastest preset for large audit models.
103
+ ### Object Filtering: `--focus` and `--hide`
95
104
 
96
- **Parameters** lists all declared parameters with their current values. Overridden values are marked with `*`.
105
+ Several CLI commands can filter the visible object set without changing model code: `run`, `render 3d`, `render wireframe`, `render inspect`, `capture`, and `check print`.
97
106
 
98
- **Solver profiling** when constraint solving occurs, shows timing breakdown (clone, solve, redundancy detection, surface building) and solver internals.
107
+ Use `forgecad run model.forge.js --quality live` to list returned object names quickly, then pass those names to `--focus` or `--hide`.
99
108
 
100
109
  ```bash
101
- forgecad run examples/cup.forge.js
102
- forgecad run examples/cup.forge.js --focus
103
- forgecad run examples/cup.forge.js --focus bracket,hinge
104
- forgecad run examples/cup.forge.js --hide "wall,bolt"
105
- forgecad run examples/cup.forge.js --connectivity
106
- forgecad run examples/cup.forge.js --journeys
107
- forgecad run examples/cup.forge.js --backend occt
108
- forgecad run examples/cup.forge.js --backend truck --quality live
109
- forgecad run examples/cup.forge.js --debug-imports
110
- forgecad run examples/cup.forge.js -p "Wall Thickness=3" -p "Body Height=200"
111
- forgecad run examples/constraints/06-complex-spectrogram.forge.js --solver-debug-out tmp/spectrogram-debug
110
+ forgecad run examples/api/static-assembly-connectors.forge.js --quality live
111
+ forgecad render 3d examples/api/static-assembly-connectors.forge.js bench.png --focus "Bench.*"
112
+ forgecad render 3d examples/api/static-assembly-connectors.forge.js slats.png --focus "Bench.Slat*"
113
+ forgecad render inspect examples/api/static-assembly-connectors.forge.js out/bench-inspect --channels rgb,mask --hide "Bench.Slat0,Bench.Slat1" --force
112
114
  ```
113
115
 
116
+ Rules:
117
+
118
+ - A bare `--focus` hides mock objects and keeps real objects.
119
+ - `--focus name1,name2` renders only matching objects.
120
+ - `--hide name1,name2` removes matching objects from the visible scene.
121
+ - Matching is case-insensitive and supports `*` / `?` globs.
122
+ - `--focus` and `--hide` are mutually exclusive.
123
+ - Filtering happens after the script runs; it does not avoid evaluating the full model.
124
+ - Filtering works on returned object names. For grouped children, use concrete child names or globs like `Bench.*`.
125
+ - If a model unions many parts into one returned shape, the original parts cannot be isolated by CLI filtering.
126
+
114
127
  ### `forgecad render`
115
128
 
116
129
  Render a Forge scene. Use a subcommand — `3d`, `inspect`, `views`, `section`, `wireframe`, `sketch`, or `hq`.
@@ -127,13 +140,13 @@ Render a Forge scene. Use a subcommand — `3d`, `inspect`, `views`, `section`,
127
140
  - `render hq` — path-traced via Blender Cycles, for documentation and marketing shots
128
141
 
129
142
  ```bash
130
- forgecad render 3d examples/cup.forge.js
143
+ forgecad render 3d examples/products/cup.forge.js
131
144
  forgecad render inspect examples/api/static-assembly-connectors.forge.js --channels rgb,mask
132
145
  forgecad render inspect channels
133
- forgecad render views examples/cup.forge.js
134
- forgecad render wireframe examples/cup.forge.js
146
+ forgecad render views examples/products/cup.forge.js
147
+ forgecad render wireframe examples/products/cup.forge.js
135
148
  forgecad render section examples/furniture/01-table.forge.js --plane XZ
136
- forgecad render hq examples/cup.forge.js --preset dramatic
149
+ forgecad render hq examples/products/cup.forge.js --preset dramatic
137
150
  ```
138
151
 
139
152
  ### `forgecad render 3d`
@@ -149,10 +162,10 @@ Use `--edges=<off|thin|bold>` to control the edge overlay. For a pure wireframe
149
162
  This is the standard way to visually verify geometry from the CLI or in agent workflows. For higher quality (path-traced, materials, HDRI lighting), use `render hq` instead.
150
163
 
151
164
  ```bash
152
- forgecad render 3d examples/cup.forge.js
153
- forgecad render 3d examples/cup.forge.js --focus
154
- forgecad render 3d examples/cup.forge.js --focus bracket
155
- forgecad render 3d examples/cup.forge.js --hide "wall,bolt"
165
+ forgecad render 3d examples/products/cup.forge.js
166
+ forgecad render 3d examples/api/static-assembly-connectors.forge.js --focus
167
+ forgecad render 3d examples/api/static-assembly-connectors.forge.js --focus "Bench.Slat*"
168
+ forgecad render 3d examples/api/static-assembly-connectors.forge.js --hide "Bench.Slat0,Bench.Slat1"
156
169
  forgecad render 3d model.forge.js --view hero
157
170
  forgecad render 3d model.forge.js --camera 45:30
158
171
  forgecad render 3d model.forge.js --camera "proj=perspective;pos=200,-160,120;target=0,0,20;up=0,0,1;fov=38"
@@ -186,7 +199,7 @@ For bundle layout, channel encodings, and manifest semantics, see [Inspection Bu
186
199
 
187
200
  ```bash
188
201
  forgecad render inspect examples/api/static-assembly-connectors.forge.js --channels rgb,mask
189
- forgecad render inspect examples/api/static-assembly-connectors.forge.js out/bench-inspect --channels collisions --focus Bench
202
+ forgecad render inspect examples/api/static-assembly-connectors.forge.js out/bench-inspect --channels collisions --focus "Bench.*"
190
203
  forgecad render inspect examples/api/static-assembly-connectors.forge.js --channels rgb,mask,collisions --hide "Bench.Slat0" --force
191
204
  ```
192
205
 
@@ -206,8 +219,8 @@ Render a Forge scene as a wireframe (edges only, no shading).
206
219
  Same as `render 3d` but renders only the edge geometry — no shaded surfaces. Useful for construction-style documentation or highlighting structural features without material detail.
207
220
 
208
221
  ```bash
209
- forgecad render wireframe examples/cup.forge.js
210
- forgecad render wireframe examples/cup.forge.js --camera iso
222
+ forgecad render wireframe examples/products/cup.forge.js
223
+ forgecad render wireframe examples/products/cup.forge.js --camera iso
211
224
  ```
212
225
 
213
226
  ### `forgecad render hq` **\[Pro\]**
@@ -221,12 +234,12 @@ Choose a `--preset` for the look: `studio` (neutral product shot), `dramatic` (h
221
234
  Output defaults to `<script-name>-hq.png`. Great for documentation, marketing renders, and social media.
222
235
 
223
236
  ```bash
224
- forgecad render hq examples/cup.forge.js
225
- forgecad render hq examples/cup.forge.js hero.png --preset dramatic --samples 1024
226
- forgecad render hq examples/cup.forge.js hero.png --view hero
227
- forgecad render hq examples/cup.forge.js hero.png --camera-json camera.json
228
- forgecad render hq examples/cup.forge.js --preset clay --size 2048
229
- forgecad render hq examples/cup.forge.js --transparent --preset glass
237
+ forgecad render hq examples/products/cup.forge.js
238
+ forgecad render hq examples/products/cup.forge.js hero.png --preset dramatic --samples 1024
239
+ forgecad render hq examples/products/cup.forge.js hero.png --view hero
240
+ forgecad render hq examples/products/cup.forge.js hero.png --camera-json camera.json
241
+ forgecad render hq examples/products/cup.forge.js --preset clay --size 2048
242
+ forgecad render hq examples/products/cup.forge.js --transparent --preset glass
230
243
  ```
231
244
 
232
245
  ### `forgecad capture gif|mp4` **\[Pro\]**
@@ -236,13 +249,13 @@ Animated orbit or joint playback.
236
249
  Renders an animated sequence by either orbiting the camera around the model or playing back a `jointsView` animation. Use `--capture orbit` (default) for a turntable rotation, `--capture animation --animation <name>` to play a named joints clip, or `--capture section-sweep` to move a clipping plane through the model. Supports `--cut-plane` to animate with a static cross-section visible. Use `--view`, `--camera`, `--camera-json`, or `--scene <file>` to choose the orbit base camera or the fixed camera for animations and section sweeps.
237
250
 
238
251
  ```bash
239
- forgecad capture gif examples/cup.forge.js
252
+ forgecad capture gif examples/products/cup.forge.js
240
253
  forgecad capture gif examples/3d-printer.forge.js out/section.gif --cut-plane "Front Section"
241
254
  forgecad capture gif model.forge.js out/raw.gif --param "Output=raw-sdf"
242
255
  forgecad capture gif model.forge.js out/front.gif --camera front
243
256
  forgecad capture gif model.forge.js out/hero.gif --view hero
244
257
  forgecad capture gif examples/3d-printer.forge.js out/sweep.gif --capture section-sweep --sweep-plane YZ
245
- forgecad capture mp4 examples/cup.forge.js
258
+ forgecad capture mp4 examples/products/cup.forge.js
246
259
  forgecad capture mp4 examples/api/runtime-joints-view.forge.js out/step.mp4 --capture animation --animation Step
247
260
  forgecad capture mp4 model.forge.js out/raw.mp4 --param "Output=raw-sdf"
248
261
  forgecad capture mp4 model.forge.js out/front.mp4 --camera front
@@ -276,8 +289,8 @@ forgecad render section examples/furniture/01-table.forge.js out/bold.svg --edge
276
289
 
277
290
  | Option | Description |
278
291
  |--------|-------------|
279
- | `--focus <names>` | Focus: no arg hides mocks; comma-separated names shows only those |
280
- | `--hide <names>` | Hide comma-separated object names |
292
+ | `--focus <names>` | Focus: no arg hides mocks; comma-separated names/globs show only those |
293
+ | `--hide <names>` | Hide comma-separated object names/globs |
281
294
  | `--camera <front\|back\|side\|right\|top\|iso\|az:el\|az:el:dist\|spec>` | Camera preset, spherical (az:el), or full spec such as `proj=perspective;pos=x,y,z;target=x,y,z;up=x,y,z;fov=45`. Repeatable. |
282
295
  | `--camera-json <file>` | Exact viewport camera JSON file |
283
296
  | `--view <name>` | Named camera view declared by the model with scene({ views }) |
@@ -299,7 +312,8 @@ forgecad render section examples/furniture/01-table.forge.js out/bold.svg --edge
299
312
  | `--min-thickness <mm>` | Critical thickness threshold in model units |
300
313
  | `--warn-thickness <mm>` | Warning thickness threshold in model units |
301
314
  | `--max-thickness <mm>` | Thick/blue heatmap threshold in model units |
302
- | `--thickness-samples <n>` | Maximum sampled triangles per object |
315
+ | `--thickness-samples <n>` | Maximum thickness point samples per object |
316
+ | `--roughness-samples <n>` | Maximum roughness point samples per object |
303
317
  | `--preset <name>` | Material/lighting preset |
304
318
  | `--width <px>` | Output width in pixels |
305
319
  | `--height <px>` | Output height in pixels |
@@ -530,7 +544,7 @@ forgecad skill one-file ~/Desktop/forgecad-context.md
530
544
  forgecad skill flattened-files ~/Desktop/forgecad-skills
531
545
  ```
532
546
 
533
- > **Workflow:** Agent writes the model -> `forgecad run` validates it -> `forgecad check print` catches printability risks -> `forgecad render inspect` produces visual evidence -> `forgecad check params` sweeps parameter robustness -> export ships the result. All in the terminal.
547
+ > **Workflow:** Agent writes the model -> `forgecad run` validates it -> `forgecad inspect mechanical-integrity` catches disconnected AI-slop patterns -> `forgecad check print` catches printability risks -> `forgecad render inspect` produces visual evidence -> `forgecad check params` sweeps parameter robustness -> export ships the result. All in the terminal.
534
548
 
535
549
  ## Validation
536
550
 
@@ -551,6 +565,20 @@ forgecad check print model.forge.js --min-wall 1.2 --warn-wall 2
551
565
  forgecad check print model.forge.js --expect-components 1 -p "Wall Thickness=3"
552
566
  ```
553
567
 
568
+ ### `forgecad inspect mechanical-integrity`
569
+
570
+ Inspect generated ForgeCAD models for mechanical integrity failures.
571
+
572
+ Scans a Forge script or a folder of generated projects and runs a mechanical integrity inspection. The inspection flags timeouts, runtime errors, missing `verify.*` checks, missing executed mechanical-interface checks, fragmented named groups, uncontracted manual assemblies, optional positive-volume object collisions, and excessive physical component counts when requested. Markdown details include suggested repair patterns such as connector-authored mates, bolted service covers, pinned levers, captured slides, hinges, clevis joints, retained shafts, and seated bearings. When `--collisions` is enabled, the Markdown details list the largest overlapping object pairs by volume so agents can repair the highest-risk interfaces first. Exact collision checks use a default 40-pair bbox-overlap budget and 30s exact-check time budget; exhausting either budget fails the file instead of silently passing a partial check.
573
+
574
+ ```bash
575
+ forgecad inspect mechanical-integrity path/to/generated-models
576
+ forgecad inspect mechanical-integrity path/to/model/main.forge.js --min-verifications 2
577
+ forgecad inspect mechanical-integrity path/to/model/main.forge.js --collisions
578
+ forgecad inspect mechanical-integrity path/to/generated-models --collisions --collision-pair-limit 250
579
+ forgecad inspect mechanical-integrity path/to/generated-models --json --timeout-ms 40000 --jobs 4
580
+ ```
581
+
554
582
  ### `forgecad check params`
555
583
 
556
584
  Sweep parameter ranges and report runtime failures, degeneracy, and new collisions.
@@ -574,6 +602,7 @@ forgecad check params path/to/model.forge.js --samples 12
574
602
  | Command | Description |
575
603
  |---------|-------------|
576
604
  | `check suite` | Run the repo invariant suite, with smoke and full profiles for the fast merge lane vs the broader regression sweep. |
605
+ | `inspect mechanical-integrity` | Inspect generated ForgeCAD models for mechanical integrity failures. |
577
606
  | `check runtime-globals` | Ensure the script sandbox does not add new lowercase injected globals. |
578
607
  | `check transforms` | Run transform and assembly invariants. |
579
608
  | `check dimensions` | Run dimension propagation invariants. |
@@ -617,7 +646,7 @@ The CLI is free for core workflows and exports. Production outputs are free to r
617
646
 
618
647
  | Free | Production outputs | Pro |
619
648
  |------|--------------------|-----|
620
- | `run`, `dev`, `studio`, `render 3d`, `export stl`, `export 3mf`, `export svg`, `check print`, `check params`, `check suite` | `cut-list`, `export sketch-pdf`, `export step`, `export brep`, `export gcode`, `export sdf`, `export urdf`, `export report`, `export cutting-layout` are free to run; Pro covers commercial use. | `render hq`, `capture gif`, `capture mp4` |
649
+ | `run`, `dev`, `studio`, `render 3d`, `export stl`, `export 3mf`, `export svg`, `check print`, `check params`, `inspect mechanical-integrity`, `check suite` | `cut-list`, `export sketch-pdf`, `export step`, `export brep`, `export gcode`, `export sdf`, `export urdf`, `export report`, `export cutting-layout` are free to run; Pro covers commercial use. | `render hq`, `capture gif`, `capture mp4` |
621
650
 
622
651
  ```bash
623
652
  forgecad license # Check signed-in account status
@@ -19,7 +19,7 @@ npm run preview # Preview production build
19
19
  ### CLI Tools
20
20
  ```bash
21
21
  forgecad export svg examples/constraints/01-fully-constrained-rect.forge.js # Export sketch to SVG
22
- forgecad render 3d examples/cup.forge.js # Render to PNG (Puppeteer + Chrome)
22
+ forgecad render 3d examples/products/cup.forge.js # Render to PNG (Puppeteer + Chrome)
23
23
  ```
24
24
 
25
25
  See [CLI.md](../CLI.md) for full CLI documentation.