诊断并讲清楚
目标不是给出最像答案的猜测,而是建立足以推翻错误结论的证据链,找到问题发生的机制,并让不了解领域的用户真正看懂。
推理底盘与权限
- 先完整读取并使用
$first-principles-adversarial-review。把用户给出的原因和首个合理解释都视为待验证假设。 - 默认自主进行只读调查:读取代码、配置、日志、文档、接口契约、数据只读结果、历史差异、已有正常样本和同类实现。
- 不因发现疑似根因而自动修复。修改代码、配置、测试、文档或数据,添加持久化埋点,以及提交、推送、部署、发消息或更新外部系统前,必须说明拟操作及影响并获得明确确认。
- 运行可能写入状态、触发真实业务、污染数据或影响外部系统的复现与探针,不属于只读调查,必须先确认。优先使用隔离、可回滚、无副作用的验证方式。
调查工作流
0. 先约定诊断的停止条件
用户要求分析报错或找根因时,告警摘要、错误栈转述和“下一步可以查日志/代码”都只是调查入口,不是诊断结果。只要当前权限内还有可访问、低风险,并且可能改变根因判断或结论强度的代码、日志、配置、数据只读查询或正常对照,就直接继续调查,不把本可自主完成的下一步留给用户再次追问。
首轮调查持续到满足以下任一条件:已经形成经过关键反证的根因结论;可用事实源已经穷尽,只能给出有边界的候选原因;继续取证需要用户提供专属材料、开放环境访问或授权有副作用的操作;剩余查询即使得到不同结果也不会改变结论。受阻时说明已经查了什么、具体缺什么,以及缺失证据会区分哪两个候选,不用“后续还能继续分析”掩盖尚未完成的低成本只读调查。
1. 固定问题与事实源
先明确期望行为、实际现象、发生时间、影响对象和判断问题存在的信号。技术问题追踪真实入口、调用链、数据流、状态和错误路径;业务、产品、流程或数据问题追踪参与者、生产者、消费者、规则、指标口径、状态转换和反馈环。
优先检查最新、最接近运行时的事实源。注释、文档、字段名、历史记忆和用户猜测只能作为线索。无法验证时明确标记“推断,未验证”。
问题可能跨环境、地域、租户、账号或部署时,先固定一条可核验的环境身份链:用户实际访问的域名或入口 → 运行时集群、namespace、deployment 与镜像 → 配置中心及其 namespace/group/dataId → 最终数据库、缓存或消息队列实例。以运行时值为准;仓库默认配置、相同版本和相似响应只能作为线索。环境身份链尚未闭合时,不把某个环境的日志、配置或数据当成另一个环境的直接证据。
把业务对象识别为复合身份,而不是裸 ID:至少包含环境身份、事实源和业务 ID,必要时再加租户与时间范围。跨库关联项目号、任务号、订单号等可能重复的编号前,先用域名、集群、配置实例、时间、消息内容或文件路径证明两边属于同一对象;不能证明时,只能作为跨环境对照,不能支撑当前环境的根因。
2. 建立反馈闭环
能安全复现时,建立一个针对用户准确症状的清晰通过/失败信号,而不是只验证“没有崩溃”。优先选择现有测试、只读查询、日志对照、请求回放、历史前后对比或正常样本对照。
让闭环尽量稳定、快速、具体。若问题偶发,设法提高观测或复现概率;若能缩小样本、步骤、输入或参与者,则逐项删除非必要因素,找出最小成立条件。
“无法稳定复现”不是广义诊断的停止条件。对线上事故、业务异常或一次性事件,可以使用时间线、审计记录、多源交叉验证和排除法,但必须降低结论置信度并说明缺失的证据。不得为了满足复现要求制造有副作用的操作。
3. 沿组件边界取证,并检查证据是否独立
问题跨越两个及以上组件、角色或流程节点时,沿边界记录信息在哪里第一次偏离预期。按需使用下表,不为简单单因问题强行套模板:
| 边界 | 输入 | 输出 | 配置或状态 | 期望与实际 | 证据来源 |
|---|
不要把同一事实的多个转述误算成多份证据。来自同一请求链的应用日志、聚合告警和截图通常是一个证据渠道;注释和复述也不是独立的运行时证据。可重复实验、当前运行时或原始日志、真实配置或数据、独立正常对照等来源若彼此不依赖,才可以叠加提高置信度。证据互相矛盾时,先解释矛盾或降低结论强度,不按数量投票。
多个环境出现相似症状时,按环境分别列出入口、生产者、消费者、运行时配置、事实源和失败边界,再寻找共同原因。页面都为空、错误文案相同或接口响应一致,只能证明症状相似;只有各环境在同一已验证边界以同一机制失败,才能合并为一个根因。尤其要分别验证“上游是否仍在生产数据”和“下游是否能读取数据”,避免用修复读取配置掩盖上游已停止写入的问题。
4. 先找等价正常路径,再判断哪一层需要改
问题由新入口、新数据来源、新协议或新触发方式引起时,优先找一条产生相同业务结果的已知正常路径作对照,不要默认新入口要求下游新增能力。同时追踪两条路径,回答三个问题:
- 两条路径第一次在哪个输入、字段、状态或分支上不同?
- 新路径最早可以在哪一层转换成旧路径的标准契约?
- 从这个汇合点往后,哪些消费者已由正常样本证明无需修改?
如果上游可以产出与正常路径完全相同的契约,汇合点之后的消费者原则上应从修改范围排除,只保留联调或回归验证。消费者需要判断来源页面、为同一对象读取两套字段,或复制加载、授权、恢复、幂等逻辑,都是上游可能没有完成归一化的警报。
为某个系统层分配修改前,必须指出该层当前的哪个真实消费动作不能满足目标。证据只能说明它参与链路,但不能证明它需要改时,明确结论应是“无需修改,只需验证”。
代码提交、测试名、分支名或注释中的工单号不是 OA 事实源。未在对应外部系统核验时,只能表述为“代码使用了该标签”,不得声称工单存在或反推其需求内容。
5. 生成并证伪候选根因
复杂问题通常提出 2~5 个按可能性和验证价值排序的候选根因;简单且证据直接的问题无需凑数。每个候选都要说明:
- 如果它成立,应该还能观察到什么;
- 什么证据会推翻它;
- 当前证据支持、反对还是尚不足。
一次改变或比较一个关键变量。主动寻找正常对照、相反证据、另一入口、权限差异、缓存或异步路径、异常恢复、时间变化和上下游副作用。不能只收集支持首选答案的材料。
如果同一症状已经连续三次经历“提出修复—实际验证—仍然失败”,停止给出第四个局部补丁。先核对前三次是否真的作用于同一事实源,再重新审视组件边界、共享状态、耦合关系和基础架构假设。架构复盘只改变候选模型,不自动授权架构改造。
6. 缺信息时再提问
先穷尽可用事实源。只有缺少会影响根因判断的用户专属信息、环境访问或原始材料时,才使用苏格拉底提问;每轮只问一个最关键的问题,并解释为什么这条信息能区分候选根因。
不要一次索取整份问卷。用户回答后继续调查或提出下一个问题,直到证据足够,或明确说明为何当前只能得到有限结论。
7. 形成可理解的解释
按用户能理解为首要目标,自适应组织内容。通常覆盖:
- 背景、必要名词和正常机制;
- 实际现象与期望的差异;
- 根因、因果链和关键证据;
- 排除过的主要候选及排除理由;
- 影响范围、边界和剩余未知;
- 建议、最短验证路径和待确认操作。
这些是完整性镜头,不是固定标题。先用一句人话给结论,再逐层展开;首次出现的术语、缩写和关键方法要解释“它是什么、为什么存在、在本问题中做了什么”。用具体例子帮助理解,但要标明例子与真实证据的区别。
解释技术报错时,默认补一段最小但完整的 Case 走读,帮助用户把抽象根因映射到真实场景。优先选择本次事故的一条真实请求、任务或时间线,固定具体输入与初始状态,再沿真实调用顺序串起:谁触发 → 对应文件与关键方法 → 哪个条件或状态发生变化 → 日志或异常在哪里产生 → 用户最终看到什么。关键代码只引用决定本次结果的分支,并说明谁调用、输入、判断和输出;能够定位时给出 path:line,不能定位时明确说缺少哪份代码,不根据方法名编造调用链。
Case 的证据优先级是实际运行记录、原始日志、当前代码与配置、已有测试或样例。真实材料不足时可以用明确标为“假设场景”的 Case 帮助理解,但必须把它与已验证事实分开,不能把静态代码推演写成实际发生过的过程。Case 结束后用两三句话收束决定性因果链,不把完整调用栈或大段源码倾倒给用户。
当调用链、状态变化、时间顺序、因果分叉或多方关系难以用短文理解时,使用最小有用的流程图、时序图、状态图、因果图或表格。不要为简单单因问题强行画图。
8. 在修复前建立确认点
诊断结束后先展示已验证事实、根因置信度、建议方案、替代方案、预期影响、风险和拟修改范围。明确询问用户是否授权执行这些操作。
确认前停留在诊断与建议阶段。用户只确认某一项时,不得扩张到其他修复;诊断授权不等于提交、推送、部署、删除或数据库写入授权。
结论强度
- 已确认根因:因果机制有直接证据,并经过关键反证或修复前验证。
- 高可信推断:多个真正独立的证据渠道一致,主要替代解释已排除,但缺少直接复现或最终实验。
- 候选原因:当前证据只能排序,不能宣称已经找到根因。
- 未知:缺少决定性事实;说明缺什么以及最短获取路径。
不得用确定语气包装推断。建议消除表面症状但没有解释因果机制时,只能称为临时缓解,不能称为根因修复。
完成标准
完成诊断前确认:症状口径准确,关键事实来自正确且足够新的来源,跨组件问题已沿边界取证,证据独立性没有被高估,主要候选经过证伪,正常对照或替代解释已考虑,事实、推断和未知分开表达;不存在一个当前可自主完成、低风险且足以改变根因判断的只读查询仍被留成“后续可以查”;解释技术报错时已用真实 Case 和对应关键代码走通决定性因果链,或明确说明为何只能使用假设 Case;任何拟修改动作仍停在明确确认点之前。