mcpField
D
debugging-patterns

debugging-patterns

github.com/romiluz13开发16636 次安装1 周前更新
代码仓库

关于 debugging-patterns

面向开发者的系统化调试技能,要求先调查根因再提出修复。它将工作分为调查、模式分析、假设测试和实施,并指导追踪调用链与核验证据。

主要功能

  1. 01修复前先调查根因
  2. 02复现并隔离故障
  3. 03使用 LSP 工具追踪调用链
  4. 04记录可验证假设与证据
  5. 05实施并验证最小修复
  6. 06通过手册处理常见故障

适用场景

  1. 01调查测试或构建失败
  2. 02追踪运行时崩溃的根源
  3. 03诊断浏览器与集成错误
  4. 04分析间歇性故障和回归问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/romiluz13/cc10x --skill debugging-patterns

安装后在 Claude Code 中输入/debugging-patterns确认已加载。

附带文件references/investigation-hygiene.mdreferences/root-cause-playbooks.md

详细介绍

系统化调试

概述

随机修复会浪费时间,还会引入新错误。快速打补丁会掩盖根本问题。

核心原则: 尝试修复前,务必先找出根本原因。只修复症状必然失败。

此技能在 v10 中仅提供指导,可深入调查过程。它不授权仅在本地打补丁、凭空猜测,或抱着“修复崩溃的那一行”的想法行事。

参考文件

只阅读当前调查所需的参考资料:

  • references/root-cause-playbooks.md:适用于构建/类型错误、不稳定测试、运行时崩溃、浏览器错误、git bisect 和边界追踪
  • references/investigation-hygiene.md:适用于上下文管理、证据记录、假设追踪、重启流程和架构升级处理

铁律

NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST

如果尚未完成阶段 1,就不能提出修复方案。

五步快速流程(参考模式)

快速调试时,使用以下简洁流程:

1. Capture error message and stack trace
2. Identify reproduction steps
3. Isolate the failure location
4. Implement minimal general fix
5. Verify solution works

调试技巧:

  • 分析错误消息和日志
  • 检查近期代码变更
  • 提出并验证假设
  • 添加有针对性的调试日志
  • 检查变量状态

根本原因追踪技巧:

1. Observe symptom - Where does error manifest?
2. Find immediate cause - Which code produces the error?
3. Ask "What called this?" - Map call chain upward
4. Keep tracing up - Follow invalid data backward
5. Find original trigger - Where did problem actually start?

切勿只在错误出现的位置修复——要追溯到最初的触发因素。 找出根本原因后,检查附近是否存在相同特征的问题,再宣布修复成功。

使用 LSP 追踪根本原因

使用 LSP 系统化追踪执行流程:

调试需求LSP 工具用法
“此函数定义在哪里?”lspGotoDefinition跳转到源代码
“哪些地方调用了此函数?”lspCallHierarchy(incoming)向上追踪调用方
“此函数调用了什么?”lspCallHierarchy(outgoing)向下追踪被调用方
“此变量的所有用法在哪里?”lspFindReferences查找所有访问位置

系统化调用链追踪:

1. localSearchCode("errorFunction") → get file + lineHint
2. lspGotoDefinition(lineHint=N) → see implementation
3. lspCallHierarchy(incoming, lineHint=N) → who calls this?
4. For each caller: lspCallHierarchy(incoming) → trace up
5. Continue until you find the root cause

重要: 务必先从 localSearchCode 获取 lineHint。切勿猜测行号。

针对每个问题提供:

  • 根本原因说明
  • 支持诊断结论的证据
  • 具体代码修复
  • 测试方法
  • 预防建议

场景操作指南

当故障符合以下情形之一时,请阅读 references/root-cause-playbooks.md:

  • 构建或类型错误
  • 测试失败
  • 运行时崩溃
  • 浏览器或控制台错误
  • 间歇性异步错误
  • “以前能用”的回归问题
  • 多组件交接失败

请让此 SKILL.md 聚焦于四阶段调查工作流。具体命令、边界追踪模式和 git-bisect 操作指南请参阅参考文件。

适用场景

任何技术问题都应使用:

  • 测试失败
  • 生产环境中的错误
  • 意外行为
  • 性能问题
  • 构建失败
  • 集成问题

