指南:Bug 修复
何时使用调试工作流
当你有一个需要诊断和修复的特定 bug 时,使用 /debug(或用自然语言说 "fix bug"、"fix error"、"debug")。该工作流提供结构化、可重现的调试方法,避免常见的修复表象而非根因的陷阱。
调试工作流支持所有供应商(Gemini、Claude、Codex、Qwen)。步骤 1-5 内联运行。步骤 6(类似模式扫描)在扫描范围较广(10+ 文件或多领域错误)时可能委派给 debug-investigator 子智能体。
Bug 报告模板
报告 bug 时,尽可能提供以下信息。每个字段都有助于调试工作流更快缩小搜索范围。
必填字段
| 字段 | 说明 | 示例 |
|---|---|---|
| 错误消息 | 精确的错误文本或堆栈跟踪 | TypeError: Cannot read properties of undefined (reading 'id') |
| 复现步骤 | 触发 bug 的有序操作 | 1. 以管理员登录。2. 导航到 /users。3. 点击任意用户的"删除"。 |
| 预期行为 | 应该发生什么 | 用户被删除并从列表中移除。 |
| 实际行为 | 实际发生了什么 | 页面崩溃,显示白屏。 |
可选字段(强烈建议提供)
| 字段 | 说明 | 示例 |
|---|---|---|
| 环境 | 浏览器、操作系统、Node 版本、设备 | Chrome 124、macOS 15.3、Node 22.1 |
| 频率 | 总是、有时、仅首次 | 始终可复现 |
| 近期变更 | bug 出现前发生了什么变更 | 合并了 PR #142(用户删除功能) |
| 相关代码 | 你怀疑的文件或函数 | src/api/users.ts、deleteUser() |
| 日志 | 服务器日志、控制台输出 | [ERROR] UserService.delete: user.organizationId is undefined |
| 截图/录屏 | 视觉证据 | 错误界面的截图 |
你预先提供的上下文越多,调试工作流需要的来回提问就越少。
严重度分级(P0-P3)
严重度决定 bug 的处理方式和修复速度。
P0 —— 严重(立即响应)
定义: 生产环境宕机、数据正在丢失或损坏、安全漏洞正在发生。
响应预期: 放下一切。在解决之前这是唯一的任务。
示例:
- 认证系统被绕过 —— 所有用户都能访问管理员端点。
- 数据库迁移损坏了用户表 —— 账户无法访问。
- 支付处理在向客户双重收费。
- API 端点返回其他用户的个人数据。
调试方法: 跳过完整模板。提供错误消息和堆栈跟踪即可。工作流立即从步骤 2(复现)开始。
P1 —— 高(当前会话内)
定义: 核心功能对大量用户不可用。可能存在变通方案但长期不可接受。
响应预期: 在当前工作会话内修复。在解决前不开始新功能。
示例:
- 包含特殊字符的搜索查询返回空结果。
- 超过 5MB 的文件上传失败(限制应为 50MB)。
- 移动应用在 Android 14 设备上启动时崩溃。
- 密码重置邮件未发送(邮件服务集成损坏)。
调试方法: 完整 5 步循环。修复后建议进行 QA 审查。
P2 —— 中(当前冲刺内)
定义: 功能可用但行为降级。影响可用性但不影响功能。
响应预期: 安排在当前冲刺。在下次发布前修复。
示例:
- 表格排序区分大小写("apple" 排在 "Zebra" 之后)。
- 暗色模式在设置面板中有不可读的文本。
- /users 端点的 API 响应时间为 8 秒(应低于 1 秒)。
- 列表为空时分页显示"第 1 页,共 0 页"。
调试方法: 完整 5 步循环。纳入 QA 回归测试套件。
P3 —— 低(待办)
定义: 美观问题、边缘情况或轻微不便。
响应预期: 加入待办。方便时修复,或与相关变更一起批量处理。
示例:
- 提示文本有错别字:"Delet" 应为 "Delete"。
- 控制台警告关于已弃用的 React 生命周期方法。
- 在 768-800px 视口宽度之间,页脚对齐偏差 2 像素。
- 内容可见后加载动画继续 200 毫秒。
调试方法: 可能不需要完整调试循环。直接修复加回归测试即可。
5 步调试循环详解
/debug 工作流按严格顺序执行这些步骤。全程使用 MCP 代码分析工具 —— 从不使用原始文件读取或 grep。
步骤 1:收集错误信息
工作流询问(或从用户接收):
- 错误消息和堆栈跟踪
- 复现步骤
- 预期与实际行为
- 环境详情
如果提示词中已提供错误消息,工作流立即进入步骤 2。
步骤 2:复现 Bug
使用的工具: search_for_pattern 搜索错误消息或堆栈跟踪关键词,find_symbol 定位精确的函数和文件。
目标是在代码库中定位错误 —— 找到抛出异常的精确行、产生错误输出的精确函数,或导致意外行为的精确条件。
此步骤将用户报告的症状("页面崩溃了")转化为代码库级别的定位(src/api/users.ts:47, deleteUser() throws TypeError)。
步骤 3:诊断根因
使用的工具: find_referencing_symbols 从错误点反向追踪执行路径。
工作流从错误位置反向追踪以找到实际原因。它检查以下常见根因模式:
| 模式 | 寻找什么 |
|---|---|
| 空值/undefined 访问 | 缺少空值检查、需要可选链、未初始化的变量 |
| 竞态条件 | 异步操作乱序完成、缺少 await、共享可变状态 |
| 缺少错误处理 | 没有 try/catch、未处理的 promise 拒绝、缺少错误边界 |
| 错误数据类型 | 期望数字但得到字符串、缺少类型转换、不正确的 schema |
| 过期状态 | React 状态未更新、缓存值未失效、闭包捕获了旧值 |
| 缺少验证 | 用户输入未清理、API 请求体未验证、边界条件未检查 |
关键纪律:诊断根因,而非症状。如果 user.id 是 undefined,问题不是"如何检查 undefined?",而是"为什么 user 在执行路径的这个点是 undefined?"
步骤 4:提出最小修复方案
工作流展示:
- 已识别的根因(带代码追踪的证据)。
- 提出的修复方案(只修改必要的部分)。
- 说明为什么这是修复根因而非症状。
工作流在此处阻塞直到用户确认。 这防止调试智能体未经批准就进行修改。
最小修复原则: 修改尽可能少的行。不重构、不改善代码风格、不添加无关功能。修复应在 2 分钟内完成审查。
步骤 5:应用修复并编写回归测试
此步骤执行两个操作:
- 实现修复 —— 应用已批准的最小变更。
- 编写回归测试 —— 一个测试:
- 复现原始 bug(没有修复时测试必须失败)
- 验证修复有效(有修复时测试必须通过)
- 防止同一 bug 在未来变更中复发
回归测试是调试工作流最重要的输出。没有它,同样的 bug 可能被任何未来变更重新引入。
步骤 6:扫描类似模式
修复应用后,工作流扫描整个代码库以查找导致 bug 的相同模式。
使用的工具: search_for_pattern 搜索已识别为根因的模式。
例如,如果 bug 是由于访问 user.organization.id 而未检查 organization 是否为 null 引起的,扫描会查找所有其他无空值检查的 organization.id 访问。
子智能体委派条件 —— 工作流在以下情况启动 debug-investigator 子智能体:
- 错误跨越多个领域(例如,frontend 和 backend 都受影响)。
- 类似模式扫描范围覆盖 10+ 文件。
- 需要深层依赖追踪才能完全诊断问题。
供应商特定的启动方式:
| 供应商 | 启动方式 |
|---|---|
| Claude Code | 使用 .claude/agents/debug-investigator.md 的 Agent 工具 |
| Codex CLI | 模型协调的子智能体请求,结果为 JSON |
| Gemini CLI | oma agent:spawn debug "scan prompt" {session_id} -w {workspace} |
| Antigravity / 回退 | oma agent:spawn debug "scan prompt" {session_id} -w {workspace} |
所有类似的脆弱位置都会被报告。确认的实例作为同一会话的一部分修复。
步骤 7:记录 Bug
工作流写入内存文件,包含:
- 症状和根因
- 应用的修复和变更的文件
- 回归测试位置
- 在代码库中找到的类似模式
/debug 的提示词模板
触发调试工作流时,你可以提供结构化提示词:
/debug
Error: TypeError: Cannot read properties of undefined (reading 'id')
Stack trace:
at deleteUser (src/api/users.ts:47:23)
at handleDelete (src/routes/users.ts:112:5)
Steps to reproduce:
1. Log in as admin
2. Navigate to /users
3. Click "Delete" on a user whose organization was deleted
Expected: User is deleted
Actual: 500 Internal Server Error
Environment: Node 22.1, PostgreSQL 16
为什么这个结构有效:
- 错误 + 堆栈跟踪 允许步骤 2 立即定位代码(
search_for_pattern搜索 "deleteUser" 找到函数;find_symbol精确定位位置)。 - 复现步骤 带有特定触发条件("组织已删除的用户")暗示了根因(null 外键)。
- 环境 排除版本特定的干扰。
对于较简单的 bug,较短的提示词即可:
/debug The login page shows "Invalid credentials" even with correct password
工作流会根据需要询问额外细节。
升级信号
这些信号表明 bug 需要超出标准调试循环的升级处理:
信号 1:同一修复尝试了两次
如果工作流提出修复、应用后同一错误再次出现,问题比初始诊断更深。在支持探索循环的工作流(ultrawork、orchestrate、work)中会触发:
- 为根因生成 2-3 个替代假设。
- 在独立工作区测试每个假设(每次尝试使用 git stash)。
- 评分结果并采用最佳方案。
信号 2:多领域根因
frontend 的错误由 backend 的变更引起,而 backend 的变更又由数据库 schema 迁移引起。当根因跨越领域边界时,升级到 /work 或 /orchestrate 以引入相关领域智能体。
示例: Frontend 显示用户名为 "undefined"。Backend 对 user.display_name 返回 null。数据库迁移添加了该列但现有行有 NULL 值。修复需要:数据库迁移(回填)、backend 空值处理和 frontend 回退显示。
信号 3:缺少复现环境
Bug 仅在生产环境中出现,本地无法复现。信号包括:
- 环境特定的配置差异。
- 仅在生产负载下才出现的竞态条件。
- 第三方服务在 staging 和 production 之间的行为差异。
行动: 收集生产日志,请求生产监控访问权限,在尝试修复前考虑添加插桩/日志。
信号 4:测试基础设施故障
无法编写回归测试,因为测试基础设施损坏、缺失或不足。
行动: 先修复测试基础设施(或使用 oma install 配置),然后返回调试工作流。
修复后验证清单
应用修复和回归测试后,验证:
- 回归测试在无修复时失败 —— 临时还原修复,确认测试捕获了 bug。
- 回归测试在有修复时通过 —— 应用修复,确认测试通过。
- 现有测试仍通过 —— 运行完整测试套件以验证无回归。
- 构建成功 —— 编译/构建项目以捕获类型错误或导入问题。
- 类似模式已扫描 —— 步骤 6 已完成,所有找到的实例已修复或记录。
- 修复是最小的 —— 仅修改了必要的行。未包含无关重构。
- 根因已记录 —— 内存文件记录:症状、根因、应用的修复、变更的文件、回归测试位置和找到的类似模式。
完成标准
调试工作流在以下条件满足时完成:
- 根因已识别并记录(不仅仅是症状)。
- 经用户批准的最小修复已应用。
- 存在回归测试,在无修复时失败,有修复时通过。
- 代码库已扫描类似模式,所有确认的实例已处理。
- Bug 报告已记录在内存中,包含:症状、根因、应用的修复、变更的文件、回归测试位置和找到的类似模式。
- 修复后所有现有测试继续通过。