feat: 接入 SCDM 优先编辑闭环并支持阵列局部间距

接入 SCDM probe/edit/cache/校验链路,增强孔组、阵列、关系式和参数表交互。

支持阵列相邻段间距、移动意图切换、结果回滚校验,并补充对应回归脚本。
This commit is contained in:
2026-08-19 18:02:47 +08:00
parent a3eb7e2476
commit 4e7877e05c
21 changed files with 5646 additions and 491 deletions
+51 -34
View File
@@ -47,27 +47,30 @@ def _verify_readme_mentions(readme: str) -> None:
"当前整体验证基线",
"不等于 CAD 级完成",
"Face 阶段的当前验收口径",
"参数化编辑路线",
"用户最常用优先 > B-Rep 上稳定可实现 > 参数语义清楚",
"`[x]` 已实现",
"`[~]` 部分实现/进行中",
"`[ ]` 未实现",
"`[x]` 不是“所有 CAD 形态都能改”",
"R1 Face 是当前主线的第一阶段收口对象",
"R8 的二级/三级传播、跨特征约束和特征组联动不算在 0~7 完成度里",
"STEP/B-Rep 参数化编辑主线",
"[不能修改 -> 立即说明原因]",
"[一级影响范围 -> 明确显示]",
"Face 阶段的当前验收口径(R1 已收口)",
"SCDM-first 主路线",
"核心路线只保留下面这一棵树",
"SCDM 内部如何处理相邻面、圆角链、二级/三级拓扑传播,交给 SCDM",
"本软件不再把手写一级、二级、三级传播当成新增能力主线",
"`[x]` 已适配",
"`[~]` 部分适配",
"`[ ]` 待适配",
"[scdm_probe_job.json -> /RunScript 扫描 STEP]",
"[scdm_feature_cache.json -> 映射为本软件能力字典和中文参数]",
"[参数化建模 -> 多个目标值统一提交,不再每行一个操作按钮]",
"[Face 偏移 -> face.offset / OffsetFaces]",
"[槽宽 -> slot.width / OffsetFaces",
"[槽深 -> slot.depth / Move 或 OffsetFaces",
"[本地 OCCT -> 只保留已验证兜底能力,不再作为新主线扩展]",
"Face 阶段的当前验收口径(本地 OCCT 兜底基线,R1 已收口)",
"已验收:平面 Face 的 `偏移`,稳定矩形/简单全平面 Face 的 `面内长度`、`面内宽度`",
"未实现/不承诺:原 CAD 历史恢复、任意复杂 Face 的通用局部重建",
"孔/槽阶段的当前验收口径(R2/R3 已收口)",
"孔/槽阶段的当前验收口径(本地 OCCT 兜底基线,R2/R3 已收口)",
"已验收:圆柱孔/盲孔的 `直径`、`半径`、`轴心`、`盲孔深度`",
"已验收:槽/半孔/长圆槽的 `槽宽`、`槽深`、`圆弧长度`",
"未实现/不承诺:孔组、阵列孔、同尺寸孔联动、多槽组联动",
"2026-08-11,在 `pyocc` 环境下已通过 `python scripts\\verify_first_level_edit_suites.py --stage hole-slot`",
"覆盖 R2/R3 孔槽专项套件、隔离执行、逻辑 Face ID 保持和孔槽阶段收口口径",
"0~7 其它阶段的当前基线",
"本地 OCCT 兜底能力的当前基线",
"verify_first_level_edit_suites.py --quick",
"verify_first_level_edit_suites.py --stage face",
"verify_first_level_edit_suites.py --stage hole-slot",
@@ -92,42 +95,56 @@ def _verify_readme_mentions(readme: str) -> None:
def _verify_roadmap_scope(readme: str) -> None:
start_marker = "STEP/B-Rep 参数化编辑主线"
end_marker = "└── 8. 二级 / 三级关系"
start_marker = "SCDM-first 主路线"
end_marker = "└── 7. 交付与兜底边界"
start = readme.find(start_marker)
end = readme.find(end_marker)
_assert(start >= 0 and end > start, "README roadmap should contain a 0~7 active scope before stage 8")
_assert(start >= 0 and end > start, "README should contain a single SCDM-first roadmap before fallback boundary")
active_scope = readme[start:end]
deferred_scope = readme[end:]
required_active_fragments = (
"├── 0. 先让用户知道“能不能改”",
"│ ├── [x] [不能修改 -> 立即说明原因]",
"│ └── [x] [路线图 -> 验收脚本守门]",
"├── 1. 平面 Face,第一条主线",
"├── 2. 孔,第二条主线",
"├── 3. 槽 / 长圆孔,从孔扩展到组合切除特征",
"├── 4. 凸台 / Boss,从切除特征扩展到加料特征",
"├── 5. 圆角 / 倒角,从主形体扩展到边修饰",
"├── 6. Edge 一级编辑,补齐底层直接改边能力",
"├── 7. 壳体 / 解析曲面,补齐高价值但边界更窄的能力",
"├── 0. 后端发现与可用性",
"│ ├── [x] [自动发现 SpaceClaim.exe -> 缓存路径、来源、版本和验证结果]",
"├── 1. SCDM 识别与缓存",
"│ ├── [x] [scdm_probe_job.json -> /RunScript 扫描 STEP]",
"│ ├── [x] [scdm_feature_cache.json -> 映射为本软件能力字典和中文参数]",
"├── 2. 能力字典、参数表和用户入口",
"├── 3. SCDM 参数化建模执行",
"├── 4. 结果校验、回滚和 ID 续接",
"├── 5. 当前已开放或正在开放的 SCDM 能力",
"[阵列间距 -> pattern.spacing / Move,整体阵列保持中心不变并等距重排;安全范围由支撑面动态计算,不针对 Face92 写死]",
"[局部间距 -> pattern.segment_spacing / Move,按“FaceA-FaceB 间距”或“零件A-零件B 间距”修改相邻段;已支持固定前项移动后侧、固定后项移动前侧、两侧均分保持中心]",
"├── 6. 下一批只按 SCDM 能力适配",
"[阵列实例位置 -> pattern.instance_position]",
"[壳体厚度 -> shell.thickness,薄壁候选配对已进 cache",
)
for fragment in required_active_fragments:
_assert(fragment in active_scope, f"README active roadmap missing: {fragment}")
forbidden_active_fragments = (
"SCDM-first 统一实施路线",
"SCDM-first Capability 适配路线图",
"SCDM-first Capability 适配路线",
"├── 6. Edge 一级编辑,补齐底层直接改边能力",
"└── 8. 二级 / 三级关系",
"[Face 二级传播",
"[孔组 ->",
"多槽组 ->",
"二级传播 ->",
"三级传播 ->",
"二级 / 三级关系",
)
for fragment in forbidden_active_fragments:
_assert(fragment not in active_scope, f"README 0~7 roadmap should defer this to stage 8: {fragment}")
_assert(fragment not in active_scope, f"README SCDM-first roadmap should not keep old route scope: {fragment}")
_assert("[Face 二级传播 -> 孔底/槽底/台阶联动]" in deferred_scope, "README should keep Face deeper propagation in stage 8")
_assert("0~7 不混入二级/三级传播任务" in active_scope, "README should document the active roadmap guard")
_assert("[Analysis Situs -> 只做辅助定位、兜底识别和开源对照]" in deferred_scope, "README should keep Analysis Situs as auxiliary boundary")
_assert("[本地 OCCT -> 只保留已验证兜底能力,不再作为新主线扩展]" in deferred_scope, "README should keep OCCT as fallback boundary")
_assert("[SCDM 之外的新能力 -> 等 SCDM 能力适配完再评估]" in deferred_scope, "README should defer non-SCDM expansion")
forbidden_global_fragments = (
"SCDM-first 统一实施路线",
"SCDM-first Capability 适配路线图",
"SCDM-first Capability 适配路线",
)
for fragment in forbidden_global_fragments:
_assert(fragment not in readme, f"README should keep only one SCDM-first route, found old title: {fragment}")
def main() -> int: