mcpField
D
diagnose

diagnose

github.com/mattpocockテスト・品質305.7k232.5k 回インストール1 日前に更新
リポジトリ

diagnose について

Diagnoseは、難しいバグの調査を体系化するスキルです。仮説を立てる前に高速で決定的なフィードバックループを作り、その後、再現、対象を絞った計測、回帰テスト、後片付けと振り返りを進めます。

主な機能

  1. 01再現可能なバグ検証ループを構築
  2. 02障害を再現して症状を記録
  3. 03反証可能な仮説を順位付け
  4. 04対象を絞って計測
  5. 05適切な接点で回帰テストを追加
  6. 06後片付けと振り返りを確認

活用シーン

  1. 01難しいバグや断続的な不具合の調査
  2. 02パフォーマンス回帰のデバッグ
  3. 03元の障害を使った修正の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mattpocock/skills --skill diagnose

インストール後、Claude Code で/diagnoseを入力して読み込まれたか確認します。

同梱ファイルscripts/hitl-loop.template.sh

詳細

診断

難しいバグに取り組むための規律です。明確な理由がある場合に限り、フェーズを省略してください。

コードベースを調査する際は、プロジェクトのドメイン用語集を参照して、関連モジュールの全体像を把握してください。また、変更対象の領域に関する ADR も確認してください。

フェーズ 1 — フィードバックループを構築する

これこそがスキルです。 それ以外はすべて機械的な作業です。バグに対して、高速で決定的であり、エージェントが実行できる合否判定シグナルがあれば、原因を突き止められます。二分探索、仮説検証、計測は、どれもそのシグナルを利用するだけです。シグナルがなければ、コードをどれだけ眺めても解決には至りません。

ここには、相応以上の労力を注いでください。積極的に取り組んでください。創意工夫してください。決して諦めないでください。

フィードバックループを構築する方法 — おおむね次の順に試してください
  1. バグに到達できる接点での失敗するテスト — 単体テスト、統合テスト、E2E テスト。
  2. 起動中の開発サーバーに対する Curl / HTTP スクリプト。
  3. フィクスチャ入力を使った CLI の実行。標準出力を既知の正常なスナップショットと比較します。
  4. ヘッドレスブラウザーのスクリプト(Playwright / Puppeteer) — UI を操作し、DOM/コンソール/ネットワークを検証します。
  5. キャプチャしたトレースの再生。 実際のネットワークリクエスト/ペイロード/イベントログをディスクに保存し、コードパスを分離した状態で再生します。
  6. 使い捨てのハーネス。 システムの最小限の構成(1 つのサービス、モック化した依存関係)を起動し、単一の関数呼び出しでバグのコードパスを実行します。
  7. プロパティベーステスト/ファジングのループ。 バグが「出力がときどき間違う」場合は、ランダムな入力を 1000 件実行し、失敗のパターンを探します。
  8. 二分探索用ハーネス。 既知の 2 つの状態(コミット、データセット、バージョン)の間でバグが発生した場合は、「状態 X で起動して確認し、繰り返す」を自動化し、git bisect run を実行できるようにします。
  9. 差分比較ループ。 同じ入力を旧バージョンと新バージョン(または 2 つの設定)に与え、出力を比較します。
  10. HITL bash スクリプト。 最終手段です。人間がクリックする必要がある場合は、scripts/hitl-loop.template.sh で その人間 を誘導し、ループが構造化された状態を保ちます。キャプチャした出力をフィードバックとして利用します。

適切なフィードバックループを構築すれば、バグは 90% 解決したも同然です。

ループ自体を反復的に改善する

ループをプロダクトとして扱ってください。何らかの ループを用意できたら、次の点を確認します。

  • 高速化できますか?(セットアップをキャッシュする、無関係な初期化を省く、テストの対象を絞る。)
  • シグナルをより明確にできますか?(「クラッシュしなかった」ではなく、具体的な症状を検証する。)
  • 決定性を高められますか?(時刻を固定する、乱数シードを設定する、ファイルシステムを分離する、ネットワークを固定する。)

不安定な 30 秒のループは、ループがない状態と大差ありません。決定的な 2 秒のループは、デバッグを強力に支援します。

非決定的なバグ

目標は再現手順を完璧にすることではなく、再現率を高めることです。トリガーを 100 回繰り返し、並列化し、負荷をかけ、時間の範囲を絞り、スリープを挿入します。50% の確率で発生するバグならデバッグできますが、1% では困難です。デバッグできるようになるまで、再現率を上げ続けてください。

ループをどうしても構築できない場合

作業を止め、その旨を明確に伝えてください。試したことを列挙してください。ユーザーには、次のいずれかを依頼します。(a) バグを再現できる環境へのアクセス、(b) キャプチャした成果物(HAR ファイル、ログダンプ、コアダンプ、タイムスタンプ付きの画面録画)、または (c) 一時的な本番環境の計測を追加する許可。ループがない状態で仮説を立てて先に進んではいけません。

