debugging-patterns について
開発者向けの体系的なデバッグスキルで、修正案を出す前に根本原因を調査するよう求めます。調査、パターン分析、仮説検証、実装の段階に沿って、呼び出し経路の追跡と証拠の確認を支援します。
主な機能
- 01修正前に根本原因を調査
- 02障害の再現と切り分け
- 03LSPツールによる呼び出し経路の追跡
- 04検証可能な仮説と証拠の記録
- 05最小限の修正と検証
- 06一般的な障害向け手順書
活用シーン
- 01テストやビルドの失敗調査
- 02ランタイムクラッシュの原因追跡
- 03ブラウザーや統合エラーの診断
- 04断続的な不具合やリグレッションの分析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ romiluz13/ cc10x --skill debugging-patternsインストール後、Claude Code で/debugging-patternsを入力して読み込まれたか確認します。
同梱ファイルreferences/investigation-hygiene.mdreferences/root-cause-playbooks.md
詳細
系統的なデバッグ
概要
場当たり的な修正は時間を浪費し、新たなバグを生みます。応急処置は根本的な問題を覆い隠します。
基本原則: 修正を試みる前に、必ず根本原因を突き止めてください。症状だけを修正しても解決にはなりません。
このスキルは v10 では助言的なものです。調査の質を高めますが、ローカルだけのパッチ、推測、または「クラッシュした行を修正する」という考え方を認めるものではありません。
参考ファイル
現在の調査に必要な参考資料だけを読んでください。
references/root-cause-playbooks.md:ビルド/型の失敗、不安定なテスト、実行時クラッシュ、ブラウザーエラー、git bisect、境界の追跡についてreferences/investigation-hygiene.md:コンテキストの管理、証拠の記録、仮説の追跡、再開手順、アーキテクチャ上のエスカレーションについて
絶対原則
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
フェーズ 1 を完了していない場合、修正案を提示してはいけません。
5 ステップの簡易プロセス(参考パターン)
迅速なデバッグには、次の簡潔な流れを使用してください。
1. Capture error message and stack trace
2. Identify reproduction steps
3. Isolate the failure location
4. Implement minimal general fix
5. Verify solution works
デバッグ手法:
- エラーメッセージとログを分析する
- 最近のコード変更を確認する
- 仮説を立てて検証する
- 効果的な位置にデバッグログを追加する
- 変数の状態を調べる
根本原因をたどる手法:
1. Observe symptom - Where does error manifest?
2. Find immediate cause - Which code produces the error?
3. Ask "What called this?" - Map call chain upward
4. Keep tracing up - Follow invalid data backward
5. Find original trigger - Where did problem actually start?
エラーが現れた箇所だけを修正してはいけません。元の引き金までさかのぼってください。 根本原因を特定したら、解決と判断する前に、近くに同じ兆候がないかを調べてください。
LSP を活用した根本原因の追跡
LSP を使って実行フローを体系的に追跡してください。
| デバッグでの必要事項 | LSP ツール | 使用方法 |
|---|---|---|
| 「この関数はどこで定義されていますか?」 | lspGotoDefinition | 定義元へ移動する |
| 「この関数を呼び出しているのはどこですか?」 | lspCallHierarchy(incoming) | 呼び出し元をさかのぼる |
| 「この関数は何を呼び出していますか?」 | lspCallHierarchy(outgoing) | 呼び出し先をたどる |
| 「この変数が使われている箇所はすべてどこですか?」 | lspFindReferences | すべての参照箇所を見つける |
呼び出しチェーンを体系的に追跡する:
1. localSearchCode("errorFunction") → get file + lineHint
2. lspGotoDefinition(lineHint=N) → see implementation
3. lspCallHierarchy(incoming, lineHint=N) → who calls this?
4. For each caller: lspCallHierarchy(incoming) → trace up
5. Continue until you find the root cause
重要: まず localSearchCode から lineHint を必ず取得してください。行番号を推測してはいけません。
各問題について、次の内容を示してください:
- 根本原因の説明
- 診断を裏付ける証拠
- 具体的なコード修正
- テスト方法
- 再発防止の提案
シナリオ別プレイブック
障害が次のいずれかに当てはまる場合は、references/root-cause-playbooks.md を読んでください。
- ビルドまたは型の不具合
- テストの失敗
- 実行時クラッシュ
- ブラウザーまたはコンソールのエラー
- 非同期処理における断続的なバグ
- 「以前は動いていた」機能のリグレッション
- 複数コンポーネント間の受け渡しの失敗
この SKILL.md では、4 フェーズの調査ワークフローに焦点を当ててください。具体的なコマンド、境界を追跡するパターン、git bisect の手順については、参考資料を使用してください。
使用する場面
あらゆる技術的な問題に使用してください。
- テストの失敗
- 本番環境のバグ
- 予期しない動作
- パフォーマンスの問題
- ビルドの失敗
- 統合の問題
特に次のような場合に使用してください:
- 時間に追われている(緊急時には推測に頼りたくなるため)
- 「手早く一つ修正すればよい」と明らかに思える
- すでに複数の修正を試した
- 前回の修正が効果を発揮しなかった
- 問題を十分に理解できていない
次の場合も省略しないでください:
- 問題が単純に見える(単純なバグにも根本原因はあります)
- 急いでいる(急ぐと必ずやり直しが発生します)
- マネージャーから今すぐ直すよう求められている(場当たり的に試すより、体系的に進める方が速く解決できます)
4 つのフェーズ
次のフェーズに進む前に、各フェーズを必ず完了してください。
フェーズ 1:根本原因の調査
修正を試みる前に、必ず以下を行ってください。
-
エラーメッセージを注意深く読む
- エラーや警告を読み飛ばさないでください
- 解決策そのものが記載されていることもよくあります
- スタックトレースを最後まで読みます
- 行番号、ファイルパス、エラーコードを記録します
-
一貫して再現する
- 安定して発生させられますか?
- 正確な手順は何ですか?
- 毎回発生しますか?
- 再現できない場合 → 推測せず、さらにデータを集めてください
-
最近の変更を確認する
- 原因となり得る変更は何ですか?
- Git の差分、最近のコミット
- 新しい依存関係、設定の変更
- 環境の違い
-
複数コンポーネントからなるシステムで証拠を集める
システムに複数のコンポーネント(CI → ビルド → 署名、API → サービス → データベースなど)がある場合:
修正を提案する前に、診断用の計測機能を追加してください。
For EACH component boundary: - Log what data enters component - Log what data exits component - Verify environment/config propagation - Check state at each layer Run once to gather evidence showing WHERE it breaks THEN analyze evidence to identify failing component THEN investigate that specific component境界を追跡する具体的な手順については、
references/root-cause-playbooks.mdをお読みください。 -
データフローを追跡する
呼び出しスタックの深い場所でエラーが発生している場合:
- 不正な値はどこから来ていますか?
- 不正な値を渡した呼び出し元は何ですか?
- 発生源が見つかるまでさかのぼって追跡してください
- 症状ではなく、発生源を修正してください
-
設定がどこで使用されるかを追跡する(サードパーティ SDK、環境変数、インポート時)
置き換え、移行、大規模なリファクタリングを提案する前に:
- 選択肢ゼロ: 設定または環境の変更だけで修正できますか? コードを書き換える案を提案する前に、その仮説を明示し、テストしてください。多くの連携バグは、アーキテクチャではなく配線の問題です。
- 環境変数がアプリケーションの設定で検証されているのに、ライブラリのコンストラクターに渡されていない場合は、誰がその値を読み取るのかを確認してください。サードパーティ SDK は、アプリの DI や設定オブジェクト経由ではなく、モジュールのインポート時/読み込み時に
process.env(または各言語の同等のもの)を読み取ることがよくあります。アプリケーションコードを変更するのではなく、環境変数を設定または修正することで解決する場合があります。 - サードパーティ SDK の置き換えを提案する前に、設定方法を少し調べてください。パッケージの README、公式ドキュメント、または
node_modules(またはベンダーパス)にあるインストール済みのソースを確認します。別のライブラリが必要なのではなく、エンドポイントやフラグが間違っている可能性があります。 - コードのコメントにインポート時の動作や環境変数への依存が記載されている場合、それらを単なる装飾ではなく、調査の手がかりとして扱い、実際に読み取る箇所を追跡してください。
フェーズ 2:パターン分析
修正する前に、パターンを見つけてください。
-
動作する例を見つける
- 同じコードベース内から、類似する動作中のコードを探します
- 壊れている箇所と似ていて、正常に動作しているものは何ですか?
-
参考資料と照らし合わせる
- パターンを実装する場合は、参考実装をすべて読みます
- ざっと読むのではなく、一行ずつ確認してください
- 適用する前に、パターンを完全に理解してください
-
違いを特定する
- 動作するものと壊れているものの違いは何ですか?
- どんなに小さくても、すべての違いを書き出します
- 「影響するはずがない」と決めつけないでください
-
依存関係を理解する
- これには他にどのコンポーネントが必要ですか?
- どの設定、構成、環境が必要ですか?
- どのような前提がありますか?
フェーズ 3:仮説とテスト
科学的な手順に従ってください。
-
単一の仮説を立てる
- 「Y が理由で、X が根本原因だと思います」と明確に述べます
- 書き留めます
- 曖昧にせず、具体的にします
-
最小限のテストを行う
- 仮説を検証するために、可能な限り最小限の変更を行います
- 一度に一つの変数だけを変更します
- 複数のことを一度に修正しないでください
-
先に進む前に検証する
- 動作しましたか? はい → フェーズ 4 へ
- 動作しませんでしたか? 新しい仮説を立てます
- 修正を次々と重ねないでください
-
わからない場合
- 「X が理解できません」と伝えます
- わかったふりをしないでください
- 助けを求めます
- さらに調査します
仮説の品質基準
反証可能性の要件: 優れた仮説は、誤りであることを証明できます。それを否定する実験を考案できないなら、その仮説は役に立ちません。
悪い例(反証不可能):
- 「状態のどこかがおかしい」
- 「タイミングがずれている」
- 「どこかに競合状態がある」
良い例(反証可能):
- 「ルート変更時にコンポーネントが再マウントされるため、ユーザーの状態がリセットされる」
- 「アンマウント後に API 呼び出しが完了し、アンマウントされたコンポーネントで状態が更新される」
- 「2 つの非同期処理がロックせずに同じ配列を変更するため、データが失われる」
違い: 具体性です。優れた仮説は、具体的で検証可能な主張を示します。
仮説の確信度スコア
確信度を付けて複数の仮説を追跡します:
H1: [hypothesis] — Confidence: [0-100]
Evidence for: [what supports this]
Evidence against: [what contradicts this]
Next test: [what would raise or lower confidence]
H2: [hypothesis] — Confidence: [0-100]
Evidence for: [...]
Evidence against: [...]
Next test: [...]
H3: [hypothesis] — Confidence: [0-100]
Evidence for: [...]
Evidence against: [...]
Next test: [...]
スコアの目安:
| 範囲 | 意味 | 対応 |
|---|---|---|
| 80-100 | 強い証拠があり、確実性が高い | 修正に進む |
| 50-79 | 間接的な証拠があり、さらなるデータが必要 | 「次のテスト」を実行する |
| 0-49 | 推測であり、根拠が弱い | 優先度を下げるか、破棄する |
ルール:
- いずれかの仮説が 80 以上になるまで、常に 2~3 個の仮説を維持します
- 新しい証拠が得られるたびに、必ず確信度を更新します
- 最も確信度の高い仮説が 50 未満の状態で、修正に進んではいけません
デバッグにおける認知バイアス
| バイアス | 落とし穴 | 対策 |
|---|---|---|
| 確証バイアス | 仮説を裏付ける証拠だけを探す | 「何があれば、自分の考えが間違いだと証明できるか?」 |
| アンカリング | 最初の説明にとらわれる | 調査を始める前に、3 つ以上の仮説を立てる |
| 利用可能性ヒューリスティック | 最近のバグから、同じ原因だと思い込む | 証拠が示すまでは、各バグを新しい事象として扱う |
| サンクコスト | その方針に 2 時間費やしたため、証拠に反して続ける | 30 分ごとに、「今初めて取り組むとしても、この方針を選ぶか?」と自問する |
メタデバッグ:自分のコード
自分が書いたコードをデバッグするときは、自分自身のメンタルモデルと向き合うことになります。
難しい理由:
- 自分で設計上の判断を下したため、それが明らかに正しいと感じます
- 実際に実装した内容ではなく、意図したことを覚えています
- 慣れによって、バグが見えなくなります
心構え:
- 自分のコードを他人のコードとして扱う - 誰か別の人が書いたかのように読みます
- 設計上の判断を疑う - 実装上の選択は事実ではなく、仮説です
- 自分のメンタルモデルが間違っている可能性を認める - コードの動作が真実であり、自分のモデルは推測です
- 自分が変更したコードを優先的に調べる - 100 行を変更して何かが壊れたなら、その行が有力な容疑箇所です
最も認めにくいこと: 「自分の実装が間違っていた」。「要件が明確でなかった」ではありません。間違えたのは、あなたです。
調査をやり直すタイミング
次の場合は、最初からやり直すことを検討します:
- 2 時間以上進展がない - 視野が狭くなっている可能性があります
- 修正を 3 回以上試しても効果がない - メンタルモデルが間違っています
- 現在の動作を説明できない - 混乱した状態に変更を重ねてはいけません
- デバッガー自体をデバッグしている - 根本的な問題があります
- 修正は機能するが、理由がわからない - これは修正ではなく、運です
やり直しの手順:
- すべてのファイルとターミナルを閉じます
- 確実にわかっていることを書き出します
- 原因ではないと判断したことを書き出します
- 以前とは異なる新しい仮説を列挙します
- フェーズ 1 から再開します
フェーズ 4:実装
症状ではなく、根本原因を修正します。
-
失敗するテストケースを作成する
- 可能な限り簡単に再現します
- 可能であれば自動テストを作成します
- テストフレームワークがない場合は、単発のテストスクリプトを作成します
- 修正前に必ず作成してください
-
修正を1つだけ実装する
- 特定した根本原因に対処します
- 一度に変更するのは1つだけです
- 「ついでに」改善することはありません
- リファクタリングをまとめて行うことはありません
-
修正を検証する
- テストは通るようになりましたか?
- ほかのテストに影響はありませんか?
- 問題は実際に解決しましたか?
-
修正が機能しない場合
- 停止します
- 試した修正の数を数えます
- 3回未満の場合:フェーズ 1 に戻り、新たな情報をもとに再分析します
- 3回以上の場合:停止してアーキテクチャを疑います(下記のステップ 5)
- アーキテクチャについて話し合わずに、修正 #4 を試してはいけません
-
修正が3回以上失敗した場合:アーキテクチャを疑う
アーキテクチャ上の問題を示すパターン:
- 修正するたびに、別の箇所で新たな共有状態/結合/問題が見つかる
- 修正の実装に「大規模なリファクタリング」が必要になる
- 修正するたびに、別の箇所で新たな症状が発生する
停止して、根本を問い直します。
- このパターンは根本的に妥当ですか?
- 「ただ惰性で続けている」状態ではありませんか?
- 症状の修正を続けるのではなく、アーキテクチャをリファクタリングすべきではありませんか?
さらに修正を試みる前に、人間のパートナーと話し合ってください。
これは仮説の失敗ではありません。アーキテクチャが間違っています。
危険信号 — 停止して手順に従う
次のように考えていることに気づいたら:
- 「とりあえず応急処置をして、調査は後で」
- 「X を変えて、うまくいくか試そう」
- 「変更をいくつか加えて、テストを実行しよう」
- 「テストは省略して、手動で確認しよう」
- 「おそらく X だろう。修正しよう」
- 「完全には理解していないけれど、これでうまくいくかもしれない」
- 「パターンでは X となっているけれど、違うやり方にしよう」
- 「主な問題はこちらです:[調査せずに修正を列挙する]」
- データの流れを追跡する前に解決策を提案する
- 設定だけの修正(オプションゼロ)と、インポート時に環境変数/設定を誰が読み取るのかの追跡を行う前に、SDK の置き換えや大規模な移行を提案する
- 「もう一度だけ修正を試す」(すでに2回以上試している場合)
- 修正するたびに、別の箇所で新たな問題が見つかる
これらはすべて、停止してフェーズ 1 に戻る必要があることを示しています。
**修正が3回以上失敗した場合:**アーキテクチャを疑います(フェーズ 4.5 を参照)。
ユーザーが、対応を誤っていると示すサイン
次のような指摘に注意してください。
- 「それは起きていないのでは?」— 検証せずに思い込んでいます
- 「それで……が分かりますか?」— 証拠を集めるべきでした
- 「推測をやめて」— 理解する前に修正を提案しています
- 「徹底的に考えて」— 症状だけでなく、根本を問い直してください
- 「行き詰まっているの?」(苛立った様子)— そのアプローチはうまくいっていません
**このような指摘があったら:**停止してフェーズ 1 に戻ります。
正当化を防ぐ
| 言い訳 | 実際のところ |
|---|---|
| 「単純な問題だから、手順は必要ない」 | 単純な問題にも根本原因があります。単純なバグなら、手順にかかる時間も短くて済みます。 |
| 「緊急だから、手順を踏む時間がない」 | 体系的なデバッグのほうが、推測と確認を繰り返すより速く解決できます。 |
| 「まずこれを試してから、調査しよう」 | 最初の修正がその後の進め方を決めます。最初から正しく行いましょう。 |
| 「修正がうまくいくと確認してから、テストを書こう」 | テストしていない修正は定着しません。先にテストを書けば、修正が有効か確認できます。 |
| 「複数の修正を一度に行えば、時間を節約できる」 | 何がうまくいったのか特定できず、新たなバグの原因になります。 |
| 「参照資料が長すぎるから、パターンを応用しよう」 | 理解が不完全なままでは、必ずバグにつながります。最後まで読んでください。 |
| 「問題が分かった。修正しよう」 | 症状が見えていることと、根本原因を理解していることは別です。 |
| 「もう一度だけ修正を試す」(2回以上失敗した後) | 3回以上の失敗は、アーキテクチャ上の問題を示します。パターンを疑い、再度修正を試してはいけません。 |
クイックリファレンス
| フェーズ | 主な活動 | 成功基準 |
|---|---|---|
| 1. 根本原因 | エラーを読み、再現し、変更を確認し、証拠を集めます | 何が起きたのか、なぜ起きたのかを理解する |
| 2. パターン | 動作する例を見つけ、比較します | 違いを特定する |
| 3. 仮説 | 仮説を立て、最小限のテストを行います | 仮説が確認されるか、新たな仮説が立つ |
| 4. 実装 | テストを作成し、修正して、検証します | バグが解決し、テストが通る |
プロセスを経ても「根本原因がない」と判明した場合
体系的な調査の結果、問題が本当に環境依存、タイミング依存、または外部要因によるものだと判明した場合:
- プロセスを完了しています
- 調査した内容を記録します
- 適切な対処(再試行、タイムアウト、エラーメッセージ)を実装します
- 今後の調査に備えて、監視やログ記録を追加します
ただし:「根本原因がない」ケースの95%は、調査が不十分です。
出力形式
## Bug Investigation
### Phase 1: Evidence Gathered
- **Error**: [exact error message]
- **Stack trace**: [relevant lines]
- **Reproduction**: [steps to reproduce]
- **Recent changes**: [commits/changes]
### Phase 2: Pattern Analysis
- **Working example**: [similar working code]
- **Key differences**: [what's different]
### Phase 3: Hypothesis
- **Theory**: [I think X because Y]
- **Test**: [minimal change made]
- **Result**: [confirmed/refuted]
### Phase 4: Fix
- **Root cause**: [actual cause with evidence]
- **Change**: [summary of fix]
- **File**: [path:line]
- **Regression test**: [test added]
### Verification
- Test command: [command] → exit 0
- All tests: PASS
- Functionality: Restored