# 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. ## 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 `.` 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. If any invariant is false, revise the construction before emitting the single complete `cad.author.v1` document.