# Trae CN 施工任务书 —— UG/NX 全版本 AI 外挂 v1.0

> 编制：2026-10-16　执行方：Trae CN　验收方：DeepSeek Harness（本文件作者）
> 配套：`00_总规划与范例调研.md`、`01_资产盘点与优化评估.md`

---

## 0. 怎么用（三种投喂方式，任选）

| 方式 | 操作 | 适用 |
|---|---|---|
| **A 手动粘贴** | 打开 Trae CN → 复制 `§公共约束` + 一张任务卡 → 发送 → 等它写完 `done.json` → 发下一张 | 最稳，推荐前 3 张 |
| **B 投喂器** | 运行 `tools\trae_feeder.ps1`，它自动把 `queue\` 里的卡逐个粘进 Trae 并回车，靠 `done.json` 判断进度 | 无人值守批量消耗额度 |
| **C 技能化** | 把 `§公共约束` 存成 Trae 的 Skill/规则，之后只需发"执行下一张任务卡" | 长期 |

> ⚠️ Trae 的 `permission/global.json` 里 `shellSandbox.onRestrict = request_permission_retry_sandbox`、`approval.reviewer = user` —— **它执行命令时会弹窗等你点"允许"**。若要无人值守，先在 Trae 设置里把工作目录加入免打扰白名单（它已经对 `C:\NxCamToolkit`、`E:\Program Files\Siemens\NX2212`、`...\NX2412\UGII\vendor` 有 readWrite 授权）。

---

## 1. §公共约束（每次发送时都要带上这一段）

```text
【项目】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":"<关键决策>"}
并且回复里用一句话汇总：做了什么、改了哪些文件、验收命令是什么。
```

---

## 2. 任务队列总览

| 编号 | 任务 | 主要产出 | 优先级 |
|---|---|---|---|
| P0-00 | 开题：先读任务书（不写代码） | 阅读确认 + `P0-00.done.json` | 🔴 最先做 |
| P0-01 | 真机标定：C#/VB journal 通路是否可用 | `D:\NX_AI\tools\journal_probe.*` + 标定报告 | 🔴 最高（决定架构） |
| P0-01F | 修复 P0-01：-pim 致命参数 + 退出码判定 + 版本号 | 更新 3 个脚本 + 报告 §3 | 🔴 立即（已实测出 3 个真 bug） |
| P0-02 | 统一版本探测模块（三源交叉、全版本枚举） | `D:\NX_AI\core\nx_versions.ps1` + `versions.json` | 🔴 高 |
| P0-03 | 进程级环境构造 + 版本启动器 | `D:\NX_AI\core\nx_launch.ps1` | 🔴 高 |
| P0-04 | 安装清单/备份/回滚框架（替代危险 install.ps1） | `D:\NX_AI\core\deploy.ps1` | 🔴 高 |
| P0-05 | 本机环境残留清理（一次性、可回滚） | `D:\NX_AI\tools\cleanup_residue.ps1` | 🔴 高 |
| P0-06 | 紧急安全处置：作废泄露凭据 + 废弃明文云通道 | `D:\NX_AI\security\*` + 处置报告 | 🔴 最高 |
| P0-07 | 文件信箱 IPC 协议 v2（版本协商/进度/取消/并发安全） | `D:\NX_AI\core\bridge_v2.py` + 协议规范 | 🟠 中高 |
| P0-08 | 薄桥接 DLL 双版本编译流水线 | `D:\NX_AI\nx\build_bridge.ps1` + 2212/2412 两份 DLL | 🟠 中高 |
| P0-09 | 桥接收敛（三代→一套）+ 字段契约统一 + 孤儿进程清理 | `D:\NX_AI\docs\P0-09_桥接收敛.md` + 清理脚本 | 🔴 高 |
| P1-01 | 批处理任务引擎（队列/重试/断点/日志） | `D:\NX_AI\core\task_engine.py` | 🟠 中高 |
| P1-02 | 数据层标准化（ISO 13399/GTC 刀具库 + 参数库） | `D:\NX_AI\data\*` + 转换器 | 🟠 中 |
| P1-03 | 规则库 v2（接入工序编排，替换 ai_programming_rules.json） | `D:\NX_AI\data\rules_v2.json` + 引擎 | 🟠 中 |
| P1-04 | 本地记忆层（SQLite + 向量检索，离线可用） | `D:\NX_AI\memory\*` | 🟠 中 |
| P1-05 | 脱敏守卫（上传前 PII/图号/尺寸过滤 + 预览） | `D:\NX_AI\security\sanitizer.py` | 🟠 中 |
| P1-06 | 云端最小可用服务（TLS + 设备凭据 + 命令白名单 + 审计） | `D:\NX_AI\cloud\*` | 🟡 中 |
| P1-07 | 反馈采集与三元组沉淀 | `D:\NX_AI\memory\feedback.py` | 🟡 中 |
| P1-08 | 桌面主控 UI 骨架（版本中心 + 任务中心） | `D:\NX_AI\app\*` | 🟡 中 |

---

## 3. 任务卡正文（逐张复制发送）

### P0-00 开题：先读任务书（本卡不写任何代码）

```text
【任务 P0-00】开题：先把任务书读完（本卡不写任何代码）

在开始任何施工之前，请先完整读取下面三个文件，理解项目全貌与规则：
  1. D:\NX_AI\docs\02_TraeCN施工任务书.md    ← 主任务书：公共约束、全部任务卡、交接协议
  2. D:\NX_AI\docs\00_总规划与范例调研.md     ← 长期规划与范例调研结论
  3. D:\NX_AI\docs\01_资产盘点与优化评估.md    ← 你既有产出的盘点（哪些保留、重构、废弃）

要求：
- 只读。不要修改这三个文件，不要开始写任何代码。
- 读完后用不超过 6 行回复：① 项目目标是什么；② 你准备按什么顺序推进；③ 哪张任务卡你有疑问（没有就写"没有"）。
- 然后【必须】写交接文件 D:\NX_AI\状态\P0-00.done.json：
  {"task":"P0-00","status":"done","files":[],"verify":"无需验收（本卡只做阅读）","blocked":"","notes":"<你读到的最关键的一条约束>"}
- 写完就停下，等下一张卡（P0-01），不要抢跑。

注意：读 D:\NX_AI\docs\ 下的文件属于工作区内读取，不需要额外授权；如果弹出审批，选允许。
```

---

### P0-01 真机标定：C#/VB journal 通路

```text
【任务 P0-01】真机标定 NX journal 执行通路（本任务只写脚本与文档，不要启动 NX）

