| name | diagnosing-bugs |
| description | Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow. |
| 触发词 | 针对棘手 bug 和性能回退的诊断循环。当用户说「诊断」/「调试这个」,或报告某些东西已损坏/抛异常/失败/缓慢时使用。 |
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
A discipline for hard bugs. Skip phases only when explicitly justified.
针对棘手 bug 的一套方法论。只有明确理由时才跳过阶段。
When exploring the codebase, read CONTEXT.md (if it exists) to get a clear mental model of the relevant modules, and check ADRs in the area you're touching.
在查阅代码库时,先阅读 CONTEXT.md(如果存在)以建立相关模块的清晰心智模型,并检查你涉及区域的 ADR。
This is the skill. Everything else is mechanical. If you have a tight pass/fail signal for the bug — one that goes red on this bug — you will find the cause; bisection, hypothesis-testing, and instrumentation all just consume it. If you don't have one, no amount of staring at code will save you.
这才是技能核心。 其他都只是机械步骤。如果你有一个针对该 bug 的紧凑的通过/失败信号——一个能在这个 bug 上变红的信号——你就会找到根因;二分法、假设检验、插桩都只是消耗这个信号而已。如果你没有这个信号,盯着代码看再多也无济于事。
Spend disproportionate effort here. Be aggressive. Be creative. Refuse to give up.
在此处投入不成比例的努力。要激进。要创造。拒绝放弃。
git bisect run it.scripts/hitl-loop.template.sh so the loop is still structured. Captured output feeds back to you.git bisect run 它。scripts/hitl-loop.template.sh 驱动他们,使循环仍然结构化。捕获的输出反馈给你。Treat the loop as a product. Once you have a loop, tighten it:
将反馈循环当作产品来对待。一旦你有了一个循环,就收紧它:
A 30-second flaky loop is barely better than no loop; a 2-second deterministic one is tight — a debugging superpower.
一个 30 秒的不稳定循环比没有循环好不到哪去;而一个 2 秒的确定性循环才是紧凑的——调试的超能力。
The goal is not a clean repro but a higher reproduction rate. Loop the trigger 100×, parallelise, add stress, narrow timing windows, inject sleeps. A 50%-flake bug is debuggable; 1% is not — keep raising the rate until it's debuggable.
目标不是完美的复现,而是更高的复现率。将触发循环 100 次、并行化、增加压力、缩小时间窗口、注入睡眠。50% 不稳定率的 bug 是可调试的;1% 则不是——持续提高复现率直到可调试为止。
Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a captured artifact (HAR file, log dump, core dump, screen recording with timestamps), or (c) permission to add temporary production instrumentation. Do not proceed to hypothesise without a loop.
停下来明确说明。列出你尝试过的方案。向用户请求:(a) 访问能复现的环境,(b) 捕获的产物(HAR 文件、日志转储、核心转储、带时间戳的屏幕录制),或 (c) 添加临时生产环境插桩的权限。不要在没有反馈循环的情况下继续假设。
Phase 1 is done when the loop is tight and red-capable: you can name one command — a script path, a test invocation, a curl — that you have already run at least once (paste the invocation and its output), and that is:
当循环紧凑且能变红时阶段 1 才算完成:你可以说出一个命令——脚本路径、测试调用、curl——你已经至少运行过一次(粘贴调用及其输出),并且它满足:
scripts/hitl-loop.template.sh.scripts/hitl-loop.template.sh 才需要人在循环中。If you catch yourself reading code to build a theory before this command exists, stop — jumping straight to a hypothesis is the exact failure this skill prevents. No red-capable command, no Phase 2.
如果你发现自己在这个命令存在之前就开始读代码构建理论,停下来——直接跳到假设正是这个技能要防止的错误。 没有能变红的命令,就没有阶段 2。
Run the loop. Watch it go red — the bug appears.
运行循环。看着它变红——bug 出现了。
Confirm:
确认:
Once it's red, shrink the repro to the smallest scenario that still goes red. Cut inputs, callers, config, data, and steps one at a time, re-running the loop after each cut — keep only what's load-bearing for the failure.
一旦变红,将复现缩小到仍能变红的最小场景。一次一个地减少输入、调用者、配置、数据和步骤,每次减少后重新运行循环——只保留对失败至关重要的部分。
Why bother: a minimal repro shrinks the hypothesis space in Phase 3 (fewer moving parts left to suspect) and becomes the clean regression test in Phase 5.
为什么要费这个劲:最小化复现缩小了阶段 3 中的假设空间(更少的活动部件值得怀疑),并成为阶段 5 中干净的回归测试。
Done when every remaining element is load-bearing — removing any one of them makes the loop go green.
当每个剩余元素都是必要支撑时完成——移除其中任何一个都会使循环变绿。
Do not proceed until you have reproduced and minimised.
在完成复现和最小化之前不要继续。
Generate 3–5 ranked hypotheses before testing any of them. Single-hypothesis generation anchors on the first plausible idea.
在测试任何一个假设之前,先生成 3–5 个排序假设。生成单个假设会让你锚定在第一个看似合理的想法上。
Each hypothesis must be falsifiable: state the prediction it makes.
每个假设必须是可证伪的:陈述它做出的预测。
Format: “If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse.”
格式:「如果 <X> 是原因,那么 <改变 Y> 会使 bug 消失 / <改变 Z> 会使它更严重。」
Show the ranked list to the user before testing. They often have domain knowledge that re-ranks instantly (“we just deployed a change to #3”), or know hypotheses they've already ruled out. Cheap checkpoint, big time saver. Don't block on it — proceed with your ranking if the user is AFK.
在测试之前将排序列表展示给用户。 他们通常拥有领域知识,可以立即重新排序(「我们刚刚部署了一个对 #3 的更改」),或者知道他们已经排除的假设。廉价的检查点,巨大的时间节省。不要阻塞——如果用户 AFK,就用你的排序继续。
Each probe must map to a specific prediction from Phase 3. Change one variable at a time.
每个探测必须对应阶段 3 中的具体预测。一次只改变一个变量。
Tool preference:
工具优先级:
Tag every debug log with a unique prefix, e.g. [DEBUG-a4f2]. Cleanup at the end becomes a single grep. Untagged logs survive; tagged logs die.
为每条调试日志打上唯一前缀标签,例如 [DEBUG-a4f2]。最后的清理变成一个 grep 命令。未标记的日志存活;标记的日志被清除。
Perf branch. For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, performance.now(), profiler, query plan), then bisect. Measure first, fix second.
性能分支。 对于性能回退,日志通常是错的。相反:建立基线测量(计时测试架、performance.now()、性能分析器、查询计划),然后二分。先测量,后修复。
Write the regression test before the fix — but only if there is a correct seam for it.
在修复之前编写回归测试——但前提是存在一个正确的接缝。
A correct seam is one where the test exercises the real bug pattern as it occurs at the call site. If the only available seam is too shallow (single-caller test when the bug needs multiple callers, unit test that can't replicate the chain that triggered the bug), a regression test there gives false confidence.
正确的接缝是指测试能按调用现场的实际方式,演练真实的 bug 模式。如果唯一可用的接缝太浅(bug 需要多个调用者时只有单调用者测试,单元测试无法复制触发 bug 的链条),在这样的接缝上写回归测试只会产生虚假的自信。
If no correct seam exists, that itself is the finding. Note it. The codebase architecture is preventing the bug from being locked down. Flag this for the next phase.
如果没有正确的接缝存在,这本身就是发现。 记下来。代码库架构阻止了 bug 被锁定。标记此问题供下一阶段处理。
If a correct seam exists:
如果正确的接缝存在:
Required before declaring done:
在宣布完成前必须完成:
[DEBUG-...] instrumentation removed (grep the prefix)[DEBUG-...] 插桩已移除(用前缀 grep)Then ask: what would have prevented this bug? If the answer involves architectural change (no good test seam, tangled callers, hidden coupling) hand off to the /improve-codebase-architecture skill with the specifics. Make the recommendation after the fix is in, not before — you have more information now than when you started.
然后问:什么可以预防这个 bug? 如果答案涉及架构变更(没有好的测试接缝、调用者纠结、隐藏的耦合),将具体信息移交给 /improve-codebase-architecture 技能。在修复落地后给出建议,而不是之前——你现在拥有的信息比开始时更多。