SKILL.md
3.3 KB查看排版效果| 1 | --- |
| 2 | name: debug-triage |
| 3 | description: 拿到报错、异常、测试失败或行为不符预期时,按固定顺序排查:复现、读原始错误、划边界、单变量验证,最后才改代码。用户说「报错了」「跑不起来」「这里不对」「帮我看看为什么」时使用。 |
| 4 | --- |
| 5 | |
| 6 | # 排错优先 |
| 7 | |
| 8 | 先弄清坏在哪一层,再动手改。跳步改代码是排错最常见的浪费。 |
| 9 | 这个技能不含脚本,不联网;只读用户给的内容,要改文件时按用户的指示做。 |
| 10 | |
| 11 | ## 顺序不能反 |
| 12 | 1. **复现**:先确认能稳定重来一次。 |
| 13 | 2. **读原始错误**:从第一行读到最后一行的 caused by。 |
| 14 | 3. **划边界**:是代码、依赖、环境,还是数据。 |
| 15 | 4. **单变量验证**:一次只改一个东西,先证明假设再修。 |
| 16 | 5. **才动手改**:最小改动,修因不修果。 |
| 17 | |
| 18 | ## 1 复现 |
| 19 | - 记下触发条件:什么输入、什么命令、什么环境、第几次出现。 |
| 20 | - 复现不了就先说明复现不了,列出已知条件,请用户补;不要在没复现的情况下声称已修复。 |
| 21 | - 偶发问题先看时间规律(并发、缓存、超时、时区、随机种子),不要当必现问题改。 |
| 22 | |
| 23 | ## 2 读原始错误 |
| 24 | - 读完整堆栈,不要只看最后一行。异常类型和消息常常不是根因。 |
| 25 | - 找第一处指向「用户自己代码」的帧,那是排查起点;上面是调用方,下面是库内部。 |
| 26 | - 分清 caused by(根因)和 during handling of / re-raised(包装后的次生错误)。 |
| 27 | - 报错里的路径、行号、版本号、请求 id 原样记下,不要意译。 |
| 28 | |
| 29 | ## 3 划边界 |
| 30 | 先判断坏在哪一层,四选一: |
| 31 | - **代码**:能稳定复现、只在这条路径出错、最近改动过。 |
| 32 | - **依赖**:升级/降级后出现,或报错来自库内部且参数合法。 |
| 33 | - **环境**:换机器就变、缺变量、权限、编码、端口占用、版本不一致。 |
| 34 | - **数据**:同代码不同数据结果不同,空值、超长、非 UTF-8、类型不符。 |
| 35 | |
| 36 | 缩小范围的办法:输入减半、注释掉一半步骤、换最小样例、在中间打点确认走到哪一步。 |
| 37 | |
| 38 | ## 4 单变量验证 |
| 39 | - 一次只改一处,改完立刻验证,记下结果。 |
| 40 | - 先把假设写成一句可验证的话:「因为 X,所以 Y」,再设计能证伪它的最小实验。 |
| 41 | - 不要同时改配置和代码;不要靠重装环境碰运气。 |
| 42 | |
| 43 | ## 5 修 |
| 44 | - 最小改动,能一行解决就不重构。 |
| 45 | - 修根因,不修症状:吞异常、加空 try、放宽断言、改测试期望值、加大超时都不算修好。 |
| 46 | - 修完给出验证方式:跑哪个命令、看哪个输出、在什么条件下算通过。 |
| 47 | |
| 48 | ## 常见错 |
| 49 | - 看到报错直接改,改了三处,仍不知道哪处生效。 |
| 50 | - 靠加 `print` 代替读堆栈,输出一堆却仍不知道边界。 |
| 51 | - 把「不再报错」当成「修好了」——异常被绕过,行为可能仍然是错的。 |
| 52 | - 复现不了就猜,猜完当成结论汇报。 |
| 53 | - 只贴最后一行报错就下判断,忽略前面的 warning 和第一条 caused by。 |
| 54 | |
| 55 | ## 输出方式 |
| 56 | 一句话说清坏在哪一层和依据(哪个帧、哪次对比、哪个实验),再给最小修复和验证步骤。 |
| 57 | 信息不够就直说缺什么,不要用「可能是」「应该是」把不确定糊过去;推断要标成推断。 |
文件内容是平台检查时读出的文本,只供查看。平台不会运行包里的任何脚本或程序。

