# Diagnosing Bugs

> 针对疑难 bug 和性能回退的诊断循环。当用户说 "diagnose"/"debug this"，或报告某处坏了/抛错/失败/变慢时使用。

- **Type:** Skill
- **Install:** `agentstack add skill-wenwuzhidao-mattpocock-skills-zh-diagnosing-bugs`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [WenWuZhiDao](https://agentstack.voostack.com/s/wenwuzhidao)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [WenWuZhiDao](https://github.com/WenWuZhiDao)
- **Source:** https://github.com/WenWuZhiDao/mattpocock-skills-zh/tree/main/skills/engineering/diagnosing-bugs

## Install

```sh
agentstack add skill-wenwuzhidao-mattpocock-skills-zh-diagnosing-bugs
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 诊断 Bug

一套应对疑难 bug 的纪律。只有在有明确理由时才跳过某个阶段。

在探索代码库时，阅读 `CONTEXT.md`（如果存在），以对相关模块建立清晰的心智模型，并检查你所触及区域的 ADR。

## 阶段 1 — 构建反馈回路

**这才是本技能的核心。** 其他一切都是机械性的。如果你拥有一个**紧凑的**、针对 bug 的通过/失败信号——一个会在_这个_ bug 上变红的信号——你就能找到病因；二分查找、假设检验和插桩都只是在消费这个信号。如果没有它，再怎么盯着代码看也救不了你。

在这里投入不成比例的精力。**要激进。要有创意。拒绝放弃。**

### 构建反馈回路的方法——大致按此顺序尝试

1. **失败的测试**，放在任何能触及 bug 的接缝上——单元、集成、e2e。
2. **Curl / HTTP 脚本**，针对运行中的开发服务器。
3. **CLI 调用**，使用固定输入（fixture），将 stdout 与一个已知良好的快照做 diff。
4. **无头浏览器脚本**（Playwright / Puppeteer）——驱动 UI，对 DOM/控制台/网络做断言。
5. **重放捕获的 trace。** 把真实的网络请求 / 载荷 / 事件日志保存到磁盘；在隔离环境中通过代码路径重放它。
6. **一次性测试脚手架。** 搭起系统的一个最小子集（一个服务，mock 掉依赖），用单次函数调用去触发 bug 的代码路径。
7. **属性 / 模糊测试回路。** 如果 bug 是「有时输出错误」，就跑 1000 个随机输入，寻找失败模式。
8. **二分查找脚手架。** 如果 bug 出现在两个已知状态（commit、数据集、版本）之间，就把「在状态 X 启动，检查，重复」自动化，这样你就能用 `git bisect run` 跑它。
9. **差分回路。** 把同一个输入分别跑过旧版本 vs 新版本（或两套配置），对输出做 diff。
10. **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：如上所述，固定且高复现率）。
- [ ] **快速的**——以秒计，而非以分钟计。
- [ ] **可由智能体运行**——你能无人值守地运行它；只有通过 `scripts/hitl-loop.template.sh` 才会有人介入回路。

如果你发现自己在这条命令存在之前就在读代码建立理论，**停下——直接跳到假设正是本技能要防止的失败。** 没有能变红的命令，就没有阶段 2。

## 阶段 2 — 复现 + 最小化

运行回路。看着它变红——bug 出现了。

确认：

- [ ] 回路产生的是**用户**所描述的失败模式——而不是碰巧就在附近的另一个失败。错的 bug = 错的修复。
- [ ] 该失败在多次运行中可复现（或者，对非确定性 bug 而言，以足够高的复现率复现，可供调试）。
- [ ] 你已捕获确切的症状（错误信息、错误输出、缓慢的耗时），以便后续阶段验证修复是否真的解决了它。

### 最小化

一旦它变红，就把复现收缩到**仍会变红的最小场景**。**一次一个**地裁掉输入、调用方、配置、数据和步骤，每裁一次就重新运行回路——只保留对失败起承重作用的部分。

为什么值得费这个功夫：最小复现缩小了阶段 3 的假设空间（剩下要怀疑的活动部件更少），并成为阶段 5 中干净的回归测试。

当**每一个剩下的元素都起承重作用**时即完成——移除其中任何一个都会让回路变绿。

在你完成复现**且**最小化之前，不要继续。

## 阶段 3 — 提出假设

在测试任何假设之前，先生成**3–5 个排序的假设**。单一假设的生成会把你锚定在第一个看似合理的想法上。

每个假设都必须是**可证伪的**：陈述它所做出的预测。

> 格式：「如果  是原因，那么  会让 bug 消失 /  会让它更严重。」

如果你说不出这个预测，那这个假设就只是一种感觉——丢弃它或把它磨锐利。

**在测试前把排序好的清单展示给用户。** 他们往往有能瞬间重新排序的领域知识（「我们刚给 #3 部署了一个改动」），或者知道他们已经排除的假设。廉价的检查点，节省大量时间。别为此阻塞——如果用户不在（AFK），就按你的排序继续。

## 阶段 4 — 插桩

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

工具偏好：

1. **调试器 / REPL 检查**，如果环境支持。一个断点胜过十条日志。
2. **有针对性的日志**，放在区分各假设的边界上。
3. 绝不「把所有东西都打日志然后 grep」。

**给每条调试日志打上标签**，用一个唯一前缀，例如 `[DEBUG-a4f2]`。这样最后的清理就变成一次 grep。没打标签的日志会残留；打了标签的日志会被清除。

**性能分支。** 对于性能回退，日志通常是错误的做法。相反：先建立一个基线测量（计时脚手架、`performance.now()`、性能分析器、查询计划），然后二分。先测量，后修复。

## 阶段 5 — 修复 + 回归测试

在修复**之前**先写回归测试——但仅当存在一个**正确的接缝**时。

正确的接缝是指测试在调用点上触发**真实 bug 模式**的那种接缝。如果唯一可用的接缝太浅（当 bug 需要多个调用方时却只有单调用方的测试，或者无法复现触发 bug 的调用链的单元测试），那里的回归测试会给出虚假的信心。

**如果不存在正确的接缝，这本身就是一个发现。** 记下它。代码库架构正在阻止 bug 被锁定。把这一点标记出来交给下一阶段。

如果存在正确的接缝：

1. 把最小复现变成该接缝上的一个失败测试。
2. 看着它失败。
3. 应用修复。
4. 看着它通过。
5. 针对原始（未最小化的）场景重新运行阶段 1 的反馈回路。

## 阶段 6 — 清理 + 复盘

在宣布完成之前必须做到：

- [ ] 原始复现不再复现（重新运行阶段 1 的回路）
- [ ] 回归测试通过（或已记录接缝的缺失）
- [ ] 所有 `[DEBUG-...]` 插桩都已移除（`grep` 那个前缀）
- [ ] 一次性原型已删除（或移到明确标记的调试位置）
- [ ] 在 commit / PR 消息中陈述最终被证明正确的那个假设——这样下一个调试者能学到东西

**然后问：什么本可以预防这个 bug？** 如果答案涉及架构变更（没有好的测试接缝、调用方纠缠、隐藏的耦合），就带着具体细节交给 `/improve-codebase-architecture` 技能。这个建议要在修复到位**之后**给出，而不是之前——你现在掌握的信息比开始时多。

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [WenWuZhiDao](https://github.com/WenWuZhiDao)
- **Source:** [WenWuZhiDao/mattpocock-skills-zh](https://github.com/WenWuZhiDao/mattpocock-skills-zh)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-wenwuzhidao-mattpocock-skills-zh-diagnosing-bugs
- Seller: https://agentstack.voostack.com/s/wenwuzhidao
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
