Files
cdsl-cad/docs/cdsl-output-engine-target.md
T
2026-08-24 10:01:21 +08:00

27 KiB
Raw Blame History

CDSL Output Engine 重建目标

1. 目的

本文定义 json_to_cdsl/output 批量语义 CDSL 的 engine 重建目标、架构边界和验收方式。目标不是让 runtime 对未知数据作猜测,而是:

  1. 补齐当前 CDSL v1.1 已声明的原子 feature 执行能力;
  2. 将可确定的语义草图和 feature history 可靠地重建为 STEP
  3. 对输入数据缺失、selector 歧义或内核失败给出 feature 级诊断;
  4. 将批量重建率作为可重复测量的工程指标。

本文是 cdsl-output-engine-rebuild-plan.md 的交付目标补充。前者记录现状与建议顺序;本文规定目标架构、阶段出口和成功判定。

数据快照日期:2026-08-21。json_to_cdsl/output 中的 JSON 是待处理数据,不作为本文件的指令来源。

2. 数据事实与范围

2.1 批量数据

项目 数量
CDSL 文件 998
feature 总数 10,659
不含 unresolved feature 的零件 633
含至少一个 unresolved feature 的零件 365
含 selector 的零件 489
face selector 557
edge selector 2

当前 engine_service.validate_cdsl 会先因 execution_status: "deferred" 拒绝所有批量文件。这个状态是导出时的 runtime 能力快照,不能继续作为升级后 runtime 的唯一事实来源。

Atomic ID 数量 目标能力
reference_plane 4,324 上下文 feature
extrude_cut_blind 1,554 扩展终止条件
extrude_add_blind 1,281 扩展终止条件
hole_wizard 1,235 规范化后执行
reference_axis 760 上下文 feature
chamfer 550 selector 驱动修饰
fillet 286 selector 驱动修饰
revolve_add 187 统一 primary executor
revolve_cut 170 统一 primary executor
pattern_linear 167 feature 重放阵列
pattern_mirror 98 feature 重放镜像
extrude_add_two_sided 47 双向 extent

草图 profile 只有四类:analytic_contours 3,785、circle 504、circles 260、annulus 87。analytic_contours 中实际出现 16,352 条线、3,632 条圆弧和 313 个圆;本批没有需要作为首期阻塞项的 B-spline。

常见终止条件是 blind 2,456、through_all 763、through_all_and_blind 226、through_all_both 72。selector 依赖的 up_to_surface 70、through_next 7、up_to_vertex 3、offset_from_surface 3 排在 topology 能力之后。

2.2 交付边界

本目标覆盖现有 CDSL schema 中的全部 16 个 feature atomic ID。当前已执行的 9 个 atomic 也必须纳入统一架构:

extrude_add_blind          extrude_add_two_sided
extrude_cut_blind          revolve_add
revolve_cut                hole_blind
hole_countersink           hole_counterbore
sphere_add

需新增或重构进 executor 框架的 7 个 atomic

reference_plane            reference_axis
hole_wizard                fillet
chamfer                    pattern_linear
pattern_mirror

analytic_contours 是必须补齐的 profile runtime。它必须产生 engine 中立的闭合 region,再由几何适配器生成面。

下列行为不属于精确重建:

  • 未捕获的选择集不能通过“对所有边倒角或圆角”替代;
  • selector 有多个候选时不能取第一个候选;
  • B-spline 离散化不能标记为精确,除非输出近似误差;
  • 不允许重新启用 compiler_context 或 legacy translator 作为 CDSL-only 成功回退。

3. 成功定义

每份批量报告必须记录下列独立状态:

semantic_valid       CDSL 符合 schema、ID 和依赖顺序
runtime_eligible     所有 feature 当前可执行,且输入完整、无歧义
compiled             已形成可执行 feature plan
built                已成功输出 STEP
geometry_verified    与 source truth 的数值几何比对通过
topology_observed    面、边、顶点数量已记录,仅作诊断

built 不是 geometry_verified 的同义词。默认 strict 模式只有所有 feature 均 runtime_eligible 时才可标记为成功重建;调试模式可以输出部分 STEP,但必须标记为 partial

