Systematic Debugging - 系统化调试

SkillDev tools

用于遇到缺陷、测试失败或异常行为,且必须在提出修复方案前调查根因的场景。未经根因分析不得只修复表象。

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Systematic Debugging - 系统化调试 skill

What this skill tells your AI

The instructions your AI receives, as published by huangwb8/skills in skills/alpha/awesome-code/agents/systematic-debugging/SKILL.md and read by ahel’s review.

铁律

NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST

违反规则的信件就是违反规则的精神。

无例外

  • 不跳过根因调查直接修复
  • 不基于猜测进行修复
  • 不尝试多个更改同时测试
  • 不在不完全理解的情况下修复

常见合理化

借口现实
"快速修复现在,稍后调查"永不会有"稍后"。技术债积累
"尝试改变 X,看是否有效"猜测不是调试。可能碰巧修复但未理解
"添加多个更改,运行测试"无法确定哪个更改有效。浪费调试时间
"可能大概差不多是 X"模糊理解导致错误修复
"不完全理解但可能有效"理解不完全=修复不完整

红色标志 - 停止并重新开始

  • "快速修复现在,稍后调查"
  • "尝试改变 X,看是否有效"
  • "添加多个更改,运行测试"
  • "可能大概差不多是 X,让我修复"
  • "不完全理解但可能有效"
  • 基于猜测而非证据的修复

所有这些意味着:停止修复。回到根因调查阶段。


四阶段框架

阶段 1:根因调查

任何修复前

  1. 仔细阅读错误消息

    • 不要跳过错误或警告
    • 它们通常包含确切解决方案
  2. 一致复现

    • 你能可靠触发吗?
  3. 检查最近变更

    • 什么变更可能导致此问题?
  4. 多组件系统收集证据

    # 对于每个组件边界:
    - 记录进入组件的数据
    - 记录退出组件的数据
    - 验证环境/配置传播
    - 检查每层状态
    运行一次以收集显示何处中断的证据
    然后分析证据以识别失败组件
    然后调查该特定组件
    
  5. 追踪数据流

    • 向后追踪到坏值起源

阶段 2:模式分析

  1. 找到工作示例
  2. 与参考对比
  3. 识别差异
  4. 理解依赖

阶段 3:假设与测试

  1. 形成单一假设:"我认为 X 是根本原因,因为 Y"
  2. 最小化测试:进行最小可能更改
  3. 验证后再继续
  4. 3+ 次修复失败时:质疑架构

阶段 4:实现

  1. 创建失败测试用例
  2. 实施单一修复:只改验证该假设所需的最小范围
  3. 验证修复:一次只验证一个假设,不把多个修复混在同一次验证里
  4. 收敛范围:避免顺手重构、无关格式化或新增未证明必要的抽象
  5. 如果 3+ 次修复失败:质疑架构

核心理念

系统化调试 不是碰运气,而是方法化地解决问题的科学流程。

┌─────────────────────────────────────────────────────────┐
│  收集证据 → 形成假设 → 系统验证 → 定位根因 → 实施修复  │
└─────────────────────────────────────────────────────────┘

核心原则

  • 基于证据,而非猜测
  • 治疗根本原因,而非症状
  • 一次验证一个假设
  • 记录整个过程

何时使用本技能

在以下场景时激活:

  • 出现错误、异常、Bug
  • 需要分析堆栈追踪(Stack Trace)
  • 提到"调试"、"排查问题"、"定位根因"
  • 生产环境问题分析
  • 跨文件或跨模块的问题追踪
  • 间歇性 Bug(时有时无)

调试工作流程

步骤 1:收集证据 📋

信息收集清单

证据类型收集方法重要性
完整堆栈追踪复制完整错误信息⭐⭐⭐⭐⭐
相关日志查看应用日志⭐⭐⭐⭐⭐
复现步骤记录如何触发问题⭐⭐⭐⭐
环境信息OS、版本、依赖⭐⭐⭐
代码变更最近的 Git 提交⭐⭐⭐⭐
用户输入触发问题的数据⭐⭐⭐