尤其适用于以下情况:

  • 时间紧迫时(紧急情况容易让人想要猜测)
  • “只要快速修一下”看起来显而易见时
  • 已经尝试过多种修复方法时
  • 之前的修复无效时
  • 尚未完全理解问题时

不要在以下情况下跳过:

  • 问题看起来很简单(简单错误也有根本原因)
  • 你很赶时间(匆忙行事必然导致返工)
  • 经理要求立即修复(系统化处理比反复折腾更快)

四个阶段

必须完成每个阶段后,才能进入下一个阶段。

阶段 1:根因调查

尝试任何修复之前:

  1. 仔细阅读错误消息

    • 不要跳过错误或警告
    • 它们通常会给出确切的解决方案
    • 完整阅读堆栈跟踪
    • 记下行号、文件路径和错误代码
  2. 稳定复现

    • 能否可靠地触发问题?
    • 具体步骤是什么?
    • 每次都会发生吗?
    • 如果无法复现 → 收集更多数据,不要猜测
  3. 检查近期更改

    • 哪些更改可能导致此问题?
    • Git 差异、近期提交
    • 新依赖项、配置更改
    • 环境差异
  4. 在多组件系统中收集证据

    当系统包含多个组件时(CI → 构建 → 签名、API → 服务 → 数据库):

    提出修复方案之前,先添加诊断检测:

    For EACH component boundary:
      - Log what data enters component
      - Log what data exits component
      - Verify environment/config propagation
      - Check state at each layer
    
    Run once to gather evidence showing WHERE it breaks
    THEN analyze evidence to identify failing component
    THEN investigate that specific component
    

    有关具体的边界追踪方法,请阅读 references/root-cause-playbooks.md。

  5. 追踪数据流

    当错误发生在调用堆栈深处时:

    • 错误值从何处产生?
    • 哪段代码以错误值调用了这里?
    • 继续向上追踪,直到找到源头
    • 从源头修复,而不是处理表象
  6. 追踪配置到其使用方(第三方 SDK、环境变量、导入时机)

    提出替换方案、迁移方案或大型重构之前:

    • 选项零: 能否仅通过更改配置或环境来修复?提出代码改写方案之前,先陈述并测试这一假设。许多集成问题是连接配置问题,而非架构问题。
    • 如果应用配置中验证了某个环境变量,却从未将其传递给库的构造函数,请问:谁在读取它? 第三方 SDK 通常会在模块导入/加载时读取 process.env(或对应语言中的等效项),而不是通过应用的 DI 或配置对象读取。解决方法可能是设置或更正环境变量,而非更改应用代码。
    • 在建议替换第三方 SDK 之前,先花些时间了解其配置方式:查看软件包 README、官方文档,或 node_modules(或供应商目录)中的已安装源码。问题可能出在端点或标志设置错误,而非需要更换库。
    • 如果代码注释描述了导入时行为或环境变量依赖,请将其视为调查线索,而不是装饰——沿着线索找到真正的使用方。
阶段 2:模式分析

先找出模式,再修复:

  1. 寻找可用示例

    • 在同一代码库中查找类似的可用代码
    • 与出问题的代码类似的部分中,哪些能正常工作?
  2. 对照参考实现

    • 如果要实现某种模式,请完整阅读参考实现
    • 不要略读——逐行阅读
    • 应用之前充分理解该模式
  3. 找出差异

    • 可用代码与出问题的代码之间有哪些不同?
    • 列出所有差异,无论多么细微
    • 不要想当然地认为“这不可能有影响”
  4. 理解依赖项

    • 此功能需要哪些其他组件?
    • 需要哪些设置、配置和环境?
    • 它依赖哪些假设?
阶段 3:提出假设并进行测试

遵循科学方法:

  1. 提出单一假设

    • 清楚地陈述:“我认为 X 是根因,因为 Y”
    • 把它写下来
    • 具体明确,不要含糊
  2. 进行最小化测试

    • 做出尽可能小的更改来测试假设
    • 一次只更改一个变量
    • 不要一次修复多个问题
  3. 验证后再继续

    • 是否有效?是 → 阶段 4
    • 无效?提出新的假设
    • 不要在此基础上继续叠加修复
  4. 遇到不确定时

    • 直说“我不明白 X”
    • 不要假装明白
    • 寻求帮助
    • 进一步调查
