feat(selector): 增加离线候选遍历与严格回放验证 Demo

- 新增 selector_candidate_demo,移除 provenance intent 后枚举候选 selector
- 对候选分支执行有界重建与严格 STEP 比较
- 仅在候选遍历完整且唯一 strict 通过时生成 selector 映射记录
- 增加 selector 候选搜索、预算限制和记录生成的测试
- 保持生产 selector resolver 不受 Demo 逻辑影响
- 更新 CADFS 能力台账,记录 IMPRINT 派生 profile 的 lineage selector 缺口
This commit is contained in:
2026-09-10 15:12:57 +08:00
parent d8fc2a9207
commit 994d06aaea
36 changed files with 9268 additions and 753 deletions
+134 -66
View File
@@ -13,24 +13,30 @@ 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
Before authoring, derive this internal brief from the requirements:
- part or multi-body intent; explicit dimensions and units;
- functional datums, origin, base plane, and positive directions;
- primary volumes, holes, pockets, bosses, ribs, patterns, and finishing;
- explicitly verifiable targets versus manual targets;
- assumptions that do not affect fit, safety, or compliance.
Dimensioned request facts take precedence over proportions inferred from an
image. Ask for clarification only when a missing interface, scale, safety, or
compliance value makes construction impossible. Otherwise choose a practical
engineering default and record it as an assumption.
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
@@ -52,16 +58,74 @@ 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.
The selector-source rule is an intentional exception to a generic “all adds,
then all cuts” sequence. For example, a bolt circle hosted on an original
flange cap must be placed immediately after the base when later additive
fusions replace that exact cap. A required final through-cut can still follow
all additive features and the earlier bolt operation.
## Operation Semantics
Use only the supplied operation list. Follow each operation's parameter schema
exactly, including required sketch state. Do not invent unsupported operation
parameters, implicit booleans, or a substitute operation after a capability
error.
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
@@ -95,16 +159,15 @@ 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 manufacturing role, for example `base_plate`,
`front_hub_boss`, `center_bore`, and `bolt_holes`. Names make dependencies and
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
The operation metadata states whether `selectors` are required, their kind,
cardinality, and server-side destination. Put only declarative selectors in a
feature's `selectors` array. Never write the destination field itself inside
`params`.
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:
@@ -112,54 +175,59 @@ unique match:
```json
{
"kind": "face",
"source": "front_hub_boss.top_planar_face",
"source": "source_feature.top_planar_face",
"match": "unique"
}
```
Do not add `role`, `query`, `host_face`, a face index, a coordinate selector,
or a Runtime selector token. The `source` value is the complete local intent.
The compiler adds its source feature as an auditable graph dependency; include
other true construction dependencies in `depends_on` yourself.
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` and `end_face` mean the positive-direction cap of a supported
extrude, sweep, loft, or cylinder. `bottom_planar_face` and `start_face` mean
the opposite cap. Select the most recent feature whose output is known to be
the required host; do not select a similar face by location, face index, or
proximity.
`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.
Translate a request's descriptive `max_z`/`min_z` wording into these output
roles before writing CDSL. Never emit `base.max_z_face` or `base.min_z_face`.
For a cylinder built in `+Z`, the top cap is `top_planar_face` and the bottom
cap is `bottom_planar_face`; reverse-direction features swap their world-Z
position but retain their own start/end roles.
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.
`hole_wizard` requires exactly one `face` selector. It uses that selector as
its host face, so a central bore on a hub should select the hub cap, while a
bolt circle on an exposed flange should select the flange cap. A selector must
name a host that contains every requested hole position. If that cannot be
made unique, redesign the feature sequence or omit the unsupported feature;
never guess a face.
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.
Before creating a hosted hole, calculate each position against the actual host
face. A local boss can be the global highest face while being too small to host
a larger bolt circle. In that case use the exposed flange cap at the bolt
radius, with its own plane height, rather than the global maximum-Z cap. Place
the hosted holes while that source cap's exact provenance is still active:
before a later fusion or cut would split, remove, or replace it. A final
through-cut may still follow all additive features, so a bolt circle can be
hosted before an unrelated final boss and before that final cut.
`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
Describe only user-requested, measurable acceptance targets in
`acceptance_targets`; leave inferred dimensions in `assumptions`. On repair,
return a complete replacement document. Preserve feature names and every
feature listed in `executed_feature_ids`, except a feature explicitly named by
the diagnostic. Features that were never executed may be changed freely to
repair an invalid selector, parameter, dependency, or geometry construction.
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.
Read structured diagnostics literally. Fix their named cause with the smallest
document change, then return the entire document. Do not add internal IDs,
weaken a requested value, silently delete a failed feature, or replace a
failed selector with an arbitrary topology element.
## 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.
If any invariant is false, revise the construction before emitting the single
complete `cad.author.v1` document.