【项目】UG/NX 全版本 AI 外挂（NX Copilot）。目标：一个独立安装、自动识别本机全部 NX 版本、
可自由切换、断网可用的 AI 自动编程软件。NX 内只允许存在"极薄桥接"，业务逻辑一律放外部程序。

【先读台账 + 总纲 · 冲突时以台账/总纲为准】
  必读①（30 秒读完）：D:\NX_AI\docs\10_状态台账.md —— 已做完什么、怎么验证的、当前基线、铁律。
                    凡台账里记录在案的【不要再重复实现、也不要重复验证】。
  必读②：D:\NX_AI\docs\09_TraeCN后续工作总纲.md
  它写明：16 张已完成卡、验收方已自行修复的 7 个缺陷（**不要重做**，重做会把已修好的逻辑改回去）、
  13 张待办卡的执行顺序，以及"卡片-现状差异对照表"（第 8 节）。
  本卡正文是在更早轮次写的，可能仍描述"待修"状态 —— 动手前先看总纲第 2 节与第 8 节。
  开工前先跑两条门禁确认起点干净（不通过就先报告，不要动手）：
      python D:\NX_AI\tools\check_py_syntax.py     # 期望：28 个 .py，0 错误 0 预警
      python D:\NX_AI\tests\run_eval.py            # 期望：通过 13/13，意外退化 0，漂移 0

【本机已核实的事实，禁止再猜，按这些事实写代码】
1. 本机装了 2 个 NX：E:\Program Files\Siemens\NX2212 与 E:\Program Files\Siemens\NX2412。
   注意：NX 不在 C 盘、不在 %ProgramFiles%，禁止把盘符写死成 C/D。
2. 版本探测的权威来源是注册表：HKLM\SOFTWARE\Siemens\NX 2212 与 HKLM\SOFTWARE\Siemens\NX 2412，
   值是 INSTALLDIR、UGII_BASE_DIR、LICENSESERVER、LANGUAGE。
   补充来源：Uninstall 项的 "Siemens NX 2212 / 22.12.1700.00000"、"Siemens NX 2412 / 24.12.7002.00005"。
   校验来源：<NX>\NXBIN\run_journal.exe 与 <NX>\NXBIN\ugraf.exe 是否存在。
3. 【重要·已实测】本机 NX 的 Python 是【以 DLL 形式内嵌】的，不需要独立 python.exe：
   E:\Program Files\Siemens\NX2212\NXBIN\python310.dll   (Python 3.10.6)
   E:\Program Files\Siemens\NX2412\NXBIN\python311.dll   (Python 3.11.9)
   E:\Program Files\Siemens\NX2412\NXBIN\nxpythonldr.dll  (NX 的 Python 加载器)
   E:\Program Files\Siemens\NX2412\NXBIN\python\          (含 NXOpen.pyd 与 NXOpen_*.pyd 全套)
   → 结论：Python journal 可用，且是版本无关性最好的通路。
   → 策略：批处理/自动化优先用 Python journal；需要进程内实时交互时才用 C#/VB。
   → 注意：NX2212 是 Python 3.10、NX2412 是 3.11，脚本必须同时兼容两个版本。
4. NX Open .NET 程序集在这里：
   E:\Program Files\Siemens\NX2212\NXBIN\managed\NXOpen.dll  (2212.0.0.0)
   E:\Program Files\Siemens\NX2412\NXBIN\managed\NXOpen.dll  (2412.0.0.0)
   两个版本是两套独立程序集 → 任何 NX 插件 DLL 必须按版本各编译一份，禁止一份打天下。
5. 编译环境：无 Visual Studio、无 .NET SDK。只能用 csc.exe：
   C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe
   目标框架 .NET Framework 4.8（本机已装）。
6. 环境变量现状（必须清理的残留）：
   UGII_VENDOR_DIR(用户级) = E:\Program Files\Siemens\NX2412\UGII\vendor   ← 单值，导致 NX2212 加载不到
   UGII_USER_DIR(用户级)   = C:\Users\Administrator\AppData\Local\NxCamToolkit\bridge
   UGII_LOCAL_USER_DEFAULTS(用户级) = C:\Users\Administrator\AppData\Roaming\NxCamWizard\nx_user.dpv ← 全局关闭了 NXOpen 签名警告
   UGII_BASE_DIR(机器级)   = E:\Program Files\Siemens\NX2412
   → 多版本切换必须用【进程级环境变量】，禁止再写系统/用户级单值变量。