假设质量标准

**可证伪性要求:**好的假设可以被证伪。如果你无法设计实验来推翻它,它就没有用。

不好的(不可证伪):

  • “状态出了问题”
  • “时机不对”
  • “某处存在竞争条件”

好的(可证伪):

  • “路由变化时组件重新挂载,导致用户状态重置”
  • “API 调用在卸载后完成,导致更新已卸载组件的状态”
  • “两个异步操作在未加锁的情况下修改同一个数组,导致数据丢失”

**区别:**具体程度。好的假设会提出具体、可测试的主张。

假设置信度评分

跟踪多个假设及其置信度:

H1: [hypothesis] — Confidence: [0-100]
    Evidence for: [what supports this]
    Evidence against: [what contradicts this]
    Next test: [what would raise or lower confidence]

H2: [hypothesis] — Confidence: [0-100]
    Evidence for: [...]
    Evidence against: [...]
    Next test: [...]

H3: [hypothesis] — Confidence: [0-100]
    Evidence for: [...]
    Evidence against: [...]
    Next test: [...]

评分指南:

范围含义行动
80-100证据充分,确定性高继续修复
50-79间接证据,需要更多数据运行“下一项测试”
0-49推测,证据薄弱降低优先级或舍弃

规则:

  • 始终保留 2-3 个假设,直到其中一个达到 80+
  • 每有一条新证据,都要更新置信度
  • 最高置信度的假设低于 50 时,切勿开始修复
调试中的认知偏差
偏差陷阱解法
确认偏误只寻找支持自己假设的证据“什么证据能证明我是错的?”
锚定偏误第一个解释成了你的锚点开始调查前先提出 3+ 个假设
可得性偏差最近遇到过类似 Bug → 假定原因相同除非证据表明并非如此,否则将每个 Bug 都视为新问题
沉没成本在一条思路上花了 2 小时,即使有相反证据仍继续每 30 分钟问自己:“如果我现在才开始,还会走这条路吗?”
元调试:调试自己的代码

调试自己编写的代码时,你是在与自己的心智模型较量。

这为何更难:

  • 设计决策是你做的——你会觉得它们显然正确
  • 你记得的是意图,而不是实际实现
  • 熟悉会让你对 Bug 视而不见

应遵循的原则:

  1. 把自己的代码当作陌生代码——像阅读别人写的代码一样阅读它
  2. 质疑自己的设计决策——你的实现选择是假设,不是事实
  3. 承认自己的心智模型可能有误——代码的行为才是事实;你的模型只是猜测
  4. 优先检查自己动过的代码——如果你修改了 100 行代码后出现问题,这些代码就是重点嫌疑对象

最难承认的话:“这是我实现错了。”而不是“需求不明确”——犯错的是你。

何时重新开始调查

遇到以下情况时,考虑从头开始:

  1. 2+ 小时毫无进展——你很可能陷入了思维定式
  2. 3+ 次“修复”都不起作用——你的心智模型有误
  3. 无法解释当前行为——不要在困惑之上继续添加改动
  4. 你在调试调试器——某些根本环节出了问题
  5. 修复奏效了,但你不知道原因——这不叫修复,只是碰巧

重新开始的步骤:

  1. 关闭所有文件和终端
  2. 写下你确定知道的事情
  3. 写下你已排除的可能性
  4. 列出新的假设(与之前不同)
  5. 从阶段 1 重新开始
阶段 4:实施

修复根因,而非表象:

  1. 创建失败测试用例

    • 尽可能简单地复现问题
    • 如果可能,编写自动化测试
    • 如果没有测试框架,则编写一次性测试脚本
    • 修复前必须有测试用例
  2. 实施单一修复

    • 解决已确认的根因
    • 一次只做一项更改
    • 不要顺手改进其他内容
    • 不要捆绑重构
  3. 验证修复

    • 测试现在通过了吗?
    • 是否有其他测试失败?
    • 问题是否确实已解决?
  4. 如果修复无效

    • 停止
    • 统计:你尝试过多少次修复?
    • 如果少于 3 次:返回阶段 1,结合新信息重新分析
    • 如果达到或超过 3 次:停止并质疑架构(见下方第 5 步)
    • 未进行架构讨论前,不要尝试第 4 次修复
  5. 如果 3 次或更多修复均失败:质疑架构

    表明存在架构问题的模式:

    • 每次修复都会在不同位置暴露新的共享状态、耦合或问题
    • 修复需要“大规模重构”才能实施
    • 每次修复都会在其他位置引发新的问题

    停止并质疑根本设计:

    • 这种模式从根本上是否合理?
    • 我们是否只是在“纯粹惯性的驱使下坚持下去”?
    • 应该重构架构,还是继续修复表象?

    尝试更多修复前,先与人类协作者讨论

    这不是假设失败,而是架构错误。

