---
name: docs-main
description: >
  当用户要求创建模块文档、补齐缺失文档、检查文档一致性、
  或更新 PRD/API/数据模型/状态机/UI 规格等模块级文档时使用。
  触发短语：写文档、补文档、更新文档、文档检查、新建模块文档、文档对齐、
  文档一致性、update docs、check docs、create module docs。
---

# 文档主技能

## 定位

帮助 AI 按正确的依赖顺序创建和维护模块文档（`docs/modules/{module}/`）。
本 skill 是文档工作流指南，不是文档事实源；事实源始终在 `docs/` 中。

## 核心规则

1. **先读再写** — 修改任何文档前，先读该文档及其上游依赖
2. **用模板** — 从 `references/` 选模板，禁止凭记忆手写结构
3. **单一事实源** — 一个事实只定义在一处，其他地方用链接引用
4. **冲突即停** — 文档与代码不一致时，报告差异并等待用户决策，不得自行选择一方
5. **按依赖顺序** — PRD → User Journey → Architecture → State Machine → UI Spec → Data Model → API → Error Codes → Test Scenarios → E2E Spec

## 工作流

### 0. Recon — 项目惯例侦察（写新模块文档前必做，~10 分钟）

> ⚠️ **跳过这一步是踩坑大头**：凭记忆写权限码格式、schema 文件名、装饰器用法、错误页路由——大概率全错。所有"项目惯例类"🔴 真坑都不是"再看一眼文档"找出来的，而是 grep 出来的。详见 `.learnings/2026-04-30-doc-review-multi-lens.md`。

新模块 / 大改文档前，用 grep / ls 从代码里捞**项目惯例**，**不靠记忆**。最少跑这 8 项：

| 侦察项 | 命令 | 防的坑 |
|---|---|---|
| 权限码格式 | `grep -rn "@RequirePermissions" backend/src/**/*.controller.ts \| head` | 单段 vs 多段冒号 |
| 审计装饰器 | `ls backend/src/**/audit/decorators/ && grep -rn "@Auditable\|@Sensitive" backend/src \| head` | 用装饰器 vs 手写 service 调用 |
| Schema 文件命名 | `ls backend/prisma/schema/` | 域前缀（`platform_*` / `corp_*` / `mfg_*` / `robot_*`），全 snake_case |
| env 变量复用 | `grep -E "AZURE_\|GRAPH\|<相关前缀>" .env.example backend/src/**/*.service.ts` | 重复定义 / 命名冲突 |
| 同类模块代码 | `cat backend/src/modules/{相邻模块}/*.service.ts` | 直接 mirror 已有结构（如 entra/sharepoint 已用 MsalClient） |
| 前端状态库 | `grep -E '"@tanstack/react-query"\|"swr"' frontend/package.json` | 文档里写错技术栈 |
| 错误页 / 通用组件 | `find frontend/src -iname '403*' -o -iname 'NoAccess*' -o -iname 'Forbidden*'` | 假设有 `/403` 页面但实际不存在 |
| 同类 PRD 风格 | `cat docs/modules/{相邻模块}/01-prd.md` | 文档结构 / 字段命名风格漂移 |

**输出**：把侦察结果写入即将创建的文档（如 `01-prd.md` 引用具体的现有装饰器名、schema 文件命名规则等），让事实写进文档而非靠记忆维护。

### 1. 读 — 建立认知

- 读目标模块 `docs/modules/{module}/README.md`
- 按依赖顺序读上游文档，识别缺失项和过期项
- 如需了解文档体系全貌，读 `docs/standards/06-documentation-system.md`

### 2. 写 — 选模板、逐项补齐

- 从模板索引中选择对应模板
- 按依赖顺序逐项补齐；一次只改一个文档，避免多文档同时处于未完成状态
- 需求改动时，先在 `docs/modules/{module}/` 落地变更，再进入代码实现

### 3. 验 — 一致性检查（必须执行，不可跳过）

改完文档后，必须按以下清单逐项扫描。这是防止"改了一个文档但其他文档残留旧口径"的关键步骤。

> 📌 **本节聚焦"对不对"（一致性 / drift）**。如果场景是"新模块 / 大改一组文档完整产出"，**额外**跑 `doc-review` skill 的 4-lens 框架做"够不够"（实现就绪度）审查——两者正交不可替代。

#### 3.0 三条 meta-rule（先理解这个，再看后面的具体 cell）

