﻿P10-07F 刀具库部件：一次建好 20 把刀，用复制粘贴带入任意零件

## 用户想法（2026-10-20 15:30）
「是不是可以把所有刀具一次做好，也用复制的方式。这样可行吗？」
→ 可行，且优于逐个建：做一个"刀具库 .prt"，用户 Ctrl+C / Ctrl+V 一次性带入目标零件。

## 一、要建的刀具（20 把，T1–T20 唯一）
| T号 | 名称 | 类型 | φ | 刃长 | 刃数 | 用途 |
|---|---|---|---|---|---|---|
| T1 | D20 平底 | mill | 20 | 45 | 4 | 大余量开粗主力 |
| T2 | D16 平底 | mill | 16 | 40 | 4 | 次开粗 |
| T3 | D12 平底 | mill | 12 | 30 | 4 | 通用粗/半精 |
| T4 | D10 平底 | mill | 10 | 25 | 4 | 中腔 |
| T5 | D8 平底 | mill | 8 | 20 | 4 | 精加工主力 |
| T6 | D6 平底 | mill | 6 | 18 | 4 | 小腔/清角 |
| T7 | D4 平底 | mill | 4 | 12 | 4 | 窄槽 |
| T8 | D3 平底 | mill | 3 | 8 | 4 | 细部 |
| T9 | R6 球刀 | ball | 12(R6) | 30 | 2 | 曲面 |
| T10 | R4 球刀 | ball | 8(R4) | 24 | 2 | 小曲面 |
| T11 | R3 球刀 | ball | 6(R3) | 18 | 2 | 清根 |
| T12 | R2 球刀 | ball | 4(R2) | 12 | 2 | 细清根 |
| T13 | 倒角刀 | chamfer | 10 | 15 | 4 | 沿边倒角 |
| T14 | 中心钻 φ3 | spot | 3 | 8 | 2 | 定心 |
| T15 | 钻头 φ3.3 | drill | 3.3 | 20 | 2 | M4 底孔 |
| T16 | 钻头 φ5.5 | drill | 5.5 | 25 | 2 | M6 底孔 |
| T17 | 钻头 φ6.8 | drill | 6.8 | 30 | 2 | M8 底孔 |
| T18 | 钻头 φ8.5 | drill | 8.5 | 35 | 2 | M10 底孔 |
| T19 | 丝锥 M8 | tap | 8 | 20 | — | 攻牙 |
| T20 | 螺纹铣刀 | thread | 10 | 25 | — | 铣螺纹 |

每把刀必须带：
```
holder 引用 BT40-ER32（参与干涉检查）
最小刀长（MoL）= 刃长 + 10mm
刀号 T 与补偿号 H 一致（T1/H1 … T20/H20）
```

## 二、交付
1. `tools\make_tool_lib.py`（journal）：一次建完 20 把刀并 SaveAs
   `D:\NX_AI\nx_templates\NXAI_刀具库.prt`
2. `tools\tool_lib_check.py --check`：独立进程打开该 .prt，读回：
   刀具数、T 号唯一性（1–20）、每把的 φ/刃长/刃数、是否引用 holder
3. 文档 `docs\17_刀具库使用说明.md`：三步"复制刀具到零件"图文
4. 更新 `data\std\tools.json`：与库内 20 把一致（不改既有键值的 id 可保留）

## 三、使用方式（写进文档）
```
① NX 打开 NXAI_刀具库.prt
② 机床视图 → 全选刀具（Ctrl+A）→ Ctrl+C
③ 打开目标零件 → 机床视图 → Ctrl+V
④ 全部 20 把刀一次到位，刀号/补偿/holder 都带过来
```

## 四、验收（实测）
1. 贴出 `tool_lib_check.py --check` 输出：20 把、T 号 1–20 唯一、无 T0
2. 贴出每把刀的 φ/刃长/刃数（表格）
3. 证明 holder 被引用（读回 holder 名称）
4. 证明 .prt 可独立打开（journal 读回 tool count=20）
5. `docs\17_刀具库使用说明.md` 存在且含三步
6. 门禁全绿 + 新增 .py 含 `P2-02 控制台编码护栏`