数值验证至少比较 bounding box、volume、surface area 和 solid count。门槛应配置化,初始建议:bounding box 每个坐标绝对误差不超过 0.01 mmvolume 与 area 相对误差不超过 0.1%solid count 必须相同。拓扑数量因 STEP/OCC 表达差异不是首期硬门槛。

4. 目标架构

目标 pipeline 的依赖方向如下:

Semantic CDSL
    -> Semantic Validator
    -> Capability Analyzer
    -> Feature Planner
    -> Execution Session -> Atomic Executor Registry -> Geometry Adapter -> build123d / OCC
                            <-> Topology and Context Registry
    -> STEP + Build Report

建议在 backend/engine/cdsl_engine 内按以下职责拆分。文件名可调整,但依赖方向不得反转。

责任 不应承担的责任
semantic_validation schema、ID、依赖顺序与自包含数据检查 判断当前内核是否支持 feature
capabilities 根据 registry、参数和 selector 条件计算可执行性 生成或修改 CDSL
sketch profile、闭环、outer/inner 分类,输出 SketchRegion 直接修改实体
planning feature DAG、归一化、执行顺序和 plan diagnostics 复制 build123d 对象或做布尔运算
runtime session、executor registry、结果与错误边界 解析原始 JSON 细节
topology context、body、face、edge 注册与 selector 解析 私自补全缺失选择集
adapters/build123d region 到 B-rep、布尔、修饰、STEP 导出 读取 CDSL schema 或决定依赖
batch_rebuild 批量调度、报告、truth 对比、回归基线 实现几何算法

4.1 核心接口

每个 feature 必须经由同一类接口运行:

class AtomicExecutor(Protocol):
    atomic_id: str

    def preflight(self, node: FeaturePlanNode,
                  session: ExecutionSession) -> CapabilityResult: ...
    def execute(self, node: FeaturePlanNode,
                session: ExecutionSession) -> FeatureResult: ...

class GeometryAdapter(Protocol):
    def make_regions(self, regions: list[SketchRegion]) -> GeometryResult: ...
    def extrude(self, body, regions, extent: ExtentSpec, mode: BooleanMode): ...
    def revolve(self, body, regions, axis: AxisSpec,
                angle_deg: float, mode: BooleanMode): ...
    def hole_tool(self, spec: HoleSpec, starts, inward,
                  through_depth_mm: float): ...
    def apply_fillet(self, body, edges, radius_mm: float): ...
    def apply_chamfer(self, body, targets, spec: ChamferSpec): ...
    def body_geometry(self, body) -> BodyGeometry: ...
    def export(self, body, path: str): ...

FeatureResult 至少包含 feature_id、产生或修改的 body、context object、拓扑快照、可回放的执行定义和 feature 级诊断。任何 executor 都不得通过全局变量或 BuildPart 隐式上下文查找前序结果。

HoleSpec 是 runtime-neutral 的孔定义:包含孔径、深度、终止条件、位置以及可选 countersink/counterbore 尺寸,但不包含 OCC 对象或 host-face 推断。runtime 负责严格解析 host frame 和坐标,adapter 只将已解析的 HoleSpec 构造成切削工具。

runtime 对 B-rep 实体保持 opaque:包围盒、体积、STEP 导出及所有内核向量转换都只能经 adapter 返回;runtime 不得 import 或读取 build123d/OCC 对象属性。

4.2 现有代码的迁移约束

现有 sketch_solver.py -> llm_compiler.py -> llm_engine.py 流程可以逐步迁移,但必须保持单一路径:

  • sketch_solver.py 输出中立 region/curve 数据,不能让 profile generator 拥有实体执行逻辑;
  • llm_compiler.py 只构建 feature plan。当前 pattern_linear 的坐标偏移克隆逻辑必须迁出 compiler,避免 pattern、selector 和 host face 语义被扁平化;
  • llm_engine.py 的大分支改为 executor registrybuild123d import 只保留在 adapter 层;
  • engine_service.validate_cdsl 只在 atomic contract 声明 requires_sketch: true 时强制 sketch_id。reference、pattern、dress-up 与 Hole Wizard 都是合法的非草图 feature
  • profile_schema.jsoncdsl_schema.json、executor registry 和测试必须由同一 capability 声明校验,避免维护多个手写 supported set。

