# Parametric Mechanical Components

A pure-MoonBit library for dimensioned mechanical components and assemblies that
export to STEP through the `gmlewis/step` CAD pipeline. The component packages
depend only on the root module: no native runtime, OCCT, or Python is required
to build models.

## Quick start

```bash
# One ISO 4762 M4 x 20 socket head cap screw
moon run components/examples/fasteners -- \
  --standard iso4762 --size M4 --length 20 --detail detailed -o M4x20.step

# Screw + washer + nut kit
moon run components/examples/hardware_kit -- --size M4 --length 20 -o kit.step

# Screw placed in a nut by named mate connectors
moon run components/examples/mate_assembly -- --size M4 --length 20 -o mate.step

# Generic 2020 T-slot frame
moon run components/examples/extrusion_frame -- \
  --width 400 --depth 300 --height 500 --series 2020 -o frame.step

# Involute gear pair
moon run components/examples/gear_pair -- \
  --module 2 --teeth 20 --mateTeeth 40 -o gear-pair.step

# NEMA 17 stepper-motor envelope
moon run components/examples/stepper_motor -- \
  --frame NEMA17 --bodyLength 40 -o nema17.step

# Parameterized outrunner brushless-motor envelope (measured 360KV defaults)
moon run components/examples/brushless_motor -- -o brushless-motor.step
# A measured 42 mm motor: override every dependent dimension.
moon run components/examples/brushless_motor -- \
  --bellDiameter 42 --faceDiameter 38 --hubDiameter 15 \
  --windowInner 16 --windowOuter 35 --lipRadius 20 \
  --statorDiameter 24 --shaftDiameter 3 --propHoleCircle 10 \
  -o motor42.step

# Parameterized tire/wheel envelope (measured 177.8 x 38.1 defaults)
moon run components/examples/tire -- -o tire.step

# Matching measured tire mounting flange
moon run components/examples/tire_mount -- -o tire-mount.step

# LM8UU linear bushing and flanged housing
moon run components/examples/linear_bearing -- --bearing LM8UU -o lm8uu.step
moon run components/examples/linear_bearing -- \
  --bearing LM8UU --flanged -o lm8uu-flanged.step

# Extrusion T-nut or heat-set insert
moon run components/examples/extrusion_hardware -- \
  --part tnut --thread M3 --slot 5 -o tnut.step
moon run components/examples/extrusion_hardware -- \
  --part heat-set --length long -o heatset.step

# Steel angle or plate blank
moon run components/examples/stock_primitive -- \
  --part angle --legA 40 --legB 40 --thickness 4 --length 50 -o angle.step

# OpenBuilds V-Slot system
moon run components/examples/vslot -- \
  --part profile --profile 2020 --length 100 -o vslot-2020.step
moon run components/examples/vslot -- --part wheel -o vwheel.step
moon run components/examples/vslot -- --part tnut -o vslot-tnut.step
moon run components/examples/vslot -- --part bracket -o bracket.step
moon run components/examples/vslot -- --part spacer -o spacer.step
moon run components/examples/vslot -- --part eccentric -o eccentric.step

# EMT tube, shaft collar, and tube mount plate
moon run components/examples/tubing -- \
  --part emt --trade 1/2 --length 304.8 -o emt.step
moon run components/examples/tubing -- \
  --part collar --bore 8 --outer 16 --width 8 -o collar.step

# Set-screw shaft collar with a real trimmed radial hole and a set screw
# (OCCT-evaluated compound)
moon run components/examples/set_screw_collar -- \
  --bore 8 --outer 16 --width 8 --thread M4 --drill 4.1 -o set-screw-collar.step

# One-piece clamp shaft collar with a real slit, clamp-screw hole, and head
# counterbore plus an ISO 4762 clamp screw (OCCT-evaluated compound)
moon run components/examples/clamp_shaft_collar -- \
  --bore 20 --outer 40 --width 15 --thread M6 \
  --screwOffset 14.73 --screw M6 --screwLength 16 -o clamp-collar.step

# SC8UU rod/bearing block (OCCT-evaluated transverse bearing seat)
moon run components/examples/stock_primitive -- --part sc8uu -o sc8uu.step

# M3 x 4 heat-set insert test boss (Ø7.6 x 8, Ø4.4 x 5 pocket)
moon run components/examples/stock_primitive -- --part heat-boss -o heat-boss.step

# Counterbored plate and smooth idler
moon run components/examples/stock_primitive -- \
  --part counterbore --width 50 --height 40 --plateThickness 8 \
  --holeSpacing 24 --through 5.5 --counterbore 9 --counterboreDepth 2 -o cb.step
moon run components/examples/stock_primitive -- \
  --part bearing --width 50 --height 40 --plateThickness 6 \
  --bearingOD 22 --fit 0.1 --boltDiameter 5.5 --holeSpacing 30 -o bearing.step
moon run components/examples/motion_stack -- \
  --part idler --idlerOuter 20 --idlerBore 8 --idlerWidth 10 \
  --idlerFlangeDiameter 24 --idlerFlangeThickness 1.5 -o idler.step

# EMT end cap and split clamp
moon run components/examples/tubing -- --part endcap --trade 1/2 -o endcap.step
moon run components/examples/tubing -- --part clamp --trade 1/2 -o clamp.step

# Generic extrusion adapters (motor, channel, and tube clamp)
moon run components/examples/adapters -- --part motor -o motor-adapter.step
moon run components/examples/adapters -- --part channel -o channel-adapter.step
moon run components/examples/adapters -- \
  --part clamp --tubeOD 17.9324 -o tube-clamp.step

# Countersunk plate and tube-to-V-Slot bracket
moon run components/examples/stock_primitive -- \
  --part countersink --width 50 --height 40 --plateThickness 8 \
  --holeSpacing 24 --through 5.5 --countersinkDiameter 9 \
  --countersinkDepth 2 -o countersink.step
moon run components/examples/stock_primitive -- \
  --part tube-bracket --tubeOD 17.9324 --tubeClearance 0.5 \
  --width 60 --height 40 -o tube-bracket.step

# P1000-style strut channel and channel nut
moon run components/examples/profile_extrusion -- \
  --profile channel-p1000 --length 1000 -o strut.step
moon run components/examples/profile_extrusion -- \
  --profile channel-nut --thread 5 -o channel-nut.step

# Rigid coupling and flanged bearing housing
moon run components/examples/motion_stack -- \
  --part coupling --couplingBore 8 --couplingOuter 16 \
  --couplingLength 20 -o coupling.step
moon run components/examples/motion_stack -- \
  --part flange-housing --housingBearingOD 22 \
  --housingBearingWidth 7 -o housing.step

# UCP-series pillow block bearing assembly (OCCT-evaluated, 8 solids)
moon run components/examples/motion_stack -- \
  --part pillow-block --pillowBlock UCP204 -o ucp204.step
moon run components/examples/motion_stack -- \
  --part pillow-block --pillowBlock UCP205 -o ucp205.step

# Helical beam coupling with clamp hubs (OCCT-evaluated body + M3 screws)
moon run components/examples/motion_stack -- \
  --part helical-coupling -o helical-coupling.step

# Generic solid rivet
moon run components/examples/rivet -- --shank 3 --length 10 -o rivet.step

# MakerBeam 10 x 10 mm extrusion (drawing article 100168)
moon run components/examples/makerbeam -- --length 100 -o makerbeam.step
moon run components/examples/makerbeam -- --length 250 --cornerRadius 0.2 -o mb.step

# DIN 471 type A external retaining ring (A 10 to A 34)
moon run components/examples/retaining_ring -- --size 20 -o din471-20.step

# DIN 472 internal retaining ring (all table sizes 8 to 40; ten measured outlines plus a parametric fallback)
moon run components/examples/din472_ring -- --size 10 -o din472-10.step
moon run components/examples/din472_ring -- --size 20 -o din472-20.step
moon run components/examples/din472_ring -- --size 22 -o din472-22.step
moon run components/examples/din472_ring -- --size 40 -o din472-40.step

# Built-in M3/M4/M5 fastener catalogue
mkdir -p components/examples/output
moon run components/examples/fasteners -- --catalog components/examples/output
```

