关于 diagnosing-bugs
面向编码 Agent 的调试技能,指导从症状出发,通过假设、针对性复现和验证逐步调查。它强调依据缺失证据选择检查方式,不要求先成功复现。
主要功能
- 01基于证据调查缺陷
- 02针对性复现与探查
- 03检验假设
- 04回归测试与验证
- 05秘密信息脱敏与清理
适用场景
- 01调查难以复现的缺陷
- 02比较不同的成因解释
- 03依据报告行为验证修复
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ marcellocurto/ skills --skill diagnosing-bugs安装后在 Claude Code 中输入/diagnosing-bugs确认已加载。
附带文件agents/openai.yamlscripts/hitl-loop.template.sh
详细介绍
诊断 Bug
通过结合复现、代码检查、临时假设和有针对性的探测来诊断棘手的 Bug。根据缺失的证据选择下一步;以下各节是调查工具,而非必须按顺序完成的关卡。
探索代码库时,如果项目有词汇表,无论文件名是什么,都请先阅读,以便清楚了解相关模块;并检查你正在处理的区域中的 ADR。
脱敏
此技能要求你展示命令、输出和捕获的工件。请先对所有机密信息进行脱敏:用 <REDACTED> 替换。基于环境变量构建循环,让凭据留在环境中,而不是出现在你展示的内容里。捕获的工件可能包含身份验证标头:只引用能体现关键信息的行,保存跟踪记录前先清除其中的机密信息,并将保存的跟踪记录放在仓库之外。
如果脱敏后的输出不足以诊断 Bug,请说明这一点并询问用户。
建立反馈循环
从用户遇到的确切症状、预期行为、入口点、环境、输入和操作顺序入手。追踪相关代码,并利用临时假设确定复现必须保留哪些条件。将这些假设与已确认的原因区分开来。
优先选择现有的检查:它应能在报告的 Bug 存在时失败,并在修复后通过。当反馈循环有助于区分原因或验证结果时,就构建或调整一个;不要要求必须先得到可运行的复现,才能检查代码或提出可测试的解释。
选择合适的检查
选择能够触达所报告故障且成本最低的检查。以下是可选方案,无需按顺序全部尝试:
- 失败测试:在能够触达 Bug 的任意边界进行测试,包括单元、集成和端到端测试。
- Curl / HTTP 脚本:针对正在运行的开发服务执行。
- CLI 调用:使用固定输入,并将标准输出与已知正确的快照进行比较。
- 无头浏览器脚本:使用 Playwright / Puppeteer 驱动 UI,并对 DOM / 控制台 / 网络进行断言。
- 重放捕获的跟踪记录。 将真实网络请求 / 载荷 / 事件日志保存到磁盘,然后在隔离环境中通过代码路径重放。
- 一次性测试框架。 启动系统的最小子集(一个服务、模拟的依赖项),通过一次函数调用来触发包含 Bug 的代码路径。
- 属性 / 模糊测试循环。 对于依赖输入的故障,使用有界输入生成,并保留随机种子和失败输入。
- 二分测试框架。 如果 Bug 出现在两个已知状态(提交、数据集、版本)之间,就自动执行“在状态 X 启动,检查,再重复”这一循环。对于提交,
git bisect run可驱动该循环。 - 差分循环。 将相同输入分别传入旧版本和新版本(或两种配置),然后比较输出。
- 人工辅助复现。 如果 Agent 无法执行该路径,请给用户提供精确操作步骤,并询问相关观察结果。如果可重复的终端引导循环有帮助,请调整
scripts/hitl-loop.template.sh,让用户在自己的终端中运行,并请他们粘贴回脚本末尾打印出的捕获内容块。
记录命令或手动操作、相关条件以及观察到的结果。区分已经复现症状的检查与仅预期能够捕获症状的检查。
改进循环
如果能让下一次实验更有价值,就改进循环:
- 能否加快速度?(缓存设置、跳过无关初始化、缩小测试范围。)
- 能否让信号更明确?(针对具体症状进行断言,而不是只检查“没有崩溃”。)
- 能否让结果更确定?(固定时间、随机数种子,隔离文件系统,冻结网络。)
速度、确定性和无人值守执行都有助于迭代,但都不是获取有用证据的前提。当下一项诊断检查能提供更多信息时,就停止优化测试框架。
非确定性 Bug
进行有界次数的运行,并记录尝试次数、失败情况和条件。如果疑似机制有此需要,且实验能保留报告中的失败,就控制调度、种子、并发或工作负载。根据检查能够消除的不确定性来决定是否进一步运行或添加插桩,而不是要求达到某个复现率。运行中没有出现失败,本身并不能证明间歇性 Bug 已消失。
无法复现时
说明尝试过哪些方法,以及证据缺口在哪里。继续进行相关代码检查、跟踪分析和安全探测,以缩小可能原因。只有当缺少特定环境、经过脱敏的产物或生产环境插桩权限会阻碍进一步推进时,才请求这些信息;等待期间继续独立调查。
在证据证实其机制之前,将首要原因视为暂定结论。如果代码或已捕获的证据足以支持获准进行的修复,即使无法复现,也要说明依据以及仍缺少的验证。未观察到原始 Bug 时,不要声称已复现或证明修复成功。
复现并简化场景
如果可以执行,应确认检查触及的是用户遇到的失败模式,而不是附近的其他错误,也不只是成功执行。记录确切症状和相关条件,以便修复后进行比较。只有在需要区分稳定结果和噪声时才重复运行。
如果有助于隔离机制或便于实际验证,可简化输入、调用方、配置、数据或步骤。一次只更改一个疑似因素,并检查相同的失败是否仍然存在。
当场景已足够小,可以测试首要解释,或其他探测更有信息价值时,就停止简化。在测试假设或应用有充分依据的修复之前,无需完成彻底的最小化。保留原始场景以供最终验证;简化后的路径可能绕过已报告的缺陷。
测试假设
在整个调查过程中提出并修正假设。当证据具体明确时,确定一个首要解释;当多个机制都符合观察结果时,则比较各种可能性。不要为了凑数而编造候选原因。
对于每个值得测试的假设,指出支持它的证据,以及能够将它与其他可能性区分开或证伪的预测。选择成本最低且结论明确的检查,然后根据结果更新解释。
例如:如果错误值是由过期缓存导致的,那么在相同输入下绕过该缓存,应能恢复预期值。应检查结果是否支持该机制,而不要想当然地认为任何改善都能证实它。
如果有助于用户理解或纠正调查过程,请分享首要解释、重要的不确定性和下一项检查。除非某项决策或缺失证据确实阻碍下一步,否则应继续推进,不必等待。
添加插桩
每项探测都必须消除某项具体的不确定性或测试某个预测。比较结果时一次只更改一个变量,以便明确归因。
工具优先级:
- 调试器 / REPL 检查:当环境支持,且暂停不会改变正在研究的行为时使用。时序或并发 Bug 通常更适合通过日志调查。
- 定向日志:在能够区分不同假设的边界处记录。
- 绝不要“记录所有内容再用 grep 搜索”。
为每条调试日志加上唯一前缀,例如 [DEBUG-a4f2]。这样最后只需用一次 grep 清理。未加标签的日志会遗留;加了标签的日志则可以清除。
对于性能回退,应使用计时工具、性能分析器或查询计划,在报告的工作负载下建立基线。根据疑似原因采用性能分析、二分查找或针对性实验。修复后使用相同的工作负载进行比较;如果缺少基线或变更后的测量结果,不要声称性能有可测量的提升。
修复与验证
如果能通过实际可行的切入点复现真实 bug,请先编写回归测试,再修复。
合适的切入点应让测试在调用处复现真实的 bug 模式。如果唯一可用的切入点过于浅显(例如,bug 需要多个调用方才能触发,却只测试单个调用方;或单元测试无法复现触发 bug 的调用链),那么在该处编写回归测试会带来虚假的信心。
如果不存在实际可行的回归测试切入点,请说明限制,并通过最接近真实行为的方式进行有意义的检查,例如原始浏览器流程、重放或命令。不要为了满足此工作流而搭建大量测试基础设施,也不要编写会造成误导的测试。
如果测试可行:
- 将已证实的失败场景转化为该切入点上的针对性回归测试。
- 修复代码前先运行测试,并确认它因预期原因失败。如果没有,请调查不匹配之处,不要将其视为已报告 bug 的证据。
- 根据已确定的机制应用修复。
- 再次运行检查,并确认预期行为通过。如果仍然失败,请重新调查。
在回归测试中保留相关的初始状态、配置和真实决策路径。测试准备不得修复所报告工作流中缺失的前置条件。一个预期能够妥善拒绝请求的检查,并不能证明所需操作确实成功。
只有在授权要求发生变化,或有证据证明测试与要求不符时,才更改预期结果。接口或测试准备的变更必须保留受保护的失败场景。不要仅仅为了让检查通过而接受新的输出、用成功的桩替换失败的协作者,或跳过回归测试。
继续完成已授权的修复和必要的重构。如果有效的失败依赖尚未解决的决策、不可用的前置条件或实质性的范围扩展,请保留失败的测试,并报告阻碍和剩余工作。仅要求复现的问题可以用红色测试收尾;要求实现的任务则仍未完成。区分行为失败与检查无法触及相关行为的情况,并确认所报告的命令确实运行了回归测试。
无论是否添加了持久化测试,只要条件允许,都要通过原始入口、环境、输入和操作顺序验证修复。精简复现或更低层级的测试可以佐证验证,但不能取代它。对于间歇性故障,请报告修复前后的观察结果和剩余的不确定性。如果无法获得修复前的失败证据或原始场景验证,请明确说明这一缺口。
确认修复后,考虑该 bug 是否揭示了可在所属模块中强制执行的稳定不变量。如果现有结构性机制(例如类型或模式约束、边界验证、lint 规则或规范入口)能够防止已证实的这类 bug,请优先采用。保留回归测试作为行为证据。对于没有可信复发可能的孤立故障,不要增加额外机制,也不要扩大已授权的范围来强制执行该不变量。
清理与报告
完成前:
- 移除调查过程中创建的临时调试代码和一次性产物,或将有用的产物保留在约定的调试位置。
- 然后在清理后的代码上运行回归检查和原始场景验证,确保记录的结果对应最终交付的代码。只有在先前运行后没有任何更改时,才重用之前的运行结果。记录结果及任何验证缺口。
- 报告有证据支持的原因、修复内容、验证证据和剩余的不确定性。如果要求发布,请在提交说明或 PR 描述中说明原因。