SuperAPI AI 工具集

diagnosing-bugs

测试与质量

查看项目

更新于 10-18 16:13

技能介绍

Diagnosing Bugs 是一套针对疑难 Bug 与性能回归的诊断循环技能,要求按阶段推进,只有明确说明理由时才可跳过某个阶段。在探索代码库时,技能建议阅读 CONTEXT.md(若存在)以建立相关模块的心智模型,并检查所在区域的 ADR(架构决策记录)。

用途

技能用于在用户要求诊断或调试,或报告某事物损坏、抛错、失败、变慢时,提供一套纪律化的诊断流程。

主要能力

脱敏

技能会展示命令、输出和捕获的工件。在此之前必须先脱敏:用 <REDACTED> 替换每个秘密。围绕环境变量构建循环,让凭据留在环境中而不是出现在展示内容里。捕获的工件可能带有认证头,只引用携带信号的行。如果脱敏后的输出不足以诊断 Bug,应明确说明并询问用户。

阶段 1:构建反馈循环

技能认为这是核心,其余都是机械性工作。如果有一个针对该 Bug 的紧凑通过/失败信号(在该 Bug 上会变红),就能找到原因;二分、假设检验和插桩都只是消费它。没有它,盯着代码无济于事。需要在此投入不成比例的精力,要激进、有创意、拒绝放弃。

构建循环的方式大致按以下顺序:在能触及 Bug 的接缝处写失败测试(单元、集成、e2e);针对运行中的开发服务器使用 curl / HTTP 脚本;用固定输入调用 CLI,并将 stdout 与已知良好快照对比;用无头浏览器脚本(Playwright / Puppeteer)驱动 UI 并对 DOM/console/network 断言;回放捕获的 trace(将真实网络请求/负载/事件日志保存到磁盘,再孤立地通过代码路径回放);一次性脚手架(启动系统的最小子集,用单次函数调用执行 Bug 代码路径);属性/模糊循环(若 Bug 是“有时输出错误”,运行 1000 个随机输入寻找失败模式);二分脚手架(若 Bug 出现在两个已知状态之间,自动化“在状态 X 启动、检查、重复”,以便 git bisect 运行);差分循环(同一输入跑旧版本与新版本或两种配置并比较输出);HITL bash 脚本(最后手段,若必须人工点击,用 scripts/hitl-loop.template.sh 驱动,使循环仍有结构,捕获输出反馈给助手)。

构建正确的反馈循环后,技能建议像对待产品一样收紧循环:能否更快(缓存设置、跳过无关初始化、缩小测试范围);能否让信号更锐利(断言具体症状,而不是“没有崩溃”);能否更确定(固定时间、种子随机数、隔离文件系统、冻结网络)。30 秒的不稳定循环几乎不比没有循环好;2 秒的确定性循环是调试超能力。

对于非确定性 Bug,目标不是干净复现,而是提高复现率。将触发循环 100 次、并行化、增加压力、收窄时间窗口、注入 sleep。50% 偶发的 Bug 可调试;1% 不可调试,因此持续提高复现率直到可调试。

当确实无法构建循环时,应停下来明确说明,列出尝试过什么,并向用户请求:(a) 访问能复现问题的环境,(b) 脱敏后的捕获工件(HAR 文件、日志转储、核心转储、带时间戳的屏幕录制),或 (c) 允许添加临时生产插桩。不要在无循环的情况下继续假设。

阶段 1 的完成标准是:有一个紧凑且能变红的循环,能说出至少已运行过一次的一条命令(脚本路径、测试调用、curl),并展示其调用和输出(脱敏后),且该命令满足:能变红(驱动实际 Bug 代码路径并断言用户的确切症状,能在此 Bug 上变红、修复后变绿,而非“运行不报错”);确定性(每次运行判决相同,不稳定 Bug 则按上述固定高复现率);快速(秒级而非分钟级);可由助手无人值守运行(人工介入仅通过 scripts/hitl-loop.template.sh)。如果在命令存在之前就开始读代码构建理论,应停下,因为直接跳到假设正是该技能要防止的失败。没有能变红的命令,就没有阶段 2。

