# Diagnose And Fix

> "诊断优先"的问题修复 skill。Use when 用户报告一个根因不明、需先定位再动手的问题（疑难 bug、隐蔽的行为异常、性能/并发问题、架构或安全隐患），而非一眼可改的简单修复时。简单机械的改动或已有明确方案的修复不必走本 skill。 接收一个问题（自由文本、issue 编号，或问题列表文件 + 编号），先侦察项目、追踪相关代码、验证问题是否真实存在，产出结构化【诊断报告】（代码分析、根本原因、影响范围、修复方案）；用户选定方案后再执行修复 → 测试 → 修复后验证 → 提交。 若输入是问题列表，修复后只在文件内标记 resolved、不提交该变更；要批量循环处理整个问题列表请用 diagnose-and-fix-batch skill。

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

---


# Diagnose and Fix Skill

可由 agent 按场景自动触发，也可手动调用：

```
@diagnose-and-fix "<问题描述>"
@diagnose-and-fix <问题列表文件> <编号>
@diagnose-and-fix                          # 进入交互模式，引导用户描述问题
```

## 设计理念

本 skill 强制执行"**理解优先于修改**"原则：

1. **Phase 1 — 诊断**：系统性探索项目，验证问题，产出诊断报告
2. **Phase 2 — 确认**：用户审阅报告，选择修复方案
3. **Phase 3 — 修复**：按确认方案执行修改、测试、验证、提交

诊断不充分时，Phase 2 会阻断流程，避免基于错误假设盲目修改。

## Phase 1 — 系统性诊断

### Step 1.1 — 问题接收与澄清

解析调用参数，提取问题描述。若信息不足，向用户询问以下几项（知道的填，不确定的跳过）：问题现象、预期行为、复现步骤、错误信息原文、已知相关文件/函数。

### Step 1.2 — 项目结构侦察

在读任何具体文件前，先建立项目全貌——用你的文件检索工具（Glob/Grep/Read，别逐个裸 `cat`），快速摸清三件事：

- **语言与框架**：看依赖清单（`go.mod` / `package.json` / `Cargo.toml` / `pubspec.yaml` / `pom.xml` / `requirements.txt` 等）
- **架构与核心目录**：入口在哪、代码主干如何组织
- **测试框架**：有没有、是什么

目的是为后续定位画一张地图，不是把整棵目录树读进上下文。仓库较大时可派 `Explore` subagent 并行侦察、只取结论。

用一两句话汇报侦察结果：语言/框架、架构模式、核心目录、测试框架（未检测到就注明）。

### Step 1.3 — 问题定位与代码追踪

围绕问题描述检索并阅读相关代码。目标是**找到根因，而不是停在第一个看起来可疑的地方**——所以下面几个角度都要覆盖到，但顺序按实际线索走，不必教条：

- **关键词检索**：用错误信息、函数名、变量名定位入口（用 Grep 工具按文件类型过滤，别用裸 `grep`）
- **调用链**：从入口向下追到问题点，记录每一跳的文件:行号
- **数据流**：追踪数据从输入到输出的转换路径，标出可疑的转换点
- **边界与异常路径**：空值、错误传播、并发、资源释放、状态一致性——bug 常藏在这里

**问题涉及外部 API / 协议 / SDK 时**（对接第三方调不通、签名或鉴权失败、返回与文档不符），追踪对象从仓内代码扩到外部契约：先找到官方文档或可运行的参考实现（官方 SDK 源码、GitHub demo），把 headers、body、参数生成逻辑与工具函数实现**逐字段**比对——「看起来差不多」不算比对过。禁止无证据归因：「可能是 X」必须先验证再写进报告。若同一假设在没有新信息的情况下已重复试错两轮，停止同方向试错，改走参考实现比对或与可工作版本的 diff。

把所有发现记下来，为 Step 1.4 验证和 Step 1.5 报告提供原始素材。

### Step 1.4 — 问题验证

**验证问题是否真实存在**，避免基于错误假设修复：