7. 现有工程：C:\NxCamToolkit（Python/tkinter 桌面工具）、C:\NX_Plugins\NxCamWizard（NX 插件成品）、
   C:\Users\Administrator\AppData\Local\NxCamToolkit\bridge（文件信箱桥接 + NxAiBridge 插件）。
   文件信箱 IPC 协议设计是对的，保留并升级；NX 侧 Python journal 路线是错的，废弃。

【硬性约束】
- 不许修改 NX 安装目录下的官方文件（UGII\menus、ugraf.exe、custom_dirs.dat 等），只允许写 vendor/user 隔离目录。
- 不许写系统级/用户级环境变量来切换版本。
- 不许删除任何文件，除非先用 Copy-Item 生成带时间戳的 .bak 且备份成功。
- 不许联网、不许连 43.167.209.150、不许使用 n x_id 私钥、不许读取 trae-jwt-token。
- 不许启动 NX 界面（本次任务未获授权）。需要 NX 在线的验证一律写成脚本 + 说明，交给人工执行。
- 每个脚本必须有：-DryRun 开关、错误处理（不许裸 except）、执行前后日志、失败时非零退出码。

【编码规范】
- 主力语言：Python 3.12（桌面侧，路径 C:\Users\Administrator\AppData\Local\Programs\Python\Python312\python.exe）
  与 PowerShell 5.1（安装/探测/系统集成）；NX 侧用 C#（.NET Framework 4.8）。
- 所有新建工程文件放 D:\NX_AI\ 下（新建），不要污染 C:\NxCamToolkit。
- 中文注释、中文日志；文件一律 UTF-8 with BOM（PowerShell 脚本必须带 BOM，否则中文乱码）。
- 每个模块配一个可独立运行的 --self-test。

【NX Open 跨版本铁律 · 本机实测得出，必须遵守】
1. 判断几何特征只能用【几何量】：面（body.GetFaces()）、边（face.GetEdges()）、
   边长（edge.GetLength()）。实测同一零件 NX2212 与 NX2412 的面数(130)、面类型分布、
   孔径分布【完全一致】。
2. 【禁止】用 NX 对象个数做业务判断。实测同一零件 list(part.Bodies)：
   NX2212=92、NX2412=2；而特征数两版都是 2。按个数分支的逻辑必然出错。
3. 下列 API 在本机两版本上【不存在】，不要再尝试（已逐一实测）：
   face.Radius / face.GetRadius() / edge.Radius / edge.ArcRadius / edge.GetCurveData() /
   part.Faces / ufs.Modl.AskFaceData / body.GetBoundingBox()
   圆柱直径的正确取法：取面的圆边，**edge.GetLength() ÷ π = 直径**
   （实测 34.55751918948773 ÷ π = 11.0000000000，即 φ11）。
4. NX Open 集合【不支持】len()/ToArray()，只能迭代（list(coll) / sum(1 for _ in coll)）。
5. face.SolidFaceType 的 str() 给出数字 id（本机该零件：2→68面、1→43面、3→19面）；
   拿不准就先反射：`dir(obj)` 列真实名字，**不要凭文档猜名字**。
6. 导入/收敛几何（Brep 特征）没有参数化孔特征，孔径只能靠几何反算 —— 这是常态，不是特例。

【执行红线 · 最高优先级，高于本卡其它任何内容】
1. 绝对禁止执行任何带 -Apply / -Force / -Execute / -Run / -Kill / -Confirm:$false 的
   写入性或破坏性开关。你可以生成它们、可以用 -DryRun 验证它们，但【不得真正执行】。
   违反实例已记录一次：P0-05 卡片明确写了"不要执行 -Apply"，但 2026-10-16 14:07:52 实际执行了
   cleanup_residue.ps1 -Apply，清除了用户级 UGII_VENDOR_DIR 与 UGII_LOCAL_USER_DEFAULTS、
   移动了 nx_user.dpv（备份在 D:\NX_AI\backup\20261016140752\，人工已确认不还原）。
2. 任何会改动用户机器状态的命令（写环境变量、改注册表、移动或删除文件、启停服务、装软件、
   改 NX 安装目录内容）一律只写进"人工执行清单"，并说明为什么必须人工执行。
   允许你自动执行的只有三类：在 D:\NX_AI\ 下创建/修改你自己的工程文件、只读探测、-DryRun。
3. done.json 必须与事实一致。若确实执行了写入操作，必须在 notes 里逐条写明
   "已执行 X，时间 HH:MM:SS，影响 Y，备份在 Z"；不得声称"未执行"。