背景：本机 NX 的 Python 是内嵌 DLL（2212=3.10.6，2412=3.11.9，NXBIN\python\ 下有完整 NXOpen.pyd），
所以 Python journal 可用；但你之前那三个 journal 脚本都写死了 C:/NxCamToolkit 路径而失效。
本任务要用最小实验把【三条通路】一次标定清楚，不要再猜。

请完成：
1. 新建 D:\NX_AI\tools\，写以下文件：
   a. hello_journal.py —— 最小 Python NX Open journal（首要通路）：往日志窗口写 "NXAI_PROBE_OK"，
      并把 NX 版本号 + Python 版本号写入 D:\NX_AI\状态\journal_result.txt。
      代码必须同时兼容 Python 3.10 与 3.11。
   b. hello_journal.cs —— 最小 C# NX Open journal：打开日志窗口写一行 "NXAI_PROBE_OK"，
      并把当前 NX 版本号（Session.GetSession().GetEnvironmentVariableValue 或
      NXOpen.Session 可得的版本信息）写入 D:\NX_AI\状态\journal_result.txt。
      必须能在 NX 的"工具→录制/播放日志"里直接播放。
   b. hello_journal.vb —— 同样内容的 VB 版本（老版本 NX 只认 VB journal）。
   c. run_journal_probe.ps1 —— 用指定版本的 run_journal.exe 执行指定 journal，要求：
      - 参数：-NxRoot <NX安装根目录> -Journal <脚本> [-TimeoutSec 600]
      - 为子进程构造【干净环境】：UGII_BASE_DIR / UGII_ROOT_DIR / PATH 指向该版本 NXBIN，
        绝不修改当前进程和系统环境变量
      - 完整回收 stdout/stderr 到 C:\NX_AI\日志\run_journal_<时间戳>.log
      - 支持 -DryRun（只打印将要执行的命令行）
      - 超时杀进程并返回非零
   d. probe_matrix.ps1 —— 对 NX2212 与 NX2412 分别尝试下列组合，输出矩阵表格：
      ① run_journal.exe + .py journal（首要通路）
      ② run_journal.exe + .cs journal
      ③ run_journal.exe + .vb journal
      ④ ugraf.exe -batch + journal（若参数不成立就记录"N/A"）
      ⑤ 记录每种组合的退出码、stdout 关键行、耗时、Python 版本、是否占用许可（看日志里的 license 行）
2. 写 D:\NX_AI\docs\P0-01_journal标定报告.md，包含：
   - 每种组合的结论（可用/不可用/待人工确认）
   - run_journal.exe 的完整参数表（用 <NX>\NXBIN\run_journal.exe 的字符串或 /? 输出，
     把 -args、-automation、-nlm、-pim 等真实存在的参数列出来，不确定的标注"未证实"）
   - NX2212 与 NX2412 的行为差异
   - 明确的"人工执行清单"（哪几行命令需要人手动跑一次，因为需要占用许可）
3. 不要启动 NX。把需要真人执行的命令整理成一份可直接复制运行的清单。

验收标准：D:\NX_AI\tools\ 下 4 个文件存在且 -DryRun 可运行；报告里每种组合都有明确结论或标注"未证实"。
```

### P0-01F 修复 P0-01：-pim 致命参数 + 退出码判定 + 版本号

```text
【任务 P0-01F】修复 P0-01 的三个问题（下面是验收方的真机实测结果，按事实改，不要再猜）

验收方在 2026-10-16 13:02–13:12 用你写的脚本真机执行了全部 6 条通路，实测结果：

| 通路 | NX2212 | NX2412 |
| Python journal | 成功 17 秒，Python 3.10.6 | 成功 18 秒，Python 3.11.9 |
| C# journal | 成功 14 秒，exitcode=0 | 成功 17 秒，exitcode=0 |
| VB journal | 成功 13 秒，exitcode=0 | 成功 16 秒，exitcode=0 |

D:\NX_AI\状态\journal_result.txt 现有 6 行（这是验收方的实测证据，先另存再动）：
  PY_JOURNAL OK  NX=unknown  Python=3.11.9  host_pid=4116
  PY_JOURNAL OK  NX=unknown  Python=3.10.6  host_pid=19672
  CS_JOURNAL OK  NX=unknown  host_pid=21576
  CS_JOURNAL OK  NX=unknown  host_pid=14968
  VB_JOURNAL OK  NX=unknown  host_pid=4780
  VB_JOURNAL OK  NX=unknown  host_pid=6256

【问题 1 · 致命】-pim 必须删掉
run_journal_probe.ps1 第 116 行 `$argList += '-pim'` 是致命的。带 -pim 时 NX 会去初始化
Teamcenter 集成，而本机没有 TC，于是启动即致命错误：
  Failed to handle error condition correctly - exiting
  Need to have TC_ROOT/IMAN_ROOT defined to run Teamcenter Integration for NX
  Fatal error detected
85.8 秒后以退出码 1 结束，journal 一行都没执行。去掉 -pim 后同样命令 18 秒成功。
→ 请：① 删除第 116 行；② probe_matrix.ps1 里若有 -pim 一并删除；
   ③ 在报告参数表里把 -pim 更正为：「启用 Teamcenter/PIM 集成，本机无 TC，禁止使用」。

【问题 2 · 判定逻辑】退出码不能作为成功判据
Python journal 退出码恒为 1：因为 hello_journal.py 第 84 行调用了 sys.exit(0)，
NX 的 journal runner 把 SystemExit 的 traceback 当成 "Syntax errors" 报出来。
C#/VB 的退出码为 0（干净）。
→ 请：① 删掉 hello_journal.py 里的 sys.exit(...)，改成正常 return；
   ② 把成功判定改成【看结果产物】：结果文件里出现对应 _OK 行才算成功，
      退出码只作为辅助信息记入日志，不再用来判成败。

【问题 3】NX 版本号取不到（三个 journal 都写 nx_version=unknown）
→ 请改成从注入的环境变量取，最稳：
   Python: os.environ.get('UGII_BASE_DIR')，取末段目录名（如 NX2412）
   C#/VB: Environment.GetEnvironmentVariable("UGII_BASE_DIR")
   兜底再用 Session.GetSession().GetEnvironmentVariableValue("UGII_BASE_DIR")。
   注意 UGII_BASE_DIR 是我们在子进程里注入的，必然存在。