1. **Ground truth 是运行时，不是源码**
   检查角色权限、多对多关系、API shape 等动态内容时，以**实际 DB 查询结果 / `/users/me` / curl 响应**为准，**不以 seed 文件或 interface 源码为准**。经典陷阱：seed 用 `upsert` 不会清除旧关系，DB 会漂移。详见 `.learnings/2026-04-14-seed-upsert-drift.md`。

2. **静态检查和动态检查必须都跑一次**
   - 只跑静态（grep / cat）→ 抓不到代码 vs 数据库漂移，抓不到 API shape 错误
   - 只跑动态（curl / query）→ 抓不到文档内部自洽问题、死链、术语漂移
   - **两者正交，不可替代**。经验数据：v2 重构 review 里，静态层找到 ~42 处 grooming 问题，动态层找到 1 个真 bug + 4 处契约不准，都是对方抓不到的。

3. **换角度 > 加轮次**
   同一个角度跑两次信号增量 ≈ 0。如果时间紧张，优先保证每个角度跑**一次**，而不是某个角度跑两次。

#### 3.1 五 cell review 矩阵（按规模选深度）

|  | **方向 A：Doc → Reality** | **方向 B：Reality → Doc** |
|---|---|---|
| **Hygiene 层**（文档内部 / 元数据）| Cell ① 链接 + frontmatter + 数字 + 术语 | — |
| **静态层**（源码 / schema / DTO）| Cell ② doc claim → grep 代码存在 | Cell ③ enumerate 代码 → 反查 doc 有无 |
| **运行时层**（DB / API）| Cell ④ doc 示例 → curl 实打 shape | Cell ⑤ 实际 DB/API 状态 → 对比 seed/doc 是否一致 🔴 |

🔴 = 最抓真 bug 的 cell（Pass-4 seed drift 就是这里抓到的）

#### 3.2 规模 → cell 选择

| 改动规模 | 必跑 cell |
|---|---|
| 单字段 tweak | ① + ② |
| 单文档大改 / 新增端点 | ①②③ + ④ |
| 模块级重构 / 新功能上线 | **全 5 个 cell** |

时间紧张砍 cell 的顺序：**先砍贵的动态 cell（④⑤）时不要两个都砍**。至少保留 ⑤ —— 它抓真 bug。

#### 3.3 每个 cell 的具体做法

**Cell ① — Hygiene（最便宜，30 秒可脚本化）**
- 所有内部 markdown 链接文件存在：`rg -o '\]\([^)]*\.md[^)]*\)' *.md`
- frontmatter 完整：`module / doc_type / status / owner / upstream_docs / last_verified`，`status != Draft`，`last_verified` 是最近日期
- 数量断言可 grep 验证："5 个角色"/"46 条字典"/"13 权限"/"N 张表"等
- 章节顺序合理（例如 changelog 时间倒序，不是乱序）
- 术语命名自洽：字段名遵循代码规范（camelCase 或 snake_case），不混用
- 跨文档 cross-reference 指向的章节确实存在（"详见 §X" → 确认 §X 写了那件事）
- 过期措辞：搜索"待实现"/"尚未"/"即将"，确认不是已完成但忘更新的

**Cell ② — 静态正向：Doc → Code grep（5 分钟）**
- 按 doc 描述的字段/端点/类型，grep 代码确认存在
- 例：doc 说 `modelId: UUID`，`grep modelId backend/prisma/schema/`
- 例：doc 说 `PUT /:id/identity`，`grep "@Put.*identity" backend/src/modules/.../*.controller.ts`
- 例：doc 说权限码 `robot-manager:write:sales`，`grep seed` 确认存在
- 过期 doc claim = 找到 doc 说了但代码没有的字段/端点 → 删文档或补代码

**Cell ③ — 静态反向：Code → Doc enumerate（15 分钟，抓遗漏）**
- 列出 code 完整集合：所有 controller 路由 / DTO 字段 / permission code / enum 值 / *Code 字段 / service public method
- 对每一项反查 doc 有无对应描述
- 发现 code 有但 doc 未提 → 文档缺漏，补
- 工具：`grep -oE "@(Get|Post|Put|Delete)\([^)]*\)" controller.ts` 枚举路由