All dimensions are millimetres, Z is up, and components use the origins and
axes documented in each builder. Every `-o` path above is a local output.
`components/examples/output/` is generated by
`components/examples/generate_all.sh` and is Git-ignored: no STEP, STL, or SVG
example artifact is stored in this repository.

## Mechanism kit and design families

`components/mechanisms` provides generic, parametric mechanism and structural
envelopes. Each builder validates every dimension, exposes named
`MateConnector`s, has analytic tests, and is an engineering envelope rather than
a vendor part or a strength claim.

```bash
# Barrel hinge with an included pin and real pin bores
moon run components/examples/mechanism_kit -- --part hinge -o hinge.step

# Clevis fork, pin, rod end, linkage bar, linear rail and carriage
moon run components/examples/mechanism_kit -- --part clevis -o clevis.step
moon run components/examples/mechanism_kit -- --part pin -o pin.step
moon run components/examples/mechanism_kit -- --part rod-end -o rod-end.step
moon run components/examples/mechanism_kit -- --part linkage -o linkage.step
moon run components/examples/mechanism_kit -- --part rail -o rail.step
moon run components/examples/mechanism_kit -- --part carriage -o carriage.step

# Lead screw and flanged nut (the thread is declared, never modelled)
moon run components/examples/mechanism_kit -- --part lead-screw -o screw.step
moon run components/examples/mechanism_kit -- --part lead-nut -o nut.step

# Belt loop, eccentric cam, roller follower, and Oldham coupling
moon run components/examples/mechanism_kit -- --part belt -o belt.step
moon run components/examples/mechanism_kit -- \
  --part belt-unequal --pulleyB 40 -o belt-unequal.step
moon run components/examples/mechanism_kit -- --part cam -o cam.step
moon run components/examples/mechanism_kit -- --part roller -o roller.step
moon run components/examples/mechanism_kit -- --part oldham -o oldham.step

# Extension and torsion springs, snap latch, O-ring, and grooved shaft
moon run components/examples/mechanism_kit -- --part extension-spring -o ext.step
moon run components/examples/mechanism_kit -- --part torsion-spring -o tor.step
moon run components/examples/mechanism_kit -- --part snap -o snap.step
moon run components/examples/mechanism_kit -- --part o-ring -o oring.step
moon run components/examples/mechanism_kit -- --part grooved-shaft -o shaft.step

# L bracket, U/Z brackets, tapped boss, and rack
moon run components/examples/mechanism_kit -- --part bracket -o bracket.step
moon run components/examples/mechanism_kit -- --part u-bracket -o u-bracket.step
moon run components/examples/mechanism_kit -- --part z-bracket -o z-bracket.step
moon run components/examples/mechanism_kit -- --part boss -o boss.step
moon run components/examples/mechanism_kit -- --part rack -o rack.step

# ANSI #40 roller-chain sprocket (measured CC0 16T/24T outlines)
moon run components/examples/mechanism_kit -- \
  --part sprocket --sprocketTeeth 16 --evaluated -o sprocket-16t.step
moon run components/examples/mechanism_kit -- \
  --part sprocket --sprocketTeeth 24 --evaluated -o sprocket-24t.step

# ANSI #40 10-pitch roller-chain segment (CC0 layout reference)
moon run components/examples/mechanism_kit -- \
  --part chain-segment --chainPitches 10 -o chain-segment.step

# Design from scratch with the typed parameter API and the @cad DSL
moon run components/examples/mechanism_design -- \
  --length 140 --width 24 --pivot 8 -o linkage.step
moon run components/examples/mechanism_design -- \
  --variant compact -o linkage-compact.step

# Assemble a clevis, rod end, and pin by a named MatePair
moon run components/examples/mechanism_assembly -- \
  -o clevis-rod-end.step
moon run components/examples/mechanism_assembly -- --mode assembly \
  -o clevis-rod-end-assembly.step

# Fuse a layered mechanism body into one OCCT-evaluated manifold
moon run components/examples/mechanism_kit -- \
  --part hinge --evaluated -o hinge-evaluated.step

# Two-pulley GT2 belt drive with a declared pitch length
moon run components/examples/belt_drive -- \
  --teethA 20 --teethB 40 --pitchLength 400 -o belt-drive.step

# Basic rack and involute pinion at the layout centre distance
moon run components/examples/rack_pinion -- \
  --module 2 --pinionTeeth 20 --rackTeeth 20 -o rack-pinion.step

# Planar four-bar linkage from the four-bar layout helper
moon run components/examples/four_bar -- \
  --ground 40 --crank 10 --coupler 40 --rocker 30 --crankAngle 45 \
  -o four-bar.step
```