阶段 2:复现 + 最小化

运行循环,观察它在 Bug 出现时变红。确认:循环产生的是用户描述的失败模式,而不是附近碰巧发生的其他失败(错误 Bug = 错误修复);失败在多次运行中可复现(非确定性 Bug 则复现率足够高);已捕获确切症状(错误消息、错误输出、慢速计时),以便后续阶段验证修复确实针对它。

一旦变红,将复现缩小到仍变红的最小场景。一次削减一个输入、调用方、配置、数据和步骤,每次削减后重跑循环,只保留对失败起承重作用的元素。理由:最小复现缩小阶段 3 的假设空间(更少嫌疑活动部件),并成为阶段 5 的干净回归测试。完成标准是每个剩余元素都承重:移除任何一个都会让循环变绿。在复现并最小化之前不要继续。

阶段 3:假设

在测试任何假设前生成 3–5 个排序假设。仅生成单一假设会锚定在第一个看似合理的想法上。每个假设必须可证伪:说明它做出的预测。格式:“如果 <原因> 是原因,那么 <动作> 将使 Bug 消失 / <动作> 将使它更糟。”若无法说明预测,该假设只是感觉,应丢弃或锐化。在测试前向用户展示排序列表。用户常有领域知识能立即重新排序(“我们刚部署了 #3 的变更”),或知道已排除的假设。这是一个低成本检查点,能节省大量时间。不要阻塞等待;若用户不在,按自己的排序继续。

阶段 4:插桩

每个探针必须对应阶段 3 的具体预测。一次只改变一个变量。工具偏好:环境支持时用调试器 / REPL 检查(一个断点胜过十个日志);在区分假设的边界处使用有针对性的日志;绝不“记录一切然后 grep”。每个调试日志标记唯一前缀,例如 [DEBUG-a4f2],最后清理只需一次 grep。未标记的日志会存活;有标记的日志会消亡。

性能分支:对于性能回归,日志通常是错误的。应建立基线测量(计时工具、performance.now()、分析器、查询计划),然后二分。先测量,后修复。

阶段 5:修复 + 回归测试

在修复前写回归测试,但仅在存在正确接缝时。正确接缝是测试在调用点实际执行 Bug 模式发生处。如果唯一可用接缝太浅(Bug 需要多个调用方时只测单个调用方、单元测试无法复现触发 Bug 的链),在该处写回归测试会给出虚假信心。如果没有正确接缝,这本身就是发现,应记录。代码库架构阻止了锁定该 Bug,需为下一阶段标记。若有正确接缝:将最小复现转变为该接缝处的失败测试;观察它失败;应用修复;观察它通过;针对原始(未最小化)场景重跑阶段 1 反馈循环。

阶段 6:清理

宣布完成前必须:原始复现不再复现(重跑阶段 1 循环);回归测试通过(或记录接缝缺失);所有 [DEBUG-...] 插桩已移除(grep 前缀);一次性原型已删除(或移到明确标记的调试位置);在提交 / PR 消息中说明最终正确的假设,让下一个调试者学习。

使用方式

在触发条件满足时,按阶段推进:先构建反馈循环并展示已运行命令及输出,再复现、最小化、生成排序假设、插桩验证、修复并添加回归测试,最后清理调试痕迹。具体安装或调用命令在资料中暂未提供。

适用场景

适用于疑难 Bug 的诊断、性能回归排查,以及用户报告某事物损坏、抛错、失败或变慢的情况。

限制

技能强调若无紧凑且能变红的反馈循环,不得进入假设阶段;若无法构建循环,应停止并请求用户提供环境访问、脱敏工件或临时生产插桩权限。回归测试仅在存在正确接缝时编写,否则应记录接缝缺失。所有展示的命令、输出和工件必须先脱敏。资料未提供具体安装命令、平台支持范围或收费信息。