# AGENTS.md

面向后续 AI 编码助手。让新会话快速理解项目现状、稳定架构、不可破坏的原则、排查入口。

---

## 1. 项目现状

**NavisworksTransport** — Autodesk Navisworks Manage 2026 物流路径规划与动画仿真插件。

核心能力：物流属性分类 · Ground/Hoisting/Rail 三类路径 · 虚拟/真实物体 · 终端安装仿真 · ClashDetective 碰撞检测 · 路径/检测数据存储。

---

## 2. 技术栈与构建

- .NET Framework 4.8 · C# 7.3 · x64 · WPF + DockPane · MSTest

### 构建流水线（必须串行，不可并行）

```bash
./build-and-deploy.bat   # 编译+部署（推荐）
```

如需单独操作：
```bash
./compile.bat            # 仅编译
./deploy-plugin.bat      # 仅部署（编译通过后）
```

**严禁**：加 `cmd.exe /c` 前缀、直接调 MSBuild、拆 PowerShell 逻辑、改 `powershell` 为 `pwsh`。

### 并行边界

| 允许并行（纯读取） | 禁止并行（产出/锁文件） |
|---|---|
| rg, ls, Get-Content, 读日志 | build-and-deploy, compile, deploy, run-unit-tests, 启动 NW |

`run-unit-tests → build-and-deploy` 是单通道流水线，不可拆分并行。

### 路径