**Cell ④ — 动态正向：Doc 示例 → curl 实打（需要运行时，15 分钟）**
- 对 07-api.md 每个响应示例，用 curl 实打并对比：shape、字段名、甚至**数值**
- 对每个状态转换在真实 API 上触发一次，验证副作用表准确
- Decimal 字段序列化是 string 还是 number，doc 有没有明说
- 报错响应体 shape 匹配 doc

**Cell ⑤ — 动态反向：实际状态 → 对比源码/文档（需要运行时 + 多角色账号）🔴**
- 实际 DB/API 状态作为 ground truth，反查 seed 源码和 doc 是否一致
- **角色权限**：调 `/users/me` 枚举每个角色的 robot-manager 权限集合，对比 seed `permissionKeys`。不一致 = seed drift bug
- **权限矩阵实测**：非 admin 用户调每个端点，HTTP 码与 PRD 矩阵逐一对比
- **审计覆盖**：PRD 声明需审计的关键字段，对应端点有无 `@Auditable()`
- **前端类型 vs 后端真实响应**：diff 实际返回字段名与前端 interface
- **硬编码值**：`organizationId` / enum 默认值 / FFSN 规则等，实际运行时值与 doc 声明一致

#### 3.4 跨文档一致性扫描（每次修改后必做）

这是 cell ① 和 cell ② 的具体落地场景：

**删除实体/功能后**：grep 扫描模块所有文档，确认已删除实体的名称、字段、接口路径、错误码零残留。包括字段表、Prisma 代码段、ER 图、示例 JSON、接口索引、测试场景、E2E 步骤。

**修改字段名/类型后**：扫描所有文档中旧字段名的引用，包括：
- 06 字段表 ↔ 06 Prisma 代码段（同一文档内上下段必须一致）
- 07 实体定义 ↔ 07 请求/响应体 ↔ 07 示例 JSON
- 09 总览行 ↔ 09 P0 详情（接口路径、字段名、错误码必须完全一致）
- 10 流程头（角色/前置/输出）↔ 10 步骤表格

**修改 HTTP 状态码/错误码后**：同步更新 04 守卫条件错误列、08 错误码表、09 测试场景期望输出、后端 error-codes.ts 常量。

**修改术语后**：全文搜索旧术语，确认零残留。常见漂移术语：角色"主管/上级" → 统一为"经理"；操作"校准分数" → "校准等级"。

#### 3.5 事实源优先级（冲突判定）

当文档间或文档与代码冲突时，按以下顺序判定事实源：

1. **运行时数据库 / API 响应**（实际查询）— 检查角色权限、多对多关系、API shape 时最高优先级
2. **Prisma schema** > 06-data-model > 其他文档
3. **后端 DTO / Controller** > 07-api > 09/10
4. **实际 API round-trip** > 07-api 示例 > 其他文档
5. **04-state-machine** > 其他文档（状态枚举）
6. **08-error-codes + error-codes.ts** > 04/09（错误码）
7. **01-prd** > 其他文档（业务规则）

> ⚠️ **经典陷阱**：当 seed 用 `upsert` 维护多对多关联（role × permission 等），`upsert` 只保证"存在"不保证"只存在这些"。老关系会永久残留。review 必须用运行时 query 作为 ground truth。详见 `.learnings/2026-04-14-seed-upsert-drift.md`。

## 模板索引

| 编号 | 文档类型 | 模板路径 |
|------|---------|---------|
| 00 | 模块 README | `references/00-module-readme-template.md` |
| 01 | PRD | `references/01-prd-template.md` |
| 02 | 用户旅程 | `references/02-user-journey-template.md` |
| 03 | 架构 | `references/03-architecture-template.md` |
| 04 | 状态机 | `references/04-state-machine-template.md` |
| 05 | UI 交互规格 | `references/05-ui-interaction-spec-template.md` |
| 06 | 数据模型 | `references/06-data-model-template.md` |
| 07 | API | `references/07-api-template.md` |
| 08 | 错误码 | `references/08-error-codes-template.md` |
| 09 | 测试场景 | `references/09-test-scenarios-template.md` |
| 10 | E2E 测试编排 | `references/10-e2e-test-spec-template.md` |

### 低频/可选模板

| 文档类型 | 模板路径 |
|---------|---------|
| ADR（架构决策记录） | `references/adr-template.md` |

## 输出要求

- **新建文档**：输出基于模板填充的完整文档内容
- **检查一致性**：输出差异表格（文档位置 / 当前值 / 期望值 / 建议动作）
- **补齐文档**：列出补齐项清单，逐项完成后标记完成状态
