debug について
Debugは、難しいソフトウェアの不具合を調査するための体系的なスキルで、開発者やコーディングエージェントを対象とします。再現可能なフィードバックループの構築と最小化を仮説立案より先に求め、計測、回帰テスト、後処理を案内します。
主な機能
- 01失敗を検出できるループの構築
- 02不具合の再現と最小化
- 03反証可能な仮説の順位付け
- 04対象を絞った計測による調査
- 05回帰テストの追加と後処理
活用シーン
- 01再現可能な症状を伴う不具合の診断
- 02断続的な失敗の調査
- 03パフォーマンス低下の追跡
- 04元のシナリオによる修正の検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dyrits/ skills --skill debugインストール後、Claude Code で/debugを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
apm.ymlagents/openai.yamlassets/hitl-loop.template.sh詳細
デバッグ
難しいバグに取り組むための規律です。明確な理由がある場合に限り、フェーズを省略してください。
コードベースを調べる際は、AGENTS.md から参照されている場合、作業対象の領域にある用語集とアーキテクチャ決定記録を読み、関連モジュールの全体像をつかんでください。レポートでは、それらが挙げていない可能性の高い記録を、代わりに挙げてください。
マスキング
このスキルでは、コマンド、出力、取得した成果物を提示します。まず、すべてのシークレットをマスキングしてください。その箇所には <REDACTED> と記載します。環境変数を使ってビルドループを組み、認証情報が提示内容ではなく環境内にとどまるようにしてください。取得した成果物には認証ヘッダーが含まれます。問題の兆候を示す行だけを引用してください。
マスキングした出力だけではバグを診断できない場合は、その旨を伝えてユーザーに尋ねてください。
フェーズ 1:フィードバックループを構築する
これがこのスキルの本質です。 それ以外はすべて機械的な作業です。バグを確実に検出する精度の高い合否判定(このバグで失敗するもの)があれば、原因を突き止められます。二分探索、仮説検証、計測は、いずれもそのループを利用するだけです。ループがなければ、どれだけコードを見つめても解決できません。
ここに並外れた労力を注いでください。果敢に取り組んでください。創意工夫してください。あきらめないでください。
おおよそ優先度の高い順に、構築方法を示します
- バグに到達する接点での失敗するテスト:ユニットテスト、統合テスト、E2E テスト。
- 起動中の開発サーバーに対する curl/HTTP スクリプト。
- フィクスチャ入力を使って CLI を実行し、標準出力を既知の正常なスナップショットと比較する方法。
- UI を操作し、DOM、コンソール、ネットワークを検証するヘッドレスブラウザースクリプト(Playwright/Puppeteer)。
- 取得したトレースを再生する。 実際のネットワークリクエスト、ペイロード、イベントログをディスクに保存し、コードパスに単独で再生させます。
- 使い捨てのハーネス。 バグのコードパスを単一の関数呼び出しで実行する最小限のシステム(1 つのサービス、モック化した依存関係)を起動します。
- プロパティ/ファジングループ。 バグが「出力がときどき間違う」ものであれば、ランダムな入力を 1000 件実行し、失敗パターンを探します。
- 二分探索ハーネス。 バグが既知の 2 つの状態(コミット、データセット、バージョン)の間で発生した場合、「状態 X で起動して確認する」という処理を自動化し、
git bisect runで実行できるようにします。 - 差分ループ。 同じ入力を旧バージョンと新バージョン(または 2 つの設定)で実行し、出力を比較します。
- HITL bash スクリプト。 最後の手段です。人間がクリックする必要がある場合は、
assets/hitl-loop.template.shを使って作業を構造化します。手順を記入し、ユーザー自身のターミナルで実行してもらい、貼り付けられたKEY=VALUEの行を読み取ります。
適切なフィードバックループを構築すれば、バグは 90% 解決したも同然です。
ループを改善する
ループをプロダクトとして扱います。ループを1 つでも作ったら、さらに改善してください。
- もっと高速化できますか?(セットアップをキャッシュする、無関係な初期化を省略する、テスト範囲を絞る。)
- シグナルをもっと明確にできますか?(「クラッシュしなかった」ではなく、具体的な症状を検証する。)
- もっと再現性を高められますか?(時刻を固定する、乱数シードを指定する、ファイルシステムを分離する、ネットワークを固定する。)
30 秒かかる不安定なループは、ループがない状態とほとんど変わりません。2 秒で確定的に動くループは精度が高く、デバッグの強力な武器になります。
非決定的なバグ
目標は完全な再現ではなく、再現率を高めることです。トリガーを 100 回ループさせたり、並列化したり、負荷を加えたり、タイミングの幅を狭めたり、スリープを挿入したりしてください。再現率 50% のバグならデバッグできますが、1% ではできません。デバッグ可能になるまで再現率を上げ続けてください。
どうしてもループを構築できない場合
作業を止め、そのことを明確に伝えてください。試したことを列挙し、ユーザーに次のいずれかを求めてください。(a)バグが再現する環境へのアクセス、(b)マスキング済みの取得成果物(HAR ファイル、ログダンプ、コアダンプ、タイムスタンプ付きの画面録画)、または(c)一時的な本番環境の計測を追加する許可。ループなしに仮説を立てて先へ進んではいけません。
完了条件:失敗するタイトなループ
Phase 1 は、ループがタイトかつ失敗を検出できる状態になったら完了です。すでに少なくとも 1 回実行済みの単一のコマンド(スクリプトのパス、テストの実行コマンド、curl)を特定でき、その実行コマンドと出力(機密情報を伏せたもの)を示せる必要があります。また、そのコマンドは次の条件を満たしている必要があります。
- 失敗を検出できる:実際のバグのコードパスを通り、ユーザーが報告した症状そのものを検証します。このバグがある状態で失敗し、修正後に成功できる必要があります。「エラーなく実行される」だけでは不十分です。_この特定のバグを検出できる_必要があります。
- 決定的:実行のたびに同じ判定結果になります(不安定なバグの場合は、上記のように高い再現率を固定できていること)。
- 高速:数秒で終わり、数分もかかりません。
- エージェントから実行可能:無人で実行できます。人が介在するのは
assets/hitl-loop.template.shを介する場合のみです。
このコマンドができる前に、仮説を立てようとしてコードを読み始めていることに気づいたら、そこで止めてください。仮説に飛びつくことこそ、このスキルが防ごうとしている失敗です。 失敗を検出できるコマンドがなければ、Phase 2 には進めません。
Phase 2:再現と最小化
ループを実行します。バグが現れたとき、失敗することを確認してください。
次の点を確認します。
- ループが再現するのは、近くでたまたま起きる別の失敗ではなく、ユーザーが説明した障害モードです。バグを取り違えれば、修正も誤ります。
- 失敗が複数回の実行で再現します(非決定的なバグの場合は、デバッグに十分な高い確率で再現します)。
- 正確な症状(エラーメッセージ、誤った出力、遅い実行時間)を記録しており、後続のフェーズで修正が実際に問題を解決したかを検証できます。
最小化
失敗を確認したら、失敗を維持できる最小のシナリオまで再現ケースを縮小します。入力、呼び出し元、設定、データ、手順を一度に 1 つずつ削り、削るたびにループを再実行して、失敗の原因として欠かせないものだけを残します。
その理由:最小の再現ケースなら Phase 3 で仮説の範囲を狭められ(疑う対象となる要素が減り)、Phase 5 でそのまま明確な回帰テストとして使えます。
残っているすべての要素が失敗に不可欠になったら完了です。どの要素を 1 つ取り除いても、ループが成功する状態です。
再現と最小化の両方が終わるまで先に進まないでください。
Phase 3:仮説を立てる
検証を始める前に、優先順位を付けた3~5 個の仮説を立てます。仮説を 1 つしか立てないと、最初に思いついたもっともらしい案に引きずられます。
各仮説は反証可能である必要があります。予測を明示してください。
形式:「原因が なら、 を変更するとバグが消える/ を変更すると悪化する」
予測を示せない場合、それは単なる思いつきです。破棄するか、明確にしてください。
検証する前に、優先順位を付けたリストをユーザーに提示してください。 ユーザーはドメイン知識を持っていて、順位をすぐに変更できることがあります(「#3 の変更をデプロイしたばかりです」)。すでに除外した仮説を知っている場合もあります。これは手軽で、大幅な時間の節約になります。ユーザーが離席中でも作業を止めず、自分の順位付けで進めてください。
Phase 4:計測する
各プローブは Phase 3 の特定の予測に対応させます。一度に変更する変数は 1 つだけです。
ツールの優先順位:
- デバッガー/REPL による調査(環境が対応している場合)。ブレークポイント 1 つは、ログ 10 個よりも有効です。
- 仮説を区別できる境界での、対象を絞ったログ。
- 「すべてログに出して grep」は絶対にしないでください。
デバッグログにはすべて、例として [DEBUG-a4f2] のような一意のプレフィックスを付けてください。最後に grep 1 回でクリーンアップできます。タグなしのログは残り、タグ付きのログは削除できます。
パフォーマンスの分岐。 パフォーマンスのリグレッションでは、通常ログは適切ではありません。代わりに、まずベースラインの計測(計測用ハーネス、performance.now()、プロファイラー、クエリプラン)を行い、その後で二分探索してください。まず計測し、修正はその後です。
フェーズ 5:修正と回帰テスト
回帰テストは修正前に作成します。ただし、適切なテストの接点がある場合に限ります。
再現によって失敗は示せますが、合意済みの動作を変更する根拠にはなりません。症状、仕様、コードの間で意図されている動作が食い違っている場合は、その矛盾をユーザーに伝え、ループを通すために要件を弱めるのではなく、観測された失敗と成功の証拠をそのまま残してください。
適切なテストの接点とは、呼び出し元で発生する実際のバグのパターンをテストできる場所です。利用できる接点が浅すぎる場合(複数の呼び出し元が必要なバグに対する単一呼び出し元のテストや、バグを引き起こした一連の処理を再現できない単体テストなど)、そこで回帰テストを行っても誤った安心感を与えます。
**適切なテストの接点がない場合、それ自体が発見事項です。**記録してください。コードベースのアーキテクチャによって、バグを確実に防ぐことができません。次のフェーズに申し送りしてください。
適切なテストの接点がある場合:
- 最小化した再現ケースを、その接点で失敗するテストにします。
- 失敗することを確認します。コードまたはフィクスチャを変更して意図的に失敗させた場合は、その変更を信頼する前に、変更していないコピーとの
diffを取り、変更が適用されたことを確認します。 - 修正を適用します。
- 成功することを確認します。
- 元の(最小化していない)シナリオに対して、フェーズ 1 のフィードバックループを再実行します。
フェーズ 6:クリーンアップ
完了を宣言する前に、以下が必要です:
- 元の再現ケースで再現しなくなったことを確認します(フェーズ 1 のループを再実行)
- 回帰テストが成功すること(またはテストの接点がないことを記録済み)
-
[DEBUG-...]の計測コードをすべて削除します(プレフィックスをgrepで検索) - 使い捨てのプロトタイプを削除します(または、デバッグ用と明示した場所に移動)
- 正しいと判明した仮説をコミット/PR メッセージに記載し、次にデバッグする人が学べるようにします