- 插件部署：`C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\`
- 日志：`...\plugins\TransportPlugin\logs\debug.log`
- Navisworks 2026 API DLL（vendor 到仓库）：`libs\navisworks-2026\`（含 Api/Timeliner/Clash/Controls/ComApi/Interop.ComApi + XML 文档）

> **不可破坏原则**：Navisworks DLL 引用必须走 `libs\navisworks-2026\` 相对路径，**禁止**改回 `C:\Program Files\Autodesk\Navisworks Manage 2026\...` 绝对引用（换机器/CI 会挂）。部署脚本中的安装路径（deploy-body.ps1）是部署目标，不是 DLL 引用，不受此限。

---

## 3. 目录与关键文件

| 目录 | 职责 |
|---|---|
| `src/Core/` | 插件入口、路径管理、动画、碰撞、渲染、配置 |
| `src/UI/WPF/` | 视图、ViewModel |
| `src/Utils/` | 单位、几何、坐标、变换、日志 |
| `src/PathPlanning/` | 网格、A*、路径几何 |
| `UnitTests/` | 回归测试 |

**高风险区域**（改动需先补测试）：`src/Core/Animation` · `src/Utils/CoordinateSystem` · `src/UI/WPF/ViewModels`

---

## 4. 核心架构规则

### 4.1 坐标系三层语义

只用三种说法，禁止「本地坐标系」：

- **宿主坐标系** — NW 文档坐标系（YUp 或 ZUp），UI/日志/拾取均以此为基准
- **内部坐标系 (Canonical Space)** — 固定 ZUp，纯数学计算在此完成
- **资产坐标系** — 插件资源专属（unit_cube.nwc, unit_cylinder.nwc）

### 4.2 命名规则

变量/字段/日志中的方向语义必须带坐标系前缀：

- 前缀：`Host` / `Canonical` / `Asset` / `Local`（仅对象自身局部轴）
- 禁止无前缀的 `PositiveX` / `upAxis` / `forwardAxis` 等

### 4.3 对象局部轴业务映射

不是第四套坐标系，而是业务解释层：把对象哪根局部轴解释为 forward/up/side。

- 真实物体：**不要依赖 `ModelItem.Transform`**（Revit 导入件多为单位旋转），优先通过 fragment 代表姿态 + Fragment默认Up 解释
- 虚拟物体：对象局部轴业务映射来自资产轴约定

### 4.4 Quaternion 固定定义（不可再质疑）

```csharp
// Rotation3D 参数顺序固定为 x, y, z, w
var rotation = new Rotation3D(qx, qy, qz, qw);
// A=x, B=y, C=z, D=w
```

禁止写成 `new Rotation3D(qw, qx, qy, qz)`。姿态问题不要再归因到「四元数顺序可能不对」。

### 4.5 真实物体 vs 虚拟物体

| | 真实物体 | 虚拟物体 |
|---|---|---|
| 坐标系 | 无独立资产坐标系，生活在宿主坐标系 | 有资产坐标系 |
| 角度调整 X/Y/Z | 按宿主坐标系 | 按资产轴约定 |
| 资源要求 | — | unit_cube.nwc 几何中心在原点 |
| 姿态来源 | fragment 代表姿态 | 资产轴约定 |

### 4.6 路径姿态链

- **Ground/Hoisting**：走平面姿态链，已禁止退回旧 yaw。起点/逐帧/终点/通行空间共享同一套尺寸语义。业务跟踪点 = 原始包围盒中心。
- **Rail**：并入 `canonical → rail pose` 链，不能在宿主空间随意补旋转。Rail 0° 基线不可被角度修正污染。

### 4.7 通行空间

必须和起点落位/逐帧位置/终点诊断共用同一套尺寸语义。典型症状：「通行空间正确但物体陷入地面」「YUp 下 Y/Z 互换」。

---

## 5. 开发原则

1. **彻底禁止 fallback**（第一原则）— 新链失败时暴露错误，不许静默退回旧链/yaw/hardcoded Z-up/默认值
2. **不向后兼容** — 只针对 NW 2026
3. **临时补丁必须清理** — 定位问题的临时代码，确认不是根因后必须删除
4. **优先复用现有工具** — `UnitsConverter`, `GeometryHelper`, `LogManager`, `HostCoordinateAdapter`, `Canonical*`, `ModelItemTransformHelper`, `RailPathPoseHelper`
5. **测试优先于猜测** — 几何/旋转/坐标问题按：看日志 → 补日志 → 补单测 → 改代码

---

## 6. 单位原则

### 6.1 三层单位语义（禁止混用）

| 场景 | 单位 | 说明 |
|---|---|---|
| 模型坐标/包围盒/路径点/几何 | **模型单位** | 取决于当前 NW 文档单位，**绝不等同于米**（如 Floor2 模型是英尺，1米=3.281模型单位） |
| UI 显示/外部交互/日志长度 | **米** | 通过 `UnitsConverter.ConvertToMeters()` / `ConvertFromMeters()` 在边界转换 |
| 配置项 | 米 | config.toml 中物体尺寸/安全间隙等均以米存储 |

### 6.2 命名规则

- 米单位变量/字段/参数以 `InMeters` 结尾（如 `objectHeightInMeters`、`safetyMarginInMeters`）
- 模型单位变量不加后缀
- 禁止把模型坐标直接当米使用；同一变量内禁止混用两种单位

### 6.3 转换入口

- `UnitsConverter.GetMetersToUnitsConversionFactor(units)` — 当前文档 米→模型单位 因子（英尺=3.281，毫米=1000，米=1）
- `UnitsConverter.ConvertToMeters(modelUnits)` / `ConvertFromMeters(meters)`
- 注意：`PathRoute.TotalLength` 等长度属性返回**米**（内部已从模型单位换算），不要再二次换算

### 6.4 测试警示

- 集成测试断言长度/尺寸时，期望值必须按当前文档单位因子换算（服务端应返回因子，如 import-route-file 的 `metersToModelUnits`），**禁止假设模型单位=米**
- 单元测试进程无 NW 文档，无法做单位换算；涉及单位换算的断言必须放集成测试

典型症状：「预期 12 米实际 3.7 米」（英尺模型）、「虚拟物体尺寸偏大 3.28 倍」。

---

## 7. 排查指引

| 问题 | 优先检查 |
|---|---|
| 虚拟物体固定偏差 | 部署目录 unit_cube.nwc → BoundingBox.Center 是否为 (0,0,0) → 起点代码 |
| 真实物体旋转轴不对 | 目标姿态算错 or NW 应用姿态错，看 `[动画姿态入口]` / `[模型增量姿态]` |
| 吊装路径不显示 | 渲染链退化段/零长度段 |
| 路径越走越偏 | 是否把实时 BoundingBox.Center 误当业务跟踪点 |
| 设为终点后列表空 | UIStateManager 队列消费 |
| 长度/尺寸偏差约 3.28 倍 | 是否把模型单位(英尺)当米用，未走 UnitsConverter（见 §6 单位原则） |

---

## 8. 推荐阅读

1. 本文件
2. `doc/working/current-engineering-state.md`
3. `doc/design/2026/coordinate-system-canonical-space-design.md`
4. `doc/design/2026/NavisworksAPI使用方法.md`
5. `.agents/skills/geometry-transform/SKILL.md`（几何/变换/姿态/坐标）
6. `.agents/skills/nw-api/SKILL.md`

---

## 9. 工具使用提示

### Shell 命令统一规范

pi 的 bash 工具使用 Git Bash（settings.json 的 `shellPath` 已配置为 `C:\Program Files\Git\bin\bash.exe`），Git Bash 原生支持 UTF-8，中文输出无乱码。

- **rg / fd / 读日志 / ls 等搜索读取命令**：直接用 bash 执行（Unix 工具天然适合 bash）：

```
rg -n '关键字' src/
```

- **Windows 批处理脚本（.bat）与部署/编译/测试流水线**：通过 `pwsh` 执行（沿用既有构建脚本约定）：

```
pwsh -NoProfile -Command "./build-and-deploy.bat"
```

> 历史背景：早期默认 shell 有 UTF-8 乱码问题才统一用 pwsh；已配置 Git Bash 后不再需要。

### edit 工具的正确格式

```json
{
  "path": "src/.../File.cs",
  "edits": [
    { "oldText": "原文本（必须完全匹配）", "newText": "新文本" }
  ]
}
```

- `path` 是顶层字段，不在 `edits` 数组内
- `oldText` 不能有歧义（匹配多个时提供更多上下文）
- 多个不重叠的编辑可以放在同一个 `edits` 数组中