堆栈追踪分析示例

# 示例错误
Traceback (most recent call last):
  File "app.py", line 45, in process_order
    result = payment_service.charge(amount)
  File "payment.py", line 78, in charge
    return api_client.post("/charge", data)
  File "api.py", line 23, in post
    response = self.session.request(method, url, **kwargs)
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

分析要点

  1. 从下往上读:最下面是根本原因
  2. 追踪调用链:app.py → payment.py → api.py
  3. 识别错误类型:SSL 证书验证失败
  4. 定位失败点:api.py 第 23 行

步骤 2:形成假设 💡

假设生成规则

  1. 基于证据:不要凭空猜测
  2. 优先考虑最近变更
  3. 从简单到复杂排序
  4. 一次只关注一个假设

假设模板

假设:[问题描述] 的原因是 [根本原因]
触发条件:[什么情况下会出现]
验证方法:[如何证明或否定]

假设示例

假设:SSL 错误的原因是生产环境缺少证书文件
触发条件:部署到生产环境后首次调用 API
验证方法:检查 /etc/ssl/certs/ 目录是否存在证书

常见根因分类

类别典型原因检查方法
配置问题环境变量、配置文件错误检查 .env、config
依赖问题版本冲突、缺失依赖检查 requirements.txt
数据问题空值、格式错误、边界值检查输入数据
并发问题竞态条件、死锁检查锁、线程安全
资源问题内存泄漏、连接池耗尽检查资源使用
逻辑错误边界条件、空值处理代码审查

步骤 3:系统验证 🔍

验证原则

  1. 一次验证一个假设(控制变量)
  2. 设计最小化验证实验
  3. 记录验证过程和结果
  4. 用排除法缩小范围

验证方法

# 方法 1:添加日志
def process_order(order_id):
    logger.info(f"Processing order: {order_id}")
    order = get_order(order_id)
    logger.debug(f"Order data: {order}")
    # ...

# 方法 2:断点调试
import pdb; pdb.set_trace()

# 方法 3:简化输入
def test():
    # 用最小输入验证
    process_order({"id": 1, "amount": 0})

验证记录模板

## 假设验证记录

### 假设 1:证书文件缺失
- **验证方法**:检查文件是否存在
- **验证结果**:❌ 文件存在
- **结论**:假设不成立,排除

### 假设 2:证书过期
- **验证方法**:检查证书有效期
- **验证结果**:✅ 证书已于 3 天前过期
- **结论**:假设成立,定位根因

步骤 4:定位根因 🎯

区分症状与根因

使用五问法(5 Whys)深入挖掘:

问题:订单处理失败

Why 1: 为什么失败?
→ API 调用返回 500 错误

Why 2: 为什么 API 返回 500?
→ 数据库查询超时

Why 3: 为什么查询超时?
→ 缺少索引导致全表扫描

Why 4: 为什么缺少索引?
→ 新增字段时未同步添加索引

Why 5: 为什么未添加索引?
→ 没有 Code Review 流程

根因:缺少 Code Review 机制(而非"API 返回 500")

根因特征

  • 可操作:可以采取措施
  • 可预防:可以防止再次发生
  • 系统级:不是个人失误

步骤 5:实施修复 🔧

修复原则

  1. 最小化修复范围
  2. 添加回归测试
  3. 修复后验证
  4. 更新文档

修复清单

## 修复计划

### 代码修复
- [ ] 修改代码:[具体位置]
- [ ] 添加测试:[测试用例]
- [ ] 运行测试确认通过

### 预防措施
- [ ] 添加检查机制
- [ ] 更新文档
- [ ] 团队分享经验

### 验证
- [ ] 本地验证
- [ ] 测试环境验证
- [ ] 生产环境验证

调试技巧库

技巧 1:二分法调试

当问题可能出现在多个位置时:

