| name | diagnosing-bugs |
| description (EN) | Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow. |
| 說明 (繁中) | 硬 bug 與效能回歸的診斷迴圈。當使用者說「diagnose」/「debug this」,或回報東西壞了/拋錯/失敗/很慢時使用。 |
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 skill has you show commands, outputs and captured artifacts. Redact every secret first: write <REDACTED> in its place. Build loops against env vars, so the credential stays in the environment rather than in what you show. Captured artifacts carry auth headers: quote only the lines that carry the signal.
這就是本技能的核心。 其他一切都是機械性作業。如果你對這個 bug 有一個緊密的通過/失敗訊號——一個會因為_這個_ bug 而變紅的訊號——你就會找到原因;二分、假設檢驗與插樁都只是在消耗它。如果你沒有這樣的訊號,再怎麼瞪著程式碼看也救不了你。
If the redacted output is not enough to diagnose the bug, say so and ask the user.
在這裡投入不成比例的精力。要積極。要有創意。拒絕放棄。
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.
git bisect run。scripts/hitl-loop.template.sh 驅動_他們_,讓迴圈仍然結構化。擷取的輸出會回饋給你。Spend disproportionate effort here. Be aggressive. Be creative. Refuse to give up.
建立正確的回饋迴圈,bug 就完成九成了。
git bisect run it.scripts/hitl-loop.template.sh so the loop is still structured. Captured output feeds back to you.把迴圈當產品來經營。一旦有了_一個_迴圈,就收緊它:
Build the right feedback loop, and the bug is 90% fixed.
一個要花 30 秒的搖擺迴圈只比沒有迴圈好一點點;一個 2 秒且確定的是緊密的——這是除錯的超能力。
Treat the loop as a product. Once you have a loop, tighten it:
目標不是乾淨的重現,而是更高的重現率。把觸發器重複 100 次、平行化、加壓力、收窄時間窗、注入 sleep。50% 會搖擺的 bug 可以除錯;1% 的不能——持續拉高重現率,直到它能被除錯。
A 30-second flaky loop is barely better than no loop; a 2-second deterministic one is tight, a debugging superpower.
停下來,明確說出來。列出你試過什麼。向使用者要求:(a) 存取能重現它的任何環境,(b) 一個擷取的產物(HAR 檔、日誌傾倒、核心傾倒、帶時間戳的螢幕錄影),或 (c) 加入暫時正式環境插樁的權限。不要在沒有迴圈的情況下繼續做假設。
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, so keep raising the rate until it's debuggable.
第一階段完成的條件是迴圈緊密且能變紅:你能指認出一個指令——一個腳本路徑、一次測試呼叫、一個 curl——你至少已經跑過一次(貼出該呼叫及其輸出),而且它:
Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a redacted 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.
scripts/hitl-loop.template.sh 才需要人在迴圈中。如果你發現自己在這個指令存在之前就讀程式碼建理論,停下來——直接跳到假設正是本技能要防止的失敗模式。 沒有能變紅的指令,就沒有第二階段。
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 (show the invocation and its output, redacted), and that is:
scripts/hitl-loop.template.sh.執行迴圈。看它變紅——bug 出現了。
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.
確認:
Run the loop. Watch it go red as the bug appears.
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, and 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.
Done when every remaining element is load-bearing: removing any one of them makes the loop go green.
在測試任何假設之前,產生 3–5 個排序的假設。單一假設容易錨定在第一個看起來合理的想法上。
Do not proceed until you have reproduced and minimised.
每個假設都必須可否證:說出它做出的預測。
格式:「如果
是原因,那麼 <改變 Y> 會讓 bug 消失 / <改變 Z> 會讓它更糟。」
Generate 3–5 ranked hypotheses before testing any of them. Single-hypothesis generation anchors on the first plausible idea.
如果你說不出預測,那假設只是一種感覺——丟棄它或把它磨利。
Each hypothesis must be falsifiable: state the prediction it makes.
在測試之前,把排序後的清單給使用者看。 他們通常擁有能立刻重新排序的領域知識(「我們剛剛部署了 #3 的改動」),或知道他們已經排除的假設。便宜的檢查點,省下大把時間。不要被它卡住——如果使用者 AFK,就照你的排序往下走。
Format: "If
is the cause, then will make the bug disappear / will make it worse."
If you cannot state the prediction, the hypothesis is a vibe: discard or sharpen it.
每個探針都必須對應到第三階段的特定預測。一次只改一個變數。
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.
工具偏好:
Each probe must map to a specific prediction from Phase 3. Change one variable at a time.
用獨特前綴標記每個除錯日誌,例如 [DEBUG-a4f2]。最後的清理變成單次 grep。未標記的日誌存活;標記的日誌陣亡。
Tool preference:
效能分支。 對效能回歸,日誌通常是錯的。改成:先建立基線量測(時序測試架、performance.now()、profiler、查詢計畫),再二分。先量測,後修復。
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.
在修復之前寫回歸測試——但只有當它有正確的接縫時。
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.
正確的接縫是測試在呼叫點實際發生的 bug 模式上運作的接縫。如果唯一可用的接縫太淺(bug 需要多個呼叫者時卻只有單一呼叫者測試、無法重現觸發 bug 的鏈的單元測試),在那裡的回歸測試會給你錯誤的信心。
如果沒有正確的接縫,那本身就是發現。 記下它。程式庫架構正在阻止 bug 被鎖定。把這個標記給下一階段。
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.
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.
If a correct seam exists:
宣告完成前必須完成:
[DEBUG-...] 插樁已移除(grep 該前綴)然後問:什麼能防止這個 bug? 如果答案涉及架構變更(沒有好的測試接縫、呼叫者糾纏不清、隱藏的耦合),把具體內容交接給 /improve-codebase-architecture 技能。在修復完成之後再提出建議,不要提前——你現在比開始時擁有更多資訊。
Required before declaring done:
(無繁中對照)
[DEBUG-...] instrumentation removed (grep the prefix)(無繁中對照)