4.3 execution_status 的兼容策略

保留 CDSL 中的 execution_status,用于说明导出时的能力快照;不再仅因其为 deferred 而拒绝升级后的 runtime。实际执行前由 CapabilityAnalyzer 为每个 feature 产生:

declared_status       CDSL 中的 execution_status
resolved_status       executable | blocked | unsupported
required_capabilities 原子、profile、selector、extent 能力
blockers              精确的缺参、歧义或内核前置条件

旧输出因此可以在 engine 升级后直接重跑;converter 重跑仍应更新导出状态,但不是重建前置条件。

5. 原子能力完成合同

5.1 Reference geometry

reference_planereference_axis 不生成实体,但必须作为正式 FeatureResult 写入 context registry,用于后续 workplane、revolve axis、mirror plane、pattern direction 和 hole host frame。

要求:

  • 使用 canonical PlaneSpecAxisSpec
  • 校验零长度向量,正交化并记录修正后的坐标系;
  • 支持由显式参数、前序 reference、feature 或 sketch 推导;
  • 无法恢复的朝向缺失返回 blocked: missing_reference_orientation,不得默认 XY
  • context feature 不修改 body,但可作为后续 feature 的依赖节点。

5.2 Analytic contour runtime

首期支持 linearccircle。固定流程为:二维 segment 归一化、端点容差拼接、闭环验证、workplane 映射、outer/inner 分类、生成 SketchRegion。一个 region 可以有一个 outer loop 和多个 hole loop。

必须诊断端点反转、退化边、自交、开放 loop、非共面输入,以及无法分类的 unknown contour。circle 是独立 loop,不能用零长度线模拟;嵌套环按奇偶包含关系分类。

对于四段等半径、90 度圆角组成的闭环,若导出逐段 clockwise 标记互相矛盾,runtime 可以依据闭环有向面积统一其短圆角方向;这是一种可证明的 rounded-rectangle 归一化。两段半圆或任意长圆弧无法仅由该规则恢复 sweep intent,必须保留原始证据或在 truth 验证中报告不匹配,不能根据目标 STEP 猜测方向。

B-spline 是后续扩展。采用采样近似时必须声明 chord tolerance 和最大偏差,且 geometry_verified 需使用对应容差策略。

5.3 Extrude 与 revolve

现有 add/cut/revolve atomic 保持原 ID,内部统一归一化为 BooleanModeExtentSpecAxisSpec。执行器先生成 region 面,再调用 adapter;不得根据“草图中有圆”改变 feature 语义。

层次 终止条件 规则
A blindmid_planethrough_allthrough_all_boththrough_all_and_blind 使用当前 body 的精确包围范围与 margin 计算 extent;双向值保持独立
B up_to_surfaceup_to_vertexoffset_from_surfacethrough_nextup_to_body 先通过 selector resolver 得到唯一目标,再由 adapter 做射线或相交查询;up_to_body 使用 active B-rep 的 body record,不允许引用失效快照

extrude_add_two_sided 必须保留正反两侧的距离与终止条件,不能简化为单个对称距离;每一侧都要独立解析 blind、through 或 selector-dependent end condition。revolve axis 可以来自显式 AxisSpec 或 owner-qualified 的 reference_axis selector;无 owner 的 source stable ID 不能被当作 OCC 轴。axis 与 profile 的退化相交必须在 preflight 阶段诊断。

5.4 Hole Wizard

hole_wizard 是独立 atomic,不在 compiler 中改写成匿名多个 hole step。执行器先解析为中立 HoleSpec,再选择 blind/countersink/counterbore/tapped 子型并调用 hole adapter。plan 和报告保留原 feature_idatomic_id

要求:

  • 由 host face selector 或明确 workplane 得到唯一孔位 frame
  • 支持 blindthrough_allthrough_all_both 与 countersink/counterbore
  • 将 SolidWorks 位置坐标转换为 host frame,不能将局部坐标当世界坐标;
  • thread、非标准钻尖或不支持孔型返回 unsupported_hole_subtype,不能静默退化为普通圆柱孔;
  • 源 STEP 的 stable_id 只是线索,host face 必须在重建中间体上重新解析。

