---
name: debug-expert
description: "Use when 程序出现错误、异常、崩溃，或行为与预期不符，或测试失败，或无法定位问题根因时。触发场景：调试、debug、报错、错误、异常、bug、问题排查、故障排查、不工作、崩溃、无法运行、出错了、为什么不生效、运行报错、跑不起来、程序挂了。"
---

# 调试专家

铁律：**先理解，再修改。** 禁止在没有复现和定位根因之前就修改代码（猜测式修改往往掩盖真实问题）。

<HARD-GATE>
在完成**阶段二（假设清单）**和**阶段三（最小复现）**之前，禁止对任何代码做出修改。
即便你"知道"原因，也必须先建立假设清单并尝试复现，再动手修改。
</HARD-GATE>

## Inputs / Outputs / Gates / Handoffs（统一契约）

- **Inputs（最小输入）**：期望 vs 实际；完整错误信息/日志/堆栈；可复现步骤（如有）；最近改动（如有）；运行环境信息（OS/版本/命令）。
- **Outputs（产物形态）**：一份可交接的调试记录（结构参考 `references/debug-log-template.md`），包含假设清单、最小复现、证据链、验证命令与回归建议。
- **Gates（继续前必须满足）**：
  - 未完成“假设清单 + 最小复现”前禁止修改代码（保持与本文件 HARD-GATE 一致）。
  - 宣称“已修复”前必须运行验证命令并贴出绿色输出或关键结果（保持与本文件后续 HARD-GATE 一致）。
  - 通用门控清单可复制使用：`../code-review-expert/references/quality-gates-checklist.md`。
- **Handoffs（推荐下游）**：
  - `tdd-master（TDD 开发大师）`：先写能复现问题的测试，再修复
  - `writing-plans（实施计划编写）`：把修复拆成可执行步骤（适合复杂问题）
  - `code-review-expert（代码审查专家）`：变更后做质量门禁

## 调试工作流

### 阶段一：问题理解

收集足够的背景信息（每次最多问 2-3 个问题）：

**必须了解**：
- "期望行为是什么？实际发生了什么？"
- "错误信息或日志是什么？"（要求贴出完整错误，不要省略）
- "最后一次正常工作是什么时候？中间做了什么改动？"

**按需追问**：
- "是否能稳定复现？还是随机出现？"
- "在什么环境发生的？（本地/测试/生产，什么 OS/版本）"
- "是否有完整的调用堆栈？"

**明确禁止**：在没有完整错误信息时就开始猜测原因。

---

### 阶段二：建立假设

根据现有信息，生成 2-5 个可能的假设（从最可能到最不可能排序）：

```
假设清单：
1. [假设 A]：可能性 高/中/低，理由：[...]
2. [假设 B]：可能性 高/中/低，理由：[...]
3. [假设 C]：可能性 高/中/低，理由：[...]

验证计划：先验证假设 1，因为 [原因]。
```

**思考方向**：
- 最近的改动（最可能的原因）
- 环境差异（本地可以，线上不行 → 看配置、依赖、权限）
- 数据问题（特定数据触发 → 看边界条件）
- 并发/时序问题（随机出现 → 看竞态条件）
- 外部依赖（网络/数据库/第三方服务）

---

### 阶段三：最小复现

在验证假设之前，先建立最小可复现的测试案例：

```python
# 目标：用最少的代码稳定复现问题
# 好处：
# 1. 确认问题确实存在（而非环境问题）
# 2. 排除无关因素
# 3. 修复后可用作回归测试

# 最小复现示例
def test_bug_reproduction():
    # 最简单的触发路径
    result = problematic_function(minimal_input)
    assert result == expected  # 这一行会失败
```

**如果无法复现**：
- 说明是环境问题 → 系统对比两个环境的差异
- 说明是特定数据问题 → 询问触发数据的特征

加载 `references/root-cause-analysis.md` 获取系统化分析工具。

---

### 阶段四：定位根因

使用二分法逐步缩小问题范围：

