mstack-diagnose について
mstack-diagnoseは、Claude CodeとCodex向けの構造化されたデバッグスキルです。証拠の収集から根本原因の分析までを導き、依頼があった場合に限りテスト済みの修正を行います。
主な機能
- 01証拠を重視した診断
- 02障害の再現と絞り込み
- 03検証可能な仮説の順位付け
- 04根本原因の検証
- 05回帰テスト付き修正の選択肢
- 06整理と証拠に基づく報告
活用シーン
- 01クラッシュやリグレッションの調査
- 02不安定な障害の発生率測定
- 03性能問題やハングの追跡
- 04確認済みの不具合修正と回帰テスト追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mubeda/ mstack --skill mstack-diagnoseインストール後、Claude Code で/mstack-diagnoseを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEevals/crash-diagnose-only/case.yamlplace-files.shprompt.mdevals/crash-diagnose-only/files/parsecfg.csettings.confevals/crash-diagnose-only/graders/01-names-null-deref-site.md02-names-trigger-line.md03-nothing-changed-no-core-left.md04-proven-vs-inferred.mdevals/flaky-set-order/case.yamlplace-files.shprompt.mdevals/flaky-set-order/files/tags.pytest_tags.pyevals/flaky-set-order/graders/01-measured-rate-before-fix.md02-explains-hash-randomization.md03-fix-keeps-order-and-passes.md04-proof-run-count-justified.mdevals/regression-bisect/case.yamlplace-files.shprompt.mdevals/regression-bisect/files/make-repo.shevals/regression-bisect/graders/01-names-first-bad-commit.md02-used-git-bisect.md03-test-green-no-bisect-left.md04-report-cause-and-proof.mdreferences/crash-linux.mdcrash-macos.mdcrash-windows.md詳細
mstack diagnose
何が壊れているのかを突き止め、証拠で裏付け、ユーザーが修正を望む場合に限って修正します。もっともらしい説明ではなく、根拠に基づく誠実な報告を目指します。最終報告の主張はすべて、このセッションで生成した出力を指し示すか、推論であることを明確に述べてください。
Claude Code と Codex でこのスキルを使う
このファイルはどちらのホストでも同じです。ホストのツール名は記載していません。「サブエージェントツール」や「質問ツール」と書かれている箇所では、ホストに相当するものを使ってください。
| このファイルの表記 | Claude Code | Codex |
|---|---|---|
| 質問ツール | AskUserQuestion | 番号付きの選択肢をチャットで提示し、返答を待つ |
| サブエージェントツール | Agent。コードを編集する場合は isolation: "worktree" を指定 | 独自の git worktree で別の codex exec を実行するか、利用可能ならセッションのエージェントツールを使用 |
| スキルフォルダー | このスキルの読み込み時にホストが示したベースディレクトリ | 読み込んだ SKILL.md があるフォルダー |
サブエージェントツールがない場合は、委任する手順を一つずつ自分で実行してください。以下のファイルは、スキルフォルダー内のパスを使って参照してください。
基本ルール
- まず証拠を確認します。 シグナルを得る前に(フェーズ 1)、仮説を立てるためにコードを読んではいけません。テスト対象を見つけるためにコードを読むのは構いません。
- 決して作り上げません。 解決できないスタックフレームは
??のままにします。見つからないログ行は、見つからないものとして扱います。証拠がないことは、存在しないことの証拠ではありません。何を検索したかを述べてください。 - システムは現状のままにします。 診断では読み取りのみを行います。システム全体に影響する変更(コアダンプハンドラー、ptrace 設定、CPU ガバナー、レジストリキー、パッケージ)は、元に戻すコマンドとともにユーザーに提案し、許可なく適用してはいけません。システムが生成した記録(コアダンプ、クラッシュレポート、ログ)はユーザーのものです。自分が作成したコピーだけを削除してください。
- クラッシュデータは秘密情報として扱います。 コアダンプ、ミニダンプ、ランタイムのクラッシュレポートは、プロセスのメモリまたは環境のコピーであり、パスワード、トークン、個人文書が含まれている可能性があります。内容は新しい
mktempパスにのみ抽出し、作業後に削除してください。引用するのはシグナルを示す行だけとし、秘密情報は<REDACTED>に置き換えてください。 - シンボルの検索ではネットワークを使います。 debuginfod やシンボルサーバーへの問い合わせでは、バイナリのビルド ID とユーザーの IP アドレスが送信されることがあります。最初の問い合わせの前にユーザーに伝え、同意がない限りプロプライエタリなバイナリは対象外にしてください。
- 試してから尋ねます。 アクセス、成果物、手作業をユーザーに求める前に、自分で実行できる方法をすべて試してください。その後、理由を添えて、質問ツールを使い一度だけ尋ねてください。
- クラッシュ記録の名前は引用符で囲みます。 クラッシュ記録から取得したプログラム名やファイル名には、引用符が含まれている可能性があります。そのため、シェルコマンドでは必ず引用符で囲んでください。プロセスは正確な名前またはバイナリパスで照合し(
pgrep -x <name>)、自分のシェルに一致する可能性のあるpkill -f <text>は決して使わないでください。シグナルを送る前に PID を確認してください。
フェーズ 0. 受付と分類
何よりも先に、以下を記録してください。完全なチェックリストと、この環境で問題を再現できない場合の対応については references/intake.md を読んでください。
- 症状をそのまま記録します。エラー文、終了コード、シグナル、または誤っている数値です。
- 発生頻度を記録します。毎回、ときどき(おおよその頻度)、または一度だけです。
- 正確な手順、バージョン(コミット、ランタイム、OS、ロックファイル)、および動作する環境との違いを記録します。
- 既知の最終正常バージョンまたはコミットがあれば記録します。回帰の二分探索が可能になります。
- 報告者自身の仮説は事実と分けて記録し、フェーズ 3 の仮説候補として扱います。
- 以下の分岐を選ぶため、問題の種類を決めます。クラッシュ、回帰、不安定な失敗、パフォーマンス、ハングまたはリーク、再現未確認のいずれかです。
- 成果物を決めます。診断のみか、診断と修正の両方かです。ユーザーが明示していない場合、「なぜ」という質問には診断を、「直して」という依頼には診断と修正の両方を行います。
ゲート:記録があり、問題の種類と成果物が決まっていること。
フェーズ 1. シグナルを得る
シグナルには 2 種類あります。
- ライブなループ。 実際のコードパスを実行し、ユーザーが報告した症状そのもので失敗する 1 つのコマンドです。適切な接点での失敗するテスト、スクリプト、スナップショットとの比較を行う CLI の実行、ブラウザースクリプト、再生したリクエスト、使い捨てのハーネス、プロパティベースのループやファジングループ、回帰の場合の
git bisect runなど、バグに最も早くたどり着けるものを使って作成します。その後、3 つの観点から改善します。セットアップをキャッシュし、無関係な起動処理を省き、対象範囲を絞って高速化します。「クラッシュしなかった」ではなく、症状そのものを検証する鋭いものにします。時間を固定し、乱数にシードを指定し、ファイルシステムを分離し、ネットワークをスタブ化して、決定論的にします。不安定な失敗の場合、ループの出力は測定された発生率です。 - 保存された記録。 すでに発生していて、要求に応じて再現できない事象については、その事象が残したコアダンプ、クラッシュレポート、ミニダンプ、ランタイムの致命的エラーログ、プロファイル、トレースなどの記録です。固定されたデータセットとして扱い、読み取ります。「もう一度確認する」ために事象を再実行してはいけません。
ライブなループの合格基準は、コマンドを実行済みであること、失敗時の出力が機密情報を伏せた状態で手元にあること、近い症状ではなく症状そのものを検証していること、実行ごとに同じ判定が得られること(不安定な失敗の場合は測定された発生率であること)、数秒で終了すること、無人で実行できることです。保存された記録の合格基準は、記録が見つかって適切なツールで読み込まれ、シンボルの状態(完全、一部、またはシンボル化されていない)が記録されていることです。
シグナルがなければ、フェーズ 2 には進みません。シグナルを得られない場合は、試したことと、何があれば先に進めるかを報告して停止します(references/intake.md に経路が順番に記載されています)。
フェーズ 2. 再現して最小化する
ループを数回実行し、報告された失敗が起きることを確認します。その後、入力、設定、データ、手順を 1 つずつ取り除き、削るたびに再実行します。
- 失敗が複数のコンポーネント(CI からビルド、デプロイまで、クライアントから API、サービス、データベースまで)をまたぐ場合は、まず各境界に入るものと出るものを、環境や設定値も含めて記録し、1 回実行します。正常な入力が不正な出力に変わるレイヤーを調査します。
- シグナルがスタックトレースやログの場合は、すべて読みます。すべての「Caused by」や連鎖した例外をたどって最も内側の例外まで確認し、最初の失敗の直前にあるログ行を読み、フレームワークやラッパーのフレームは原因ではなく、伝達経路として扱います。
合格基準は、失敗が繰り返し発生すること(または、実行回数に対する失敗数として発生率が測定されていること)、そして残っている要素をどれか 1 つ取り除くと成功することです。保存された記録の場合は、記録を 1 つの知見に絞り込みます。たとえば、障害が発生したスレッドとフレーム、ホットパス、リークしたメモリを保持し続けている連鎖などです。
フェーズ 3. 仮説を立てる
仮説を検証する前に、優先順位を付けた 3~5 個の仮説を書きます。絞り込んだ知見、同じコードベース内で動作する類似コードとの比較(どんなに小さな違いでもすべて列挙します)、周辺のコード構造、変更履歴(git log -S '<string>' -- <file>、git log -G '<regex>' -- <file>、git blame -L <a>,<b> <file>)、報告者の見立てを参考にして仮説を立てます。それぞれに「X が原因なら、Y を変更すると失敗が解消する」という形式の予測を記載します。予測のない仮説は、具体化するか、削除します。
合格基準は、優先順位を付けた仮説の一覧と、それぞれの予測がすべて書き出されていることです。
フェーズ 4. 切り分けて立証する
プローブごとに予測を 1 つ検証し、一度に変更する変数は 1 つにします。
- コストが低く、より多くのことを明らかにするプローブから順に実施します。たとえば、ログの検索、単体テスト、結合テスト、完全な再現の順です。結果によって次の手順が変わらないプローブは省略します。
- デバッガーまたは REPL を優先します。次に有効なのは、仮説を切り分ける境界に一時的なログを追加し、それぞれに
[DEBUG-a4f2]のような一意の接頭辞を付けて、簡単に削除できるようにする方法です。「すべてをログに出して grep する」ことは避けてください。 - パフォーマンスについては、まずベースラインを測定し、その後で原因を二分探索します(
references/performance.md)。 - 答えが、先行する判断の結果ではなく、コード内の誤った判断になるまで「なぜ」を問い続けます。その最初の誤った判断が根本原因です。症状を引き起こした状態が妥当なら、その状態で動作しなかったコードが根本原因です。その状態が存在するはずのないものなら、クラッシュ箇所にガードを追加してもバグを隠すだけであり、実際に修正すべきなのはその状態を生成した箇所です。
- プローブによって仮説が否定されたら、その仮説を根拠に行った変更はすべて元に戻します。
- 1 つの前提に基づく 2 つの修正が同じチェックに失敗したら、その前提を 1 文で書き出し、ほかのことを試す前にその前提を直接検証します。修正の失敗が合計 3 回に達したら、そこで止めます。設計自体が誤っている可能性があるため、4 回目の修正に進む前に、各試行の証拠を添えて質問ツールでユーザーに確認します。
- 独立した仮説は、サブエージェントツールを使って並行して検証できます。仮説ごとに 1 つのサブエージェントを割り当て、それぞれ別のワークツリーを使い、コミットとループ実行コマンドを明記した簡潔な指示を渡します。サブエージェントの判定を受け入れる前に、判断を確定するコマンドを自分で再実行してください。結果がない場合は合格ではなく、未解決の点として扱います。
ゲート:予測の 1 つが、結果を変えたプローブによって確認されていること。さらに、独立したチェックが少なくとも 1 つ同じ結論を示していること(または、障害箇所で終わるシンボル化されたスタックトレースなど、単独で決定的な記録があること)。ほかの仮説は否定されているか、未検証として記録されていること。さらに、仕組みが最初の誤った判断における file:symbol:line まで特定されていること。診断のみを行う場合は、ここからフェーズ 6 に進みます。
フェーズ 5. 修正し、回帰テストを追加する
- 実際に障害が起きる箇所を検証する、適切な境界を見つけます。浅すぎる境界でのテストは、誤った安心感を与えます。
- まず失敗するテストをコミットし、意図した理由で失敗することを確認します。コードやフィクスチャを変更して障害を強制した場合は、変更が反映されたことを示すために、クリーンなコピーとの差分を
diffで確認します。 - 証拠によって正当化される最小限の修正を行い、テストが成功することを確認してから、元の最小化していないループを再実行します。
- 「役に立つかもしれない」変更は仮説であり、修正ではありません。リリースしてはいけません。
- 適切な境界がない場合は、浅いテストを書かないでください。「適切な境界なし」を所見として記録し、ループの失敗時と成功時の出力を貼り付けます。
ゲート:症状が発生したときと同じ箇所で、変更前は失敗し、変更後は成功すること(または、両方の出力を添えた「適切な境界なし」という所見があること)。否定された仮説に基づく変更が残っていないこと。
フェーズ 6. クリーンアップして報告する
- タグ付きのデバッグ行をすべて削除し(
git grep -n '\[DEBUG-'の出力が空であること)、使い捨てのハーネス、および抽出したコアファイルやダンプも削除します。 - 二分探索を行った場合は、最後に
git bisect resetを実行します。 - ユーザーの承認を得て行ったシステム変更は元に戻すか、元に戻すコマンドとともに一覧にします。
- 以下のレポートを作成します。
ゲート:デバッグ接頭辞の検索結果が空であること、システムが元の状態に戻っていること(または残っているものがすべてパス付きで記載されていること)、レポートが作成されていること。
問題の種類別の分岐
フェーズ 0 で選んだ分岐のファイルを読み、分岐で必要な場合はプラットフォームのファイルも読みます。プラットフォームはマシンから判定します(uname -s、coredumpctl、xcrun、cdb が存在するかどうか)。実行環境のホストから判定してはいけません。
| 問題 | 読むファイル | フェーズでの変更点 |
|---|---|---|
| クラッシュ、セグメンテーション違反、異常終了、パニック、コアダンプ | references/crash-linux.md、references/crash-macos.md、references/crash-windows.md のいずれか。Python、Node、JVM、Go、Rust、.NET の場合は references/runtimes.md も読みます | フェーズ 1 では通常、保存済みの記録を使います。まずメモリ不足による強制終了を除外します。クラッシュしたフレームだけでなく、すべてのスレッドを読みます |
| リグレッション | references/regression.md | フェーズ 1 では scripts/bisect-run.sh を使って git bisect run を実行します。最初の不具合コミットにより、フェーズ 3 の対象を 1 つの差分に絞り込みます |
| 不安定な失敗 | references/flaky.md | フェーズ 1 で失敗率を測定します。「修正済み」とするには、事前に実行回数を決めておく必要があります |
| パフォーマンスの問題 | references/performance.md | すべての主張に、ばらつきとともに測定値を示します。最も低コストな原因から修正します |
| ハング、デッドロック、メモリリーク | references/hang-leak.md | フェーズ 1 では、スタックダンプを 2〜3 回取得するか、サニタイザーのレポートを使います |
| 本番環境のインシデント(現在ユーザーに影響が出ている) | references/incident.md | まず緩和し、次に診断します。深刻度に応じて対応のペースを決めます。修正後に、誰かを責めない事後検証を行います |
| 再現できない、報告が曖昧 | references/intake.md | フェーズ 0 で上記のいずれかの分岐に振り分けるか、解決に必要な情報を示して終了します |
このスキルのコマンド
references/ 内のコマンドラインは、ツールの公式ドキュメントで確認するか、実機で実行して確認済みです。「マシン上で調べる」と記されたコマンドは未確認のため、まずツールの --help または man ページを読み、フラグを推測してはいけません。ユーザーのマシンでコマンドが失敗した場合は、代替手段を即興で考えるのではなく、正確なエラーを報告します。
証拠の評価
根本原因にはそれぞれ 1 つのティアを付け、修正にはそれぞれ 1 つの判定を付けます。
| 根本原因のティア | 判定の基準 |
|---|---|
| 確認済み | 症状が現れる対象そのもので再現され、1 つの変数だけを変更する調査で予測どおりに結果が変わった場合(または変更前後の記録が予測どおりに異なる場合)。file:symbol:line に対応づけられていること。リグレッションを二分探索した場合は、現在のコードに最初の不具合コミットの変更を戻すとループが通ること |
| 裏付けあり | シンボル化されたコア、トレース、二分探索の結果など、実際の記録が該当箇所を示し、それに反する証拠がないものの、調査によって結果が変わっていない場合。再現できない過去のクラッシュで到達できる最高の評価です |
| 推定 | コードまたは時系列に基づく推論を、実行せずに順を追って説明したものです。「A と B を踏まえると、D のため C である可能性が高い」のように記述します |
| 仮説 | 証拠と整合しますが、ほかの説明も成り立つ場合です。証拠となる点と反する点を挙げ、競合する仮説として列挙します |
| 不明 | 調査しても何も見つからなかった場合です。検索した内容を列挙します |
| 修正の判定 | 意味 |
|---|---|
| VERIFIED | 元のループが修正前は失敗し、修正後は同じ対象で成功すること。失敗するテストを先にコミットしていること(または「適切な seam なし」と記録していること)。不安定な失敗では、事前に決めた実行回数すべてで成功すること(references/flaky.md)。パフォーマンスの修正では、実行ごとのばらつきを上回る差が示されること(references/performance.md) |
| NOT VERIFIED | チェックを実行したが症状が残っている場合、またはチェックを実行できなかった場合 |
| INCONCLUSIVE | 対象を誤っている、ノイズが効果を上回る、または主張している内容を検証できていないチェックの場合。「結論不確定」は合格を意味しません。また、ユニットテストに合格しても、ブランチの動作が示されるだけで、不具合が解消されたことは証明されません |
結果が簡単に出すぎる場合は、結果を信頼する前に、観察方法を疑ってください。
レポート
次の形式でレポートを作成します。該当しない行は省略し、その理由を記載します。
Diagnosis: <problem type>. <One sentence that answers the user's question.>
Root cause: <tier>. Fix: <VERIFIED, NOT VERIFIED, INCONCLUSIVE, or not attempted>.
Symptom (verbatim, redacted): ...
Signal: <loop command, or record path, format and symbol status>. Failing output: ...
Rate or baseline: <k of N runs failed> or <median, range, run count, what limits it>
Proximate cause: <where the failure surfaced, such as the crashing frame or the failing assertion>
Root cause: <file:symbol:line>, the first wrong decision. <The mechanism in two sentences.>
How it was proven: <probe>, predicted <...>, observed <...>
Hypotheses: <rank, prediction, probe, and confirmed, refuted or untested for each>
Fix and proof: <commits in order>, failing then passing output, original loop rerun, <0 of M> or <before and after>
Competing explanations and unknowns: <what else fits, what was searched and not found>
Impact: <data lost and where to recover it>, <will it recur>, <how to avoid it>
System state: <changes made and undone>, <files deleted>, <records left in place and their paths>
Skipped phases: <phase and reason>
各行で、証拠が証明することと推論を分けて記述します。原因が本当に曖昧な場合は、推測で確信を装うのではなく、その旨を明記します。