`components/common` adds an additive parameter/design-family API. Existing
builders keep their direct `Double` signatures; a family wraps one for
interactive or scripted exploration:

```moonbit
let specs = [
  @common.ParamSpec::new(
    name="length", default_mm=120.0, min_mm=60.0, max_mm=400.0,
    description="linkage bar length",
  ),
  @common.ParamSpec::new(name="pivot", default_mm=8.0, min_mm=4.0, max_mm=20.0),
]
let family = @common.DesignFamily::new(
  name="pivot-linkage",
  specs~,
  build=fn(parameters) {
    @mechanisms.linkage_bar(
      @common.expect_ok(parameters.get("length")),
      @common.expect_ok(parameters.get("pivot")),
      6.0,
      8.0,
    )
  },
)
let part = family.build_values([("length", 140.0)])
```

`ParamSet` validates names, ranges, and units; `DesignFamily` records named
variants and builds only validated parameter sets. `ParamSet::length` returns a
typed `@cad.Length`; the `*_from_lengths` builders (for example
`linkage_bar_from_lengths`) make the millimetre unit explicit. Bare `Double`
dimensions are millimetres. `@mechanisms.linkage_family()` is a ready-made
family with `compact` and `long` presets; the design example uses it.
`@mechanisms.four_bar_layout()` closes a planar four-bar linkage at a crank
angle and reports its joint positions, the Grashof condition, and whether it is
a crank-rocker.

`components/examples/mechanism_design` is the design-from-scratch example. It
runs with `--headless` for agents and `--view` for the owner; see
[`docs/boundaries.md`](../docs/boundaries.md) for the view/iterate loop. It and
`mechanism_kit` accept `--evaluated` to fuse their layers with OCCT when a
single trimmed manifold is needed.
`components/examples/mechanism_assembly` shows the interface side: it places a
rod end in a clevis with a named `MatePair` (`eye-seat` ↔ `eye-bore`), inserts
the pin through both prongs and the eye, checks connectivity, and can write the
assembly product structure.

## Construction systems and commodity tubing

`profile` V-Slot parts use the OpenBuilds 20-series cross-section: 20 x 20 or
20 x 40, a 9.16 mm V mouth narrowing to a 6.25 mm neck, 90 degree included V
lips, an 11 mm cavity, 1.5 mm diagonal webs, and 4.2 mm core bores. V-Slot is
**not** the generic T-slot envelope in `profiles/tslot.mbt` and is not
interchangeable with a vendor B-slot6 section; keep the mating geometry with
the intended rail.

The V-wheel body is modelled at its published boundary (23.89 mm OD, 10.23 mm
wide, 90 degree groove, Ø16 bearing pockets, Ø11 mid-lip bore). Bearing pockets
and core bores are analytic cylinders. Bearings, shims, threads, and structural
ratings are not modelled.

MakerBeam 10 x 10 mm uses the section of MakerBeam's drawing article 100168: a
3 mm slot on each face over a 41.1 degree dovetail undercut, a 4 x 4 mm core,
and a Ø2.5 mm centre bore that is the M3 end-thread tap drill. The section area
is 48.75 mm². It is **not** the generic T-slot or the OpenBuilds V-Slot section,
and a generic T-nut does not automatically fit it. MakerBeam's R0.2 drawing
radii and the M3 x 8 mm end threads are not modelled; the end threads are
declared by `end-thread-a`/`end-thread-b` connectors only. MakerBeamXL 15 x 15
and OpenBeam 15 x 15 are not implemented: their dimensioned sections could not
be obtained under usable terms.

