mcpField
D
diagnosing-bugs

diagnosing-bugs

github.com/vinvcn開発5.4k4.2k 回インストール1 日前に更新
リポジトリ

diagnosing-bugs について

diagnosing-bugsは、難しいソフトウェアの不具合を調査するエージェントスキルです。診断の前に症状を検出できる高速なフィードバックループを作り、最小化した再現例、反証可能な仮説、回帰テストに基づいて修正します。

主な機能

  1. 01症状に特化したループの構築
  2. 02再現条件の最小化
  3. 03仮説の順位付けと検証
  4. 04対象を絞った計測
  5. 05修正と回帰テストの追加

活用シーン

  1. 01断続的または不安定な不具合の調査
  2. 02正常状態間で発生した回帰の特定
  3. 03実際の障害を最小の再現例に縮小
  4. 04修正の検証と再発防止

インストール

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

$npx skills add https://github.com/vinvcn/mattpocock-skills-zh-cn --skill diagnosing-bugs

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

同梱ファイルagents/openai.yamlscripts/hitl-loop.template.sh

詳細

不具合の診断

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

コードベースを調べる際は、まず GLOSSARY.md(存在する場合)を読み、関連モジュールの明確な全体像を把握し、変更する領域に関する ADR を確認してください。

機密情報のマスキング

このスキルでは、コマンド、出力、取得したアーティファクトを提示するよう求めます。まず、すべてのシークレットをマスキングしてください:<REDACTED> に置き換えます。ビルドループでは環境変数を使い、認証情報を提示する内容ではなく環境内に留めてください。取得したアーティファクトに認証ヘッダーが含まれている場合は、シグナルを含む行だけを引用してください。

マスキング後の出力ではバグを診断するのに不十分な場合は、その旨を説明し、ユーザーに尋ねてください。

Phase 1 - フィードバックループを構築する

これがこのスキルの核心です。 それ以外はすべて機械的な手順です。このバグで赤になる タイトな 合否シグナルがあれば、原因を特定できます。二分探索、仮説検証、計測はいずれも、このシグナルを利用するだけです。これがなければ、どれだけコードを見つめても解決できません。

ここには不釣り合いなほどの労力をかけてください。妥協せず、創意工夫を凝らし、あきらめないでください。

ループの構築方法 - おおむね次の順に試す
  1. 失敗するテスト。バグに到達できる境界に配置します。ユニット、インテグレーション、E2E のどれでもかまいません。
  2. Curl / HTTP スクリプト。実行中の開発サーバーにリクエストを送ります。
  3. CLI の実行。フィクスチャ入力を使い、標準出力を既知の正しいスナップショットと diff で比較します。
  4. ヘッドレスブラウザースクリプト(Playwright / Puppeteer)。UI を操作し、DOM/コンソール/ネットワークをアサートします。
  5. 取得済みトレースをリプレイする。 実際のネットワークリクエスト/ペイロード/イベントログをディスクに保存し、隔離された環境でコードパスにリプレイします。
  6. 使い捨てのハーネス。 システムの最小限の部分(1 つのサービス、モック化した依存関係)を起動し、1 回の関数呼び出しでバグのコードパスをトリガーします。
  7. プロパティ/ファズループ。 バグが「ときどき出力が間違う」場合は、1000 個のランダムな入力を実行して失敗モードを探します。
  8. 二分探索用ハーネス。 バグが既知の 2 つの状態(コミット、データセット、バージョン)の間で発生する場合は、「状態 X で起動して確認し、繰り返す」を自動化し、git bisect run を実行できるようにします。
  9. 差分比較ループ。 同じ入力を旧バージョンと新バージョン(または 2 つの設定)で実行し、出力を diff で比較します。
  10. HITL bash スクリプト。 最後の手段です。人がクリックする必要がある場合は、scripts/hitl-loop.template.sh で 人 を操作し、ループを構造化された状態に保ちます。取得した出力をあなたに返します。

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

ループをタイトにする

ループを製品のように扱ってください。ループが 1 つ できたら、さらに タイトに してください。

  • もっと速くできますか?(セットアップをキャッシュする、無関係な初期化を省く、テスト範囲を狭める。)
  • シグナルをもっと明確にできますか?(「クラッシュしなかった」ではなく、具体的な症状をアサートする。)
  • もっと決定論的にできますか?(時刻を固定する、乱数生成器にシードを設定する、ファイルシステムを隔離する、ネットワークを固定する。)

30 秒かかる不安定なループは、ループがないのとほとんど変わりません。一方、2 秒で動く決定論的なループは、タイトなデバッグの超能力です。

非決定的なバグ

目標はクリーンな再現ではなく、再現率を上げることです。100 回繰り返し、並列化し、負荷をかけ、タイミングの幅を狭め、スリープを挿入してください。再現率が 50% の不安定なバグならデバッグできますが、1% ではできません。デバッグ可能になるまで、再現率を上げ続けてください。

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

いったん止めて、明確に説明してください。何を試したかを列挙してください。ユーザーに次のいずれかを求めてください:(a) 再現可能な環境へのアクセス、(b) マスキング済みの取得アーティファクト(HAR ファイル、ログダンプ、コアダンプ、タイムスタンプ付きの画面録画)、または (c) 一時的な本番環境の計測を追加する許可。ループがないまま仮説を立て続けてはいけません。