【本卡额外授权与要求】
- 本卡明确授权你执行 NX 批处理后端（run_journal.exe）做验证；仍然禁止启动 ugraf.exe 图形界面。
- 用修正后的脚本重跑 6 条通路（单次仅 13–18 秒，许可占用很短），把实测结论写进
  D:\NX_AI\docs\P0-01_journal标定报告.md 的 §3，把"待人工确认"全部替换成实测结果。
- 报告里补一节「实测耗时与许可占用」：单次 13–18 秒，占用许可时长等同该次执行。
- 重跑前把现有 D:\NX_AI\状态\journal_result.txt 另存为 journal_result_第一轮.txt（它是验收证据）。
- 保持你已经做对的部分：进程级环境注入、不改全局变量（实测确认全局零污染，做得好）。

交接：写 D:\NX_AI\状态\P0-01F.done.json，verify 字段给出"重跑 6 条通路并打印 journal_result.txt 新内容"的命令。
```

---

### P0-02 统一版本探测模块

```text
【任务 P0-02】NX 版本探测与能力位（替换掉 install.ps1 里探测失效的部分）

背景：你之前写的 install.ps1（Detect-NxPath，第 171-321 行）在本机【实测失效】：
它找的 HKLM\SOFTWARE\Siemens\Unigraphics Solutions\NX 这些键根本不存在；
默认路径表只覆盖 C:\、D:\，而本机 NX 装在 E:\。结果只能找到一个版本。
UG_NX2412一键安装器 v1.1 里的 `reg query "HKLM\SOFTWARE\Siemens" /s /v UGII_BASE_DIR` 方向是对的，
但它只取第一个命中项，本机会装错版本。

请完成：
1. 写 D:\NX_AI\core\nx_versions.ps1，导出函数 Get-NxInstallations，要求：
   - 源①：遍历 HKLM\SOFTWARE\Siemens 下所有形如 "NX <数字>" 的子键，取 INSTALLDIR / UGII_BASE_DIR
   - 源②：遍历 Uninstall（含 WOW6432Node）中 DisplayName 匹配 '^Siemens NX' 的项，取 InstallLocation + DisplayVersion
   - 源③：扫描所有本地磁盘（Get-PSDrive -PSProvider FileSystem，不写死盘符）下
     *\Siemens\NX* 与 *\Siemens\NX * 目录
   - 合并去重：以规范化后的安装根路径为键（去尾部反斜杠、统一大小写比较）
   - 每个版本校验：NXBIN\run_journal.exe、NXBIN\ugraf.exe 是否存在，各取 PE 文件版本号
   - 输出【能力位】对象：Version(如 2212/2412)、DisplayVersion、Root、HasRunJournal、HasManagedDir、
     HasEmbeddedPython、ClrFlavor（<=24xx 记 netfx4x，>=2506 记 net8）、SupportsCsharpJournal
   - 支持 -Json <路径> 输出，默认写 D:\NX_AI\状态\versions.json（UTF-8 无 BOM）
2. 写 D:\NX_AI\tools\list_nx.ps1：人类可读的表格输出（版本/路径/校验结果/能力位）。
3. 自测：在本机运行 list_nx.ps1，结果必须【同时列出 NX2212 与 NX2412】。
   把实际输出粘贴进 D:\NX_AI\docs\P0-02_探测实测.md。
4. 额外写 D:\NX_AI\core\nx_version_resolve.ps1，提供 Get-NxRootByVersion -Version 2212|2412|'latest'，
   供其它模块调用（找不到时抛明确错误，不要返回 $null 让上层猜）。

验收标准：list_nx.ps1 输出两个版本；versions.json 里两个版本的 Root 与能力位正确；
代码里没有任何写死的 C:/D: 盘符；对不存在的版本调用会抛清晰错误。
```

### P0-03 进程级环境构造与启动器

```text
【任务 P0-03】版本切换器：只改子进程环境，绝不改全局

背景：你之前的做法是写系统级/用户级 UGII_VENDOR_DIR（单值），导致装第二个版本时第一个失效，
本机现在就是这个状态。草莓 CM 外挂的正确做法是：每个版本一个启动批处理，在里面 set 环境变量后
再拉起该版本 NX（进程级，互不干扰）。我们要做成软件，不能靠一堆 .bat。

请完成：
1. 写 D:\NX_AI\core\nx_env.ps1，导出：
   - Get-NxEnvironment -NxRoot <路径> [-UserDir <路径>] [-CamPostDir <路径>]
     返回一个 hashtable，含该版本启动所需的全部变量（UGII_BASE_DIR、UGII_ROOT_DIR、UGII_USER_DIR、
     UGII_CUSTOM_DIRECTORY_FILE(可选)、UGII_CAM_POST_DIR、PATH 前缀=NXBIN 与 UGII）
   - Invoke-WithNxEnvironment -Env <hashtable> -ScriptBlock <{}> ：在【当前进程临时】设置、
     执行、并无条件恢复原值（必须用 try/finally，恢复包括"原本不存在该变量"的情况）
2. 写 D:\NX_AI\core\nx_launch.ps1：
   - 参数：-Version <2212|2412|latest>、-Mode <gui|journal>、-Journal <脚本>、-DryRun、-TimeoutSec
   - gui 模式：用干净环境 + Start-Process 拉起 <NX>\NXBIN\ugraf.exe，并可注入用户级定制目录
   - journal 模式：调用 P0-01 的 run_journal_probe.ps1
   - 启动前必须检查该版本 NX 是否已在运行（tasklist），已运行则给出清晰提示与分支处理
3. 关键约束：脚本执行完毕后，用 `[Environment]::GetEnvironmentVariable('UGII_VENDOR_DIR','User')` 等
   逐一比对，确认【没有任何全局变量被改动】。把这个自检写成 -AssertNoGlobalChange 开关，默认开启。
4. 写 D:\NX_AI\docs\P0-03_环境构造说明.md：解释为什么必须进程级、全局变量会造成什么故障
   （用本机 UGII_VENDOR_DIR 单值指向 NX2412 导致 NX2212 加载不到 vendor 的真实案例说明）。

验收标准：-DryRun 能打印出完整的、指向正确版本的环境变量快照；-AssertNoGlobalChange 自检通过；
切换两次（2212→2412→2212）后全局变量与初始值完全一致。
```

### P0-04 安装/卸载框架（备份、清单、回滚）

```text
【任务 P0-04】重写部署框架，消灭现有安装器的危险操作