EMT tubes use the measured ANSI C80.3 / UL 797 outside diameter and nominal
wall (a 1/2 in EMT is 17.9324 mm OD, not 12.7 mm). No coupling, thread, bend, or
electrical/structural rating is claimed. The EMT end cap is a spigot closure
sized from the tube OD/ID, and the split clamp is a generic one-bolt collar
whose ring is a slit tube and whose ears are separate prisms embedded into the
slit edges.

P1000-style strut channel uses the published 41.3 mm envelope, 2.6 mm (12
gauge) wall, 22.2 mm front opening, and 14.3 mm back-wall holes on 47.6 mm
centres. It is manufacturer-style geometry, not a universal standard; the
brand's serrated lip teeth, end treatment, and load rating are not modelled.
The channel nut is a generic block sized to enter the opening and bear on the
lips, not a vendor spring nut.

A conical countersink is not a prismatic cut. `plate_with_countersinks` builds
each seat as an exact annular wedge of revolution layered between a stepped
through-hole layer and a countersink-diameter layer, so the seat is a real
`CONICAL_SURFACE` and the layer volumes sum exactly. The layered split clamp and
the layered channel have the same property; where a layer deliberately embeds
into another (the clamp ears), the documentation states the embed and the union
is a nominal rather than a boolean result.

A layered accessory exports by default as several touching closed solids. When
one watertight solid is wanted (for downstream mesh or boolean consumers),
`Component::to_step_evaluated` / `write_step_evaluated` fuses the layers into
one boolean union and evaluates it with OCCT, producing a single trimmed
`MANIFOLD_SOLID_BREP` with the same physical volume as the layer sum. This is
an opt-in development path: it requires `python3`, OCCT (`occt-draw` or
`DRAWEXE`), and `$MOONBIT_STEP_ROOT`, and the library itself stays kernel-free.
The default layered `to_step` / `write_step` output is unchanged. A
single-layer flat component is already one closed solid and is returned
unchanged. The evaluated file keeps the component description and the
machine-readable feature record in its header; only the geometry is replaced by
OCCT's trimmed result. The set-screw shaft collar makes this evaluated result
its primary artifact because the flat writer cannot trim its radial hole; the
example's set screw is a second, disjoint solid in the same evaluated compound.

## Named connectors and the golden preview

Every public component builder exposes at least one named `MateConnector`
(`cylindrical-bore`, `cylindrical-shaft`, `plane-face`, `threaded`,
`profile-slot`, or `datum`). Connectors are metadata: they never add geometry,
change the volume or bounding box, or appear in the STEP file.

For developer inspection, `Component::connector_sidecar()` lists each
connector's origin, primary axis, and a deterministic secondary axis. The
secondary axis stays on a global axis unless the connector's placement
deliberately carries a twist. With `STEP_CONNECTOR_SIDECAR` set,
`Component::write_step` writes a sibling `<out>.connectors.tsv`.

`./compare-golden.sh` uses this by default: it generates the sidecar, opens the
golden and parametric pair in SolidCraft, and adds a named `joint.origin`
(`connector/<name>`) at every connector frame. SolidCraft's native joint
origins are the interactive equivalent of OnShape mate connectors; STEP itself
has no standard visual mate connector. The `joint.origin` frames are a
developer visualization only: they are application features in the running
SolidCraft session, never part geometry, and they do not change the STEP file,
its volume, bounding box, layer count, or golden measurement. A missing sidecar,
an unavailable GUI, a refused tab, or a failed `joint.origin` prints a note and
never fails generation or measurement. Use `--no-connectors` to disable the
frames or `--no-helper` to fall back to `open -a` without them; automated agents
use `--headless`.

## Package map

| Package | Contents |
|---|---|
| `common` | Units-aware validation, detail levels, thread representation, metadata, placement, `Component`, `MateConnector`, and `MatePair`. |
| `standards` | Metric thread data and ISO/DIN dimension tables (ISO 4032/4035/4762/7089/709x/7380/8752/10642, DIN 471/472/557/913/916/976/1587, …). |
| `fasteners` | Screws, bolts, nuts, washers, pins, rods, set screws, generic solid rivets, DIN 471 type A external retaining rings (A 10 to A 34), and DIN 472 internal retaining rings (all table sizes 8 to 40; measured outlines for 10, 12, 14, 16, 18, 20, 24, 28, 32, and 40 mm, parametric for the rest). |
| `profiles` | Generic T-slot sections, the vendor 2020 B-slot6 A section, OpenBuilds-compatible V-Slot 2020/2040 sections, the MakerBeam 10 x 10 section, a gusseted V-Slot corner bracket, P1000-style strut channel, and a generic channel nut. |
| `motion` | Shafts, stepped/keyed shafts, spacers and V-Slot wheel spacers (plain and eccentric), bushings, plain, set-screw, and clamp shaft collars, keys, dowel pins, standoffs, compression springs, ball bearings (envelope, shielded, and full-complement deep-groove), LM-series linear bushings, flanged linear housings, UCP-series pillow-block bearing boundaries, approximated GT2 timing pulleys, smooth idlers, V-Slot wheels, EMT tubing with end caps and split clamps, rigid couplings, helical beam couplings, flanged bearing housings, a parameterized tire/wheel envelope measured from the owner-authored `tire.step` model, and a matching tire mounting flange measured from `tire-mount.step`. |
| `mechanisms` | Generic engineering envelopes for a barrel hinge, clevis, pin, rod end, linkage bar, linear rail and carriage, lead screw and flanged nut, equal- and unequal-pulley timing-belt loops, eccentric cam and roller follower, Oldham coupling, extension and torsion springs, snap latch, O-ring, grooved shaft, L/U/Z brackets (L with optional gusset), tapped boss, a straight-flank basic rack with a pinion-layout helper, ANSI #40 roller-chain sprockets (measured CC0 16T/24T outlines), and a CC0-matched ANSI #40 10-pitch chain segment. |
| `motors` | NEMA 17 and NEMA 23 stepper-motor envelopes, mounting interfaces, NEMA mounting plates, a generic NEMA-to-20-series extrusion adapter, and a parameterized outrunner brushless-motor envelope measured from the owner-authored 360KV model (conical 5-spoke bell, windows, rim and lip, stator hub, prop and mount holes, shaft). |
| `stock` | EN 10056 angle sections, configurable flat plate blanks with analytic circular holes and obround slots, counterbored and countersunk plates, bearing-housing plates, tube-to-plate and tube-to-V-Slot adapter brackets, generic channel-to-extrusion adapters and extrusion-to-tube clamps, SC8UU-style rod/bearing blocks, and heat-set insert bosses. |
| `gears` | Involute spur gears, a smooth single-extrusion arc-run spur presentation, external pairs, and exact-internal-involute planetary sets. |
| `planetary` | Fully parametric herringbone planetary gearbox (sun, equally spaced planets, inward-facing ring) with every generator option as a parameter, exact line/arc extrusions when `num_elbows` is 0, and otherwise the true helical twist of each elbow as smooth ruled B-spline flanks with sharp piecewise-linear elbow creases; named mate connectors on every gear. |
| `assemblies` | Rigid placements, linear/circular patterns, hardware kits, extrusion frames, bolted joints, collision/contact reports, connectivity checks. |
| `collision` | Kernel-free AABB/OBB collision and contact classification. |
| `catalog` | Machine-readable catalogue/query API over the component families. |
| `examples/*` | Runnable generation programs and generated STEP output. |