## 约束
- 不改 NX 官方文件；库文件放 D:\NX_AI\nx_templates
- 不改已有 tools.json 的既有条目数值（只补/对齐）
- 完成后写 `状态\P10-07F.done.json`

## 追加：必须修掉面铣/侧面的进刀（P10-07C 未完成项）
P10-07C 交卡时实测：
```
TPL_FACE  进刀=linear（直线进刀，RampAngle=0）  状态=params_only   ← 不达标
TPL_SIDE  进刀=linear（直线进刀，RampAngle=0）  状态=params_only   ← 不达标
TPL_POCKET_R/S/F 进刀=helical_clw ✅ 状态=verified
```
用户明确要求："铣刀进刀，非切削移动里的进刀方式改成螺旋进刀。"

### 要做的
1. 在 `gen_templates.py` 里为 FACE / SIDE 显式设置
   `非切削移动 → 进刀 → 类型 = Helical（螺旋）`，参数：
   螺旋直径 0.6D、螺旋角 2°、最小斜面长度 25%D
2. **必须真正写入 .prt**（不是只写配置 json）：重新生成模板后，
   用独立进程 `cam_verify_saved.py` 读回这两道工序的 engage 类型，证据写
   `状态\engage_read.json`（要求 FACE/SIDE 出现 helical 字样）
3. 状态从 `params_only` 提升为 `verified`（即 .prt 里可读回）
4. 若确实无法对 FACE/SIDE 设螺旋（例如 NX 对 PLANAR 类不支持 Helical），
   **必须**在模板定义里加显式例外标记并说明原因：
   `engage_linear_reason="planar_no_helical_support"`
   且 `template_check --list` 输出要显示该例外标记（不许静默用直线）
5. 验收：`template_check --check TPL_FACE` 输出 `进刀=helical...` 或
   带 `例外：planar_no_helical_support` 的 linear，二者其一，否则判失败

## 硬性修正（用户 2026-10-20 16:45，覆盖上文所有"例外"条款）
**用户原话：「必须采用螺旋进刀。」**

### 规则（不允许任何例外）
- 所有铣类模板（TPL_FACE / TPL_SIDE / TPL_POCKET_R / TPL_POCKET_S / TPL_POCKET_F /
  TPL_ZLEVEL / TPL_HOLEMILL / TPL_SURFACE）的**进刀方式必须是 Helical（螺旋）**。
- 之前写的"面铣/侧面可从外部下刀用直线"的例外条款**作废**，不许再引用。
- `engage_linear_reason` 这个例外字段**删除**，不许用它绕过。

### 如果某工序类型不支持 Helical（例如 PLANAR_MILL / FACE_MILLING）
**不许**退化成 linear，正确做法是**换工种**：
```
平面铣(FACE/PLANAR) 不支持 Helical
  → 改用 CAVITY_MILL（型腔铣）处理同一平面区域，它支持螺旋进刀
  → 或用 ZLEVEL_PROFILE（深度轮廓）按 Z 层走
```
即：**为了满足"必须螺旋"，允许调整工序类型，不允许放弃螺旋。**

### 校验（判定标准，达不到即失败）
```
template_check --check <TPL>：
  从 .prt 读回 engage 类型
  出现 helical 字样 → 通过
  出现 linear/ramp/arc 且无螺旋 → 失败，exit 非 0，并打印实际读到的类型
```
`--check all` 必须**8 个铣类模板全部 helical**，否则 exit 非 0。

### 验收
1. `template_check --check all` → 8 个铣类模板逐个打印 `进刀=helical...`，exit=0
2. 独立进程读回 .prt 的实际 engage 类型（贴原文，不许只看配置）
3. 若某个模板因换工种导致参数变化（如 ap/ae），说明变化原因