| 验证项 | 结论 |
|--------|------|
| 代码中是否存在描述的行为？ | ✅ 确认 / ❌ 不存在 / ⚠️ 部分存在 |
| 问题是否可被当前代码路径触发？ | ✅ 可触发 / ❌ 条件不满足 / ⚠️ 概率性 |
| 问题描述是否与代码实际行为一致？ | ✅ 一致 / ❌ 描述有误 / ⚠️ 需更多信息 |

两种提前收束（均**不修改代码**，对应末尾「终态」）：

- **问题不存在 / 描述与代码对不上**：告知用户实际观察到的行为，询问重新描述还是跳过。用户确认跳过 → 终态 `skipped_inconsistent`。
- **问题已被缓解 / 无需修复**：说明现状，确认后——若输入为问题列表则按 Step 3.6 标记（`fix_solution: no-op: <原因>`、`commit: none`）——终态 `skipped_noop`。

否则继续 Step 1.5。

### Step 1.5 — 诊断报告生成

#### 修复方案：生成与推荐规则

报告里的每个方案都是**可执行的推荐，不是草图**——给出具体改法、落点文件/函数。生成与推荐时守住下面这条线：

- **推荐标准**：选「最标准、最佳实践、且匹配本项目规模」的方案，不是最复杂的。**忽略实现工时**，只权衡正确性与运维契合度；推荐方案要对得上【根本原因】分类，治根因而非补症状。
- **右尺寸**：不引入超出问题所需的抽象、可配置性、分层；也不用「就地打补丁」掩盖根因。能 50 行解决就别写 200 行。
- **遵循项目约定**：若仓库有 `conventions/` 或既成模式，优先选贴合它们的方案；若启用了 `code-conventions` skill，加载它作为规范来源。
- **方案数量按需**：
  - 根因清晰、最佳解唯一 → 只给**一个**推荐方案，附一句「为何不考虑其它思路」。
  - 存在 **2–3 个各有取舍、且代码本身无法裁决**的合理方案 → 才并列，每个配一句 trade-off，并对推荐项标 `[推荐]`，在【方案比较】里说明核心取舍。
- **quick-fix 直通**：当修复**无歧义、纯机械、无需任何设计讨论**（如错误日志级别、缺失 nil/error 检查、硬编码值提取为配置、配置键拼写、死导入）→ 在方案名后标 `[quick-fix]`，可省去多方案对比，直接进确认。**任何需要设计取舍的改动都不是 quick-fix。**

输出完整的结构化诊断报告：

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 诊断报告
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

【问题摘要】
  描述：<一句话概括问题>
  严重性：P0 崩溃/数据损坏 | P1 功能失效 | P2 行为异常 | P3 体验问题
  验证状态：✅ 已确认 | ⚠️ 部分确认 | ❌ 未确认

【代码分析】
  问题位置：
    - <文件路径>（第N行，FunctionName）
    - <文件路径>（第N行，FunctionName）  ← 若涉及多处

  调用链：
    <入口> → <中间层> → <问题点>

  相关代码片段：
    ```<语言>
    // <文件>:<行号>
    <关键代码，精简，仅展示问题相关部分>
    ```

【根本原因】
  <清晰、具体的一到三段描述>
  原因分类：逻辑错误 | 竞态条件 | 资源泄漏 | 配置错误 | 接口契约违反 | 缺失校验 | 其他

【影响范围】
  直接影响：<受影响的功能/模块>
  潜在影响：<可能的连带问题>
  数据风险：<是否有数据一致性风险>

【修复建议】  （方案数量按上方规则；机械修复在名称后标 [quick-fix]）

  方案 A — <名称>  [推荐]
    做法：<具体改法，含落点文件/函数>
    优点：<为什么好（对得上根本原因）>
    缺点/风险：<需要注意>
    改动范围：<预计修改哪些文件>
    改动量：小（<20行）| 中（20-100行）| 大（>100行）

  方案 B — <名称>                      ← 仅多方案时
    做法：<具体改法>
    优点：<为什么好>
    缺点/风险：<需要注意>
    改动范围：<预计修改哪些文件>
    改动量：小 | 中 | 大

【方案比较】
  单方案：一句话说明为何不考虑其它思路。
  多方案：说明为什么推荐 A 而非 B，核心取舍是什么。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
