Composing assemblies
Single parts start from an archetype. Assemblies — a controller box with a snap lid, a lamp bracket mating an E27 cup, a whole bench station — start from a sentence. The Cockpit’s Assemble screen composes multi-part products from the catalog: parts, joints, shared dimensions and wiring.
The one rule on the panel says it all:
The model drafts; the deterministic pipeline judges.
An LLM answer is treated exactly like hand-written YAML — grounded against the registries and validated by the same CAD-free pipeline, never trusted raw.
Describe the assembly
Section titled “Describe the assembly”Open Assemble, describe the whole product in one prompt:
pegboard bench station: dovetail slider, adapter plate with a snap-fit controller box, E27 lamp on a bracket, cable from the controller to the socket; lighten the box
Press Compose assembly. Attach an SVG first with + SVG asset if a part needs an engraving or a contour cutout — see SVG assets below.
What the composer actually does
Section titled “What the composer actually does”The model never writes a full document. It emits a compact, typed form — parts, structured joint endpoints, scoped shared dimensions, optional wiring — and the server does the rest, deterministically:
- Retrieval. A coverage-aware search picks up to 15 candidate archetypes from the catalog — the parts your prompt names, plus their complementary mates drawn from the interface compatibility matrix and datum-declared joint cliques. The model can only choose parts from this grounded pool.
- Grounding digest. A deterministic catalog digest is assembled from the registries alone: joint types with their pose rules, each archetype’s params, datums and ports, known-compatible mates, shared-parameter candidates, the contract vocabulary, and a few worked examples.
- Compose. The model returns a schema-constrained draft — archetype ids pinned to the candidate list, joint types pinned to the registered joint types.
- Ground every name. Each part, datum, port, modifier and parameter is resolved against the registries; rotations snap to legal quarter-turns; near-miss names are fuzzy-corrected; anything unresolvable becomes a finding, never a silent drop.
- Expand & validate. The compact form expands into a full
assembly/v1document — shared dimensions materialized into the parts that agree on them — and runs through the ordinary CAD-free validation.
It repairs itself
Section titled “It repairs itself”Composition isn’t one shot. If the draft doesn’t pass, the composer feeds the findings back to the model — fix only what the findings name, re-emit the full corrected assembly — for up to four repairs. It stops early when two attempts produce the same findings (no progress), then keeps the best attempt by score. The draft header shows how many iterations ran and which one was selected.
In practice the auto-run converges a good prompt to BUILD REQUIRED on its own, and a single build promotes it to FULLY VERIFIED.
The draft — and its verdict
Section titled “The draft — and its verdict”Compose lands you on the Assembly Draft screen with the composed
assembly/v1 YAML (editable), the design rationale, and the current findings.
The badge tells you exactly how far the draft got:
| Badge | Meaning |
|---|---|
| FAIL | schema, grounding or CAD-free validation did not pass |
| PRE-CAD PASS | schema + grounding + CAD-free validation all pass, nothing deferred |
| BUILD REQUIRED | pre-CAD valid, but some contract/wiring checks can only run at build time (they’re listed as deferred to build) |
| FULLY VERIFIED | a CAD build ran and every check passed |
| BUILD FAILED | a build was attempted and failed |
| EDITED | you changed the YAML — re-measure with Validate changes |
Wiring continuity (does the cable actually pass through every part in the pose?) is always a build-time check, so a clean draft that routes a cable will sit at BUILD REQUIRED until you forge it.
From the draft you can:
- Validate changes — re-measure the edited YAML, CAD-free.
- Open in workspace — validate and open in the Workspace without building.
- ⚒ Forge assembly — build every part and verify the fit in the assembled pose (enabled once the draft is clean, un-edited, and CAD is on).
A forged assembly opens in the Workspace: the 3D lens places each part by its reported pose, and the Assembly Honesty lens shows the per-joint fit findings — no interference, screws clear, the cable continuous across every part.
History keeps everything
Section titled “History keeps everything”Every composed draft is saved — the failed ones too, because their findings are part of the story. The History panel lists each attempt with its badge, part count, timestamp and prompt; click any row to reopen the draft exactly as it was, with no recompute.
SVG assets
Section titled “SVG assets”For an engraving or a cutout, attach an SVG with + SVG asset before
composing. The server cleans the path data up front (dropping specks, merging
hatch slivers — and reporting what it changed); if the file is unusable the job
is refused before any model call. The model is told to reference the asset with
a literal @svg marker and never retype the path data; the server substitutes
the real cleaned geometry when it writes the final document. Using @svg on a
part that has no SVG parameter is a recorded finding — a lost requirement, not a
silent drop.
What an assembly is
Section titled “What an assembly is”The composer produces the same assembly/v1 document you could write by hand:
schema: assembly/v1id: esp32_box_with_lidstrict: trueroot: box # the single frame of referenceshared: # mating dimensions stated once — a desync is unrepresentable wall: 2.4mm boss_sx: 46mmparts: - ref: box product: { archetype: enclosure_base_v1@1, params: { ... } } - ref: lid product: { archetype: enclosure_lid_snap_v1@1, params: { ... } }joints: # in chain order from the root - type: lid_seat a: box.rim b: lid.seat rotate: [0, 0, 0]contract: must_have: [seated_lid, press_fit_alignment]Joint endpoints are written as part.datum; the first joint naming a part
establishes its pose, later joints only verify the fit. Joints come
from the fail-fast joint registry — an unknown type is
a load error. See the declaration language for the
full grammar.