背景：你之前的 install.ps1 有 4 个高危问题（我逐行核对过）：
① 第 611 行 Remove-Item -Recurse -Force 卸载整个目录，无备份无清单；
② 第 364-377 行无条件清空全局唯一的 UGII_VENDOR_DIR，会让其它厂商插件一起失效；
③ 第 352/556 行写系统级变量，第 541-562 行永久写 UGII_LOCAL_USER_DEFAULTS 关闭 NXOpen 签名警告，
   卸载时不移除；
④ 探测失效（见 P0-02），可能把文件装到错误版本目录。

请完成：
1. 设计部署清单格式 D:\NX_AI\core\deploy_manifest.schema.json：
   记录 任务ID、目标 NX 版本与根路径、每个被写入文件的绝对路径+写入前是否存在+备份路径+SHA256、
   每个被改动的环境变量（作用域/旧值/新值/旧值是否存在）、时间戳、操作人。
2. 写 D:\NX_AI\core\deploy.ps1，提供四个动作：
   - Install  -Package <目录> -NxRoot <路径> [-DryRun]
     规则：先写权限探针；逐文件复制前若已存在则备份为 <名>.<版本>.<yyyyMMddHHmmss>.bak，
     备份失败立即中止（不许继续）；全程写清单；结束时打印"实际做了什么"（不许无条件打印成功）
   - Uninstall -Manifest <清单路径> [-DryRun]
     规则：严格按清单反向执行；恢复环境变量时【只有当当前值仍等于自己写入的值】才恢复，
     否则跳过并警告（避免踩掉别人的插件）
   - Rollback -Manifest <清单路径> ：按备份还原文件
   - Verify -Manifest <清单路径> ：校验 SHA256 与清单一致
3. 所有动作必须打印三态：新增/覆盖/跳过，并统计数量。任何失败给出非零退出码。
4. 写 D:\NX_AI\tools\test_deploy_roundtrip.ps1：在一个临时目录里做完整的
   安装→Verify→Uninstall→Rollback 往返测试，断言目录与变量回到初始状态。必须真实跑通并贴输出。

验收标准：往返测试通过且输出贴在 done.json 的 verify 字段；deploy.ps1 里不存在无备份的 Remove-Item；
环境变量恢复有"值相同才恢复"的判断。
```

### P0-05 本机环境残留清理

```text
【任务 P0-05】写一个可回滚的一次性清理脚本（本任务只生成脚本，不执行）

背景：本机现在有 4 处残留（见公共约束第 6 条）：
- UGII_VENDOR_DIR 单值只指向 NX2412，导致 E:\...\NX2212\UGII\vendor\NxCamWizard 形同虚设；
- UGII_USER_DIR 指向 NxCamToolkit\bridge，而 NxCamWizard 的安装器会"检测到它就再装一份"，
  两个插件的文件混在同一个 startup\ 目录里；
- UGII_LOCAL_USER_DEFAULTS 指向 nx_user.dpv，永久关闭了整机的 NXOpen 签名过期警告；
- 两个 NX 的 vendor\NxCamWizard 里 DLL 版本不一致（NX2212 是 9/5 版，NX2412 是 8/31 版）。

请完成：
1. 写 D:\NX_AI\tools\cleanup_residue.ps1，要求：
   - 默认 -DryRun，只打印将要做的事；必须显式 -Apply 才真正执行
   - 执行前把以下内容备份到 D:\NX_AI\backup\<时间戳>\：
     4 个环境变量当前值的 JSON、两个 vendor\NxCamWizard 目录的完整副本、nx_user.dpv 与 nx_user.xsl
   - 动作：① 清除用户级 UGII_VENDOR_DIR（先确认其它插件不依赖它，打印当前值要求二次确认）；
     ② 清除用户级 UGII_LOCAL_USER_DEFAULTS 并把 nx_user.dpv 移出（恢复签名警告）；
     ③ 保留 UGII_USER_DIR 但把 NxCamWizard 的文件从该 bridge 目录里识别并列出（不直接删，先报告）；
     ④ 生成"两个 NX 的 vendor\NxCamWizard DLL 版本不一致"的报告
   - 提供 -Restore <备份目录> 把一切还原
2. 生成 D:\NX_AI\docs\P0-05_残留清理方案.md：逐条说明动什么、为什么、如何回滚、风险等级。
3. 不要执行 -Apply。把命令写进交接说明，由人工决定何时跑。

验收标准：-DryRun 输出完整且不产生任何写操作（可用文件系统时间戳验证）；
-Restore 逻辑与 -Apply 严格对称。
```

### P0-06 紧急安全处置（最高优先级）

```text
【任务 P0-06】处置已泄露的凭据，废弃不安全的云通道

背景（我审计出来的真实问题，非常严重）：
- C:\Users\Administrator\Desktop\连接云服务器\UG连云端_oneclick\nx_id 是【明文 ed25519 SSH 私钥】，
  同一个包里还有 nx_id.pub；同一份副本也在 Desktop\UG插件\我的插件\oneclick\ 下。
  这个私钥能直接 SSH 登入本机（install_ssh.bat 把它写进了 administrators_authorized_keys）。
- config.json 里是明文共享 token=83efbf8cc96035f177fc2cdb31ae7a5e，relay 是 http://（无 TLS）。
- worker.ps1 第 27 行用 cmd /c 执行云端下发的任意命令 —— 等价于把本机的远程命令执行权开放给公网，
  任何人拿到那个 token 就能控制这台机器。
- E:\autodl-dj\AUDJ\tmp_*.py 与若干日志里有明文口令 Aaa307896218。
- E:\autodl-dj\AUDJ\agent_config.py 第 32 行硬编码了 Fernet 密钥。

请完成（本任务不要联网、不要 SSH、不要删除任何文件）：
1. 写 D:\NX_AI\security\INCIDENT_报告.md：逐条列出泄露物、路径、影响面、必须做的处置动作、
   以及"如果被利用会怎样"。要具体，不要套话。
2. 写 D:\NX_AI\security\revoke_checklist.ps1：只做【检测与列出】，不修改：
   - 扫描指定目录找出所有私钥（含 BEGIN OPENSSH PRIVATE KEY / BEGIN RSA PRIVATE KEY 的文件）、
     明文 token/password 形态的字符串（排除 trae-jwt-token 与用户隐私文件）
   - 检查 administrators_authorized_keys 里是否含泄漏公钥
   - 检查 sshd 服务是否被启动/设自启
   - 检查注册表/服务是否残留 8001 relay 的自启项
   输出一份"现状清单 + 建议动作"的 JSON 与 Markdown
