mcpField
D
diagnosing-bugs

diagnosing-bugs

github.com/utarn开发4979 次安装8 周前更新
代码仓库

关于 diagnosing-bugs

面向开发者和编码 Agent 的疑难调试流程,涵盖构建反馈循环、复现与缩减问题、检验假设、修复和清理。它强调先建立能检测具体症状的快速、确定性检查,再形成原因判断。

主要功能

  1. 01构建针对症状的反馈循环
  2. 02复现并缩减故障场景
  3. 03排列可证伪的假设
  4. 04进行有针对性的探测
  5. 05添加回归测试并清理

适用场景

  1. 01调查间歇性故障
  2. 02将报告的症状转为可重复测试
  3. 03保留诊断记录并追查原因

安装

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

$npx skills add https://github.com/utarn/engineer-skills --skill diagnosing-bugs

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

附带文件agents/openai.yamlscripts/hitl-loop.template.sh

详细介绍

诊断 Bug

处理棘手 Bug 的方法。只有在明确说明理由时,才跳过阶段。

探索代码库时,如果存在 CONTEXT.md,请先阅读,以便清楚了解相关模块;同时检查你要修改区域的 ADR。

脱敏

此技能要求你展示命令、输出和捕获的工件。先对所有机密信息进行脱敏——用 <REDACTED> 替代。让构建循环通过环境变量运行,这样凭据就保留在环境中,而不会出现在展示内容里。捕获的工件包含身份验证标头:只引用能体现关键信息的行。

如果脱敏后的输出不足以诊断 Bug,请说明这一点并询问用户。

阶段 1 — 构建反馈循环

这就是本技能的核心。其他一切都只是机械操作。如果你有一个针对该 Bug 的快速通过/失败信号——它会因_这个_ Bug 而失败——你就能找到原因;二分查找、假设检验和插桩都只是利用这个信号。如果没有,再怎么盯着代码看也无济于事。

在这里投入不成比例的精力。积极尝试,发挥创意,不要轻易放弃。

构建反馈循环的方法 — 大致按以下顺序尝试
  1. 在任何能触及 Bug 的位置编写失败测试——单元测试、集成测试或端到端测试。
  2. 对运行中的开发服务运行 Curl / HTTP 脚本。
  3. 使用测试样例输入调用 CLI,将标准输出与已知的正确快照进行比较。
  4. 编写无头浏览器脚本(Playwright / Puppeteer)——驱动 UI,并断言 DOM、控制台和网络行为。
  5. **重放捕获的跟踪记录。**将真实的网络请求、负载或事件日志保存到磁盘;通过隔离的代码路径重放。
  6. **一次性测试程序。**启动系统的最小子集(一个服务、模拟依赖),通过一次函数调用执行有 Bug 的代码路径。
  7. **属性/模糊测试循环。**如果 Bug 表现为“有时输出错误”,则运行 1000 个随机输入,寻找失败模式。
  8. **二分查找测试程序。**如果已知 Bug 出现在两个状态之间(提交、数据集、版本),则自动执行“在状态 X 启动、检查、重复”,以便运行 git bisect run。
  9. **差异比较循环。**使用相同输入运行旧版本与新版本(或两种配置),并比较输出。
  10. **人工参与的 Bash 脚本。**最后的手段。如果必须由人点击,就用 scripts/hitl-loop.template.sh 驱动_他们_,让循环依然有条理。捕获的输出会反馈给你。

构建正确的反馈循环,Bug 就解决了 90%。

收紧循环

把循环当作产品来打磨。一旦你有了_一个_循环,就要收紧它:

  • 能否让它更快?(缓存初始化、跳过无关启动步骤、缩小测试范围。)
  • 能否让信号更明确?(针对具体症状进行断言,而不是只检查“没有崩溃”。)
  • 能否让结果更具确定性?(固定时间、设定随机数种子、隔离文件系统、冻结网络。)

30 秒且不稳定的循环几乎不比没有循环强;2 秒且稳定的循环才称得上紧凑——也是调试的超能力。

非确定性 Bug

目标不是稳定复现,而是提高复现率。将触发条件循环 100 次、并行运行、增加压力、缩小时间窗口、注入休眠。复现率为 50% 的 Bug 可以调试;1% 的则不行——持续提高复现率,直到能够调试。

确实无法构建循环时

停止并明确说明。列出你尝试过的方法。向用户索取:(a) 能够复现问题的环境访问权限;(b) 脱敏后的捕获工件(HAR 文件、日志转储、核心转储、带时间戳的屏幕录像);或 (c) 添加临时生产环境插桩的许可。不要在没有反馈循环的情况下继续推测。

完成标准 — 一个能快速迭代并变红的循环