完了条件 - 赤になるタイトなループ

Phase 1 の完了条件は、ループがタイトかつ赤になりうることです。1 つのコマンド(スクリプトのパス、テストの実行コマンド、curl)を示せており、少なくとも 1 回実行済み(実行コマンドと出力を提示し、マスキング済み)で、次を満たす必要があります。

  • 赤になりうる - 実際のバグのコードパスを通り、ユーザーの正確な症状をアサートするため、そのバグで赤になり、修正後は緑になります。「エラーなく実行できる」では不十分です。この特定のバグを検出できる 必要があります。
  • 決定論的 - 実行するたびに同じ判定になります(不安定なバグの場合は、上記のように再現率を高めます)。
  • 高速 - 数分ではなく、数秒で実行できます。
  • エージェントが実行可能 - 無人で実行できます。人間が介在する場合は scripts/hitl-loop.template.sh を通す必要があります。

コマンドを用意する前にコードを読んで理論を組み立てていることに気づいたら、止めてください。すぐに仮説に飛びつくのは、このスキルが防ごうとしている失敗です。 赤になりうるコマンドがなければ、Phase 2 には進めません。

Phase 2 - 再現 + 最小化

ループを実行します。赤になる、つまりバグが発生することを確認してください。

次を確認してください。

  • ループが発生させる失敗モードは、近くで発生した別の失敗ではなく、ユーザーが説明したものです。別のバグなら、修正も間違っています。
  • 失敗は複数回の実行で再現します(または非決定的なバグの場合は、デバッグに使えるほど十分に高い再現率です)。
  • 正確な症状(エラーメッセージ、誤った出力、遅い処理時間)を取得済みで、後のフェーズで修正が実際に解決したことを検証できます。
最小化

赤になったら、再現ケースをそれでも赤になる最小のシナリオまで縮小します。入力、呼び出し元、設定、データ、手順を一つずつ削り、削るたびにループを再実行します。失敗に不可欠な部分だけを残してください。

理由:最小限の再現ケースは Phase 3 の仮説空間を狭め(疑うべき変動要素が減り)、Phase 5 でクリーンなリグレッションテストになります。

完了条件:残っている要素はすべて失敗に不可欠で、どれか一つを取り除くとループが緑になります。

再現して最小化するまでは先に進まないでください。

Phase 3 - 仮説を立てる

仮説を検証する前に、優先順位を付けた仮説を 3~5 個作成してください。仮説が 1 つだけだと、最初のもっともらしい考えに固執します。

各仮説は反証可能でなければなりません。どのような予測が導かれるかを説明してください。

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

予測を説明できないなら、それは単なる印象です。捨てるか、練り直してください。

検証前に、優先順位を付けたリストをユーザーに提示してください。 ユーザーはドメイン知識を持っていることが多く、すぐに順位を変えたり(「#3 の変更をデプロイしたばかりです」)、どの仮説がすでに除外されているかを知っていたりします。わずかな確認で大幅に時間を節約できます。この確認によって作業を止めないでください。ユーザーが離席中なら、自分の順位付けに従って続けてください。

フェーズ 4 - 計測

各プローブは、フェーズ 3 の具体的な予測に対応していなければなりません。一度に変更する変数は 1 つだけです。

ツールの優先順位:

  1. 環境が対応している場合は、デバッガー/REPL による調査を使用します。ブレークポイント 1 つは、ログ 10 行に勝ります。
  2. 対象を絞ったログを、仮説を区別できる境界に配置します。
  3. 「すべてをログに出して grep する」ことは絶対に避けてください。

各デバッグログには、一意のプレフィックスを付けてください。例:[DEBUG-a4f2]。最後のクリーンアップ時に、grep で一度に検索できます。タグのないログは残ってしまいますが、タグ付きのログは削除する必要があります。

パフォーマンスに関する分岐。 パフォーマンスのリグレッションでは、通常ログは役に立ちません。代わりに、まずベースライン測定(計測用ハーネス、performance.now()、プロファイラー、クエリプラン)を確立してから、二分探索します。修正より先に測定してください。

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

ただし、適切なシームが存在することを前提に、修正の前にリグレッションテストを作成します。

適切なシームとは、呼び出し元で実際に発生するのと同じ形で、テストから実際のバグパターンを再現できる箇所です。利用できるシームが浅すぎる場合(バグには複数の呼び出し元が関わるのに、テストでは呼び出し元が 1 つしかない場合や、ユニットテストではバグを引き起こす一連の処理を再現できない場合)、その箇所でのリグレッションテストは誤った安心感を与えます。

適切なシームが存在しないこと自体が発見です。 そのことを記録してください。コードベースのアーキテクチャによって、バグを確実に再発防止できない状態です。次の段階に向けて、その旨を記録してください。

適切なシームが存在する場合:

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

フェーズ 6 - クリーンアップ

完了を宣言する前に、次の作業を行ってください。

  • 元の再現ケースで問題が再現しなくなっている(フェーズ 1 のループを再実行)
  • リグレッションテストが通る(または適切なシームがないことを記録済み)
  • すべての[DEBUG-...]計測コードを削除済み(プレフィックスを grep)
  • 使い捨てのプロトタイプを削除済み(または、デバッグ用と明示した場所に移動済み)
  • 次のデバッガーが学べるよう、正しい仮説をコミットメッセージまたは PR メッセージに記載済み

コメント