5.5 Selector 与 topology registry

selector 是 dress-up、Hole Wizard、pattern 和 selector-dependent extent 的共同前置能力。每完成一个 feature,registry 记录:

feature_id, parent feature ids, body id, context objects,
generated/owned faces and edges, bbox, center, area, normal,
surface or curve type, adjacency signature, local feature signature

每次实体变更都产生新的 active B-rep snapshot,旧 OCC 对象不能继续用于 selector。若且唯若新旧拓扑项存在唯一、完整且几何等价的签名匹配(包括 bbox、中心、面积/长度、朝向与邻接签名),才可将其 durable owner provenance 继承到新对象;分裂、合并、修改或多候选匹配不得继承 owner。这样 owner_feature_id 仍可约束当前实体上的有效对象,而不会把所有存活拓扑误标为最后一个变更 feature。

解析顺序固定为:owner_feature_id 限定候选集,显式 kind 限定面/边/轴,再以几何签名评分,最后应用置信度和唯一性阈值。0 个候选报 selector_not_found,多个同分候选报 selector_ambiguous。两种情况都不能继续 strict rebuild。

原始 stable_id 不能被当作 OCC 持久名称。解析器必须输出候选、评分和最终原因,而不是隐藏地选择拓扑对象。

5.6 Fillet 与 chamfer

实现顺序为:edge selector、face selector 展开到边、单距离 chamfer、双距离或角度 chamfer、tangent propagation。tangent propagation 只能从已解析 edge 出发,沿当前 B-rep 中共享顶点且切向连续的 edge chain 扩展,不能退化为全局边集合。每次 OCC 修饰后都重新扫描 registry,因为此前 B-rep 对象可能失效。

不得提供“没有 selector 时对全部边应用”的回退。当前 550 个 chamfer 与 286 个 fillet feature 均没有 selector;这不是仅新增 runtime 函数就能解决的问题。它们必须由 converter/exporter 提供选择集,或由针对 source truth 的独立 selector enrichment pass 产生唯一、可审计的 selector,才可进入严格重建池。

5.7 Feature-level pattern

pattern_linearpattern_mirror 重放 source feature 的语义执行定义,不复制完整 body,也不在 compiler 中仅平移三维坐标。每个实例有独立 transform scope,并通过相同 atomic executor 在当前 body 上执行。

  • linear pattern 支持一维和二维 direction/spacing/count,并保留 direction reverse
  • mirror pattern 使用 canonical plane,支持显式 plane 或 registry reference
  • source feature 必须已成功执行,且其 selector/reference 经 transform 后仍可唯一解析;显式 host_face.frame 与局部孔位是可直接变换的坐标 contract,未显式 frame 的 host selector、dress-up selector 和 B 层终止 selector 在具备完整 transform contract 前必须阻断;
  • 无 source feature、不可变换 selector 或布尔失败时,整个 pattern 阻断并给出实例级错误。

6. 数据补全责任

engine 负责执行确定的 CDSL,不负责虚构 source intent。下列数据问题必须由 exporter/converter 或可审计 enrichment pass 解决:

数据缺口 当前数量 所需动作
Hole Wizard 缺少 semantic selections 761 捕获 host face、placement frame 和位置关联
缺 source sketch parent 153 记录草图 parent feature/reference plane
reference plane 朝向未捕获 21 导出 origin、normal、x direction 或稳定派生关系
hole 直径或深度缺失 3 捕获原始尺寸及单位
revolve 缺 selection 或 axis 2 捕获 revolve axis/reference
fillet 尺寸无效 1 导出有效 radius/distance
chamfer 缺 semantic selections 1 捕获 edge/face 选择集

部分 Hole Wizard 虽有 host_face,但其来自 source STEP 推断。enrichment pass 必须将其转换为可解析 selector contract,并在置信度不足时保留 unresolved。同一规则适用于 fillet/chamfer,不能为了提高覆盖率创造不稳定 ID。

7. 分阶段交付与覆盖目标