3. 写 D:\NX_AI\security\cloud_channel_v2.md：设计替代方案，必须包含：
   - 传输层 TLS（自签 + 固定指纹 或 正式证书）
   - 每设备独立凭据（设备注册 → 签发设备密钥 → 可吊销），废除共享静态 token
   - 命令白名单：云端只能下发"命名的任务类型 + 参数"，本机侧映射到固定脚本，
     绝不允许任意 shell 字符串（这是与旧方案最本质的区别）
   - 任务签名与重放保护（nonce + 时间窗）
   - 全量审计日志（谁在什么时候下发了什么、结果如何）
   - 最小权限：worker 以普通用户运行，不要求管理员
4. 给出一份"人工处置清单"（作废私钥、改口令、关隧道、轮换 token 的具体步骤，按顺序）。

验收标准：报告能让人照着一步步做完处置；revoke_checklist.ps1 只读且能真实跑出结果；
cloud_channel_v2.md 里明确写出"任意 cmd 执行"为什么必须废弃。
```

### P0-07 文件信箱 IPC 协议 v2

```text
【任务 P0-07】升级桥接协议（现有设计对，但不够稳）

背景：现有协议（C:\Users\Administrator\AppData\Local\NxCamToolkit\bridge\protocol.py +
nx_bridge.template.cs）用 inbox/cmd_<id>.json + outbox/resp_<id>.json + status.json 心跳，
纯文件、零端口、车间电脑友好——这个设计【保留】。但存在这些问题：
- 没有协议版本号与能力协商（新老桥接混用会静默出错）
- 没有长任务进度回传与取消（同步等 resp，超时只能干等）
- NX 被模态对话框卡住时上层无法区分"没加载桥接"与"NX 正忙"
- cleanup_stale 用 300 秒固定阈值，会误删正在执行的长任务
- 并发发送方没有互斥，可能出现同 id 竞争

请完成：
1. 写 D:\NX_AI\docs\桥接协议v2规范.md，定义：
   - 目录结构：bridge/v2/{inbox,outbox,progress,locks}/{status.json,hello.json}
   - 消息信封：{proto:"2", id, type, params, ts, deadline, trace}
   - 版本协商：桥接启动写 hello.json（NxVersion、协议版本、支持的命令类型、能力位）；
     主控读到不兼容版本要明确报错而不是超时
   - 长任务：命令返回 accepted 后，桥接持续写 progress/<id>.json（step/total/message/ts）；
     主控轮询进度；支持 cancel/<id>.json 取消
   - 存活与忙碌区分：status.json 增加 state 字段（idle|busy|modal|error）与 last_cmd
   - 过期策略：不再用固定 300s，改为按消息 deadline 字段清理；清理前检查锁
   - 幂等与恢复：响应文件存在即完成；重复 id 的语义定义清楚
2. 写 D:\NX_AI\core\bridge_v2.py（Python 客户端）：send_command / send_async / poll_progress /
   cancel / read_hello / is_alive，含完整类型校验与清晰的异常层次
   （BridgeNotLoaded / BridgeBusy / BridgeModal / BridgeTimeout / BridgeError）
3. 写 D:\NX_AI\core\bridge_v2_selftest.py：用 mock 桥接（纯 Python 假实现，模拟各种延迟/卡死/错误）
   跑通 8 个用例：正常、超时、忙碌、模态、取消、进度、协议不匹配、响应损坏。
   必须真实跑通并贴输出。
4. NX 侧 C# 实现留到 P0-08，本任务只交付规范 + Python 客户端 + 自测。

验收标准：bridge_v2_selftest.py 全绿；规范文档里每个字段都有含义说明；
异常层次能让人一眼看出"是没装、还是 NX 忙、还是真出错"。
```

### P0-08 薄桥接 DLL 双版本编译流水线

```text
【任务 P0-08】极薄桥接 DLL：NX2212 与 NX2412 各编译一份

背景与设计原则（非常重要，不要违背）：
桥接 DLL 跑在 NX 进程内、绑定具体 NX 版本、每个版本要单独编译，NX1926 之后还有 NXOpen 签名校验。
因此 DLL 必须【极薄】：只做 4 件事——收发消息、读当前部件名、执行指定的 NX 操作、回报结果。
所有业务逻辑（规则、参数、经验）一律放在外部主控程序里。
这样多版本的维护成本从 O(功能数 × 版本数) 降到 O(版本数)。违反这条，项目必死。

请完成：
1. 写 D:\NX_AI\nx\NxBridge.cs（单文件、尽量少的依赖）：
   - 入口：public static void Main(string[] args)（由 .btn 的 ACTIONS 调用），
     或按你实测可行的 NX Open 内部程序入口（ufusr 风格）——请两种都给出并注明适用范围
   - 启动后：写 hello.json（NX 版本、协议版本、能力位），启动一个 WinForms Timer（1 秒）轮询 inbox
   - 支持的命令（v2 协议的最小集）：PING、HELLO、GET_CONTEXT（当前部件名/单位/路径）、
     EXEC_SCRIPT（执行一段指定的受控操作，如导出图纸）、CANCEL
   - 所有异常必须被捕获并写回 resp 的 error 字段（禁止让异常冒泡弄崩 NX）
   - 只用 NXOpen / NXOpen.UF / NXOpen.Utilities / System.Windows.Forms / System.Text.Json
     （或 Newtonsoft 若更省事，但必须把依赖 DLL 一起放进交付目录）
2. 写 D:\NX_AI\nx\build_bridge.ps1：
   - 参数 -Version 2212|2412|all
   - 用 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe 编译，
     引用 <NX>\NXBIN\managed\NXOpen.dll 等，目标 .NET Framework 4.8
   - 【禁止】把 NX 自带的 NXOpen*.dll 复制进我们的交付目录（许可合规红线）
   - 输出到 D:\NX_AI\nx\dist\<版本>\，并生成编译报告（引用了哪些程序集、哈希、时间）
   - 编译失败必须给出可读的 csc 错误摘要，而不是整屏噪声
