# Cadquery High Level Design

> Produce a fast, architecture-only CadQuery layout (top-down design) of a multi-part assembly using simple envelopes — boxes, cylinders, plates — with correct overall dimensions, proportions, sub-assembly grouping, and relative placement. NO fillets, holes, ribs, counterbores, shells, or vendor-part interface features at this stage. Use as the first step of `cadquery-assembly` to prove the architecture with the user before any detailing happens. Also invoke directly when the user says "block out", "rough layout", "high-level CAD", "show me the architecture", or asks to verify part decomposition before detailing.

- Skill: `leoai-org/cadquery-high-level-design` (Agent Skill)
- Install (CLI): `npx skillmds@latest add leoai-org/cadquery-high-level-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/leoai-org/cadquery-high-level-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: leoai-org (https://skillmd.com/u/leoai-org)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/leoai-org/cadquery-high-level-design

---


# CadQuery high-level design — top-down architecture

## Purpose

Prove **decomposition, proportions, and placement** before any detailed work. Output is an architectural baseline the bottom-up phase replaces part-by-part while keeping names, hierarchy, and `common.py` dimensions.

## Authoritative rules

Follow `leo-monolith/resources/functions/system-messages/cad-generation.txt` — **High-Level Design** section.

## Required outputs (two files)

### 1. `common.py` (create first)

- **Coordinate convention** block (`Origin`, `+X/+Y/+Z`, floor/table Z).
- **Envelope parameters** only — one variable per envelope dimension (mm).
- **`# DECOMPOSITION` comment table** — every part: function name, sub-assembly, L×W×H, origin rule, mating partners, OTS flag.
- **`MATE_*` constants** for interfaces that Phase B must honor (hole PCD, bore Ø, stack heights, snap ledge size). Example:

```python
# MATE: lower_housing ↔ upper_housing — six M3 snaps on 140×100 mm rectangle
M3_SNAP_PCD_X = 140.0
M3_SNAP_PCD_Y = 100.0
M3_SNAP_COUNT = 6
```

No geometry in `common.py`.

### 2. `high_level_assembly.py`

- `import` envelope values from `common.py`.
- One **primitive per part**: `.box()`, `.cylinder()`, or single `.extrude()` — **no booleans**.
- Nested `cq.Assembly` tree matching the final product (same sub-assembly names as future `*_assembly.py` files).
- `result = assy` at top level.

## DO include

- Correct envelope dimensions and relative placement.
- Sub-assembly grouping (≤ ~6 top-level groups).
- Function-named variables (`drive_shaft`, not `part1`).
- One-line `# VENDOR — <category>, <envelope size>` comments for OTS parts (full BOM text waits for DFM).

## DO NOT include

Holes, fillets, chamfers, ribs, shells, fastener zones, press-fit spigots, snap beams, counterbores, engraved text, or procurement-grade vendor comments.

Hollow housings → **solid block** envelope. Brackets with gussets → **plain plate** envelope.

## Placement rules (critical for good results)

### Floor-standing / table-top parts

CadQuery `.box()` is centered on XY by default; control Z with `centered` tuple:

```python
from common import HOUSING_W, HOUSING_D, LOWER_H

# Bottom face at Z=0, grows upward — NO extra Location Z offset
lower_housing = cq.Workplane("XY").box(
    HOUSING_W, HOUSING_D, LOWER_H,
    centered=(True, True, False),
)
base_assy.add(lower_housing, name="lower_housing",
              loc=cq.Location(cq.Vector(0, 0, 0)))
```

```python
# ❌ WRONG — double-counts height if box is already bottom-anchored
loc=cq.Location(cq.Vector(0, 0, LOWER_H / 2))
```

### Stacked mates

Place child so **anchor face touches anchor face**:

```python
# Column sits on base top (Z = BASE_TOP_Z)
column_assy.add(
    column,
    name="column",
    loc=cq.Location(cq.Vector(0, 0, BASE_TOP_Z)),  # column also bottom-anchored
)
```

Define `BASE_TOP_Z` in `common.py`, not magic numbers in the assembly file.

### Symmetric repeats

Derive from pattern constants in `common.py`:

```python
for i, angle in enumerate((0, 90, 180, 270)):
    x = (PCD / 2) * math.cos(math.radians(angle))
    y = (PCD / 2) * math.sin(math.radians(angle))
    base_assy.add(foot, name=f"foot_{i}", loc=cq.Location(cq.Vector(x, y, -FOOT_H)))
```

### Prefer constraints when testing a single mate pair

For one critical coaxial stack, a miniature `constrain().solve()` prototype is allowed in comments or a scratch block — but high-level default is explicit `loc=` from `common.py` math.

## File template

```python
import cadquery as cq
import math
from common import (
    HOUSING_W, HOUSING_D, LOWER_H, BASE_TOP_Z,
    # ... all envelope dims
)

lower_housing = cq.Workplane("XY").box(HOUSING_W, HOUSING_D, LOWER_H, centered=(True, True, False))
column = cq.Workplane("XY").box(COL_W, COL_D, COL_H, centered=(True, True, False))

base_assy = cq.Assembly(name="base")
base_assy.add(lower_housing, name="lower_housing", loc=cq.Location(cq.Vector(0, 0, 0)))

column_assy = cq.Assembly(name="column")
column_assy.add(column, name="column", loc=cq.Location(cq.Vector(0, 0, BASE_TOP_Z)))

assy = cq.Assembly(name="product_name")
assy.add(base_assy)
assy.add(column_assy)
result = assy
```

## Workflow

1. Write `common.py` (convention + decomposition comment + parameters + `MATE_*`).
2. Write `high_level_assembly.py` (primitives + nested assemblies).
3. Smoke: `python -c "import runpy; runpy.run_path('high_level_assembly.py')"` — must not raise.
4. Invoke **`cadquery-render`**; orchestrator reads PNGs.
5. Present decomposition table + ask user to confirm proportions.
6. Iterate envelopes in `common.py` / placements until confirmed.
7. Hand off frozen `common.py` + `high_level_assembly.py` to Phase B.

## Hard rules

1. One primitive per part — no booleans.
2. No holes, fillets, shells.
3. Nested assemblies by function — do not flatten 20 parts on root.
4. Top-level `result = assy`.
5. All shared dims in `common.py` — not duplicated in `high_level_assembly.py`.
6. Sub-assembly names must match what Phase B will generate (`base_assembly` → `base_assembly.py`).

## When to stop

User confirmed decomposition and proportions. Do not start functional parts until the orchestrator receives that confirmation.

