关于 systematic-debugging
面向开发者的调试技能,通过四个设有门槛的阶段调查故障,再决定是否修改代码。它强调可复现证据、可验证假设,以及排除常见原因后审视设计。
主要功能
- 01收集错误、复现步骤和环境信息
- 02比较正常与故障案例
- 03逐一验证基于证据的假设
- 04多次验证失败后审视架构假设
- 05理解根因后再修复
适用场景
- 01调查可稳定复现的软件故障
- 02将问题缩小到最小示例
- 03排查故障背后的环境差异
- 04多种假设失败后重新评估设计
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ pixel-process-ug/ superkit-agents --skill systematic-debugging安装后在 Claude Code 中输入/systematic-debugging确认已加载。
附带文件defense-in-depth.mdroot-cause-tracing.md
详细介绍
系统化调试
概述
调试是调查,而不是实验。本技能要求严格遵循 4 阶段流程——根因调查、模式分析、假设测试和架构审视——以避免盲目尝试调试,并确保在应用任何修复之前都已理解问题。
开始时请说明:“我正在使用系统化调试技能来调查此问题。”
核心原则
┌─────────────────────────────────────────────────────────────────┐
│ HARD-GATE: NEVER GUESS. NEVER SHOTGUN DEBUG. │
│ NEVER CHANGE CODE WITHOUT UNDERSTANDING WHY IT IS BROKEN. │
│ │
│ You are a detective gathering evidence, not a gambler trying │
│ random fixes. If you are changing code without understanding │
│ the root cause, STOP immediately. │
└─────────────────────────────────────────────────────────────────┘
阶段 1:根因调查
**目标:**准确了解实际发生了什么,而不是你认为发生了什么。
操作
- **仔细阅读错误消息。**阅读完整消息,包括每一行以及堆栈跟踪。
- **重现错误。**如果无法重现,就无法修复。找出确切的操作步骤。
- **收集证据。**收集:
- 完整的错误消息和堆栈跟踪
- 触发错误的输入
- 预期行为与实际行为
- 环境详情(版本、配置、操作系统)
- **检查近期更改。**上次正常工作之后发生了哪些变化?
- 近期提交(
git log、git diff) - 依赖项更新
- 配置更改
- 环境更改
- 近期提交(
证据收集检查清单
- 已捕获完整错误消息(未截断)
- 已从下往上阅读堆栈跟踪
- 已通过具体步骤可靠地重现错误
- 已记录预期行为与实际行为
- 已检查近期更改(
git log --oneline -20) - 已检查相关日志
停止 — 强制门槛:满足以下条件之前,不要进入阶段 2:
- 你能够稳定地重现错误
- 你已获取完整错误消息和堆栈跟踪
- 你知道近期发生了哪些变化
- 你能够准确描述错误(而非含糊其辞)
阶段 2:模式分析
**目标:**缩小问题所在位置及其发生时机的范围。
操作
- **寻找正常工作的示例。**此功能在其他上下文、使用其他输入或在其他环境中是否正常工作?
- **比较正常与异常的情况。**正常情况与异常情况之间有哪些不同?
- **检查依赖项。**所有必需的服务、库和配置是否都存在且正确?
- **隔离范围。**能否用最小示例重现问题?去掉所有非必要内容。
比较矩阵
填写此表以识别模式:
| 因素 | 正常情况 | 异常情况 | 是否不同? |
|---|---|---|---|
| 输入数据 | |||
| 环境 | |||
| 配置 | |||
| 依赖项 | |||
| 时机/顺序 | |||
| 用户/权限 | |||
| 状态/上下文 |
停止 — 强制门槛:满足以下条件之前,不要进入阶段 3:
- 你已找到至少一个可供比较的正常情况
- 你已比较正常与异常的情况并找出差异
- 你已将范围缩小到可重现问题的最小情况
- 已验证依赖项(版本、可用性、配置)
阶段 3:假设与测试
**目标:**提出一个具体、可测试的假设,并通过尽可能小的更改进行验证。
操作
- **提出一个假设。**根据阶段 1 至 2 收集的证据,最有可能的单一原因是什么?
- 明确说明:“错误发生是因为[具体原因]”
- 如果无法具体说明,请返回阶段 1 或阶段 2
- **设计最小测试。**要确认或否定此假设,最小的更改是什么?
- 优先添加测试用例,而非修改生产代码
- 优先使用日志记录或断言,而非更改代码
- 优先回退更改,而非编写新代码
- 应用更改并测试。
- 只进行验证假设所需的更改
- 运行测试套件
- 观察结果
- 评估。
- 如果已确认:继续修复,并编写回归测试
- 如果被否定:记录所得结论,提出新假设,然后返回步骤 1
假设记录模板
Hypothesis #1: [description]
Test: [what you did]
Result: CONFIRMED / DENIED
Learning: [what this taught you]
Hypothesis #2: ...
决策表:假设检验方法
| 假设类型 | 测试方法 | 示例 |
|---|---|---|
| 最近的代码更改导致了问题 | git bisect 或回退提交 | “该错误是在提交 abc123 中引入的” |
| 数据形状不匹配 | 添加日志/断言 | “API 返回的是 null,而不是数组” |
| 竞态条件 | 添加时序日志或串行执行 | “请求 B 在请求 A 之前完成” |
| 配置错误 | 比较不同环境的配置 | “生产环境使用了不同的 DB 主机” |
| 依赖版本问题 | 锁定到已知正常的版本 | “库 2.0 更改了 API 接口” |
停止 — 硬性门槛:除非满足以下条件,否则不要进入阶段 4:
- 至少测试了 3 个假设,且全部被否定
- 每个假设都具体且可测试
- 每次测试都尽可能精简(一次只做一项更改)
- 记录了每个失败假设中获得的经验
阶段 4:架构质疑
目标: 如果 3 个或更多假设都失败了,问题可能出在结构上。退一步,重新审视各种假设。
只有在至少尝试过 3 次阶段 3 且未成功后,才会进入此阶段。
操作
- 质疑你的假设。 你一直认为什么是事实,但实际上可能并非如此?
- 数据的形状是否和你认为的一样?
- 控制流是否符合你的预期?
- 类型是否和你认为的一样?
- API 契约是否符合你的假设?
- 质疑设计。 当前方法是否存在根本性缺陷?
- 设计中是否存在竞态条件?
- 是否存在状态管理问题?
- 是否存在不恰当的抽象?
- 职责是否分配不当?
- 考虑重新设计。 有时,解决办法不是打补丁,而是重构。
- 能否简化设计,从根本上消除这一类错误?
- 是否有更适合处理此情况的模式?
- 是否应该替换,而不是修复?
- 寻求外部意见。 如果你陷入困境:
- 向其他人解释问题(橡皮鸭调试法)
- 搜索依赖项中已知的问题
- 查看其他人是否遇到过类似问题
停止 — 硬性门槛:满足以下条件后才能继续:
- 写下已质疑的假设清单
- 明确决定:修补当前设计,还是重新设计
- 如果重新设计:实施前先制定计划
- 如果修补:根据假设审查结果提出一个新假设
调试决策流程图
Error encountered
|
v
Can you reproduce it?
|
+-- NO --> Gather more information (logs, user reports, monitoring)
| Try different inputs, environments, timing
| Do NOT proceed until reproducible
|
+-- YES -> Read the FULL error message and stack trace
|
v
Is the cause obvious from the error?
|
+-- YES -> Form hypothesis, test it (Phase 3)
| Still write a regression test
|
+-- NO --> Complete Phase 1 evidence gathering
|
v
Find working case for comparison (Phase 2)
|
v
Identify differences
|
v
Form and test hypotheses (Phase 3)
|
+-- Fixed --> Write regression test, verify
|
+-- 3+ failed hypotheses --> Phase 4
危险信号表
| 危险信号 | 含义 | 操作 |
|---|---|---|
| 不理解错误就更改代码 | 盲目试错式调试 | 返回阶段 1 |
| 修复有效,但不知道原因 | 偶然修复,很可能再次出现问题 | 继续调查,直到弄清原因 |
| 同一错误反复出现 | 未解决根本原因 | 前往阶段 4,质疑设计 |
| 修复在其他地方引发新错误 | 存在意料之外的耦合 | 继续前先梳理依赖关系 |
| “在我的机器上能运行” | 环境差异 | 前往阶段 2,使用比较矩阵 |
| 修复需要超过 20 行代码 | 可能是设计问题 | 前往阶段 4 |
| 调试超过 30 分钟 | 思维陷入僵局 | 休息一下,重新阅读阶段 1 中的证据 |
| 反复阅读同一段代码 | 忽略了某个根本问题 | 换个角度思考,大声解释问题 |
| 多个原因看起来同样可能 | 调查不充分 | 返回阶段 1,收集更多证据 |
反模式 / 常见错误
| 反模式 | 错误原因 | 正确做法 |
|---|---|---|
| 随意修改内容,看看 Bug 会不会消失 | 浪费时间,还会引入新 Bug | 先提出假设 |
| 添加 try/catch 来压制错误 | 掩盖真正的问题 | 修复根本原因 |
| 从头重写整个功能 | 很少需要采取这种极端做法 | 定位并修复具体问题 |
| 没有证据就归咎于框架 / 库 | 通常是你的代码有问题 | 用最小复现证明是框架 Bug |
| 修复后跳过回归测试 | Bug 会再次出现 | 务必编写测试 |
| 修复表面症状,而非根本原因 | 补丁会不断累积,系统会逐渐退化 | 追查真正原因 |
| 调试超过 45 分钟却不暂停反思 | 思维定式会降低效率 | 休息一下,重新阅读阶段 1 的证据 |
| 忽略错误消息或堆栈跟踪 | 答案往往就在错误信息中 | 阅读错误信息的每一行 |
集成点
| 技能 | 关联 |
|---|---|
test-driven-development | 每个 Bug 修复都必须包含回归测试(RED-GREEN 循环) |
verification-before-completion | 修复 Bug 后,用新的证据进行验证 |
resilient-execution | 执行任务期间进行调试时,暂停任务,完成调试后再继续 |
code-review | 审查修复是否完整,以及是否有副作用 |
self-learning | 在 learned-patterns.md 中记录新的调试模式 |
acceptance-testing | 验证修复不会破坏验收标准 |
快速参考:不要做什么
- 不要随意修改内容,看看 Bug 会不会消失
- 不要添加 try/catch 来压制错误
- 不要把从头重写整个功能作为首选方案
- 不要没有证据就归咎于框架 / 库
- 不要修复后跳过编写回归测试
- 不要修复表面症状,而非根本原因
- 不要调试超过 45 分钟却不暂停反思
- 不要忽略错误消息或堆栈跟踪
技能类型
RIGID —— 必须按顺序遵循这 4 个阶段的流程。每个阶段都有一个必须满足的硬性门槛,满足后才能继续。切勿在不了解代码为何出错的情况下修改代码。
评论
支持 Markdown