## Verification

```bash
./test-all.sh
python3 scripts/compare_golden.py             # fixtures against the downloaded corpus
python3 scripts/validate_step.py components/examples/output/iso4762-M4x20.step
python3 scripts/validate_step.py --no-mesh \
  components/examples/output/mechanism-hinge.step
python3 scripts/validate_frame_geometry.py \
  components/examples/output/frame-2020-400x300x500.step \
  --width 400 --depth 300 --height 500 --series 2020
```

`validate_step.py` checks ISO 10303-21 syntax, references, per-shell topology
and orientation, PLANE planarity, OCCT `checkshape`, and watertight
tessellation. The validators and OCCT are optional development tools; the
library itself does not depend on them.

Assembly checks are available in MoonBit:

```moonbit
let collisions = assembly.collisions()
let contacts = assembly.contacts()
let floating = assembly.disconnected_instances()
```

## Mate connectors and pairs

`MateConnector` is a named attachment frame on one component. `MatePair` is the
relationship between two named connectors. Both types are defined once in
`components/common`; `gmlewis/urdf` and `gmlewis/cad` import them rather than
keeping local copies.

```moonbit
let hole = @common.MateConnector::new(
  "bore",
  placement=@common.Placement::translation(0.0, 0.0, 0.0),
  axis=(0.0, 0.0, 1.0),
  kind=@common.MateKind::CylindricalBore,
  gender=@common.MateGender::Female,
  diameter_mm=5.0,
  depth_mm=10.0,
)

let pair = @common.MatePair::new(parent="bore", child="shaft", offset_mm=2.0)
let alignment = pair.resolve(parent_connector, child_connector)
```

- **Units.** The connector stores a `Placement` in millimetres and degrees. At a
  URDF boundary use `from_m_rad` and `to_m_rad`, which convert to and from
  metres/radians.
- **Axis.** `axis` is an independent unit direction in the component-local
  frame, not the placement's +Z. It is the insertion, approach, or joint axis.
- **Names.** Names are stable, unique within a component, and lower-case
  kebab-case (`shaft`, `bore`, `mount-front`, `bolt-hole-1`).
- **Kinds and genders.** `MateKind` classifies the interface; `MateGender`
  describes geometric engagement, never strength. A bore is female, a shaft is
  male, and datum/plane/slot frames are neutral.
- **Fit.** `fit` reuses `@cad.Fit`; it records declared clearance intent and does
  not change the nominal STEP geometry.
- **Snapping.** `snap_connectors` reproduces the URDF offset/twist/flip frame
  snap. `MatePair::resolve` additionally checks kind, gender, diameter, and fit,
  and records any interface-convention axis flip in `MateAlignment`.
- **Assembly.** `Assembly::add_mate_pair(parent_instance, child, pair)` resolves
  the pair against a placed parent and returns the updated assembly plus the
  alignment.

Connectors are metadata: adding one, rebasing a component to a connector, or
resolving a pair never changes exported STEP geometry, layer count, or volume.
A geometric mate is not a structural-strength or safety claim.

Every implemented family exposes at least one named connector: fasteners expose
shaft/thread/head or bore/bearing-face frames, bearings expose bore and
outer-seat frames, shafts expose end frames, extrusions expose four face slots
and end datums, NEMA motors expose mounting, pilot, shaft, rear, and per-hole
frames, the brushless outrunner envelope exposes both shaft ends, the rotating
bell face, the fixed mount face, and its measured prop and mount hole set, and
plates expose face and per-hole frames. The mechanism kit's
clevis/pin and lead-screw/nut interfaces are exercised through
`MatePair::resolve` in its tests, which checks kind, gender, and nominal
diameter.

