---
name: contract-check
description: >
  当 AI 准备开始任何代码改动前使用，用于判定本次改动是否触碰"契约面"
  （API / 数据模型 / 状态机 / 权限 / UI 规格 / 事件），并强制走"文档先行"流程：
  触碰契约面则先对齐 docs/modules/ 对应文档，缺口先补文档再动代码；
  仅内部实现则可直接进入实现。被 plan-feature / start-feature /
  backend-main / frontend-main / database-main 等核心开发 skill 在入口处前置调用。
  触发短语：开始开发、要改这个、动手前、契约检查、contract check、
  这算契约改动吗、要不要先改文档。
  不触发：纯阅读/探索任务、纯运维（部署、备份、故障排查）、
  纯文档撰写（用 docs-main）。
---

# contract-check 技能

## 定位

任何代码改动开始前的**第 0 步前置检查**。一句话：

> 这次改动出了我这个文件 / 模块，别人会不会察觉？

会被察觉的部分叫**契约面**，必须先对齐文档；不会被察觉的叫**内部实现**，可以直接动手。

## 何时调用

- `plan-feature` 完成需求摘要后、调用 `backend-main`/`frontend-main`/`database-main` 之前。
- `start-feature` 创建分支并准备进入开发前。
- `backend-main` / `frontend-main` / `database-main` 进入实现前的第一步。
- 用户直接说"开始改 XXX"而未经过 plan-feature 时，AI 主动先跑一次。

被调用过且本轮上下文未变化时，无需重复调用。

## 契约面定义

属于契约面（**改动必须先对齐文档**）：

| 类别 | 具体内容 | 对应文档 |
|------|---------|---------|
| API | HTTP 路径、方法、请求/响应字段名与结构、错误码 | `docs/modules/{module}/07-api.md` |
| 数据模型 | Prisma schema、表结构、字段含义、约束、索引、关系 | `docs/modules/{module}/06-data-model.md` |
| 状态机 | 状态枚举值、允许的状态转换、转换条件 | `docs/modules/{module}/04-state-machine.md` |
| 权限 | 角色、权限点、可见性规则、数据范围 | IAM 模块 + 各模块 PRD |
| UI 规格 | 页面结构、关键交互、用户可见文案/流程、导航 | `docs/modules/{module}/05-ui-interaction-spec.md` |
| 事件 | Temporal workflow signal、消息队列事件、跨模块通知 | 模块 PRD + workflow 文档 |

不属于契约面（**可直接动手**）：

- 私有函数 / service 内部方法的拆分、重命名、抽取
- 算法或实现替换（输入输出和副作用不变）
- 性能优化、查询调优、缓存策略调整
- 代码风格、注释、命名（不影响外部调用）
- 测试代码本身的重构

## 执行流程

### Step 1：列出本次改动的范围

基于用户需求或 PRD 摘要，列出预计会动到的：
- 文件 / 目录（path glob）
- 模块（对应 `docs/modules/` 哪一个）
- 改动性质（新增 / 修改 / 删除 / 重构）

### Step 2：契约面判定矩阵

对每一条改动，逐项过下面的判定问题，**任何一条命中"是"即触碰契约面**：

```
□ 会新增 / 删除 / 修改 HTTP 路径或方法吗？
□ 会改请求体 / 响应体的字段名、字段类型、嵌套结构吗？
□ 会引入新的错误码或改变现有错误码语义吗？
□ 会改 Prisma schema（字段、约束、关系、索引、enum）吗？
□ 会改某个业务对象的状态枚举或允许的状态转换吗？
□ 会新增 / 删除 / 调整角色或权限点吗？
□ 会新增 / 删除前端可达页面，或改导航结构吗？
□ 会改用户可见的关键交互流程或核心文案语义吗？
□ 会新增 / 修改 Temporal signal、workflow 入参、跨模块事件吗？
```

### Step 3：输出"契约面清单 + 文档对齐状态"

格式：

```
## 契约面识别结果

模块：{module}

### 触碰契约面的改动
1. [API] POST /api/xxx 新增字段 yyy
   - 文档：docs/modules/{module}/07-api.md → 已对齐 / 需补充 / 缺失
2. [Schema] 表 zzz 新增字段 aaa
   - 文档：docs/modules/{module}/06-data-model.md → 已对齐 / 需补充 / 缺失

### 仅内部实现的改动
- service 层拆分 XxxService.foo() → 不需要文档同步

### 文档缺口（必须先补）
- docs/modules/{module}/07-api.md 缺 POST /api/xxx 的字段 yyy 定义
```

### Step 4：根据对齐状态决策

- **全部"已对齐"** → 通过，进入实现阶段。
- **有"需补充" / "缺失"** → 停止，先调用 `docs-main` 补文档，与用户确认后再继续。
- **判定不确定** → 当作触碰契约面处理，先读文档；仍不确定则向用户澄清。

## 与其他 skill 的衔接

- 上游：`plan-feature`（拿到需求摘要后调用本 skill）。
- 下游：
  - 触碰契约面 + 文档有缺口 → `docs-main`
  - 触碰契约面 + 文档已对齐 → `backend-main` / `frontend-main` / `database-main`
  - 仅内部实现 → 直接进入对应开发 skill

## 反模式

- ❌ 跳过契约面判定，直接动代码，事后再补文档（事后必忘）。
- ❌ 用"小改一下"为由绕过判定。判定本身只需 30 秒，绕过的代价可能是后端前端不一致的 bug。
- ❌ 判定结果只在脑子里过一遍，不显式输出"契约面清单"——人看不到就无法挑战。
- ❌ 把"补充文档"留到 PR 里再做。PR 阶段补文档容易和代码不一致。

## References

- [`docs/standards/12-five-meta-rules.md`](../../../docs/standards/12-five-meta-rules.md) —— 5 条元根因规则。**规则 1（契约面唯一真相源 + 派生位多点钉死 + 自动校验）** 是本 skill 的元约束来源。
- [`docs/standards/11-troubleshooting-methodology.md`](../../../docs/standards/11-troubleshooting-methodology.md) —— 契约面漂移引发的事故按方法论 6 段复盘。
