诊断 Bug
SkillDev toolsA diagnostic loop for tricky bugs and performance regressions. Use when the user says "diagnose" / "debug this", or reports that something is broken / throwing exceptions / failing / slow.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the 诊断 Bug skill
What this skill tells your AI
The instructions your AI receives, as published by wenwuzhidao/mattpocock-skills-zh in skills/engineering/diagnosing-bugs/SKILL.md and read by ahel’s review.
一套针对疑难 bug 的准则。只在有明确理由时才跳过某个阶段。
在探索代码库时,读 CONTEXT.md(如果存在)以对相关模块建立清晰的心智模型,并检查你正在触碰的区域里的 ADR。
脱敏
这个技能会让你展示命令、输出和捕获的产物。先给每一个密钥脱敏——用 <REDACTED> 替代它。围绕环境变量构建循环,让凭据留在环境里,而不是留在你展示的东西里。捕获的产物携带认证头:只引用携带信号的那些行。
如果脱敏后的输出不足以诊断 bug,就说出来并询问用户。
阶段 1 — 构建反馈循环
这才是本技能的核心。 其余一切都是机械操作。如果你有一个针对该 bug 的紧凑通过/失败信号——一个能在这个 bug 上变红的信号——你就会找到原因;二分、假设检验和埋点都只是消费它。如果你没有这个信号,再怎么盯着代码看也救不了你。
在这里投入不成比例的努力。要有攻击性。要有创造力。拒绝放弃。
构建它的几种方式——大致按此顺序尝试
- 在任何能触及该 bug 的接缝处写一个失败的测试——单元、集成、e2e。
- 针对运行中的开发服务器的 Curl / HTTP 脚本。
- 用固定输入的 CLI 调用,把 stdout 对照一个已知良好的快照做 diff。
- 无头浏览器脚本(Playwright / Puppeteer)——驱动 UI,对 DOM/console/network 做断言。
- 回放捕获的 trace。 把一个真实的网络请求 / 载荷 / 事件日志存到磁盘;在隔离环境中让它重新走一遍代码路径。
- 用完即弃的测试台。 起一个系统的最小子集(一个服务、mock 掉依赖),用单次函数调用触发 bug 的代码路径。
- 属性/模糊循环。 如果 bug 是「有时输出错误」,跑 1000 个随机输入,寻找失败模式。
- 二分测试台。 如果 bug 出现在两个已知状态之间(commit、数据集、版本),把「在状态 X 启动、检查、重复」自动化,这样你就能
git bisect run它。 - 差分循环。 把同一个输入分别跑过旧版本和新版本(或两种配置),对输出做 diff。
- HITL bash 脚本。 最后手段。如果必须有人来点击,就用
scripts/hitl-loop.template.sh驱动他们,让循环仍然是结构化的。捕获的输出反馈给你。
构建对的反馈循环,bug 就修好了 90%。
收紧循环
把循环当成一个产品来对待。一旦你有了一个循环,就收紧它:
- 我能让它更快吗?(缓存 setup、跳过无关的初始化、缩小测试范围。)
- 我能让信号更锐利吗?(对具体症状而不是「没崩」做断言。)
- 我能让它更确定吗?(钉住时间、给 RNG 设种子、隔离文件系统、冻结网络。)
一个 30 秒的抖动循环几乎不比没有循环强;一个 2 秒的确定性循环才叫紧凑——一种调试的超能力。
非确定性 bug
目标不是一次干净的复现,而是更高的复现率。把触发器循环 100 次、并行化、加压力、缩窄时序窗口、注入 sleep。50% 抖动的 bug 是可调试的;1% 的不可调试——不断提高这个率,直到它可调试。
当你确实构建不出循环时
停下来并明确说出。列出你尝试过什么。向用户请求:(a) 访问任何能复现它的环境,(b) 一份脱敏后的捕获产物(HAR 文件、日志转储、core dump、带时间戳的录屏),或 (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> 将让它变得更糟。」
如果你陈述不出预测,那这个假设就是一种感觉——丢弃它或把它磨锐利。
在检验之前把排好序的列表展示给用户。 他们常常拥有能瞬间重新排序的领域知识(「我们刚给 #3 部署了一个改动」),或者知道他们已经排除掉的假设。廉价的检查点,巨大的省时。别为此阻塞——如果用户 AFK,就按你的排序继续。
阶段 4 — 埋点
每个探针都必须对应阶段 3 里的一个具体预测。一次改变一个变量。
工具偏好:
- 如果环境支持,用调试器 / REPL 检查。一个断点胜过十条日志。
- 在区分不同假设的边界处打有针对性的日志。
- 绝不「打一堆日志然后 grep」。
给每条调试日志打标签,用一个唯一前缀,例如 [DEBUG-a4f2]。最后的清理就变成一次 grep。没打标签的日志会残留;打了标签的日志会被清掉。
性能分支。 对于性能回归,日志通常是错的做法。改为:建立一个基线测量(计时测试台、performance.now()、profiler、查询计划),然后二分。先测量,再修复。
阶段 5 — 修复 + 回归测试
在修复之前写回归测试——但仅当存在一个正确的接缝时。
一个正确的接缝,是指测试能在调用点触发真实的 bug 模式(如其真实发生的那样)。如果唯一可用的接缝太浅(bug 需要多个调用方而测试只有单个调用方、单元测试无法复现触发 bug 的调用链),在那里放一个回归测试会给出错误的信心。
如果不存在正确的接缝,那本身就是一个发现。 记下它。代码库架构正在阻止这个 bug 被锁死。把它标记出来供下一阶段处理。
如果存在正确的接缝:
- 把最小化后的复现变成该接缝处的一个失败测试。
- 看着它失败。
- 施加修复。
- 看着它通过。
- 针对原始的(未最小化的)场景重新跑阶段 1 的反馈循环。
阶段 6 — 清理 + 事后复盘
宣布完成之前必须做到:
- 原始复现不再复现(重新跑阶段 1 的循环)
- 回归测试通过(或接缝缺失的情况已记录在案)
- 所有
[DEBUG-...]埋点已移除(grep那个前缀) - 用完即弃的原型已删除(或移到一个明确标记的调试位置)
- 最终证明正确的那个假设写在了 commit / PR 消息里——好让下一个调试者学到东西
然后问:什么本可以防止这个 bug? 如果答案涉及架构改动(没有好的测试接缝、调用方纠缠、隐藏耦合),就把具体情况交接给 /improve-codebase-architecture 技能。这个建议要在修复落地之后给出,而不是之前——你现在掌握的信息比开始时更多。
Signals
- GitHub stars
- 23
- Forks
- 4
- Last commit
- Aug 2026
Advanced
- Item type
- skill
- Key
diagnosing-bugs-wenwuzhidao- Source
- github.com/wenwuzhidao/mattpocock-skills-zh