## CAD kernel boundary

This component library is **kernel-free by design**. **SolidCore / SolidCraft
is the required CAD engine** for boolean trimming, fillets and chamfers,
tessellation, import of vendor parts, and interactive edits. The flat writer's
`difference()`/`union_all()` concatenate faces; that nominal representation is
the architectural contract, not a limitation of the library. Resolve real
geometry with `write_step_evaluated` (OCCT) or by opening the STEP in
SolidCraft (`./run-example.sh <example> --view`). A component that needs a
blind socket or a real trim is built as one closed solid with explicit faces,
so the flat output is never an untrimmed stack.

The full Tier 1 / engine / Tier 2–3 boundary, including the `--view` iteration
loop and how imported vendor parts are referenced through SolidCraft, is in
[`docs/boundaries.md`](../docs/boundaries.md).

## Limitations

- Helical threads use the ISO 68-1 basic profile as a swept ridge. They are not
  tolerance-class threads and omit runout and root relief.
- Generic T-slot profiles are engineering envelopes, not a claim of
  cross-manufacturer compatibility. The 2020 B-slot6 A section is a faithful
  reproduction of its vendor reference.
- Extrusion frames use full-height posts and rails cut to the clear span;
  brackets, T-nuts, and end machining are not modelled.
- Bearing rolling elements are analytic spheres; ball diameter and ring
  chamfers are envelope geometry.
- Detailed fastener chamfers are real ruled or conical faces with
  engineering-default sizes where the standard leaves them open.
- Every component carries a machine-readable feature record (modeled,
  approximated with deviation, omitted with reason) in the STEP header.
- Evaluated 3D fillets/chamfers are optional (OCCT); the flat writer refuses
  them with a typed error.
- The internal ring gear uses an exact involute envelope with a declared
  `0.05 * module` backlash; profile shift, helix, and ring root fillets are
  omitted.
- NEMA motor envelopes model the mounting interface, pilot boss, and plain
  shaft. Body length and shaft length are parameters, not standards; electrical
  internals, rear shafts, shaft flats, and load ratings are omitted.
- The brushless outrunner envelope is measured from the owner-authored
  `components/testdata/golden/external/brushless-motor-360kv.step` model (kept locally,
  Git-ignored). Its conical bell sheet is represented by five flat
  conical-sector spokes, and the measured 2 mm window corner rounds are not
  modelled. Stator windings, magnets, bearings, phase wires, and every
  electrical or performance rating are omitted. All dimensions are parameters
  so a measured motor can be matched; the defaults are not a FlyCat or any
  other manufacturer's published drawing.
- The tire/wheel envelope is measured from the owner-authored
  `components/testdata/golden/external/tire.step` model (kept locally,
  Git-ignored). It is a smooth tire ring, a hub tube and bore, a 2 mm inset back
  plate, and straight radial ribs; the defaults include 6 ribs. Tread blocks,
  grooves, rubber compound, carcass, bead wires, valves, and every load, speed,
  or inflation rating are omitted. All dimensions are parameters, including the
  rib count and phase.
- The tire mounting flange is measured from the owner-authored
  `components/testdata/golden/external/tire-mount.step` model (kept locally,
  Git-ignored). It is a solid front plate with three bolt holes, a rear ring,
  a hub tube and bore, and six 2 mm radial slots. The mating bolts and the tire
  are separate parts; no finish, material, or strength rating is implied. All
  dimensions are parameters.
- LM-series linear bushings and flanged housings are boundary envelopes. Rolling
  elements, cages, seals, recirculation grooves, flange hole patterns, and load
  ratings are omitted.
- UCP-series pillow blocks (UCP204, UCP205) reproduce the CC0 Innerscene
  references (Koyo published dimensions) as eight separate solids: a housing
  casting with a rounded base plate, two obround mounting slots on the bolt
  pitch, a bottom centre relief, and a horseshoe arch around the insert seat; a
  self-aligning outer race (spherical outside diameter); an extended inner race
  with 45 degree rim chamfers and two radial set-screw holes; two contact
  seals; two DIN 916 M6 set screws; and a hex grease fitting on the crown. Both
  mating interfaces are real (the shaft bore and the two base mounting slots).
  The compound bounding box and overall height match the references exactly,
  the volume is within 0.02%, and the outer race, seals, set screws, and housing
  match the reference part-by-part. The parts sit at the reference's
  0.025-0.05 mm clearances, so they stay separate under the OCCT union. The
  rolling elements and cage between the races are omitted, the set-screw holes
  are 6.1 mm tap drills (the M6 threads are declared by connectors), and the
  grease fitting is a plain envelope. `detail = Simplified` collapses the insert
  to a plain sleeve (two solids). The flat writer cannot trim the relief, seat
  bore, or set-screw holes, so `write_step_evaluated` (OCCT) is the accepted
  artifact. No load, life, or safety rating is implied.
- UCP-series pillow-block dimensions use the published Koyo boundary values; the
  cast arch flank and skirt coordinates, insert races, seal widths, set-screw
  positions, and grease-fitting dimensions are measured from the references and
  are not derivable from the other parameters.
