SuperAPI AI 工具集

oracle-debug

测试与质量

查看项目

更新于 10-16 04:06

技能介绍

Oracle Debug 是一套系统化的调试方法论,用于处理各类技术问题。其主张是:随意的修复既浪费时间,又会引入新的缺陷;快速补丁会掩盖底层问题。核心原则是:在进行永久性纠正修复之前,先找到根本原因。只有在需要限制安全、生产或数据丢失影响时,临时性遏制才是合适的。资料明确指出,违反该流程的字面要求,就是违反调试的精神。

铁律

在没有先进行根本原因调查之前,不得进行任何修复。如果没有完成第一阶段,就不能提出修复方案。

适用场景

适用于任何技术问题,包括:测试失败、生产环境缺陷、异常行为、性能回退、构建或集成失败、间歇性失败。

尤其在以下情况中使用:处于时间压力之下;“只需一个快速修复”看起来显而易见;已经尝试过多次修复;上一次修复没有生效;并不完全理解问题本身。

四个阶段

必须完成每个阶段后才能进入下一阶段。

第一阶段 — 根本原因调查

在尝试任何修复之前:

使用项目的领域术语表和 ADR,在追踪之前先对相关模块建立清晰的心智模型。

认真阅读错误信息。阅读完整的堆栈跟踪、行号、文件路径和错误代码。不要跳过警告。

构建快速反馈循环。如果没有针对缺陷的快速、确定性的通过/失败信号,再多的代码阅读也无济于事。应在此投入不成比例的努力。建议按顺序尝试:在触及缺陷的接缝处编写失败测试;针对运行中的开发服务器使用 Curl / HTTP 脚本;使用夹具输入进行 CLI 调用;无头浏览器脚本(Playwright/Puppeteer);重放捕获的追踪(网络负载、事件日志);一次性测试夹具(系统的最小子集);针对“有时出错”缺陷的属性/模糊循环;二分排查夹具(例如 git bisect run);差分循环(旧版本与新版本对比);HITL bash 脚本(最后手段——结构化人工点击)。

迭代该循环:使其更快、更精准、更确定。一个 30 秒的不稳定循环几乎不比没有循环好。

复现缺陷。在安全时运行循环。确认失败与用户描述一致,并捕获确切的症状。当复现不安全或不可能时,改用历史产物、静态证据或有针对性的遥测。

检查近期变更。git diff、近期提交、新依赖、配置变更、环境差异。

追踪数据流。在多组件系统中,在每个边界添加诊断性埋点:每个组件边界只记录所需的最小字段;对凭据、授权数据、会话标识符、个人数据和负载进行脱敏;验证环境/配置传播;检查每一层的状态。运行一次以收集证据,然后缩小到出问题的组件。

沿调用栈向后追踪。错误的值源自何处?是谁用错误的值调用了它?一直向上追踪直到找到源头。在源头修复,而不是在症状处修复。

非确定性缺陷

目标不是干净复现,而是提高复现率。缩小时间窗口,一次只改变一个条件。将添加的延迟或负载视为扰动,而不是证据。在没有明确授权和安全的操作计划的情况下,不要重放改变状态的流量、对生产环境施压或收集敏感产物。

当确实无法构建循环时

停下来并明确说明。向用户请求:对可复现该问题的环境的访问权限;捕获的产物(HAR、日志转储、核心转储、屏幕录制);允许添加临时生产埋点。不要在没有可解释证据的情况下声称找到了根本原因。安全循环更可取,但在循环不可用时,基于产物的调查同样有效。

第二阶段 — 模式分析

在修复之前先找到模式。在大型代码库中寻找可工作的示例,可以委托给只读子代理(参见 atelier-orchestrator 中的 Delegation)。第一、三、四阶段保留在主线程中。

寻找可工作的示例。在同一代码库中定位类似的可用代码。

与参考实现比较。如果实现的是已知模式,完整阅读参考实现。

识别差异。列出可工作代码与损坏代码之间的每一处差异,无论多小。

理解依赖。这段代码依赖哪些组件、配置、设置和假设?

