mcpField
D
diagnose

diagnose

github.com/leandrocfe开发4141 次安装11 周前更新
代码仓库

关于 diagnose

diagnose 是面向编码 Agent 的疑难调试技能,强调先建立可靠的反馈循环,再分析代码。它依次指导复现问题、提出假设、定向插桩、编写回归测试并清理调试产物。

主要功能

  1. 01构建确定性故障反馈循环
  2. 02复现并记录准确故障
  3. 03排列可证伪的假设
  4. 04在关键代码边界定向插桩
  5. 05添加回归测试并清理

适用场景

  1. 01调试间歇性故障
  2. 02调查已报告的线上问题
  3. 03追踪跨提交或版本的回归

安装

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

$npx skills add https://github.com/leandrocfe/skills --skill diagnose

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

附带文件scripts/hitl-loop.template.sh

详细介绍

诊断

用于处理疑难 Bug 的流程。只有给出明确理由时才能跳过阶段。

探索代码库时,请使用项目的领域词汇表,清楚了解相关模块,并检查你正在处理的领域中的 ADR。

阶段 1 — 构建反馈循环

这就是这项技能。 其他一切都是机械操作。如果你有一个快速、确定且可由 Agent 运行的通过/失败信号来检测 Bug,就能找到原因——二分、假设检验和插桩都只是利用这个信号。如果没有,再多花时间盯着代码也无济于事。

在这里投入不成比例的精力。积极尝试。大胆创新。不要放弃。

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

构建好反馈循环,Bug 就有 90% 修好了。

迭代改进循环本身

把循环当作产品。构建出_一个_循环后,问问自己:

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

一个运行 30 秒且不稳定的循环,和没有循环相比几乎好不了多少。一个确定且只需 2 秒的循环,则是调试的超能力。

非确定性 Bug

目标不是得到干净的复现,而是提高复现率。将触发条件循环 100 次、并行运行、增加压力、缩窄时序窗口、注入休眠。复现率为 50% 的 Bug 可以调试;1% 的不行——提高复现率,直到可以调试为止。

确实无法构建循环时

停下来并明确说明。列出你尝试过的方法。请用户提供:(a) 可复现问题的环境访问权限;(b) 捕获的产物(HAR 文件、日志转储、core dump、带时间戳的屏幕录像);或 (c) 在生产环境中添加临时插桩的许可。不要在没有循环的情况下继续提出假设。

在确信循环可靠之前,不要进入阶段 2。

阶段 2 — 复现

运行循环。观察 Bug 出现。

确认:

  • 循环产生的是用户描述的失败模式,而不是恰好与之相关的其他失败。Bug 搞错了,修复也会错。
  • 失败在多次运行中可复现(对于非确定性 Bug,则需要达到足以进行调试的复现率)。
  • 你已捕获确切症状(错误消息、错误输出、缓慢的时序),以便后续阶段验证修复是否真正解决了问题。

复现 Bug 之前不要继续。

阶段 3 — 提出假设

在测试任何假设之前,先生成 3-5 个按优先级排序的假设。只生成一个假设会让你锚定在第一个看似合理的想法上。

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

格式:“如果 是原因,那么 <更改 Y> 会让 bug 消失 / <更改 Z> 会让问题恶化。”

如果你无法说明预测,这个假设就只是凭感觉——请舍弃或进一步明确。

在测试之前,先向用户展示排序后的列表。 他们通常掌握能立刻调整排序的领域知识(“我们刚刚部署了 #3 中的更改”),或者知道哪些假设已经被排除。这是成本低、节省时间多的检查点。不要因此停下来——如果用户暂时不在线,就按你的排序继续。

阶段 4 — 埋点

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

工具优先级:

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

为每条调试日志添加唯一前缀,例如 [DEBUG-a4f2]。最后清理时只需 grep 一次。没有标签的日志会残留下来;带标签的日志则会被清除。

性能分支。 对于性能回归,日志通常不是正确的工具。应先建立基准测量(计时测试框架、performance.now()、profiler、query plan),然后再进行二分排查。先测量,再修复。

阶段 5 — 修复 + 回归测试

在修复之前编写回归测试——但前提是存在合适的测试接缝。

合适的测试接缝是指测试能在调用点按实际 bug 模式进行验证。如果唯一可用的接缝过于浅显(bug 需要多个调用方,但测试只覆盖单个调用方;或单元测试无法复现触发 bug 的调用链),在那里编写回归测试会带来虚假的信心。

如果不存在合适的测试接缝,这本身就是一项发现。 请记录下来。这说明代码库的架构阻碍了对该 bug 的测试锁定。请在下一阶段指出这一点。

如果存在合适的测试接缝:

  1. 将最小化复现转化为一个在该接缝处失败的测试。
  2. 观察它失败。
  3. 应用修复。
  4. 观察它通过。
  5. 针对原始场景(未最小化)重新运行阶段 1 的反馈循环。

阶段 6 — 清理 + 事后分析

在宣布完成之前,必须完成以下事项:

  • 原始复现不再出现(重新运行阶段 1 的循环)
  • 回归测试通过(或已记录不存在合适的测试接缝)
  • 已移除所有 [DEBUG-...] 埋点(grep 该前缀)
  • 已删除一次性原型(或将其移至明确标记的调试位置)
  • 在 commit / PR 消息中说明最终证实的假设——让下一位调试人员能够吸取经验

然后问:怎样才能避免这个 bug? 如果答案涉及架构变更(缺少良好的测试接缝、调用方相互缠绕、隐藏的耦合),请将详细信息交接给 skill /improve-codebase-architecture。请在修复合入之后再提出建议,而不是之前——现在你掌握的信息比刚开始时更多。

评论

支持 Markdown