- The 5-to-8 mm helical beam coupling reproduces the CC0 Innerscene reference:
  an OD 25 x 30 sleeve with 45 degree x 0.5 mm outer chamfers, a stepped 5/8 mm
  bore, a continuous 0.7 mm helical slit through the wall (3 turns at a 3.2 mm
  pitch), and two clamp hubs (0.8 mm axial radial slits with a 3.2 mm clearance
  hole, a 6.1 mm head counterbore along Y, and two M3 x 12 ISO 4762 clamp
  screws). The helical slit has two smooth ruled B-spline walls sampled at 60
  cross-sections per turn, and each clamp slit opens through its end face. The
  body is within 0.05% of the reference volume and the three-solid compound is
  within 0.15%. Clamp screws default to presentation orange so they stand out
  against the sleeve; colour is not a material claim. The clamp-screw threads
  are declared by connectors, never modelled. No torque, torsional stiffness,
  or misalignment rating is implied.
- Extrusion T-nuts use one generic hex body for every catalogued retention
  style. The bore is a thread envelope; spring balls and style-specific
  retention are not modelled.
- Heat-set inserts model the two raised knurl bands as cylindrical reliefs, not
  a diamond knurl. Pull-out and torque strength require testing.
- The EN 10056 angle root fillet is one analytic cylindrical surface; its toe
  radii are analytic arcs.
- A plate blank is a generic primitive. Hole patterns do not imply a
  standardized commercial part.
- V-Slot has real lip, cavity, web, and core-bore geometry, plus V-wheels,
  T-nuts, a gusseted corner bracket, and plain/eccentric wheel spacers. The
  V-Slot section is verified analytically; the wheel and corner-bracket goldens
  are Xem Studio references (CC BY 4.0). EMT couplings, saddles, bends, and
  other conduit fittings are not implemented; the EMT end cap, split clamp,
  tube mount plate, tube-to-V-Slot bracket, and generic extrusion-to-tube clamp
  are.
- The generic adapters — NEMA motor to 20-series extrusion, P1000 channel to
  20-series extrusion, and extrusion-to-tube clamp — are original parametric
  engineering constructions built from the verified NEMA frame, P1000 channel,
  20-series slot, and EMT interfaces. They do not reproduce a vendor part and
  no reference STEP was used as a geometry source. The tube clamp is a layered
  ring/ear/base part whose accepted artifact is the OCCT-evaluated union. No
  thread, fastener, clamp force, or strength rating is claimed.
- DIN 471 type A external retaining rings are flat stamped rings with two
  lugs, plier holes, a free bore, and a declared shaft-groove interface. The
  DIN 471 table (d1, s, d3, a, b, d5, d2, m, t, n) is cross-checked between two
  independent sources and covers A 10 to A 34. The *free-state outline*
  between the back and the lugs is not dimensioned by DIN 471; it is the
  published FreeCAD-library model geometry (CC BY 3.0, by nachotineo), so the
  model bore can differ from d3 by up to 0.13 mm. Sharp edges, no edge breaks,
  no spring temper, and no load or fatigue rating. The shaft groove is
  declared by the `groove-seat` connector but is not modelled.
- DIN 472 internal retaining rings are flat stamped rings with two inward
  lugs, plier holes, a free outside diameter, and a declared bore-groove
  interface. The DIN 472 table (d1, s, d3, a, b, d5, d2, m, t, n) is
  cross-checked between the Aspen Fasteners sheet, the Stpektas table, and the
  Xem Studio sheet (CC BY 4.0) and covers 8 to 40 mm. The *free-state outline*
  is not dimensioned by DIN 472. Ten sizes use licensed measured outlines, each
  re-encoded as this library's own line/arc loop: 12/20 mm from CC0 Innerscene
  models, and 10/14/16/18/24/28/32/40 mm from CC BY-SA 4.0
  FreeCAD-parts_library B-reps. Those eight measured outline data sets remain
  CC BY-SA 4.0; the rest of the source remains Apache-2.0. Their reference
  edge breaks are real 45° chamfers equal to 10% of ring thickness (0.1, 0.12,
  or 0.175 mm), applied to both face boundaries as evaluated multi-edge
  chamfers; those eight sizes require `write_step_evaluated`. The 12/20 mm
  CC0 rings remain flat and sharp. The 40 mm reference measures 1.75 mm thick
  (the Aspen table row gives 1.8 mm); the encoded outline follows the measured
  reference. **Every other DIN 472 table size is generated parametrically from
  the standard's `d3`, `a`, `b`, `d5`, and `s`**, so the builder does not
  depend on which reference B-reps exist. The parametric construction
  reproduces the ten measured envelopes within about 0.1 mm and their material
  areas within a few percent; it is recorded as a 0.1 mm engineering
  approximation and those rings are sharp. No spring temper, load, or fatigue
  rating. The bore groove is declared by the `groove-seat` connector but is not
  modelled.
- MakerBeam 10 x 10 is the exact dimensioned section of drawing article 100168
  (3 mm slot, 1 mm lip, 41.1 degree dovetail, 4 x 4 core, Ø2.5 bore), verified
  against an independent MIT-licensed implementation of the same drawing. The
  R0.2 drawing radii and M3 end threads are omitted. MakerBeamXL 15 x 15 and
  OpenBeam 15 x 15 are not implemented: the drawing folder is access-restricted
  and no licensed step model matched the published dimensions.
- GT2 timing pulleys use an approximate trapezoidal tooth form built from the
  published 2 mm pitch, 0.254 mm pitch-line offset, 0.76 mm depth, and 1.49 mm
  width. Adjacent-tooth joint points are deduplicated (including the 2π seam),
  so the extruded toothed body is a valid watertight solid; optional end
  flanges are separate abutting annular layers (three solids). They are a
  prototyping approximation, not a licensed exact profile, and carry no torque
  or belt-life rating.