第三阶段 — 假设与测试

使用科学方法。

生成 3 至 5 个排序假设。只生成单一假设会锚定在第一个看似合理的想法上。每个假设必须是可证伪的:说明它所做的预测。在测试之前将排序列表展示给用户——他们往往拥有领域知识,可以立即重新排序。

格式:“如果 <X> 是原因,那么 <改变 Y> 会使缺陷消失 / <改变 Z> 会使它更严重。”

一次只测试一个变量。做出尽可能小的改动来检验假设。

埋点与预测对应。每个探针必须对应一个具体预测。优先使用调试器/REPL 而非日志;优先在边界处使用有针对性的日志,而不是“记录一切再 grep”。

为每条调试日志打上唯一前缀标签,例如 [DEBUG-a4f2]。清理时只需一次 grep。

性能回退。使用可用的侵入性最小的证据建立基线测量,然后二分排查。先测量,后修复。

当不知道时,就说不知道。不要假装。寻求帮助或进一步研究。

第四阶段 — 实施

修复根本原因,而不是症状。

创建失败测试用例。尽可能最简单的复现。必须在修复之前存在。

正确的接缝是指测试在调用点按实际发生方式演练真实的缺陷模式。如果唯一可用的接缝太浅,请注明代码库架构正在阻碍缺陷被锁定。

实施单一修复。解决根本原因。一次一个改动。不要做“顺便改进”。不要捆绑重构。

验证修复。测试是否通过?其他测试是否仍然通过?原始复现是否不再复现?

如果修复无效:停下来;统计失败的修复尝试次数;如果少于 3 次,带着新信息返回第一阶段;如果大于等于 3 次,质疑架构。每次修复都暴露出的模式问题、隐藏耦合和共享状态,都是错误模式的迹象。在尝试第 4 次修复之前与用户讨论。

清理与复盘

在宣布完成之前:原始复现不再复现(重新运行第一阶段循环);回归测试通过(或记录接缝缺失);所有 [DEBUG-...] 埋点已移除;一次性原型已删除或移至明确标记的调试位置;正确的假设已在提交 / PR 信息中说明;你已经问过:“什么本可以预防这个缺陷?”

危险信号 — 停下来并返回第一阶段

如果发现自己有以下想法:“先快速修复,之后再调查”;“先试着改改 X 看看行不行”;“添加多个改动,然后运行测试”;“跳过测试,我手动验证”;“大概是 X,让我修一下”;“我不完全理解,但这可能有效”;“模式说是 X,但我会用不同方式调整”;“再试一次修复”(在 2 次以上失败之后);每次修复都在不同地方暴露新问题。以上都意味着:停下来,返回第一阶段。

常见借口与事实

“问题很简单,不需要流程”——简单问题也有根本原因。“紧急情况,没时间走流程”——系统化调试比反复折腾更快。“先试试这个,然后再调查”——第一次修复就设定了模式。从一开始就做对。“等确认修复后再写测试”——未经测试的修复不会持久。先写测试来证明缺陷。“一次做多个修复省时间”——无法隔离哪个有效,会导致新缺陷。“参考太长,我会调整这个模式”——部分理解必然导致缺陷。“我看到问题了,让我修一下”——看到症状不等于理解根本原因。

快速参考

阶段一 根本原因:关键活动为阅读错误、构建循环、复现、追踪数据流;成功标准是理解是什么以及为什么。阶段二 模式分析:关键活动为寻找可工作的示例并比较;成功标准是识别差异。阶段三 假设:关键活动为形成理论、最小化测试;成功标准是确认假设或产生新假设。阶段四 实施:关键活动为失败测试、单一修复、验证;成功标准是缺陷解决、测试通过。

调试总结

每次会话后总结:问题(一句话)、根本原因(实际哪里错了)、修复(如何修复)、验证(测试结果)、预防(是否添加回归测试?架构发现?)。

参考资料

常见缺陷模式 → references/bug-patterns.md;技术与安全实践 → references/techniques.md;结构灵感来自 obra/superpowers systematic-debugging。