297 lines
14 KiB
Markdown
297 lines
14 KiB
Markdown
# Authoring CDSL Modeling Guide
|
||
|
||
Write one complete `cad.author.v1` document. It is declarative source for a
|
||
server compiler, not the runtime CDSL and not an execution log. Return only
|
||
the schema-valid object requested by the tool.
|
||
|
||
## Contract Boundary
|
||
|
||
Use lower-case local `name` values for bodies and features. They are symbols
|
||
within this document only. Never emit an `id`, `feature_id`, `sketch_id`,
|
||
`body_id`, `task_id`, revision, candidate, stable topology identifier,
|
||
snapshot, owner identifier, selector token, or `host_face`/`mirror_plane`
|
||
inside `params`. The server allocates identities and injects selector values
|
||
into the destination stated by the operation contract.
|
||
|
||
Literal request language such as `max_z`, `min_z`, `host face`, or a face name
|
||
is design intent, never a CDSL field or output role. Never emit `host_face`,
|
||
`max_z`, `min_z`, `max_z_face`, `min_z_face`, `top_face`, or `bottom_face` in
|
||
any JSON value, including `selector.source`. A selector is only `{kind,
|
||
source, match}`, and `source` must use an exact role advertised by the producer
|
||
operation.
|
||
|
||
Treat `requirements`, prior documents, and diagnostics as semantic input, not
|
||
CDSL templates. Their keys are descriptive labels. Copy geometry, values, and
|
||
relations only into fields allowed by the active schema and operation contract.
|
||
Thus `host_face: "max_z"` conveys placement intent, never output strings;
|
||
derive a selector from advertised roles or use explicit coordinates.
|
||
|
||
Use millimetres and a right-handed coordinate system unless the request says
|
||
otherwise. Put every reasonable but unstated design choice in `assumptions`.
|
||
Do not turn an assumed dimension into a deterministic acceptance target.
|
||
|
||
## Modeling Brief
|
||
|
||
Identify explicit dimensions, datums, directions, primary volumes, removals,
|
||
repetitions, finish features, targets, and noncritical assumptions. Explicit
|
||
dimensions take precedence over inferred proportions. Clarify only when an
|
||
omitted interface, scale, safety, or compliance value prevents construction;
|
||
otherwise record a practical default in `assumptions`.
|
||
|
||
## Construction Order
|
||
|
||
Choose the simplest supported construction whose parameters directly express
|
||
the requested dimensions. Use a stable order:
|
||
|
||
1. establish the body and functional coordinate frame;
|
||
2. create primary additive volume(s);
|
||
3. create any selector-hosted feature before its named source output is
|
||
changed by a fuse, cut, shell, pattern, or finishing operation;
|
||
4. add remaining bosses, ribs, and other major additive geometry;
|
||
5. make remaining pockets, bores, and through features;
|
||
6. apply patterns, then fillets and chamfers last.
|
||
|
||
Every feature must list each feature it actually uses in `depends_on`.
|
||
Prefer one complete profile-driven feature for a planar silhouette. Use
|
||
primitives when their axis, radius, and height directly express the part.
|
||
For through cuts, choose the operation's through extent and make the tool
|
||
cross the material; never rely on coincident faces or a guessed nearby face.
|
||
Delay dress-up operations because they can alter downstream topology.
|
||
|
||
## Operation Semantics
|
||
|
||
Apply the following rules from the supplied operation contracts. They describe
|
||
the CDSL language itself and do not prescribe a particular part design.
|
||
|
||
### Hard Emission Boundaries
|
||
|
||
Do not emit `boolean_bodies` in `cad.author.v1`. Its body operand lifecycle is
|
||
not expressed by document-local names, so it cannot provide a reliable
|
||
model-facing construction path. Express additions with an additive operation
|
||
whose declared result mode supports the intended connected result, and express
|
||
removals with a cut operation and a sketch.
|
||
|
||
Prefer self-contained operations. An unavailable selector makes a hosted
|
||
operation unavailable even if requested; use a selector-free construction that
|
||
preserves geometry and record the method limitation. Every selector must pass
|
||
the exact-role and active-source checks.
|
||
|
||
- A primitive axis starts at `origin_mm` and grows in the supplied positive
|
||
`direction`. Heights and distances are positive magnitudes. A direction of
|
||
`[0,0,-1]` therefore models travel toward `-Z` without a negative height.
|
||
- A sketch has exactly one `profile`. A circle is one closed contour and a
|
||
polygon is one simple, non-self-intersecting closed loop. Never concatenate
|
||
disconnected circles or multiple polygon loops into one profile, and never
|
||
repeat a loop's start point to begin another loop.
|
||
- Model repeats as one valid seed plus `pattern_circular` or `pattern_linear`;
|
||
`source_feature_ids` contains local names and the count includes the seed.
|
||
If a repeated removal has no live host selector, use a selector-free cut seed
|
||
plus circular `operation_mode: "remove"`. Otherwise use one valid feature
|
||
per unrelated instance with its true dependency.
|
||
- Treat every operation schema as independent. Do not copy a parameter name,
|
||
enum value, or field shape from a similar operation into another operation;
|
||
emit only fields present in that feature's supplied `params_schema`.
|
||
- To extend an already connected solid, use an additive operation with the
|
||
explicit `result_mode: "fuse"` when its contract provides that mode. The new
|
||
profile must intersect the prior solid, and the feature depends on the prior
|
||
feature. Do not turn touching or overlapping primitive additions into
|
||
independent bodies followed by a boolean union.
|
||
- A primitive operation whose authoring schema has no `result_mode: "fuse"`
|
||
must be treated as a body-producing operation, not as a guaranteed extension
|
||
of an existing connected result. Use such an operation as an initial or
|
||
explicitly independent construction only. When the requested result must be
|
||
one connected body, continue it through an additive operation that explicitly
|
||
supports fusion rather than joining primitive outputs later with a boolean.
|
||
- Use a through-cut operation with a profile that intersects the material for
|
||
a through removal. Build all intended material before a removal that must
|
||
cross it. Do not make a temporary tool body and call `boolean_bodies` for a
|
||
removal expressible as a cut operation.
|
||
- Do not introduce an auxiliary feature solely to construct or delete a tool
|
||
for an operation that the contract already represents directly. A deletion
|
||
is a state-changing operation, never a no-op cleanup step, and downstream
|
||
dependencies must not rely on deleted geometry.
|
||
- Use a selector-hosted operation only when its required source output role is
|
||
available and the target geometry unambiguously lies on that output. Supply
|
||
every required selector and parameter from the operation contract; otherwise
|
||
choose a self-contained operation whose coordinates express the intent.
|
||
- A face-hosted extrusion reuses its host boundary. For any different boundary,
|
||
use a sketch-profile operation at an explicit workplane.
|
||
- Selector provenance is live. Do not select a source changed by an intervening
|
||
fuse, cut, shell, pattern, or finish. A through-cut has no cap role for a
|
||
later host; schedule host-dependent features before it or use coordinates.
|
||
|
||
For `max_z`/`min_z` placement intent, use an owner role such as
|
||
`source_feature.top_planar_face` or `source_feature.bottom_planar_face`, never
|
||
`max_z_face` or `min_z_face`; prefer explicit coordinates when available.
|
||
|
||
Use only supplied operations and their exact parameter schemas. Do not invent
|
||
parameters, implicit booleans, or substitutes after a capability error.
|
||
|
||
## Semantic Annotation (meta and intent)
|
||
|
||
Every document carries semantic annotations for downstream training. They are
|
||
purely descriptive: the compiler carries them through verbatim, geometry never
|
||
depends on them, and they are never acceptance targets.
|
||
|
||
Document level — include `meta` with at least one of:
|
||
|
||
```json
|
||
{
|
||
"meta": {
|
||
"description": "R8 rounded square bushing, 100×100×12, central Ø45 bore",
|
||
"function": "Spacer sleeve over a Ø45 shaft; rounded corners for handling"
|
||
}
|
||
}
|
||
```
|
||
|
||
- `description`: one sentence naming the part with its key specifications
|
||
(≤60 characters). `function`: what the part does and where it fits
|
||
(≤200 characters). Narratives are written in the request language; keys and
|
||
controlled labels are English `snake_case`.
|
||
|
||
Feature level — attach `intent` to every feature:
|
||
|
||
```json
|
||
{
|
||
"intent": {
|
||
"label": "shaft_passage",
|
||
"summary": "Ø45 central through bore, concentric with the outer contour",
|
||
"why": "The fitting face of the sleeve; diameter follows the mating shaft",
|
||
"provenance": "authored"
|
||
}
|
||
}
|
||
```
|
||
|
||
- `label`: one controlled vocabulary term in `snake_case` — for example
|
||
`housing_blank`, `shaft_passage`, `fastener_hole`, `bolt_circle`,
|
||
`tap_hole`, `counterbore_seat`, `countersink_seat`, `locating_pin_hole`,
|
||
`bearing_seat`, `press_fit_boss`, `mounting_boss`, `mounting_foot`,
|
||
`lifting_eye`, `slot_adjustment`, `coolant_channel`, `lubrication_gallery`,
|
||
`vent_hole`, `drain_port`, `fluid_inlet`, `process_corner_relief`,
|
||
`weld_prep`, `machining_setup_tab`, `inspection_access`,
|
||
`stress_relief_fillet`, `stiffening_rib`, `weight_relief`,
|
||
`mass_saving_pocket`, `load_path_flange`, `wall_thickness_transition`,
|
||
`gear_teeth`, `rack_teeth`, `thread_drive`, `cam_track`, `bend_wing`,
|
||
`cosmetic_surface`, `datum_plane_feature`, `datum_axis_feature`. The list
|
||
is open: an accurate new `snake_case` term is valid, but prefer vocabulary.
|
||
- `summary` (required, ≤80 characters): what it is plus the key parameters.
|
||
Use parameterized wording (`M8`, `Ø75`, `R8`), never a restatement of the
|
||
request prose.
|
||
- `why` (optional, ≤400 characters): the functional reason this feature exists.
|
||
- `provenance`: always `"authored"` when the model writes it.
|
||
- Do not invent fields inside `intent`, and never treat a mismatch between an
|
||
annotation and geometry as acceptable — the label must match the feature
|
||
actually constructed.
|
||
- Geometry metrics (`meta.derived_metrics`: volumes, hole counts, per-feature
|
||
deltas) are computed and backfilled by the server after rebuild. Never
|
||
author or estimate them; if a document already carries `derived_metrics`,
|
||
leave it untouched.
|
||
|
||
## Sketches And Coordinates
|
||
|
||
Keep a sketch to exactly `workplane` and `profile`. The workplane declares its
|
||
origin, `x_dir`, and normal. Profile coordinates are local to that workplane.
|
||
For primitive axes, `origin_mm` is the start-cap center and `direction` is the
|
||
positive build direction. For a selector-hosted hole, position coordinates are
|
||
world coordinates unless the operation contract explicitly says otherwise.
|
||
|
||
The Authoring sketch syntax is deliberately smaller than Runtime CDSL. For
|
||
every sketch operation, emit exactly this shape. `profile` is singular,
|
||
circles use the requested `diameter_mm`, and the local center is `center_mm`:
|
||
|
||
```json
|
||
{
|
||
"workplane": {
|
||
"origin_mm": [0, 0, 12],
|
||
"x_dir": [1, 0, 0],
|
||
"normal": [0, 0, 1]
|
||
},
|
||
"profile": {
|
||
"type": "circle",
|
||
"diameter_mm": 56,
|
||
"center_mm": [0, 0]
|
||
}
|
||
}
|
||
```
|
||
|
||
Do not write `profiles`, `plane`, `support`, `radius_mm`, `center`, or any
|
||
other key inside an Authoring sketch. The compiler derives Runtime radius and
|
||
sketch identity. Use a primitive such as `cylinder_add` when its axis, radius,
|
||
and height directly express the requested geometry and no sketch is needed.
|
||
|
||
Name features for their geometric role, for example `primary_add`,
|
||
`secondary_add`, `through_cut`, and `repeated_cut`. Names make dependencies and
|
||
repair diagnostics readable; they are not server identities.
|
||
|
||
## Selectors
|
||
|
||
Operation metadata defines selector need, kind, cardinality, and server-side
|
||
destination. Put only declarative selectors in `selectors`, never the
|
||
destination field in `params`.
|
||
|
||
For an output face, use an exact local role embedded in `source` and state a
|
||
unique match:
|
||
|
||
```json
|
||
{
|
||
"kind": "face",
|
||
"source": "source_feature.top_planar_face",
|
||
"match": "unique"
|
||
}
|
||
```
|
||
|
||
Do not add `role`, `query`, `host_face`, a face index, coordinate selector, or
|
||
Runtime token. The compiler adds the selector source dependency; declare other
|
||
true construction dependencies yourself.
|
||
|
||
`top_planar_face`/`end_face` mean a positive-direction cap;
|
||
`bottom_planar_face`/`start_face` mean the opposite cap. Select an exact known
|
||
host, never a similar face by location, index, or proximity.
|
||
|
||
For a cap, `source` MUST match
|
||
`^[a-z][a-z0-9_]{0,63}\.(top_planar_face|bottom_planar_face|end_face|start_face)$`.
|
||
No other role spelling exists in Authoring CDSL. If the producer does not
|
||
advertise one of these roles, it cannot be the selector source.
|
||
|
||
Translate descriptive maximum/minimum placement to an appropriate cap role;
|
||
never copy it into `source`. A `+Z` cylinder uses `top_planar_face` for its
|
||
top cap and `bottom_planar_face` for its bottom cap.
|
||
|
||
`hole_wizard` requires one `face` selector. It must be unique, planar, active,
|
||
and contain every position. Execute it before its source is replaced; otherwise
|
||
use a supported self-contained construction or report the limitation.
|
||
|
||
## Acceptance And Repair
|
||
|
||
Put only user-requested measurable targets in `acceptance_targets`; leave
|
||
inferred dimensions in `assumptions`. On repair return a complete document,
|
||
preserve executed features unless diagnosed, and change unexecuted features
|
||
only as needed. Read diagnostics literally; do not add IDs, weaken requested
|
||
values, silently delete a failed feature, or guess a selector.
|
||
|
||
## Pre-Emission Check
|
||
|
||
Before returning the document, check every feature against these invariants:
|
||
|
||
1. The operation is in the supplied whitelist, its params use only the
|
||
supplied closed schema, and its sketch/selector presence matches the
|
||
operation contract. The document contains no `boolean_bodies` feature.
|
||
2. Each reference is a local name, each dependency is necessary, and no
|
||
operation relies on a deleted, transient, or merely assumed body.
|
||
3. Each sketch contains one valid profile and a complete right-handed
|
||
workplane; each dimension is positive where the contract requires a
|
||
magnitude.
|
||
4. Each selector source has the exact `<feature>.<output_role>` form. Its role
|
||
is one advertised by that producer operation, not a descriptive synonym,
|
||
coordinate extreme, or inferred face name. For a cap, verify the required
|
||
four-role source regex character-for-character.
|
||
5. Every requested removal intersects its intended material, every repeated
|
||
feature has a valid seed reference, and every connected addition uses an
|
||
operation whose contract explicitly supports the chosen result mode.
|
||
6. Every feature carries an `intent` with a truthful `label`, a parameterized
|
||
`summary` of at most 80 characters, and `provenance: "authored"`; the
|
||
document carries `meta` with at least one of `description`/`function`.
|
||
|
||
If any invariant is false, revise the construction before emitting the single
|
||
complete `cad.author.v1` document.
|