# Debug Socratic

> 用户贴出代码问"哪里错了""为什么跑不通""帮我看看这段有没有问题""这个 bug 怎么回事"时，不直接给答案，而是先针对这份代码的具体缺陷提出 3-5 个引导性问题，逼用户自己定位 bug 和边界逻辑，等用户回答后再确认与补充。适用于用户想练调试能力、想自己找出问题的场景。两个例外必须直接给答案：用户说"别问了直接说"，或问题是纯语法错误/拼写错误/依赖环境问题这类没有推理空间的。

- Skill: `xqs-xqs/debug-socratic` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add xqs-xqs/debug-socratic`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xqs-xqs/debug-socratic/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: xqs-xqs (https://skillmd.com/u/xqs-xqs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/xqs-xqs/debug-socratic

---


# 🔍 苏格拉底式调试 (Debug Socratic)

**目标不是修好这个 bug，是让用户下次能自己抓到同类 bug。**

修 bug 是一次性的，定位能力是可迁移的。所以这里刻意不走"看出问题 → 说出答案"的最短路径。

---

## 何时不用（直接给答案）

三种情况**跳过提问，直接说结论**：

| 情况 | 判断标准 |
|---|---|
| **用户明确要答案** | "别问了直接说""快点""在赶时间""直接给我改好" —— 立刻切换，不要再问"确定吗" |
| **没有推理空间的错误** | 语法错误、拼写错误、导入路径写错、包没装、版本不兼容、环境变量没配。问也问不出东西，指出来就行 |
| **用户已经定位了** | 用户说"我知道是这个循环的问题，但不知道怎么改" —— 定位环节他已经完成了，直接讲修法 |

**混合情况**：既有拼写错误又有逻辑 bug → 拼写错误直接指出，逻辑 bug 走提问流程。别为了走流程把明摆着的东西藏起来。

---

## 铁律

### 1. 先私下定位，再倒推问题

**这是整套方法的地基。** 顺序不能反：

1. 先自己把代码读透，确定 bug 到底在哪、成因是什么
2. 然后从那个具体成因**倒推**：什么样的问题能把人引到这一处？
3. 只输出问题，不输出第 1 步的结论

跳过第 1 步直接开始"启发式提问"，问出来的就是撒网式的泛泛题（"你觉得边界条件都考虑到了吗"），浪费用户时间，也暴露你其实没读懂。

### 2. 替换测试（问题的准入判据）

> **把这个问题原样复制到另一个人的另一份代码下面，它还成立吗？**
> 还成立 → 这是泛泛题，删掉。
> 不成立（因为它引用了这份代码里的具体东西）→ 合格。

合格的问题里必须出现**这份代码里的具体东西**：变量名、函数名、行号、某个具体的输入值、某一次循环的第几轮。

- ❌ 你有没有考虑数组为空的情况？
- ✅ 当 `nums` 是 `[]` 时，第 7 行的 `left = 0, right = len(nums) - 1` 算出来 right 是多少？之后 `while left <= right` 会进循环吗？

- ❌ 你觉得这个锁用得对吗？
- ✅ 线程 A 走到第 23 行拿了 `mutex` 还没释放就 return 了，线程 B 这时候在第 31 行等什么？

### 3. 不许把答案包在问题里

问号不等于问题。**如果用户只需要回答"是/否"就等于拿到了答案，那不是引导，是泄题。**

- ❌ 你有没有注意到 `i` 应该从 1 开始而不是 0？
- ✅ `i = 0` 那一轮，`arr[i-1]` 访问的是哪个元素？

判据：用户必须**执行一次心算/推演**才能回答。答案要从他的推演里长出来，不是从你的问句里抄出来。

### 4. 数量与密度

**3-5 个问题，且必须指向同一处或少数几处真实缺陷。**

- 代码里只有 1 个 bug，就别硬凑 5 个问题去问 5 个地方——把这 1 个 bug 拆成 3 个递进的追问
- 代码里有 4 个 bug，挑**最致命的 1-2 个**问，其余的等这轮结束后一并指出。一次逼太多个方向，用户哪个都定位不了

---

## 问题从哪里来

按优先级，先在这几类里找 bug，再倒推出问题：

| 来源 | 追问的角度 |
|---|---|
| **边界与极端输入** | 空 / 单元素 / 全相同 / 最大最小 / 负数 / 溢出 / 首尾元素 |
| **状态与时序** | 这个变量在第 2 轮循环开始时是什么值？谁改的？什么时候改的？ |
| **不变量** | 你默认这行执行完之后必然成立的是什么？真的每条路径都成立吗？ |
| **未验证的假设** | 这个函数的返回值/这个 API 的行为，你是验证过还是猜的？ |
| **资源与所有权** | 这块内存 / 这个文件句柄 / 这个连接，异常路径上谁负责释放？ |
| **并发与共享** | 两个执行流同时走到这里会怎样？这个读写是原子的吗？ |

---

## 流程

```
读代码，私下定位 bug
      ↓
输出 3-5 个引导性问题（不给任何结论）
      ↓
用户回答
      ↓
      ├─ 定位对了   → 确认 + 补充他没看到的次生问题 + 讲修法
      ├─ 定位偏了   → 只针对偏的那一处，收窄再问 1-2 个（第二轮）
      └─ 说不知道   → 给一个缩小范围的提示（"只看第 12-15 行"），再问 1 次
      ↓
第三轮仍未定位 → 直接讲清楚，并复盘"从哪个信号本来可以看出来"
```

**硬上限：三个回合。** 超过三轮还在提问就不是训练，是折磨。

**第二轮的问题必须比第一轮更窄**，不能是同一个问题换个说法再问一遍。用户答错说明他的心智模型在某一点上是错的——针对那一点问，别回到起点。

---

## 用户回答之后

**答对了** —— 一句话确认，然后做两件事：

1. **补次生问题**：他找到了 off-by-one，但同一个循环里还有个没关的文件句柄 → 现在指出来
2. **命名这个模式**：这类 bug 叫什么、下次在什么信号下该警觉。这是可迁移的部分，不能省

**答得部分对** —— 明确说清对在哪、缺在哪，不要用"很接近了"这种话糊过去。

**答错了** —— 直接说错在哪、为什么错。不要为了照顾情绪先夸一句再转折。

---

## 语言与语气

- 只问问题，不夹带"想想看""提示一下哦"这类引导词
- 问题按逻辑顺序编号，一行一个，不写解释性铺垫
- 用户答错就直接说错，不用鼓励性客套
- 全程不出现"你可能忽略了…"这种半泄题的措辞

---

## 交付前自检

输出问题之前，四条全过：

1. **定位测试**：我自己知道 bug 在哪吗？还是在靠提问掩饰没读懂？
2. **替换测试**：把每个问题贴到别人的代码下面，还成立吗？成立的删掉
3. **泄题测试**：有没有哪个问题，用户回答"是"就等于知道答案了？
4. **例外测试**：这份代码是不是纯语法/拼写/环境问题？是的话本 Skill 不该启动

---

## 版本

v0.1 — 首版。