# 在中间点添加日志
def complex_function(data):
    logger.info("Step 1: Start")
    result1 = step1(data)
    logger.info(f"Step 1 result: {result1}")

    logger.info("Step 2: Start")
    result2 = step2(result1)
    logger.info(f"Step 2 result: {result2}")

    logger.info("Step 3: Start")
    result3 = step3(result2)
    logger.info(f"Step 3 result: {result3}")

    return result3

技巧 2:最小化复现

# 从复杂场景中提取最小复现用例
def test_minimal_reproduction():
    # 不需要完整的订单数据
    order = {"amount": 100}  # 最小输入
    result = process_payment(order)
    assert result.success

技巧 3:对比法调试

# 对比工作版本和失败版本
def test_working_vs_broken():
    # 工作版本
    result_working = old_api_call(data)

    # 失败版本
    try:
        result_broken = new_api_call(data)
    except Exception as e:
        print(f"Broken: {e}")

    # 对比差异
    compare_results(result_working, result_broken)

技巧 4:环境隔离

# 使用 Docker 隔离环境
docker run -it python:3.11 bash

# 或使用虚拟环境
python -m venv debug_env
source debug_env/bin/activate

常见问题模式

模式 1:时序问题

症状:间歇性失败,时好时坏

根因:竞态条件、异步操作未正确等待

调试方法

# 添加重试和延迟
from tenacity import retry, stop_after_attempt, wait_fixed

@retry(stop=stop_after_attempt(3), wait=wait_fixed(1))
def flaky_operation():
    # 可能失败的操作
    pass

模式 2:内存问题

症状:性能逐渐下降,最终崩溃

根因:内存泄漏

调试方法

import tracemalloc

tracemalloc.start()
# ... 运行代码 ...
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
    print(stat)

模式 3:状态污染

症状:测试单独通过,批量运行失败

根因:测试间共享状态

调试方法

@pytest.fixture(autouse=True)
def reset_state():
    # 每个测试前重置状态
    reset_database()
    reset_cache()
    yield
    cleanup()

验证清单

修复完成后,检查:

  • 根本原因已识别(非症状)
  • 修复方案最小化
  • 添加回归测试
  • 本地验证通过
  • 文档已更新(如需要)
  • 团队已分享经验
  • 预防措施已实施

相关参考

约束

公共硬约束

本块由 docs/templates/skill-common-constraints.md 统一维护;每个 SKILL.md## 约束 必须逐字同步本块,不得在副本中改写公共规则。

  • 任务需要落盘时,使用唯一的 ./.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/ 根目录;共享材料放入 shared/,Skill 专属材料放入该 Skill 的 input/output/log/
  • 正式交付物、源代码和正式计划按项目约定保存,不写入任务工作区;未经授权不覆盖、删除、迁移或远程写入。
  • 项目维护变更检查 BAC 可用性并记录需求、AI 产出、工具结果、文件改动和验证摘要;BAC 只做过程审计,不替代署名、责任或合规判断。
  • 不记录 API Key、访问令牌、密码、Cookie、环境/凭据文件、私有 Prompt、身份信息、本地用户名、主机名或不必要的大体积原始数据。
  • 文件路径必须规范化并限制在授权项目范围内;外部 URL、子进程和网络访问遵循最小权限,防止路径遍历、SSRF 和命令注入。
  • Skill 版本唯一记录在自身 config.yaml:skill_info.version;公开 API、协议、目录或配置变更同步文档与 CHANGELOG.md
  • bensz-collect-bugs 是一个 Agent Skill;仅将 Bensz Agent Skill 或 Bensz 基础设施本身的设计缺陷交给它。先脱敏写入 ~/.bensz-skills/bugs/,当前任务不中断,只有用户明确要求才公开上报,禁止直接修改用户已安装的 Skill 源码。

Signals

GitHub stars
48
Forks
7
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
systematic-debugging-huangwb8
Source
github.com/huangwb8/skills