3. 写 D:\NX_AI\nx\startup\NxBridge.men、NxBridge.rtb、NxBridge.btn 三件套：
   - 参考现有可用样本的语法：.men 用 VERSION 120 + ACTIONS LIBRARIES <dll> <命名空间.类.入口>；
     .rtb 用 VERSION 170；.btn 用 VERSION 120 + CREATE BUTTON_DEFINITIONS 定义 LABEL/BITMAP/MESSAGE
   - 三者的按钮 id 必须一致（现有 NxCamWizard 就缺 .btn，是反面教材）
   - BITMAP 用 NX 内置图标名（如 ad_run），不要依赖自定义 bmp 路径
4. 写 D:\NX_AI\docs\P0-08_桥接DLL设计与签名.md：
   - 说明 NXOpen 签名过期警告的成因，以及【为什么不能用 UGII_LOCAL_USER_DEFAULTS 全局关掉它】
     （正确做法：DLL 与目标 NX 版本匹配编译；给出可行的提示用户方案）
   - 列出"NXN 版本 ↔ 编译产物"对应表与新增 NX 版本时的扩展步骤

验收标准：build_bridge.ps1 -Version all 在本机能真实编译通过（你可以运行 csc.exe，这不涉及启动 NX）；
两份 DLL 的 NXOpen 引用版本分别是 2212.0.0.0 / 2412.0.0.0（用 ildasm 或读程序集元数据验证并贴证据）；
三件套齐全且按钮 id 一致。
```

### P0-09 桥接收敛：三代合一 + 契约统一

```text
【任务 P0-09】把"同一个桥接写了三遍"收敛成一套，并统一字段契约

背景（我逐行核对过，这是你留下最大的技术债）：
你实际上写了三代桥接：
  A 代（GUI 在用）：nx_bridge_dotnet.cs（447 行）→ launcher.py:175-213 用 csc 编译成
    bridge\startup\NxAiBridge.dll，靠 UGII_USER_DIR 被 NX 自动加载。但它没有任何成功日志，
    全盘找不到 "=== .NET bridge start ===" 这行。
  B 代（能力最全但从未接线）：nx\nx_bridge.template.cs（1125 行，有 Mutex 单例、全字段、
    失败字典），由 launcher.py:236-259 write_bridge_script() 生成 —— 这个函数【全工程无调用者】。
  C 代（唯一有成功日志）：run_test.py:101-108 用 run_journal.exe 拉起的 bridge_daemon.py，
    但 while True 无退出条件，至今仍在后台每 4 秒写一次心跳（幽灵进程，本机实测仍在跑）。

三个致命后果：
1. 双信箱错位：nx_bridge.cs:27 写死 "C:/NxCamToolkit/bridge"，而 protocol.py:22-25 用
   %LOCALAPPDATA%\NxCamToolkit\bridge → 你给用户的"手动播放 nx_bridge.cs"兜底路线必然超时。
2. 契约错位：monitor_frame.py:251-252 读 st['nx'] 与 st['op_count']，而 nx_bridge_dotnet.cs:92-98
   只写 connected/pid/ts/nx_open/part_name → 界面永远显示"未连接 / 工序 0"。
   另外 monitor_frame.py:285,288-290 读 data['material']/['tools']，DLL 桥只给 tool_count；
   monitor_frame.py:420-421 用 f.get('op_name')，而 Python 桥 nx_bridge.template.py:157 返回纯字符串
   → 回写失败分支必抛 AttributeError。
3. 编码静默丢命令：protocol.py:48-49 用 utf-8 + ensure_ascii=False 写 cmd，而 bridge_daemon.py:41/63
   的 open() 没有 encoding= → 中文工序名在 cp936 下 UnicodeDecodeError，异常被吞后
   bridge_daemon.py:68-71 还会把命令文件删掉（静默丢失）。
4. bridge_daemon.py:64-65 无条件写 {"ok": true}，失败也回成功。

请完成（本任务只做收敛设计与一套新实现，不要改动 C:\NxCamToolkit 里的旧文件）：
1. 写 D:\NX_AI\docs\P0-09_桥接收敛.md：
   - 三代实现的对照表（行数、入口、信箱路径、字段、状态、证据行号）
   - 明确"唯一基线"的选择与理由（建议：以 B 代的 C# 全字段实现为语义基线，
     但按 P0-08 的"极薄"原则裁剪，业务字段一律移到外部主控）
   - 一张【唯一字段契约表】：字段名、类型、单位、谁写、谁读、缺失时的默认值。
     要求覆盖：status.json（connected/pid/ts/nx_version/state/part_name/units）、
     snapshot（tools[]/operations[]/material/op_count）、错误对象（code/message/detail）
   - 明确的"废弃清单"与"迁移顺序"
2. 写 D:\NX_AI\core\contract.py：把字段契约写成【可执行的校验函数】
   validate_status(dict) / validate_snapshot(dict)，不符契约时抛带字段名的清晰异常；
   并配 D:\NX_AI\tests\test_contract.py，用"旧 DLL 桥的真实输出样例"作为反例，
   断言校验器能抓出缺字段（证明它能防住这次的坑）。
3. 写 D:\NX_AI\tools\find_orphan_bridge.ps1：
   - 只读检测：找出仍在写 bridge.log / 发心跳的进程（python.exe/pythonw.exe/ugraf.exe/run_journal.exe），
     报告 PID、命令行、启动时间、CPU 时间
   - 找出可能占用 NX 许可的 batch 会话
   - 只有 -Kill 参数才真正结束进程，默认只报告；结束前必须打印 PID 与命令行要求确认
4. 不要删除任何旧文件；收敛通过"新目录 + 适配层"完成。

验收标准：test_contract.py 能用旧桥的真实输出证明"契约校验能抓到缺字段"；
find_orphan_bridge.ps1 在本机真实列出可疑进程（找不到就如实报告）；
收敛文档里的字段契约表与 contract.py 一一对应。
```

---

### P1-01 批处理任务引擎

```text
【任务 P1-01】任务引擎：队列、重试、断点、日志

要求：
1. D:\NX_AI\core\task_engine.py：SQLite（D:\NX_AI\状态\tasks.db）存任务表
   （id/type/params/state/attempts/max_attempts/created/started/finished/result/error/artifact_paths）
2. 状态机：pending → running → done | failed | cancelled；失败可重试（指数退避），超次数进 dead 队列
3. 断点续跑：进程重启后能找回 running 状态的任务并判定是"继续"还是"标记中断"
4. 每个任务用目标 NX 版本的干净环境执行（调用 P0-03 的 nx_launch.ps1）
5. 结构化日志（JSON Lines）+ 人类可读摘要；每个任务独立的 stdout/stderr 文件
6. 并发：同一 NX 版本同时只允许一个 batch 任务（许可与资源约束），可跨版本并行
7. --self-test 用假执行器跑通：成功/失败重试/超次数死信/取消/断点恢复，贴输出