- Set-screw shaft collars are one boolean difference (a chamfered annular body
  minus a radial hole). Their primary artifact is the OCCT-evaluated trimmed
  solid from `write_step_evaluated`; the flat writer cannot trim the radial hole
  and is not the accepted output. The builder's hole diameter defaults to the
  ISO metric internal minor diameter (tap drill) of the declared thread; a
  caller may pass a measured clearance hole instead. The thread itself is
  declared by the `set-screw-thread` connector and is never modelled. The
  example additionally places a DIN 916 plain-envelope set screw in the hole;
  `--noScrew` exports the collar alone. No holding torque, material, or strength
  rating is included.
- NEMA mounting plates are generic plate blanks with the frame bolt pattern and
  pilot clearance bore. Plate size, thickness, and clearance are caller
  parameters; no stiffness or strength rating is implied.
- SC8UU-style rod/bearing blocks reproduce the CC BY 4.0 Xem Studio reference:
  34 x 30 x 22 mm, R2 rounds on the four edges parallel to the +Y bearing axis,
  a nominal Ø15 LM8UU seat, and four Ø3.3 mounting holes on a 24 x 18 mm pitch.
  The matching rod interface is Ø8. Seat clearance is a separate diametral
  parameter; press/free-fit intent is connector metadata and does not add a
  tolerance or imply retention strength. The reference and model share the same
  envelope, surface inventory, and nominal volume. The bearing and rod are
  separate parts. Use `write_step_evaluated` for the real mounting bores; no
  load, life, or mounting-strength rating is implied.
- The M3 x 4 heat-set test boss reproduces the CC BY 4.0 Xem Studio reference:
  Ø7.6 x 8 mm, a Ø4.4 x 5 mm blind pocket opening at +Z, and a Ø3.4 through
  screw-clearance bore. Geometry is true-size nominal; insert pocket clearance
  and fit intent are separate, and a 0.1 mm minimum radial shelf above the
  clearance bore is a validation default. The insert, thread, and diamond knurl
  are separate or omitted. No pull-out, torque, boss-strength, or material
  rating is implied.

- The `mechanisms` package is a set of generic engineering envelopes, not a
  vendor catalogue. A hinge, clevis, pin, rod end, linkage, rail, carriage, lead
  screw, nut, belt loop, cam, follower, Oldham coupling, spring, snap latch,
  O-ring, groove, bracket, boss, or rack here is a dimensioned parametric
  construction; no load, torque, fatigue, wear, or safety rating is implied.
- Extension springs model straight end legs by default, or closed planar wire
  loops with `hook_loop_radius_mm`; an axial hook bend is omitted. Torsion
  springs use two straight legs without a leg bend radius.
- Threads are never modelled in `mechanisms`: they are declared by `Threaded`
  connectors. Lead-screw and tapped-boss bores are the ISO metric internal minor
  diameter. Belt loops are smooth envelopes without teeth; the equal- and
  unequal-pulley builders compute the exact open-belt pitch length
  (`2 C + pi D`, and `pi (r1+r2) + 2 alpha (r2-r1) + 2 sqrt(C^2-(r2-r1)^2)`) and
  the unequal builder uses the exact external tangents. Pulleys are separate
  parts declared by their axes.
- Linear-rail mounting holes are real through holes in a separate base slab;
  the base slab and the profiled upper body abut nominally rather than through a
  kernel union. The carriage channel and bolt holes are real geometry.
- Layered mechanism parts (hinge leaves/knuckles/pin, clevis prongs, carriage
  walls/top slab, Oldham hub bodies/slotted faces/disc, bracket legs/gusset,
  roller/pin) are separate closed bodies with nominal abutments. They are not
  fused by the flat writer; use `write_step_evaluated` (or
  `mechanism_kit --evaluated`) or SolidCraft when one manifold is required. The
  `rail` base slab is also fused by that path.
- The ANSI #40 sprocket's 16T and 24T tooth outlines are measured from the CC0
  Innerscene references and re-encoded as original line/arc data; other tooth
  counts use the fitted tip-angle engineering envelope. The plate and hub are
  separate layers and the accepted artifact fuses them with
  `write_step_evaluated`. The ANSI #40 10-pitch chain segment reproduces the CC0
  layout reference exactly (42 solids); both the reference and this envelope are
  layout models with overlapping plate rows, not a functional articulated chain.
  Chain links/rollers are modelled only in that segment; `roller_chain_path_length_mm`
  gives the open-chain pitch path. No load, wear, or fatigue rating.
- The Oldham coupling has real slotted hub faces and real disc tongues with a
  declared `slot_clearance`; the slot must be narrower than the hub bore so the
  inner sector arc remains continuous. No torque, misalignment, or wear rating
  is implied.
- Sprocket/chain envelopes, bevel gears, and worm gears are recorded gaps. Their
  exact tooth forms need a licensed, dimensioned reference or a defensible
  standard tooth-space construction; a guessed envelope is not shipped. The rack
  uses exact straight basic-rack flanks; the mating pinion uses the existing
  involute spur-gear builder.

## License

Apache-2.0, matching the parent repository. The measured DIN 472 outline data
for the 10/14/16/18/24/28/32/40 mm sizes is derived from
[FreeCAD-parts_library](https://github.com/sisul01/FreeCAD-parts_library) by
sisul01, re-encoded as original line/arc loops, and remains
[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). The
parametric fallback is original Apache-2.0 code derived from the standard's
published dimensions; all other source remains Apache-2.0.