信頼できるループを用意できるまで、フェーズ 2 に進まないでください。

フェーズ 2 — 再現する

ループを実行し、バグが現れるのを確認してください。

次の点を確認します。

  • ループによって、ユーザーが説明した失敗パターンが発生すること — 近くで起きる別の失敗ではありません。別のバグを直しても、修正にはなりません。
  • 複数回の実行で失敗を再現できること(非決定的なバグの場合は、デバッグに使えるほど高い確率で再現できること)。
  • 後のフェーズで修正が実際にバグに対処したか検証できるよう、症状の正確な内容(エラーメッセージ、誤った出力、遅い処理時間)を記録していること。

バグを再現するまで先に進まないでください。

フェーズ 3 — 仮説を立てる

検証を始める前に、優先順位を付けた仮説を3〜5個作成します。仮説を1つだけ立てると、最初に思いついたもっともらしい考えに引きずられます。

各仮説は反証可能でなければなりません。つまり、予測を明示します。

形式:「原因が なら、 を変更するとバグが解消し、 を変更すると悪化します。」

予測を示せない場合、その仮説は単なる思いつきです。破棄するか、具体化してください。

検証する前に、優先順位を付けたリストをユーザーに見せてください。 ユーザーが専門知識を持っていて、すぐに順位を変更できることがあります(「#3に関する変更をデプロイしたばかりです」)。あるいは、すでに除外した仮説を知っている場合もあります。簡単な確認で、大幅に時間を節約できます。返答を待って作業を止める必要はありません。ユーザーが応答できない場合は、自分の順位に従って進めてください。

フェーズ 4 — 計測する

各調査は、フェーズ 3 の具体的な予測に対応させます。一度に変更する変数は1つだけです。

ツールの優先順位:

  1. デバッガー/REPLでの調査(環境が対応している場合)。ブレークポイント1つで、ログ10件分の情報が得られます。
  2. 仮説を区別できる境界に、対象を絞ったログを追加します。
  3. 「すべてをログに出してgrepする」方法は使わないでください。

すべてのデバッグログに、[DEBUG-a4f2] のような一意のプレフィックスを付けます。最後にプレフィックスを1回grepすれば、ログをまとめて削除できます。タグのないログは残り、タグ付きのログは削除できます。

パフォーマンスの分岐。 パフォーマンスのリグレッションでは、通常、ログは適切な手段ではありません。代わりに、計測の基準値(タイミングハーネス、performance.now()、プロファイラー、クエリプラン)を取り、その後で二分探索します。まず計測し、修正はその後です。

フェーズ 5 — 修正とリグレッションテスト

リグレッションテストは修正前に作成します。ただし、適切なテスト箇所がある場合に限ります。

適切なテスト箇所とは、呼び出し元で発生する実際のバグパターンをテストできる箇所です。利用できる箇所が浅すぎる場合(複数の呼び出し元が必要なバグに対する呼び出し元1つだけのテストや、バグを引き起こした呼び出しチェーンを再現できない単体テストなど)、そこでリグレッションテストを作成すると、誤った安心感を与えます。

適切なテスト箇所がないこと自体が調査結果です。 その事実を記録してください。コードベースのアーキテクチャによって、バグの再発を防ぐ仕組みを整えられません。次のフェーズでこの問題を報告してください。

適切なテスト箇所がある場合:

  1. 最小化した再現ケースを、その箇所で失敗するテストにします。
  2. テストが失敗することを確認します。
  3. 修正を適用します。
  4. テストが成功することを確認します。
  5. 元の(最小化していない)シナリオに対して、フェーズ 1 のフィードバックループを再実行します。

フェーズ 6 — クリーンアップと事後分析

完了を宣言する前に、以下を必ず行います。

  • 元の再現ケースで再現しなくなったことを確認する(フェーズ 1 のループを再実行)
  • リグレッションテストが成功することを確認する(または、適切なテスト箇所がないことを記録する)
  • すべての[DEBUG-...]計測コードを削除する(プレフィックスをgrepする)
  • 一時的なプロトタイプを削除する(または、デバッグ用であることが明確な場所に移動する)
  • 正しかった仮説をコミット/PRのメッセージに記載する。次にデバッグする人が学べるようにするためです。

次に、「このバグを防ぐには何が必要だったか」を考えてください。 回答にアーキテクチャの変更(適切なテスト箇所がない、呼び出し元が複雑に絡み合っている、隠れた依存関係があるなど)が含まれる場合は、具体的な情報を添えて/improve-codebase-architectureスキルに引き継ぎます。提案は修正を適用した後に行ってください。作業を始めたときよりも、多くの情報が得られているためです。

コメント