批量覆盖数字是静态“输入就绪池”,不是尚未实现内核下的通过率承诺。所有数字均要求无 unresolved、profile 限于本批四类、analytic_contours 仅含 line/arc/circle,且终止条件在当前阶段已支持。

阶段 交付物 阶段出口 静态就绪池
P0 batch_rebuild、基线 manifest、feature 级报告 998 个输入均有机器可读结果;可复现首个阻断 feature 998
P1 capability analyzer、execution session、reference plane/axis、校验修正 非草图 atomic 可规划;旧 deferred 不再是唯一阻断理由 -
P2 analytic_contours region resolver line/arc/circle、洞与闭环测试通过 -
P3 unified extrude/revolve 与 A 层终止条件 基础实体池全部通过 runtime preflight,并以 truth 运行回归 266 current / 271 historical estimate
P4 topology/selector registry 与 Hole Wizard 有 position、唯一 host face 的孔可严格执行 309 current / 312 historical estimate
P5 fillet/chamfer 和 selector enrichment 闭环 只接受唯一 selector;所有缺 selector 输入明确阻断 取决于 enrichment
P6 linear/mirror feature replay source feature、context、transform 和实例诊断完整 341 current / 343 historical estimate
P7 B 层终止条件、剩余数据补全和回归收敛 633 个无 unresolved 零件按实际 feature 组合进入全量目标池 633

P3 的 271、P4 的 312 与 P6 的 343 都是初始导出统计的历史估计。按当前 998 份 CDSL 的严格闭合-region contract 复算后,P3/P4/P6 静态池分别为 266/309/341:差额来自仅 reference history 或 consumed profile 无闭合 region,不能由 runtime 补齐。P3 的 266 件中另有 4 件缺 captured extent reference 或 revolve axis,因而当前 strict runtime-eligible 为 262P4/P6 当前 strict runtime-eligible 分别为 277/290,主要阻断是 threaded Hole、缺 active body/reference 及不可变换的 selector。它们不是简单相加。

运行时以 phase_pools.select_static_phase_pool 固化 P3/P4/P6 输入定义:无 unresolved、仅该阶段允许的 atomic、至少一个 primary feature,且所有 consumed sketch 都是四种可解析 profile 的闭合 region。静态池不代表每个 feature 的 selector/reference 已完整捕获;当前缺 axis、extent reference 或 history 中无 active body 的文件必须在 strict preflight 报具体 blocker,不能被计入 runtime-eligible。

剩余 365 个带 unresolved 的零件不能仅靠补 engine atomic 达到严格重建。P7 的目标是把每个零件归入“可通过数据补全解锁”或“当前证据不足”,而不是报告模糊失败。

8. 批量基准与 CI 门槛

新增单一入口,例如 backend/engine/cdsl_engine/batch_rebuild.py,接收 CDSL 目录、truth 目录和输出目录。每次运行至少产生:

manifest.json
parts/<part_id>.report.json
parts/<part_id>.step
summary-by-atomic.json
summary-by-blocker.json

每份报告包含:

part_id, cdsl_path, semantic_valid, runtime_eligible, compiled, built,
geometry_verified, topology_observed, first_blocker, feature_results,
unsupported_atomic_ids, unsupported_profile_types, unresolved_input,
selector_resolution, numeric_comparison, timings

报告还必须输出稳定的 failure_categoryinput_incompleteselector_resolutionunsupported_capabilityocc_execution_failuregeometry_mismatchcoordinate_frame_mismatch_candidategeometry_verified 是唯一成功类别。未请求 --build 但已通过预检的报告标为 runtime_eligible_not_built,它是非终态,不是失败或 verified。该分类只归纳已有证据,不能将构建完成或坐标框候选计为 verified。

numeric_comparison 必须保留严格的 passed 判定,并把体积、面积、实体数及无序包围盒跨度均吻合、但绝对坐标框不吻合的情况标为 coordinate_frame_mismatch_candidate。该标记仅帮助定位 workplane/export frame 数据问题,不能替代 geometry_verified