4. 涉及凭据（私钥、口令、token）只允许检测与列出，禁止删除、禁止联网、禁止尝试登录。
5. done.json 的 files 字段必须是纯字符串数组（["绝对路径", ...]），
   不得塞入对象或 PowerShell 的 hashtable 文本（P0-04 犯过这个错）。

【完成时必须做的交接动作】
在 D:\NX_AI\状态\<任务编号>.done.json 写入（UTF-8 无 BOM）：
{"task":"<任务编号>","status":"done|partial|failed","files":["产出文件绝对路径"],
 "verify":"<我该怎么验收，给出可直接复制的命令>","blocked":"<阻塞点或空>","notes":"<关键决策>"}
并且回复里用一句话汇总：做了什么、改了哪些文件、验收命令是什么。

【任务 FIX-01】修复 D:\NX_AI\tools\NxLauncher.py 的语法错误
【状态】**验收方已于 2026-10-16 修复并验证**，本卡只剩"复核 + 补测"。
  原缺陷不止一个，实为**一条 5 连缺陷链**（都因为该文件从未被成功执行过而潜伏）：
    ① 语法错：第 106 行非 raw docstring 里的 `<NX>\UGII\...` → `\U` 触发
       truncated \UXXXXXXXX escape（与 propose_plan.py 同一类事故）
    ② 调 nx_versions.ps1 时把 `-Json` 当开关传（它其实是**输出文件路径**参数）→ 参数绑定失败
    ③ 即使参数对了也解析不到数据：脚本**写文件**、而代码读 stdout
    ④ 字段名不匹配：输出是 `Version`/`Root`，代码用 `target["version"]`/`target["root"]` → KeyError
    ⑤ 缺 `import tempfile`：第 150 行用 `tempfile.mkdtemp` → NameError
  修复后：`--dry-run --version 2412` **退出码 0**，正确列出 NX2212/NX2412 及 E 盘安装根。
  语法门禁（`tools/check_py_syntax.py`）现为 **28 个 .py、0 错误 0 预警**。
  备份：`D:\NX_AI\backup\NxLauncher.py.before_FIX01`
  本卡只剩：复核上述 5 处改动 + 补一条"启动器 detect_nx 能解析出 ≥1 个版本"的集成测试。
  **注意**：部署目标写的是 `<NX>\UGII\vendor\NX Copilot\startup\`，这属于"往 NX 目录塞文件"，
  与用户决定的"不设 UGII_VENDOR_DIR 全局变量"不冲突，但**是否用官方推荐方式加载仍需确认**。

实测证据（验收方用 ast.parse 检查全部 .py）：
  D:\NX_AI\tools\NxLauncher.py  (10 KB, 2026-10-16 15:23:42)
  -> SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 109-110:
     truncated \UXXXXXXXX escape

含义：这个文件连 import/执行都不可能成功。它里面写着"调 deploy.ps1 把 DLL + 三件套部署到
      <NX>\UGII\vendor\NX Copilot\startup\"，说明它是 P0-08/P0-09 交付的部署器，
      但从来没有被真正运行过——否则这个错误第一时间就会暴露。

请完成：
1. 定位并修复语法错误。根因大概率是：**非 raw 字符串/docstring 里的 Windows 路径反斜杠**
   被 Python 当成转义序列（`\U`、`\N`、`\x` 等）。正确写法二选一：
   - 该字符串前加 r：`r"D:\NX_AI\..."`（推荐）
   - 或把反斜杠双写：`"D:\\NX_AI\\..."`
   本卡实测同类坑还出现在我这边的 propose_plan.py（docstring 里 `\NX_AI` 的 `\N`），已修，
   可作为对照参考。
2. **全项目扫描同类问题**：写一个 `D:\NX_AI\tools\check_py_syntax.py`，
   用 `ast.parse` 遍历 D:\NX_AI 下所有 .py（跳过 __pycache__），报告所有语法错误文件。
   这个脚本必须留下，作为以后每次交付前的自检门禁。
3. 修完后**真正运行一次** NxLauncher.py（-DryRun 优先），把输出贴进报告。
   如果它需要管理员权限或会改动 NX 安装目录，只允许跑到 -DryRun，其余写进人工清单。

验收标准：`check_py_syntax.py` 报告全项目 0 个语法错误；NxLauncher.py 至少 -DryRun 能跑通并给出输出。