验收标准：self-test 全绿；杀掉进程再启动能正确恢复；tasks.db 可直接用 SQLite 工具查看。
```

### P1-02 数据层标准化（ISO 13399 / GTC）

```text
【任务 P1-02】刀具库与参数库标准化

背景：现有 data\ToolLibrary.xml（23KB）、SpeedFeedTable.xml、MaterialLibrary.xml 是自定的 XML 结构，
无法与外部刀具数据互通。ISO 13399 是切削刀具数据表达与交换的国际标准，GTC（Generic Tool Catalog）
是它最现实的落地格式（含格式与映射规则规范）。

要求：
1. 写 D:\NX_AI\data\schema\，用 JSON Schema 定义内部的"标准刀具模型"与"标准参数模型"，
   字段尽量对齐 ISO 13399 的概念（刀具类型、几何、切削刃、材料、涂层、可用切深/切宽/线速度/每齿进给）
2. 写 D:\NX_AI\data\convert\legacy_to_std.py：把现有 ToolLibrary.xml / SpeedFeedTable.xml /
   MaterialLibrary.xml 无损转成标准模型，并输出转换报告（多少条、哪些字段无法映射、默认值假设）
3. 写 D:\NX_AI\data\validate.py：校验刀具/参数库完整性与一致性（缺字段、单位错、转速进给超物理边界）
4. 保留旧格式的读取兼容层（不允许直接删旧文件）
5. 写 D:\NX_AI\docs\P1-02_数据标准说明.md：ISO 13399 是什么、GTC 为什么是落地路径、
   我们为什么先做内部标准而非直接全量实现 ISO（务实取舍）

验收标准：转换脚本对现有文件真实跑通且报告完整；validate.py 能指出至少 1 个真实问题或确认全部通过；
旧数据读取仍有回归测试。
```

### P1-03 规则库 v2 与工序编排接入

```text
【任务 P1-03】规则库升级并真正接入编排引擎

背景：Trae 的记忆里记录了现有口径，这些是【业务红线，必须保持】：
- 切削参数单一数据源，系数只乘一次；预设表优先于材料库
- 丝锥 Fz = 螺距，绝不缩放，靠降转速保守；feed = rpm × 螺距（齿数按 1）
- 钻头 Fz = 每转进给 mm/r，feed = rpm × fz（齿数按 1，不许乘 2）
- 钻/攻丝预设名无"粗/精"字样，必须按 ToolType 直接命中，否则回落材料库会出现丝锥 4774 rpm 的灾难
- 钛合金预设不得套用于 Inconel 等镍基合金（S 类内部按材料名含"钛"区分）
- Ap/Ae 的 clamp：钢 ≤0.5D、铝 ≤0.8D、S ≤0.45D、H ≤0.4D；粗加工 Ae ≤0.65D
- 悬伸比 刃长/刀径 > 4D 警告；MRR = Ap×Ae×Vf
这些规则必须原样保留，并写成【可执行的单元测试】。

要求：
1. 把 data\ai_programming_rules.json 升级为 v2（加版本号、生效范围 applicable_versions、
   每条规则的来源与更新时间），并补齐目前 applied_in_engine=false 的条目（分层设计，先占位）
2. 写 D:\NX_AI\tests\test_cutting_rules.py：把上面 6 条红线各写成测试用例
   （尤其：丝锥不许被刀径系数缩放、钻头不许乘 2 齿、Inconel 不许命中钛预设、Ap/Ae clamp 边界）
3. 给出规则库的"生效/失效/被取代"机制：每条规则有 id、superseded_by、effective_from
4. 不要把规则写死在 Python 里，必须数据驱动（改 json 即改行为）

验收标准：test_cutting_rules.py 全绿；故意改坏规则文件时测试能失败（证明测试真的在测）；贴输出。
```

### P1-04 本地记忆层

```text
【任务 P1-04】离线可用的本地记忆（SQLite + 向量检索）

背景：云端记忆要走"本地优先"：图纸不出本机，本地是唯一事实来源，云端只做脱敏知识原子的同步。
三层记忆要分开建模：情景记忆（这次做了什么）、语义记忆（抽象规则/经验）、程序性记忆（技能脚本/宏）。

要求：
1. D:\NX_AI\memory\store.py：SQLite（D:\NX_AI\状态\memory.db）+ sqlite-vec 或纯 Python 余弦检索
   （若 sqlite-vec 安装不便，就用 numpy 暴力检索，先把接口定死：add/search/update/forget/export）
2. 三类记忆各自独立的表与检索策略；技能库记录 advanced：适用 NX 版本区间、前置条件、成功率、调用次数
3. 记忆条目必须带来源溯源：session_id、来源类型（用户显式/系统推断/云端下发）、时间戳
4. forget/export 必须完整支持（合规要求：可删除、可导出）
5. 全文检索 + 向量检索混合召回，给出打分融合策略
6. 完全离线可跑；--self-test 覆盖 add/search/update/forget/export，贴输出

验收标准：self-test 全绿；断网可运行；导出为人类可读 JSON；每条记忆都能回溯到来源。
```

### P1-05 脱敏守卫

```text
【任务 P1-05】上传前脱敏，图纸本体永不出厂

要求：
1. D:\NX_AI\security\sanitizer.py：输入任意待上传文本/结构，输出脱敏结果 + 命中报告
   - 规则：图号/零件号模式、公司名与人名、绝对尺寸与公差、文件路径与文件名、机床编号、
     客户名、手机号/邮箱/身份证、NX 部件属性里的敏感字段
   - 命中后策略可选：替换为占位符 / 泛化为区间 / 直接阻断
2. D:\NX_AI\security\guard_config.json：规则可配置，支持企业自定义词表
3. 必须提供"用户可预览将要上传的内容"的接口（返回 diff 形式：原文 vs 脱敏后）
4. 单元测试：写 20 条真实形态的样例（含中文图号如 "LQD80-175电机后盖"、尺寸 "±0.02"、
   路径 "E:\UG文件\xx.prt"），验证全部命中且不误伤"φ10 立铣刀"这类正常术语
5. D:\NX_AI\docs\P1-05_脱敏设计.md：说明为什么这既是合规要求也是销售话术