当循环足够紧凑且能够变红时,阶段 1 即告完成:你能说出一条命令——脚本路径、测试调用或 curl——你至少已经运行过一次(展示调用和输出,并对敏感信息做脱敏),并且这条命令:

  • 能够变红 — 它会驱动实际的 Bug 代码路径,并断言用户的确切症状,因此在此 Bug 存在时会变红,修复后会变绿。不能只是“运行时没有报错”——它必须能够_捕获这个特定 Bug_。
  • 结果确定 — 每次运行的结论都相同(对于不稳定 Bug:如上所述,固定并保持较高的复现率)。
  • 速度快 — 只需几秒,而不是几分钟。
  • 可由 Agent 运行 — 无需人工值守即可运行;仅通过 scripts/hitl-loop.template.sh 引入人工参与。

如果你发现自己正在阅读代码、试图构建理论,而这条命令还不存在,请停下来——直接跳到假设正是这项技能要避免的错误。 没有能够变红的命令,就不要进入阶段 2。

阶段 2 — 复现 + 最小化

运行循环。观察它变红——Bug 出现了。

确认:

  • 循环产生的是用户描述的故障模式,而不是碰巧发生在附近的另一种故障。Bug 搞错了,修复也会错。
  • 多次运行都能复现故障(对于非确定性 Bug,复现率也要足够高,以便据此调试)。
  • 你已记录确切症状(错误消息、错误输出、耗时过长),以便后续阶段验证修复是否确实解决了问题。
最小化

循环变红后,将复现用例缩减到仍会变红的最小场景。每次只删减一项输入、调用方、配置、数据或步骤,并在每次删减后重新运行循环——只保留对故障起关键作用的部分。

为何要这样做:最小复现用例能缩小阶段 3 的假设范围(可疑因素更少),也能成为阶段 5 中清晰的回归测试。

当剩下的每个元素都起关键作用时,即可完成——移除其中任意一个,循环都会变绿。

复现并且完成最小化之前,不要继续。

阶段 3 — 提出假设

在测试任何假设之前,先提出 3–5 个按可能性排序的假设。只提出一个假设会让你锚定在第一个看似合理的想法上。

每个假设都必须可证伪:明确说明它会得出什么预测。

格式:“如果 是原因,那么 <更改 Y> 会让 Bug 消失 / <更改 Z> 会让 Bug 加重。”

如果你无法说明预测,那么这个假设就只是一种直觉——请舍弃或完善它。

测试之前,先向用户展示排序后的列表。 用户通常掌握相关领域知识,可以立即调整排序(“我们刚部署了针对 #3 的更改”),也可能知道哪些假设已被排除。这是个成本很低、能大幅节省时间的检查点。不要因此停下来等待——如果用户暂时不在线,就按你的排序继续。

阶段 4 — 加入检测手段

每个探查都必须对应阶段 3 中的具体预测。每次只更改一个变量。

工具优先级:

  1. 调试器 / REPL 检查,如果环境支持。一个断点胜过十条日志。
  2. 在能区分不同假设的边界处添加有针对性的日志。
  3. 绝不要“记录所有内容再用 grep 搜索”。

为每条调试日志添加唯一前缀,例如 [DEBUG-a4f2]。最后清理时只需执行一次 grep。未标记的日志会遗留下来;已标记的日志则可以清除。

性能分支。 对于性能回退,日志通常不是正确的手段。应先建立基线测量(计时工具、performance.now()、性能分析器、查询计划),然后再进行二分排查。先测量,再修复。

阶段 5 — 修复 + 回归测试

在修复前编写回归测试——但前提是存在合适的切入点。

合适的切入点是指:测试能在调用点复现真实的错误模式。如果唯一可用的切入点过于浅显(当错误需要多个调用方时却只测试单个调用方,或单元测试无法复现触发错误的调用链),那么在此处编写回归测试会带来虚假的信心。

如果不存在合适的切入点,这本身就是一项发现。 请记录下来。代码库架构使这个错误无法被测试锁定。请在下一阶段提出这一问题。

如果存在合适的切入点:

  1. 将最小化复现转化为该切入点上的失败测试。
  2. 确认测试失败。
  3. 应用修复。
  4. 确认测试通过。
  5. 针对原始(未经最小化的)场景,重新运行阶段 1 的反馈循环。

阶段 6 — 清理 + 事后复盘

宣布完成前必须:

  • 原始复现不再复现(重新运行阶段 1 的反馈循环)
  • 回归测试通过(或已记录不存在合适的切入点)
  • 已移除所有 [DEBUG-...] 插桩(使用 grep 搜索此前缀)
  • 已删除临时原型(或将其移至明确标记的调试位置)
  • 在提交 / PR 消息中说明最终验证正确的假设——让下一位调试者有所收获

然后思考:什么本可以避免这个错误? 如果答案涉及架构变更(没有合适的测试切入点、调用方纠缠、存在隐藏耦合),请根据具体情况移交给 /improve-codebase-architecture 技能。请在修复完成后再提出建议,而不是之前——现在你掌握的信息比开始时更多。

评论

支持 Markdown