请选择：
  A) 采用方案 A 进行修复
  B) 采用方案 B 进行修复          ← 仅多方案时列出
  C) 我有其他想法：___
  D) 报告有误，我想补充信息
  E) 仅需报告，暂不修复
```

## Phase 2 — 用户确认

等待用户回复，按选择处理：

- **A / B**：进入 Phase 3，执行对应方案
- **C（自定义）**：用户说明想法后，评估可行性，给出简短分析，再次确认后进入 Phase 3
- **D（补充信息）**：接收补充，回到 Step 1.3 重新分析，更新报告后再次等待确认
- **E（仅报告）**：输出 `📄 诊断完成，未执行修复` 后结束（终态 `user_declined`）。不写问题列表（如需手动改状态，见末尾「终态」说明）

## Phase 3 — 修复执行

### Step 3.1 — 修改代码

按确认方案最小范围修改，保持原代码风格。追踪所有改动文件和行号。

改完后简述：每个文件改了什么、总增删行数。

### Step 3.2 — 测试

**复用 Step 1.2 侦察到的测试框架**，不从零重新探测。命令优先级：项目自定义入口（Makefile `test` 目标 / `package.json` `scripts.test`）→ 该语言的约定测试命令 → 均无则询问用户。

优先只跑覆盖本次改动的测试（按包/目录/文件缩小范围）以快速反馈；通过后再视耗时跑一次相关全量，确认无回归。

**测试失败时**：展示错误摘要，说明准备如何调整，询问确认后回到 Step 3.1 重试，最多 **3 次**。超限则告知用户，停止流程，不提交，不标记（终态 `skipped_test_failed`）。

输出：`🧪 测试通过（N 用例）` 或 `❌ 测试失败：<摘要>`

### Step 3.3 — 格式化

**沿用 Step 1.2 的语言/工具链判定**，只对本次修改的文件执行。优先用项目自带的格式化入口（Makefile `fmt`/`lint` 目标、`package.json` `scripts.format`/`scripts.lint`、仓库内 formatter 配置如 `.prettierrc`/`rustfmt.toml`/`.golangci.yml`），无则回退该语言的默认格式化工具。

未找到工具时跳过并提示，不阻塞流程。

输出：`🎨 格式化完成` 或 `⚠️ 未找到格式化工具，已跳过`

### Step 3.4 — 修复验证与代码 review

两道独立把关，都通过才进提交。

**(1) 修复验证 — 独立 subagent**

与 Step 1.4「验证问题存在」对称：修复后必须独立确认「问题已消除」，而不是默认改完就好。派一个验证 subagent（`Explore` 或 `general-purpose`），**只喂**：原问题描述、Step 1.4 的三项结论、本次改动文件:行号。让它**不预设修复成功**，对照 Step 1.4 逐条复核，重点落在根因/复现路径：

| 验证项 | 修复前（Step 1.4） | 期望修复后 |
|--------|------------------|-----------|
| 描述的行为是否仍存在？ | ✅ 确认 | ❌ 已消除 |
| 问题路径是否仍可触发？ | ✅ 可触发 | ❌ 不可触发 |
| 根因是否已被消除？ | — | ✅ 已消除 / ⚠️ 部分 / ❌ 未消除 |

subagent **只回结论、不改代码**。判定「未消除 / 部分消除」即视为修复未达标 → 回 Step 3.1 重改（与 Step 3.2 测试**共享同一 3 次重试上限**，超限则停止、不提交、不标记，终态 `skipped_test_failed`）。

**(2) 代码 review — 引用现有 skill**

若启用了 `code-review` 或 `requesting-code-review` skill，调用它审查本次 diff，重点：是否真正治根因（对得上诊断报告）、有无引入回归、是否符合选定方案与项目约定。未启用则跳过并提示。

- review 报出的 **P0/P1** 先处理（回 Step 3.1，计入同一重试预算）再继续；
- **P2/P3** 记入完成摘要，交用户决定是否本次一并处理。

输出：`🔍 修复验证：问题已消除` + `🧐 review：N 项（P0:x P1:x P2:x P3:x）` 或对应失败/跳过摘要。

### Step 3.5 — 提交

修复方案已在 Phase 2 确认，此处**直接提交，无需再次询问**。

提交前先看 `git log` 近若干条提交，沿用项目既有的 commit 风格（type 集合、scope 命名、语言）；项目无明显约定时按下方缺省规范。

再执行 `git diff --name-only HEAD` 核查改动文件：仅当混入与本次修复无关的改动时才停下告知用户由其决定；否则只 add 本次修改的文件后直接提交：

```bash
git add <仅本次修改的文件>
git commit -m "<subject>" -m "<body>" -m "<footer>"
```

**Commit 消息规范（缺省）：**
```
<type>(<scope>): <subject>   ← 动词原形开头，≤72字符，不加句号

