from __future__ import annotations from pathlib import Path import sys PROJECT_ROOT = Path(__file__).resolve().parent.parent SCRIPT_DIR = PROJECT_ROOT / "scripts" README_PATH = PROJECT_ROOT / "README.md" if str(SCRIPT_DIR) not in sys.path: sys.path.insert(0, str(SCRIPT_DIR)) from verify_first_level_edit_suites import QUICK_COMMANDS, STAGES # noqa: E402 def _assert(condition: bool, message: str) -> None: if not condition: raise AssertionError(message) def _command_path(script_name: str) -> Path: script_path = SCRIPT_DIR / script_name if script_path.exists(): return script_path return PROJECT_ROOT / script_name def _commands() -> tuple[tuple[str, str, tuple[str, ...]], ...]: collected: list[tuple[str, str, tuple[str, ...]]] = [] for stage_name, _stage_label, cases in STAGES: for _label, command in cases: collected.append((stage_name, command[0], command[1:])) for _label, command in QUICK_COMMANDS: collected.append(("quick", command[0], command[1:])) return tuple(collected) def _verify_script_inventory() -> None: for stage_name, script_name, _args in _commands(): path = _command_path(script_name) _assert(path.exists(), f"{stage_name} command target is missing: {script_name}") def _verify_readme_mentions(readme: str) -> None: required_fragments = ( "当前整体验证基线", "不等于 CAD 级完成", "Face 阶段的当前验收口径", "参数化编辑路线图", "用户最常用优先 > B-Rep 上稳定可实现 > 参数语义清楚", "`[x]` 已实现", "`[~]` 部分实现/进行中", "`[ ]` 未实现", "`[x]` 不是“所有 CAD 形态都能改”", "R1 Face 是当前主线的第一阶段收口对象", "R8 的二级/三级传播、跨特征约束和特征组联动不算在 0~7 完成度里", "STEP/B-Rep 参数化编辑主线", "[不能修改 -> 立即说明原因]", "[一级影响范围 -> 明确显示]", "Face 阶段的当前验收口径(R1 已收口)", "已验收:平面 Face 的 `偏移`,稳定矩形/简单全平面 Face 的 `面内长度`、`面内宽度`", "未实现/不承诺:原 CAD 历史恢复、任意复杂 Face 的通用局部重建", "孔/槽阶段的当前验收口径(R2/R3 已收口)", "已验收:圆柱孔/盲孔的 `直径`、`半径`、`轴心`、`盲孔深度`", "已验收:槽/半孔/长圆槽的 `槽宽`、`槽深`、`圆弧长度`", "未实现/不承诺:孔组、阵列孔、同尺寸孔联动、多槽组联动", "2026-08-11,在 `pyocc` 环境下已通过 `python scripts\\verify_first_level_edit_suites.py --stage hole-slot`", "覆盖 R2/R3 孔槽专项套件、隔离执行、逻辑 Face ID 保持和孔槽阶段收口口径", "0~7 其它阶段的当前基线", "verify_first_level_edit_suites.py --quick", "verify_first_level_edit_suites.py --stage face", "verify_first_level_edit_suites.py --stage hole-slot", "verify_first_level_edit_suites.py --stage edge", "verify_first_level_edit_suites.py --stage boss --stage round-chamfer --stage shell --stage analytic", "一级编辑总验证入口", "真实 STEP 失败项", ) for fragment in required_fragments: _assert(fragment in readme, f"README missing first-level acceptance fragment: {fragment}") for stage_name, _stage_label, _cases in STAGES: _assert( f"--stage {stage_name}" in readme or stage_name in {"round-chamfer", "shell", "analytic"}, f"README should mention how to run stage {stage_name}", ) for stage_name, script_name, _args in _commands(): if script_name == "main.py": continue _assert(script_name in readme, f"README should mention {stage_name} command script {script_name}") def _verify_roadmap_scope(readme: str) -> None: start_marker = "STEP/B-Rep 参数化编辑主线" end_marker = "└── 8. 二级 / 三级关系" 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") 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. 壳体 / 解析曲面,补齐高价值但边界更窄的能力", ) for fragment in required_active_fragments: _assert(fragment in active_scope, f"README active roadmap missing: {fragment}") forbidden_active_fragments = ( "[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("[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") def main() -> int: readme = README_PATH.read_text(encoding="utf-8") _verify_script_inventory() _verify_readme_mentions(readme) _verify_roadmap_scope(readme) print("first-level acceptance docs ok") return 0 if __name__ == "__main__": raise SystemExit(main())