Imported from 0xEdenY/eden-claude-skills (
change-guard/SKILL.md). Install upstream withnpx skills add 0xEdenY/eden-claude-skills --skill change-guard. Copyright stays with the author.
变更守卫 Skill
AI 编程最大的隐患不是写错一行代码,而是改了 A 忘了改 B、C、D。项目越大,这种"牵一发动全身"的问题越严重。本 Skill 提供四个工作流来系统性地解决这个问题。
四个工作流
| 工作流 | 什么时候用 | 做什么 |
|---|---|---|
| 变更前:影响分析 | 开始改代码之前 | 分析这次变更会影响哪些文件和模块 |
| 变更后:完整性检查 | 改完代码、commit 之前 | 检查是否遗漏了关联更新 |
| 出问题:系统性排查 | 代码出了 bug | 从症状出发,系统性定位根因 |
| 定期:文档同步 | 每完成 3-5 个 Task 或每轮迭代后 | 确保 docs/ 目录和代码一致 |
工作流 1:变更前 — 影响分析(对话式)
什么时候用: 在让 AI 开始改代码之前,先搞清楚这次改动的"爆炸半径"。
核心原则: 改代码之前先画地图,不要一头扎进去。
对话引导规则: 用户说"我要改 XXX"时,不要直接开始改。通过 2-4 轮提问收敛变更范围:
-
明确意图(1轮)
- "你想达到什么效果?改完之后用户/系统的行为会怎么变?"
- 给出选项帮用户聚焦:这是修 bug、改行为、加功能、还是重构?
-
确认范围(1-2轮)
- 读取相关代码后,列出你认为需要改的文件,问用户:"我的理解对吗?还有什么我没想到的?"
- 如果变更涉及接口变化(API、类型、数据模型),追问:"这个接口的调用方有哪些?前端也需要改吗?"
-
产出影响清单(1轮)
- 输出结构化影响清单,让用户确认后再动手
影响清单格式:
## 影响分析:[变更描述]
### 直接修改
- [ ] [文件1]:[改什么]
- [ ] [文件2]:[改什么]
### 关联修改(必须跟着改)
- [ ] [文件3]:因为 [文件1] 的 [XX] 变了,这里的 [YY] 也要更新
- [ ] [文件4]:...
### 可能受影响(需要验证)
- [ ] [文件5]:[为什么可能受影响]
### 需要更新的测试
- [ ] [测试文件1]:[原因]
### 需要更新的文档
- [ ] [文档1]:[原因]
影响清单持久化:
- 简单变更(1-3 文件):留在对话中
- 复杂变更(4+ 文件或跨模块):写入
docs/impact-{描述}.md,跨 session 可读 - 项目结束后批量清理
docs/impact-*.md
用户确认后,再按清单逐项修改。
常见的影响链(AI 经常漏掉的):
改了后端 API 返回格式
→ 前端 API 调用处的类型定义
→ 前端处理响应的逻辑
→ 前端显示数据的组件
→ API 测试的断言
→ API 文档(如果有的话)
改了数据库表结构
→ 迁移文件(⚠️ 见下方数据模型变更检查清单)
→ ORM 模型/类型定义
→ Repository/DAO 层查询
→ 服务层使用该数据的逻辑
→ 前端表单字段(如果有对应输入)
→ 种子数据/测试 fixtures
数据模型变更额外检查:
→ 新列:默认值合理吗?NOT NULL 列现有行怎么填?
→ 删列/改列:数据丢失风险?需要先备份或迁移数据吗?
→ 约束:该加 unique/FK 吗?FK 是 CASCADE 还是 RESTRICT?
→ 索引:新查询需要建索引吗?改了列名现有索引还有效吗?
→ 迁移安全:迁移可回滚吗?有 down migration 吗?
→ 数据量:大表操作会锁表吗?需要分批迁移吗?
改了共享类型定义(如 TypeScript interface)
→ 所有 import 该类型的文件
→ 所有使用该类型的函数签名
→ 所有相关测试
改了认证/授权逻辑
→ 所有受保护的路由
→ 前端的登录/权限判断
→ 测试中的认证 mock
→ API 文档中的认证说明
改了环境变量
→ .env.example
→ 部署配置(Docker/CI/CD)
→ 文档中的部署说明
→ 代码中读取该变量的所有位置
工作流 2:变更后 — 完整性检查
什么时候用: 代码改完了,commit 之前。
核心原则: 不要相信 AI 的"我已经完成了"——用清单逐项验证。
通用检查清单:
## 变更完整性检查
### 类型一致性
- [ ] 改了类型定义后,所有引用处都更新了吗?
- [ ] 函数签名变了,所有调用处的参数都更新了吗?
- [ ] API 返回值变了,前端处理逻辑跟着更新了吗?
### 数据一致性
- [ ] 改了数据模型后,迁移文件写了吗?
- [ ] 数据库约束(NOT NULL、FK 等)和代码逻辑一致吗?
- [ ] 新加的 NOT NULL 列有合理的默认值吗?现有数据不会因为缺值而导致迁移失败吗?
- [ ] 迁移可回滚吗?(有 down migration 或者知道怎么手动回滚)
- [ ] 需要建索引的查询场景覆盖了吗?
- [ ] 种子数据/测试 fixtures 还能正常工作吗?
### 前后端一致性
- [ ] 后端 API 变更后,前端的 API 调用更新了吗?
- [ ] 后端返回的数据结构变了,前端的类型定义更新了吗?
- [ ] 新增/删除的 API 字段,前端表单和展示都处理了吗?
- [ ] 错误码或错误格式变了,前端的错误处理更新了吗?
### 测试完整性
- [ ] 新增/修改的功能有对应的测试吗?
- [ ] 现有测试跑通了吗?
- [ ] 改了业务逻辑的测试断言还正确吗?
### 配置和环境
- [ ] 新增了环境变量?.env.example 更新了吗?
- [ ] 新增了依赖?package.json / requirements.txt 更新了吗?
- [ ] 部署配置需要改吗?
### 错误处理
- [ ] 新代码的错误路径处理了吗?
- [ ] 没有空 catch/except 块吗?
- [ ] 外部调用有超时和错误处理吗?
简化版(小改动用这个):
改完代码后,请回答这 6 个问题:
1. 你改了哪些文件?
2. 有没有其他文件 import 或调用了你改的内容,但你没有更新?
3. 类型定义和实际实现一致吗?
4. 现有测试还能通过吗?
5. 你做了什么我没要求的事?
6. 如果改动涉及 UI:四种状态都处理了吗?(正常/加载/空数据/错误,参考 ux-principles)
工作流 3:出问题 — 系统性排查(对话式)
什么时候用: 出了 bug,尤其是"改了一个地方后另一个地方莫名其妙坏了"这种。
核心原则: 从症状出发,通过提问缩小范围,不猜不跳步。
对话引导规则: 用户说"出 bug 了"时,不要直接尝试修复。通过逐步提问定位根因:
第 1 步:理解症状(1-2轮)
不要急着看代码。先问清楚:
- "具体的错误表现是什么?报错信息?还是行为不符合预期?"
- "这个问题是一直存在,还是最近才出现的?如果是最近才出现,你记得最后一次正常是什么时候?"
- "能稳定复现吗?还是间歇性的?"(间歇性 → 可能是竞态/异步/缓存问题)
第 2 步:缩小范围(1-2轮)
根据症状描述,引导定位:
- 如果最近才出现:"我查一下最近的 commit,看哪次改动最可能引入这个问题。"
→
git log --oneline -10,找到可疑 commit 后git diff分析 - 如果不确定何时出现:"从出错的位置往上追调用链,看数据是从哪里来的,经过了哪些处理。"
- 追问:"你觉得问题更可能出在 [选项A]、[选项B]、还是 [选项C]?"(基于分析给出 2-3 个假设)
第 3 步:验证假设(1轮)
- "我写一个最小的测试来验证这个假设——如果假设正确,测试应该失败;修复后测试应该通过。"
- 跑测试,确认或排除假设。排除了就回到第 2 步换方向。
第 4 步:修复并防护(1-2轮)
确认根因后:
- "我来修复这个问题。修复前先做影响分析——修复本身会不会引入新问题?"
- 修复 → 为这个 bug 写回归测试 → 跑全量测试
- "代码库中有没有其他地方存在类似的问题?我帮你搜一下。"
第 5 步:沉淀(1轮)
- "这个 bug 的模式是 [描述]。要不要加到 CLAUDE.md 的禁止项里,防止下次再犯?"
AI 生成代码的高频 bug 模式:
| Bug 模式 | 症状 | 根因 | 预防规则 |
|---|---|---|---|
| 类型不一致 | 运行时类型错误 | 改了类型定义但漏了调用处 | 改类型后全局搜索引用 |
| 前后端不同步 | 前端显示异常/空白 | 改了 API 但没改前端 | 影响分析必须包含前端 |
| 隐式依赖断裂 | 功能莫名失效 | 改了被隐式依赖的代码 | 减少隐式依赖,用显式导入 |
| 状态不一致 | 数据错乱 | 多处维护同一状态 | 单一数据源原则 |
| 迁移遗漏 | 数据库错误 | 改了模型没写迁移 | 模型变更必须伴随迁移 |
| 空值未处理 | 随机崩溃 | AI 假设数据总是存在 | 所有外部数据都可能为空 |
| 异步竞态 | 间歇性 bug | 没有处理并发情况 | 异步操作加锁或幂等 |
工作流 4:定期 — 文档同步
什么时候用: 每完成 3-5 个 Task 后、每轮迭代结束后、或发现文档和代码对不上时。
为什么重要: docs/ 里的文档不只是给人看的——下次你让 Claude Code 做新任务时,它会读取这些文档作为上下文。文档过时 = AI 基于错误信息写代码。
日常小改动时,工作流 2 的完整性检查清单中已包含"文档是否需要更新"。 本工作流用于阶段性的全面校验——范围更广、更系统。
对 AI 的指令:
请对照代码和文档,做一次全面的同步检查:
1. 读取 docs/prd.md 中的数据模型章节,对比实际的数据库 schema/模型文件
- 字段是否一致?(新增了没写、删了没删、类型改了没更新)
- 关系是否一致?
2. 读取 docs/prd.md 中的功能规格章节,对比实际的 API 路由/服务层代码
- 有没有 PRD 里有但代码没实现的功能?
- 有没有代码实现了但 PRD 里没写的功能?
- API 的输入/输出和 PRD 描述一致吗?
3. 读取 docs/tech-stack.md,对比实际的依赖和项目结构
- 技术栈列表还准确吗?
- 项目结构还和文档描述一致吗?
- 第三方服务列表还准确吗?
4. 读取 docs/tasks.md,检查任务状态
- 哪些 Task 已完成但没标记?
5. 读取 CLAUDE.md,对比实际情况
- 常用命令还正确吗?
- 技术栈描述还准确吗?
- 有没有新发现的禁止项该加但没加?
输出一份不一致报告。
报告格式:
# 文档同步检查报告
**检查日期:** [日期]
**代码版本:** [最近 commit hash]
## ❌ 不一致(必须修复)
| 文档 | 章节 | 问题 | 建议修改 |
|------|------|------|---------|
| [文档] | [章节] | [描述] | [建议] |
## ⚠️ 可能不一致(需要人工确认)
| 文档 | 章节 | 问题 |
|------|------|------|
| [文档] | [章节] | [描述] |
## ✅ 一致
- [列出检查过且一致的部分]
各文档同步规则:
| 文档 | 重点检查 | 变更标注方式 |
|---|---|---|
| docs/prd.md | 数据模型 vs schema、功能规格 vs API、失败场景 vs 错误处理 | > VN 变更:[内容] |
| docs/tech-stack.md | 依赖版本、第三方服务列表、项目结构图、ADR | 直接更新 |
| docs/tasks.md | 已完成的 Task 标记 ✅ | ### Task X.X:[名称] ✅ (日期) |
| CLAUDE.md | 常用命令、技术栈描述、禁止项 | 直接更新 |
特别注意: AI 经常悄悄引入新依赖但不更新文档,改了 API 返回格式但不更新 PRD。这两个是最高频的不一致来源。
在 CLAUDE.md 中引用本 Skill
## 变更规范
- 修改代码前,先做影响分析(参考 change-guard skill),确认变更的爆炸半径
- 特别注意:改后端 API 必须同步检查前端调用处
- 特别注意:改数据模型必须同步更新迁移文件和所有查询处
- commit 前跑一遍完整性检查清单
- 每完成 3-5 个 Task 后,运行一次文档同步检查
- 文档同步完成后,如有 docs/dependency-map.md,触发 consistency-guard W2 做一致性校验
与其他 Skill 的协作
- architecture-principles:原则 3(可删除性)和原则 5(清晰分层)是从源头减少"牵一发动全身"的方法。如果分层清晰、模块自包含,变更的爆炸半径就自然小。change-guard 是在分层不够完美时的安全网。原则 7(管理演进)要求记录 ADR——文档同步检查会提醒你是否有新的架构决策需要记录。
- product-builder:阶段 4(任务拆分)中,每个 Task 可以在开始前用影响分析来确认范围。
- product-iteration:迭代阶段的代码修改,每次走影响分析 → 修改 → 完整性检查。每轮迭代结束后运行文档同步。
- ux-principles:简化版完整性检查第 6 条引用 ux-principles 的四种状态检查。
- excalidraw-diagram:影响分析(W1)产出的变更范围,可以用 excalidraw-diagram 画依赖关系图来直观呈现。