CI 分三层运行:

  1. 单元与 contract 测试:每个 atomic executor、profile resolver、selector 歧义、extent 计算与 capability/schema 同步;
  2. 小型集成 fixturereference -> sketch -> primary feature -> dress-up/pattern 跨 feature 路径;
  3. 批量回归:保存按零件和 atomic 分组的基线,禁止已验证零件退化,新增通过必须附带数值比对。

每次新增 atomic 或终止条件,必须同时更新 schema contract、capability registry、executor、诊断、单元测试和至少一个批量 fixture。不得只把名称加入 SUPPORTED_ATOMIC_IDS

8.1 当前 P3 严格基线

2026-08-23 已按当前静态 P3 pool 运行以下 CDSL-only 基线;每个零件在独立进程中构建,单件 timeout 为 15 秒:

PYTHONPATH=backend/engine python -m cdsl_engine.batch_rebuild \
  json_to_cdsl/output --out /tmp/cdsl-p3-current-baseline \
  --phase p3 --build --build-timeout 15

最终结果为 266/266 已完成、262 份 strict runtime eligible、253 份 built、57 份 geometry verified。其余终态分类为 147 份 geometry_mismatch、49 份 coordinate_frame_mismatch_candidate、6 份 input_incomplete、5 份 occ_execution_failure、2 份 selector_resolution。这是一份验收基线而非成功率承诺:坐标框候选和已构建 STEP 均没有并入 verified。

该命令和输出目录结构是可恢复的;CI 应将经过审查的报告摘要保存在持久化工件中,而不依赖本机 /tmp 的 STEP 临时文件。

同日使用相同的 CDSL-only、每件 15 秒隔离构建策略完成 P4 池:309/309 已完成、277 份 strict runtime eligible、258 份 built、59 份 geometry verified。其余终态为 150 份 geometry_mismatch、49 份 coordinate_frame_mismatch_candidate、8 份 input_incomplete、5 份 occ_execution_failure、12 份 selector_resolution、26 份 unsupported_capability。P4 的 5 个 OCC 失败均已出现于 P3 基础主体能力池,未发现 Hole Wizard 新增的 OCC 失败。

P6 池也已使用同一策略完成:341/341 已完成、290 份 strict runtime eligible、268 份 built、60 份 geometry verified。其余终态为 159 份 geometry_mismatch、49 份 coordinate_frame_mismatch_candidate、9 份 input_incomplete、6 份 occ_execution_failure、14 份 selector_resolution、44 份 unsupported_capability。其中嵌套 pattern source 已按可回放 feature definition 递归执行;不能产生实体的 context source 会在 capability preflight 以 unsupported_pattern_source 阻断,不会再被归为 OCC 执行失败。

P7 的全量 capability 审计也已完成:998/998 份 CDSL 均有 machine-readable report,全部 semantic valid290 份 strict runtime eligible(未请求 --build,因此分类为 runtime_eligible_not_built)、612 份 input_incomplete、96 份 unsupported_capability。这证明所有当前输入均被审计和分类,但不将 preflight 通过等同于 STEP 构建或 geometry verified。

9. 完成判定

本目标完成需要同时满足:

  1. schema 已声明的 16 个 feature atomic 都有 executor、preflight contract 和 feature 级诊断;
  2. analytic_contours 的 line/arc/circle 可构成带洞 region,并由统一 adapter 执行;
  3. 266 个当前基础静态就绪零件均已由 phase-pool 回归审计;其中 262 个在现有输入下通过 strict runtime preflight,剩余 4 个以缺 axis/reference 的 feature-level blocker 报告;当前 CDSL-only P3 基线为 253 built、57 geometry verified,且所有非 verified 结果已有严格终态分类;
  4. Hole、dress-up、pattern 与 selector-dependent extent 不再依赖 compiler 内特例或全局 build123d 状态;
  5. 每个无法严格重建的零件都能区分为输入缺失、selector 歧义、未支持能力或 OCC 执行失败;
  6. 批量报告和 CI 基线持续追踪 998 个输入,且 CDSL-only 成功路径不调用 legacy translator。

这样,engine 的扩展单位是可独立测试、可替换内核、可追溯失败原因的原子能力,而不是为某一批零件增加临时分支。