diagnosing-bugs
用于诊断棘手的 Bug 和性能回退问题。当用户说“诊断”/“调试这个”,或报告某些功能损坏、抛出错误、失败或运行缓慢时使用。
Diagnosing Bugs - 疑难 Bug 与性能回归的系统化诊断流程
技能概述
Diagnosing Bugs 是一套针对疑难 Bug 和性能回归的诊断纪律:它要求先把"能稳定复现、能明确判红"的反馈循环建起来,再去提假设、埋点验证和修复,从而避免靠读代码猜原因。
适用场景
- 用户说"帮我诊断""debug 一下",或反馈某处报错、抛异常、失败、变慢:技能会先要求建立一个能对这个具体症状判红的命令,再进入分析。
- 线上偶发、本地无法复现的 Bug:技能给出提高复现率的做法——把触发动作循环上百次、并行化、加压力、收窄时间窗口、注入 sleep,把 1% 的偶现变成可调试的 50% 复现。
- 性能回归定位:这类问题不靠日志,而是先建立基线测量(计时脚本、profiler、查询计划),再做二分查找,先测量后修复。
核心功能
- 构建并收紧反馈循环:按优先级给出十种复现手段——失败测试、curl/HTTP 脚本、带固定输入的 CLI 调用、无头浏览器脚本、轨迹重放、最小化独立跑通环境、属性/模糊测试、二分定位、新旧版本差分、以及最后手段的人机协同脚本。循环建好后还要继续收紧:更快、信号更准、更确定。
- 复现、最小化与假设排序:确认循环红的是用户描述的那个症状而非旁边的另一个失败,然后一次只砍一个元素把复现缩到最小;在测试任何假设之前先列出 3–5 条可证伪的假设并给出预测,并把排序结果拿给用户过一眼。
- 修复、回归测试与收尾:先写回归测试再改代码,但前提是存在"正确的测试切面"——能复现真实调用链路的切面;如果只有过浅的切面,技能明确要求把"缺少正确切面"本身当作结论上报,而不是写一个给人虚假信心的测试。收尾清单包含:原始复现场景不再出现、回归测试通过、调试埋点全部清除、临时原型删除、把最终成立的假设写进提交信息。
常见问题
为什么必须先建反馈循环,不能直接读代码找原因?
技能把这一点写成了硬性门槛:如果有一个对这个 Bug 判红的、紧的通过/失败信号,二分、假设验证、埋点都只是机械执行;如果没有,盯代码多久都没用。所以"没有可判红的命令,就不进入下一阶段"。
完全无法复现的 Bug 怎么办?
技能要求停下来明说,而不是硬猜。需要列出你已经尝试过的手段,然后向用户要三样东西之一:能复现该问题的环境访问权限、一份已脱敏的现场产物(HAR 文件、日志、core dump、带时间戳的录屏),或是在生产环境加临时埋点的许可。
调试过程中的日志和凭证安全吗?
技能强制要求脱敏:所有命令、输出和现场产物中的密钥一律写成 <REDACTED>,凭证通过环境变量传递以留在环境里而非展示内容中。抓到的产物往往带认证头,只引用携带信号的那几行。如果脱敏后信息不足以定位问题,技能要求直接说明并找用户要更多信息。
它支持偶现(非确定性)Bug 吗?
支持,但目标不同:不追求一次干净的复现,而是把复现率推高。做法是在循环里重复触发 100 次、并行、加压、收窄时序窗口,把复现率提到足以调试的水平再往下走。
找不到合适的回归测试切面怎么办?
切面太浅(比如 Bug 需要多个调用方,却只有一个单调用者的单元测试)时,写出来的测试会给出虚假信心。技能要求把"缺少正确切面"当作本次诊断的发现记录下来并上报——这本身说明代码架构在阻碍这个 Bug 被锁死。
它和普通的 debug 流程有什么区别?
区别在于顺序和纪律:先花不成比例的时间建循环、再复现并最小化、然后才允许提假设,而且假设必须先写成可证伪的预测("如果 X 是原因,那么改 Y 会让 Bug 消失"),一次只改一个变量。埋点日志必须带唯一前缀(如 [DEBUG-a4f2])以便收尾时一次 grep 清干净。