mcpField
R
root-cause-tracing

root-cause-tracing

github.com/secondsky開発240431 回インストール5 週間前に更新
リポジトリ

root-cause-tracing について

呼び出しチェーンをさかのぼり、症状ではなくエラーの発端を特定する開発者向けデバッグスキルです。テスト汚染の調査やスタックトレースの記録方法も扱います。

主な機能

  1. 01呼び出しチェーンをたどるエラー調査
  2. 02発端特定のためのスタックトレース記録
  3. 03テストを個別実行して汚染源を特定
  4. 04根本原因の修正と防御策の追加

活用シーン

  1. 01実行深部で発生するエラーの調査
  2. 02無効なデータの発生元の特定
  3. 03テスト汚染を起こすテストの発見

インストール

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

$npx skills add https://github.com/secondsky/claude-skills --skill root-cause-tracing

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

詳細

根本原因の追跡

概要

バグはコールスタックの深い場所で表面化することがよくあります(間違ったディレクトリでの git init、間違った場所へのファイル作成、間違ったパスでのデータベースのオープンなど)。エラーが現れた場所を修正したくなりますが、それでは症状に対処しているだけです。

基本原則: 呼び出しチェーンをさかのぼり、最初のトリガーを見つけてから、発生源で修正します。

使用する場面

次の場合に使用します:

  • 実行の深い段階でエラーが発生する(エントリーポイントではない)
  • スタックトレースに長い呼び出しチェーンが表示される
  • 無効なデータがどこで発生したのか不明である
  • 問題を引き起こすテスト/コードを特定する必要がある

追跡プロセス

1. 症状を観察する
Error: git init failed in ~/project/packages/core
2. 直接の原因を見つける

この問題を直接引き起こしているコードは何ですか?

await execFileAsync('git', ['init'], { cwd: projectDir });
3. 何がこれを呼び出したかを確認する
WorktreeManager.createSessionWorktree(projectDir, sessionId)
  → called by Session.initializeWorkspace()
  → called by Session.create()
  → called by test at Project.create()
4. さらにさかのぼって追跡する

どの値が渡されましたか?

  • projectDir = ''(空文字列!)
  • cwd が空文字列の場合、process.cwd() に解決される
  • それがソースコードのディレクトリです!
5. 最初のトリガーを見つける

空文字列はどこから来ましたか?

const context = setupCoreTest(); // Returns { tempDir: '' }
Project.create('name', context.tempDir); // Accessed before beforeEach!

スタックトレースの追加

手動で追跡できない場合は、計測コードを追加します:

// Before the problematic operation
async function gitInit(directory: string) {
  const stack = new Error().stack;
  console.error('DEBUG git init:', {
    directory,
    cwd: process.cwd(),
    nodeEnv: process.env.NODE_ENV,
    stack,
  });

  await execFileAsync('git', ['init'], { cwd: directory });
}

重要: テストでは console.error() を使用してください(logger は表示されない場合があります)

実行して記録する:

bun test 2>&1 | grep 'DEBUG git init'

スタックトレースを分析する:

  • テストファイル名を探す
  • 呼び出しを引き起こした行番号を見つける
  • パターンを特定する(同じテストか?同じパラメーターか?)

汚染を引き起こすテストの特定

テスト中に何かが現れるものの、どのテストが原因かわからない場合:

二分探索スクリプトを使って、テストを1つずつ実行します:

# Example: find which test creates .git in wrong place
bun test --run --bail 2>&1 | tee test-output.log

テストを1つずつ実行し、最初に汚染を引き起こした時点で停止します。

実例:空の projectDir

症状: .git が packages/core/(ソースコード)に作成される

追跡チェーン:

  1. git init が process.cwd() で実行される ← cwd パラメーターが空
  2. WorktreeManager が空の projectDir で呼び出される
  3. Session.create() に空文字列が渡される
  4. beforeEach の前にテストが context.tempDir にアクセスする
  5. setupCoreTest() が最初に { tempDir: '' } を返す

根本原因: 空の値にアクセスするトップレベル変数の初期化

修正: beforeEach の前にアクセスされた場合に例外をスローする getter に tempDir を変更

さらに多層防御を追加:

  • レイヤー 1:Project.create() がディレクトリを検証する
  • レイヤー 2:WorkspaceManager が空でないことを検証する
  • レイヤー 3:NODE_ENV ガードが tmpdir 外での git init を拒否する
  • レイヤー 4:git init の前にスタックトレースを記録する

重要な原則

エラーが現れた場所だけを修正してはいけません。 最初のトリガーを見つけるために、さかのぼって追跡します。

スタックトレースのヒント

テストでは: logger ではなく console.error() を使用します。logger は抑制される場合があります 操作の前に: 危険な操作が失敗した後ではなく、その前に記録します コンテキストを含める: ディレクトリ、cwd、環境変数、タイムスタンプ スタックを記録する: new Error().stack で完全な呼び出しチェーンを確認できます

実際の効果

デバッグセッションの結果:

  • 5段階の追跡で根本原因を発見
  • 発生源で修正(getter による検証)
  • 4層の防御を追加
  • 1847 件のテストに合格し、汚染はゼロ

コメント