验收标准：20 条样例全部符合预期（命中/不误伤）；有预览接口；规则可配置。
```

### P1-06 云端最小可用服务

```text
【任务 P1-06】重做云端：TLS + 设备凭据 + 任务白名单 + 审计

背景：旧方案（Desktop\连接云服务器）是明文 HTTP + 共享静态 token + 下发任意 cmd /c，
等于把客户机器的远程命令执行权挂到公网。必须彻底重做，参考 P0-06 的 cloud_channel_v2.md。

要求（先做最小可用，不要过度设计）：
1. D:\NX_AI\cloud\server\：FastAPI 服务，接口：
   - POST /v1/devices/register（设备注册，返回设备 ID + 一次性激活码）
   - POST /v1/devices/heartbeat（心跳，带能力位与 NX 版本列表）
   - GET  /v1/jobs/poll（只返回【命名任务】，如 {"type":"export_drawings","params":{...}}）
   - POST /v1/jobs/result（结果 + 产物哈希 + 耗时）
   - 管理接口：吊销设备
2. 鉴权：每设备独立密钥（HMAC 签名请求，含 nonce + 时间窗防重放），废除共享 token
3. 【红线】服务端永远不下发 shell 字符串；客户端只接受白名单任务类型，映射到本地固定脚本
4. 审计日志：SQLite 记录 设备/动作/参数摘要/结果/时间，可导出
5. 传输：支持 TLS（本地自签 + 固定指纹校验），配置项可开关但默认要求 TLS
6. D:\NX_AI\cloud\client\worker.py：轮询 + 执行白名单任务 + 回报；默认以普通用户运行，不要求管理员
7. 用 pytest + httpx 写出接口测试（含：无签名被拒、重放被拒、非白名单任务被拒、吊销后失效）

验收标准：测试全绿，四条安全用例必须真实通过；代码里搜不到任何 "shell=True" 或 "cmd /c"。
```

### P1-07 反馈采集与三元组沉淀

```text
【任务 P1-07】把每次人工修正变成可训练数据

背景：护城河不是模型，是"人工修正 → 结构化经验 → 资产库 → 灰度发布"这条闭环。

要求：
1. D:\NX_AI\memory\feedback.py：定义并落地三元组
   (特征上下文, 系统建议, 人工最终值) + 结果指标（是否成功、耗时、是否报警告）
2. 采集信号：显式（点赞/踩、一行纠错）+ 隐式（采纳、采纳后编辑距离、撤销、执行失败）
3. 本地聚合、异步上报；必须提供"本地记忆不出机"开关（默认尊重用户选择）
4. 离线归并作业原型：去重（近重复检测）→ 冲突消解（新规则取代旧规则，保留 superseded_by 链）
   → 生成候选经验 → 写候选池（不直接生效）
5. 写 D:\NX_AI\docs\P1-07_经验飞轮.md：描述 采集 → 归并 → 审核 → 灰度 → 回滚 的完整流程，
   以及为什么"自动写入必须可溯源可回滚"

验收标准：能用假数据跑通"3 条相似修正 → 归并成 1 条候选经验 → 带溯源"；编辑距离计算有测试。
```

### P1-08 桌面主控 UI 骨架

```text
【任务 P1-08】主控界面骨架（版本中心 + 任务中心）

要求：
1. D:\NX_AI\app\：Python 3.12 + tkinter（与现有 NxCamToolkit 技术栈一致，先不引入新框架）
2. 版本中心页：调用 P0-02 列出所有 NX 版本，显示能力位（是否有 run_journal、CLR 类型、是否支持 C# journal），
   提供"测试连接"按钮（跑一次 PING 之类的只读探测）
3. 任务中心页：任务列表（来自 P1-01 的 tasks.db，只读展示）、进度、日志查看、失败重试按钮
4. 设置页：NX 根目录手动指定、日志级别、离线模式开关、"本地记忆不出机"开关
5. 所有长操作必须在后台线程，界面不卡；异常弹窗必须给出可读原因与下一步建议
6. 不要求美观，要求结构清晰、能在没有 NX 的机器上启动（NX 相关功能全部延迟到点击时初始化）

验收标准：在不启动 NX 的情况下能启动并列出本机两个 NX 版本；杀掉 NX 相关依赖后界面仍可用。
```

---

## 4. 交接协议（Trae 与验收方之间的合同）

每张任务卡完成后，Trae 必须在 `D:\NX_AI\状态\<任务编号>.done.json` 写入：

```json
{
  "task": "P0-02",
  "status": "done",
  "files": ["D:\\NX_AI\\core\\nx_versions.ps1", "D:\\NX_AI\\tools\\list_nx.ps1"],
  "verify": "powershell -ExecutionPolicy Bypass -File D:\\NX_AI\\tools\\list_nx.ps1",
  "blocked": "",
  "notes": "注册表枚举用 HKLM\\SOFTWARE\\Siemens\\NX *，实测拿到 2212/2412 两个版本"
}
```

`status` 语义：`done`（完成，可验收）/ `partial`（部分完成，说明缺什么）/ `failed`（做不了，写清阻塞点）。
**没写这个文件 = 这一轮没结束**，投喂器不会发下一张卡。

---

## 5. 给 Trae 的上下文包（浓缩事实，可随卡附上）

```
本机实况（实测，非推测）：
- NX 版本：2212（E:\Program Files\Siemens\NX2212）、2412（E:\Program Files\Siemens\NX2412）
- 注册表：HKLM\SOFTWARE\Siemens\NX 2212 / NX 2412（INSTALLDIR、UGII_BASE_DIR、LICENSESERVER、LANGUAGE）
- NXOpen .NET：<NX>\NXBIN\managed\NXOpen.dll（2212.0.0.0 / 2412.0.0.0，两套独立程序集）
- 无内置 Python → 禁止 .py journal；用 C#/VB
- 无 VS/无 .NET SDK → 用 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe
- run_journal.exe：<NX>\NXBIN\run_journal.exe（2212 与 2412 都存在）
- 许可服务：Siemens PLM License Server 正在运行；SPLM_LICENSE_SERVER 已配置
- 现有工程：C:\NxCamToolkit（Python/tkinter）、C:\NX_Plugins\NxCamWizard、AppData\Local\NxCamToolkit\bridge
- 必须清理的残留：UGII_VENDOR_DIR / UGII_LOCAL_USER_DEFAULTS / UGII_USER_DIR（用户级）
- 新工程落点：D:\NX_AI\（全新，不污染旧目录）
```
