diagnosing-bugs について
コーディングエージェント向けのデバッグスキルです。症状から仮説を立て、証拠に基づく再現と検証へ進めます。再現を最初の前提とせず、不足する証拠に応じて確認方法を選びます。
主な機能
- 01証拠に基づくバグ調査
- 02的を絞った再現とプローブ
- 03仮説の検証
- 04回帰テストと確認
- 05秘密情報のマスキングと後片付け
活用シーン
- 01再現が難しいバグの調査
- 02複数の原因候補の比較
- 03報告された動作に基づく修正確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marcellocurto/ skills --skill diagnosing-bugsインストール後、Claude Code で/diagnosing-bugsを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlscripts/hitl-loop.template.sh
詳細
バグの診断
再現、コードの調査、暫定的な仮説、対象を絞った調査を組み合わせて、難しいバグを診断します。不足している証拠に基づいて次のステップを選びます。以下のセクションは調査に役立つ手段であり、順番どおりに完了しなければならない段階ではありません。
コードベースを調べるときは、関連するモジュールを明確に把握できるよう、ファイル名にかかわらず、プロジェクトに用語集があれば読んでください。また、変更する領域の ADR も確認してください。
マスキング
このスキルでは、コマンド、出力、取得したアーティファクトを提示します。まず、すべてのシークレットをマスキングしてください。該当箇所には <REDACTED> と記入します。認証情報が提示内容ではなく環境内に留まるよう、環境変数を使ってループを構築してください。取得したアーティファクトには認証ヘッダーが含まれます。重要な情報を示す行だけを引用し、トレースをディスクに保存する前にシークレットを除去してください。保存したトレースはリポジトリの外に置いてください。
マスキングした出力だけではバグを診断できない場合は、その旨を伝えてユーザーに確認してください。
フィードバックループを構築する
まず、ユーザーが示した正確な症状、期待される動作、エントリーポイント、環境、入力、操作手順を確認します。関連するコードをたどり、暫定的な仮説を立てて、再現時に維持すべき条件を特定します。仮説は、確定した原因と明確に区別してください。
報告されたバグで失敗し、修正後に成功する可能性がある既存のチェックを優先します。原因を見分けたり、結果を検証したりするのに役立つ場合は、フィードバックループを構築または調整してください。コードを調査したり、検証可能な説明を立てたりする前に、実行可能な再現を必須としないでください。
役立つチェックを選ぶ
報告された障害に到達できる、最もコストの低いチェックを選びます。以下は選択肢であり、すべてを順番に試す必要はありません。
- 失敗するテスト:バグに到達できる任意の接続点で実行する単体テスト、統合テスト、E2E テスト。
- Curl/HTTP スクリプト:実行中の開発サーバーに対して実行します。
- CLI の実行:フィクスチャー入力を使用し、標準出力を既知の正常なスナップショットと比較します。
- ヘッドレスブラウザースクリプト:Playwright/Puppeteer で UI を操作し、DOM、コンソール、ネットワークを検証します。
- 取得したトレースの再生:実際のネットワークリクエスト、ペイロード、イベントログをディスクに保存し、コードパスを単独で通して再生します。
- 一時的なハーネス:システムの最小限の部分(1 つのサービス、モック化した依存関係)を立ち上げ、単一の関数呼び出しでバグのコードパスを実行します。
- プロパティ/ファジングループ:入力に依存する障害では、範囲を限定して入力を生成し、シードと失敗した入力を保持します。
- 二分探索ハーネス:既知の 2 つの状態(コミット、データセット、バージョン)の間でバグが発生した場合、「状態 X で起動し、チェックして、繰り返す」処理を自動化します。コミットの場合は、
git bisect runでこのループを実行できます。 - 差分ループ:同じ入力を旧バージョンと新バージョン(または 2 つの設定)に通し、出力を比較します。
- 人の支援による再現:エージェントが対象のコードパスを実行できない場合、ユーザーに正確な操作を伝え、関連する観察結果を尋ねます。ターミナル上で繰り返し実行できるループが役立つ場合は、
scripts/hitl-loop.template.shを調整し、ユーザー自身のターミナルで実行してもらい、最後に出力される取得ブロックを貼り付けるよう依頼します。
コマンドまたは手動での操作、関連する条件、観察された結果を記録します。症状を再現したチェックと、症状を検出すると予想されるだけのチェックを区別してください。
ループを改善する
次の実験の有用性が高まる場合は、ループを改善します。
- もっと速くできますか?(セットアップをキャッシュする、無関係な初期化を省く、テスト範囲を絞る。)
- シグナルをより明確にできますか?(「クラッシュしなかった」ではなく、特定の症状をアサートする。)
- より決定的にできますか?(時間を固定する、乱数生成器にシードを指定する、ファイルシステムを分離する、ネットワークを固定する。)
速度、決定性、無人実行は反復に役立ちますが、有用な証拠を得るための必須条件ではありません。次の診断チェックから得られる知見のほうが多くなる段階で、ハーネスの最適化を止めてください。
非決定的なバグ
実行回数に上限を設け、試行、失敗、条件を記録してください。疑われる仕組みから妥当性があり、かつ実験によって報告された失敗が保たれる場合は、スケジューリング、シード、並行実行数、またはワークロードを制御してください。追加の実行や計測は、必要な再現率を満たすためではなく、解消できる不確実性に基づいて選んでください。失敗しなかった実行だけで、不安定なバグがなくなったと証明されるわけではありません。
再現できない場合
試したことと、証拠が不足している点を明記してください。原因を絞り込める範囲で、関連コードの調査、トレース分析、安全なプローブを続けてください。特定の環境、機密情報を削除したアーティファクト、本番環境での計測許可を求めるのは、その情報が不足していて先に進めない場合に限り、回答を待つ間も独立して進められる調査は続行してください。
証拠によって仕組みが明らかになるまでは、最有力の原因を暫定的なものとして扱ってください。再現できなくても、コードや取得済みの証拠が承認済みの修正を裏付ける場合は、その根拠と、まだ必要な検証を説明してください。実際に観測していない限り、元のバグを再現した、または修正できたと主張しないでください。
シナリオを再現して絞り込む
実行できる場合は、チェックが単に成功するだけ、あるいは近接する別のエラーを起こすだけでなく、ユーザーが報告した失敗モードに到達することを確認してください。修正後に比較できるよう、正確な症状と関連条件を記録してください。安定した結果とノイズを見分ける必要がある場合に限り、再実行してください。
仕組みの切り分けや検証の実用性向上に役立つ場合は、入力、呼び出し元、設定、データ、または手順を減らしてください。疑う要因を一度に一つずつ変更し、同じ失敗が残るか確認してください。
最有力の説明を検証できる程度にシナリオが小さくなったとき、または別のプローブのほうが有益になったときに、絞り込みを止めてください。仮説の検証や、根拠に裏付けられた修正の適用前に、完全な最小化を行う必要はありません。最終検証に備えて元のシナリオを保持してください。縮小した経路では、報告された不具合を回避してしまう可能性があります。
仮説を検証する
調査の全過程を通じて仮説を立て、見直してください。証拠が具体的な場合は最有力の説明を一つ定め、複数の仕組みが観測結果と合致する場合は、それらを比較してください。候補数を満たすために仮説を作り出さないでください。
検証する価値のある各仮説について、それを支持する証拠と、他の仮説と区別する、または仮説を否定する予測を特定してください。最も低コストで決定的なチェックを選び、その結果に基づいて説明を更新してください。
たとえば、古いキャッシュが誤った値の原因なら、同じ入力でそのキャッシュを迂回すると期待される値に戻るはずです。改善が見られたからといって仮説を裏付けると決めつけず、その結果が仕組みを支持するか確認してください。
ユーザーが調査の進捗を把握したり、誤りを指摘したりするうえで役立つ場合は、最有力の説明、重要な不確実性、次に行うチェックを共有してください。判断や不足している証拠が実際に次の手順を妨げていない限り、待たずに続行してください。
計測する
各プローブは、特定の不確実性を解消するか、予測を検証するものでなければなりません。結果の原因を特定できるよう、比較時は一度に一つの変数だけを変更してください。
ツールの優先順位:
- デバッガー/REPL による調査:環境が対応し、処理を一時停止しても調査対象の動作が変わらない場合に使用します。タイミングや並行実行に関するバグでは、通常はログを使用する必要があります。
- 対象を絞ったログ:仮説を区別できる境界に配置します。
- 決して「すべてをログに出して grep する」方法は使わないでください。
すべてのデバッグログに、[DEBUG-a4f2] のような一意のプレフィックスを付けてください。これにより、最後に grep を一度実行するだけでクリーンアップできます。タグのないログは残り、タグ付きのログは削除できます。
パフォーマンスのリグレッションでは、タイミング計測ハーネス、プロファイラー、またはクエリプランを使い、報告されたワークロードでベースラインを確立してください。疑われる原因に応じて、プロファイリング、二分探索、または焦点を絞った実験を行ってください。修正後も同じワークロードを比較してください。修正前または修正後の測定値が得られない場合は、測定に基づく改善を主張しないでください。
修正と検証
実用的な接点を通じて実際のバグを再現できる場合は、修正前に回帰テストを作成します。
適切な接点とは、テストが呼び出し元で発生する実際のバグのパターンを再現できる場所です。利用できる接点が浅すぎる場合(複数の呼び出し元が必要なバグに対して単一の呼び出し元しかテストしない、バグを引き起こした連鎖を再現できない単体テストなど)、そこでの回帰テストは誤った安心感を与えます。
実用的な回帰テストの接点がない場合は、その制約を説明し、元のブラウザ操作、再生、コマンドなど、実際の動作を通じて可能な限り有意義なチェックを行います。このワークフローを満たすことだけを目的に、大掛かりなテスト基盤や誤解を招くテストを作成しないでください。
そのテストが実用的な場合は、次の手順を実行します。
- サポート対象の失敗シナリオを、その接点で行う焦点を絞った回帰テストにします。
- コードを修正する前にテストを実行し、意図した理由で失敗することを確認します。そうならない場合は、報告されたバグの証拠とみなすのではなく、不一致を調査します。
- 確立された仕組みに基づいて修正を適用します。
- チェックを再実行し、意図した動作が成功することを確認します。それでも失敗する場合は、調査に戻ります。
回帰テストでは、関連する初期状態、設定、実際の判断経路を維持します。セットアップで、報告されたワークフローに欠けている前提条件を補わないでください。正常な拒否を期待するチェックでは、必要な操作が成功することを証明できません。
承認済みの要件が変更された場合、または要件に照らしてテストが誤りだったと証拠により確認できた場合に限り、期待値を変更します。インターフェースやセットアップを変更する場合も、保護対象の失敗ケースを維持してください。成功させることだけを目的に、新しい出力を受け入れたり、失敗している協力先を成功するスタブに置き換えたり、回帰テストをスキップしたりしないでください。
承認済みの修正と必要な再構成を続けます。有効な失敗が未解決の判断、利用できない前提条件、または実質的なスコープ拡大に依存する場合は、失敗するテストを残し、阻害要因と残作業を報告します。再現のみを求める依頼であれば、テストが失敗した状態で完了できますが、実装依頼は未完了のままです。動作上の失敗と、動作に到達できなかったチェックを区別し、報告されたコマンドが実際に回帰テストを実行したことを確認してください。
永続的なテストを追加したかどうかにかかわらず、可能であれば元のエントリーポイント、環境、入力、手順を使って修正を検証します。縮小した再現や低レベルのテストは検証の裏付けになりますが、その代わりにはなりません。断続的な失敗については、修正前後の観察結果と残る不確実性を報告します。失敗前の証拠または元のシナリオによる検証のいずれかが得られない場合は、その不足を明記します。
修正を確認した後、バグによって明らかになった安定した不変条件を、それを管理するモジュールで強制できるか検討します。実証されたバグのクラスを防げる場合は、型やスキーマの制約、境界での検証、リンター規則、正規のエントリーポイントなど、既存の構造的な仕組みを優先します。回帰テストは動作上の証拠として残します。再発の信頼できる可能性がない単発の失敗に対して仕組みを追加せず、不変条件の強制を目的に承認済みのスコープを拡大しないでください。
クリーンアップと報告
完了する前に、次の作業を行います。
- 調査のために追加した一時的なデバッグ用計測や使い捨ての成果物を削除するか、有用な成果物は合意済みのデバッグ用の場所に保管します。
- その後、クリーンアップ済みのコードで回帰チェックと元のシナリオの検証を実行し、リリース対象のコードに対する結果を記録します。それ以降に何も変更されていない場合に限り、以前の実行結果を再利用できます。結果と検証上の不足を記録します。
- 裏付けのある原因、修正、検証の証拠、残る不確実性を報告します。公開が依頼されている場合は、コミットまたは PR の説明に原因を記載します。