[body]  ← 解释"为什么"，引用诊断报告根本原因，可选

Fixes: <问题描述一句话>
```

- type：`fix`（bug）/ `refactor`（重构）/ `perf`（性能）/ `security`（安全）/ `feat`；项目另有惯用 type 则从其惯例。
- scope：取自本次改动所在的模块/包/目录，与项目既有 scope 命名保持一致。

输出：`🎉 <hash7> — <subject>`

### Step 3.6 — 标记问题列表（仅当输入为问题列表文件时）

若本次输入是问题列表文件 + 编号，修复完成后把对应条目标记为已修复——**但不提交这次变更**。这是有意为之：本 skill 聚焦单个问题的诊断与修复，问题列表的提交时机交给你统一掌控（要批量循环处理整个问题列表，用 `diagnose-and-fix-batch` skill）。

按原文件格式写入：

| 字段 | 值 |
|------|----|
| status | resolved |
| resolved_at | YYYY-MM-DD |
| fix_solution | 已选方案名 + 一句描述 |
| commit | 代码提交的 `<hash7>`，未提交则填 `uncommitted` |

写入格式：
- Markdown → 追加 `### ✅ 修复记录` 小节
- JSON → 合并字段到对应对象
- YAML → 追加字段到对应条目
- 纯文本 → 追加 `[resolved DATE | 方案 | commit: HASH]`

文件只读时，输出待写内容供你手动应用。完成后提示：`📝 已标记 #<编号> resolved（未提交，提交时机由你决定）`

## 完成摘要

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🏁 诊断与修复完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
问题：<一句话>
严重性：P<N>
根本原因：<一句话>
采用方案：<方案名>
改动文件：<N> 个
测试：通过（N 用例）
修复验证：问题已消除
代码 review：N 项（P0:x P1:x P2:x P3:x） 或 未启用
提交：<hash7> 或 未提交
问题列表：已标记 resolved（未提交） 或 不适用
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

## 终态

本 skill 处理单个问题的最终结果，归为下列其一。被 `diagnose-and-fix-batch` 编排时，subagent 据此映射上报；独立使用时仅作为收束说明。**只有 `completed` 与 `skipped_noop` 会写问题列表**（若输入为问题列表），其余跳过态不动列表，并提示用户可手动把状态设为 `skipped`。

| 终态 | 触发点 | 含义 |
|------|--------|------|
| `completed` | Step 3.5/3.6 | 修复完成；代码已提交（git 未初始化等情况则未提交），问题列表已标记 resolved |
| `skipped_inconsistent` | Step 1.4 | 问题不存在 / 描述与代码对不上，用户确认跳过 |
| `skipped_noop` | Step 1.4 | 问题已缓解 / 无需修复，用户确认（列表标记 `no-op`） |
| `user_declined` | Phase 2-E | 用户选「仅报告，暂不修复」 |
| `skipped_test_failed` | Step 3.2/3.4 | 测试或修复后验证重试超 3 次，停止、不提交、不标记 |

## 错误处理

各 Step 内已说明的失败处理（验证不存在、测试/验证超限、review 分级）不再重复，此处只列横切与环境类异常：

| 情况 | 处理 |
|------|------|
| 问题描述过于模糊 | 进入交互模式，引导用户补充 |
| 涉及多个独立问题 | 拆分为子问题，分别给出修复建议，询问优先修复哪个 |
| git 未初始化 | 跳过提交，仍完成修改、测试、验证 |
| 工作区有无关改动 | 提交前告知用户，由其决定是否 stash |
| 代码 / 问题列表文件只读 | 输出待写内容供手动应用，不直接写入 |