```
定位策略：
1. 确认问题的边界（从哪里开始出错，到哪里结束）
2. 在中间点添加检查点，判断问题在前半段还是后半段
3. 重复，直到定位到具体的函数/行
```

**常用调试工具**：

```python
# Python：pdb 调试
import pdb; pdb.set_trace()  # 设置断点

# 或者使用 print 调试（快速但临时）
print(f"DEBUG: variable={variable!r}, type={type(variable)}")

# 日志记录
import logging
logging.debug("状态: %s", state)
```

```bash
# 查看进程状态
ps aux | grep process_name
# 查看端口占用
lsof -i :8080
# 查看系统日志
journalctl -u service_name -n 100 --no-pager
# 查看 Docker 容器日志
docker logs container_name --tail 100
```

加载 `references/debugging-patterns.md` 获取特定类型问题的调试模式。

---

### 阶段五：修复与验证

定位根因后：

1. **制定修复方案**（不要第一个想到的方案就是最好的）：
   - 方案 A：[描述]，优点/缺点
   - 方案 B：[描述]，优点/缺点
   - 推荐：[哪个方案，为什么]

2. **实施修复**

3. **验证清单**（完成前强制检查，不得跳过）：

<HARD-GATE>
在宣布"已修复"之前，必须在本条消息中实际运行验证命令，得到绿色输出才能结束。不得仅凭分析判断就宣称修复完成。
</HARD-GATE>

   - [ ] 原始问题是否已解决？（运行最小复现案例）
   - [ ] 是否有其他类似的代码也存在相同问题？（用 `rg` 全局搜索）
   - [ ] 修复是否引入了新问题？（运行完整测试套件）
   - [ ] 是否需要添加回归测试防止将来重现？
   - [ ] 根因是否真正解决，而非只是绕过症状？

4. **记录**（如果是重要的 Bug）：
   ```
   根因：[什么导致的]
   触发条件：[什么情况下会触发]
   修复方式：[如何修复]
   预防措施：[如何防止再次发生]
   ```

---

## 特殊问题处理

### 随机/偶发性问题

- 极大概率是**竞态条件**或**内存问题**
- 增加日志详细度，在生产环境收集更多信息
- 检查并发访问共享资源的代码
- 使用压测工具提高触发频率

### 只在特定环境出现

系统对比两个环境：
```bash
# 对比环境变量
diff <(env | sort) <(ssh prod 'env | sort')
# 对比依赖版本
pip freeze vs pip freeze（生产）
# 对比配置文件
diff local.env prod.env
```

### 性能问题

先测量，再优化，不要靠直觉：

```python
# Python 性能分析
import cProfile
cProfile.run('main_function()', sort='cumulative')

# 简单计时
import time
start = time.perf_counter()
# ...代码...
print(f"耗时：{time.perf_counter() - start:.3f}秒")
```

---

## 红旗警告：当你想跳过流程时

遇到以下想法，立刻停下，回到当前应该所在的阶段：

| 借口 | 现实 |
|------|------|
| "错误很明显，我知道原因，直接改就好" | "明显原因"往往是症状不是根因。30 秒建个假设清单不会耽误你。 |
| "问题太紧急，没时间走流程" | 猜测式修改引入新 bug 比走流程耗时更长。紧急时更要冷静。 |
| "已经修了类似的 bug，这次一样" | 表面相似的 bug 根因可能完全不同。相似性是陷阱。 |
| "最小复现太麻烦，能复现就行" | 无法最小复现 = 无法确认修复 = 留下定时炸弹。 |
| "测试过了，差不多能用" | "差不多"不是通过标准。必须运行验证清单中的每一项。 |
| "这个问题太随机，复现不了" | 随机问题 = 竞态条件/内存问题。不复现不代表可以跳过假设阶段。 |

## 参考资源

- `references/root-cause-analysis.md` — 根因分析工具和框架
- `references/debugging-patterns.md` — 常见问题类型的调试模式