危险信号——停止并遵循流程

如果你发现自己在想:

  • “先快速修一下,之后再调查”
  • “只要试着改一下 X,看看是否有效”
  • “一次做多项更改,然后运行测试”
  • “跳过测试,我手动验证一下”
  • “问题大概出在 X,我来修一下”
  • “我还没完全理解,但这或许有用”
  • “模式建议这么做,但我会换种方式”
  • “主要问题如下:[未调查就列出修复方案]”
  • 尚未追踪数据流就提出解决方案
  • 尚未排除仅需配置调整的修复方案(选项零),也未追踪导入时哪些对象读取环境变量或配置,就提议替换 SDK 或进行大规模迁移
  • “再尝试修复一次”(此前已尝试 2 次或更多)
  • 每次修复都会在不同位置暴露新问题

以上任何一种情况都意味着:停止。返回阶段 1。

**如果 3 次或更多修复均失败:**质疑架构(见阶段 4.5)

用户指出你做错了时的信号

留意以下纠正:

  • “这不是正在发生吗?”——你未经验证就下了结论
  • “这样能让我们看到……吗?”——你本该收集证据
  • “别猜了”——你还没弄清楚就提出修复方案
  • “深入思考”——应质疑根本设计,而不只是表象
  • “我们卡住了吗?”(语气沮丧)——你的方法不起作用

**看到这些信号时:**停止。返回阶段 1。

防止自我辩解

借口事实
“问题很简单,不需要遵循流程”简单问题也有根因。对简单 Bug 来说,这套流程很快。
“情况紧急,没时间遵循流程”系统化调试比反复猜测和试错更快。
“先试试这个,再调查”第一次修复会定下处理模式。一开始就应该做好。
“等确认修复有效后再写测试”未经测试的修复难以持久。先写测试才能验证修复。
“一次做多项修复能节省时间”无法确定哪项修复有效,还会引入新 Bug。
“参考内容太长,我会自行调整模式”理解不完整必然导致 Bug。请完整阅读。
“我看出问题了,让我修一下”看到表象 ≠ 理解根因。
“再尝试修复一次”(失败 2 次或更多后)失败 3 次或更多说明存在架构问题。应质疑处理模式,而非再次修复。

快速参考

阶段关键活动成功标准
1. 根本原因阅读错误信息,重现问题,检查变更,收集证据了解问题是什么以及原因
2. 模式查找可用示例,进行比较找出差异
3. 假设提出理论,进行最小化测试得到确认或提出新假设
4. 实施创建测试,修复问题,验证结果问题已解决,测试通过

当流程揭示“没有根本原因”时

如果系统调查发现,问题确实与环境、时间有关或由外部因素导致:

  1. 你已完成调查流程
  2. 记录你调查的内容
  3. 实施适当的处理方式(重试、超时、错误消息)
  4. 添加监控和日志记录,以便后续调查

但是: 95% 的“没有根本原因”案例都是调查不充分。

输出格式

## Bug Investigation

### Phase 1: Evidence Gathered
- **Error**: [exact error message]
- **Stack trace**: [relevant lines]
- **Reproduction**: [steps to reproduce]
- **Recent changes**: [commits/changes]

### Phase 2: Pattern Analysis
- **Working example**: [similar working code]
- **Key differences**: [what's different]

### Phase 3: Hypothesis
- **Theory**: [I think X because Y]
- **Test**: [minimal change made]
- **Result**: [confirmed/refuted]

### Phase 4: Fix
- **Root cause**: [actual cause with evidence]
- **Change**: [summary of fix]
- **File**: [path:line]
- **Regression test**: [test added]

### Verification
- Test command: [command] → exit 0
- All tests: PASS
- Functionality: Restored

评论

支持 Markdown