ln-628-concurrency-auditor について
ln-628-concurrency-auditorは、並行処理、非同期パターン、プロセス間のリソースアクセスを監査するスキルです。2段階の検出を行い、スコア付きの結果をコーディネーターに報告します。
主な機能
- 01非同期処理の競合確認
- 02スレッドとgoroutineの安全性確認
- 03TOCTOUとデッドロックの検出
- 04非同期コード内のブロッキングI/O検出
- 05リソース競合の確認
- 06プロセス間競合の分析
活用シーン
- 01並行コードの競合状態の調査
- 02プロセス間の共有リソースアクセスの調査
MCP 対応
データフローや呼び出し経路の分析にhex-graph、局所的なコード読み取りにhex-lineを使用できます。利用できない、または適さない場合は、組み込みのファイル・検索ツールに切り替えます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ levnikolaevich/ claude-code-skills --skill ln-628-concurrency-auditorインストール後、Claude Code で/ln-628-concurrency-auditorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/audit_output_schema.mdaudit_scoring.mdaudit_summary_contract.mdaudit_worker_core_contract.mdcleanup_evidence_contract.mdevaluation_coordinator_runtime_contract.mdevaluation_parallelism_policy.mdevaluation_research_contract.mdevaluation_summary_contract.mdevaluation_worker_runtime_contract.mdloop_health_contract.mdmcp_integration_patterns.mdmcp_tool_preferences.mdrefinement_trace_contract.mdtwo_layer_detection.mdreferences/scripts/evaluation-runtime/cli.mjsreferences/templates/audit_worker_report_template.md詳細
パス: ファイルパス(
references/、../ln-*)は、このスキルディレクトリからの相対パスです。
Concurrency Auditor(L3 ワーカー)
タイプ: L3 ワーカー
並行処理、非同期パターン、プロセス間のリソースアクセスを監査する専門ワーカーです。
目的と範囲
- 並行処理を監査します(カテゴリ 11:優先度高)
- 7 つのチェック項目:非同期処理の競合、スレッドセーフ性、TOCTOU、デッドロック、ブロッキング I/O、リソース競合、プロセス間の競合
- 2 層の検出:grep で候補を見つけ、エージェントがコンテキストを踏まえて判断します
- 適合スコア(X/10)を算出します
入力
必須読み込み: references/audit_worker_core_contract.md を読み込みます。
必須読み込み: references/mcp_tool_preferences.md および references/mcp_integration_patterns.md を読み込みます。
次の情報を含む contextStore を受け取ります:tech_stack、best_practices、codebase_root、output_dir。
データフローまたは呼び出し経路の分析によって並行処理に関する所見の質が大きく向上する場合は、まず hex-graph を使用します。利用可能な場合、局所的なコードの読み取りにはまず hex-line を使用します。MCP が利用できない場合、未対応の場合、またはインデックス化されていない場合は、組み込みの Read/Grep/Glob/Bash を使用して続行し、レポートに代替手段を記載します。
ワークフロー
必須読み込み: 検出方法について references/two_layer_detection.md を読み込みます。
- コンテキストを解析 --
contextStoreからtech_stack、言語、output_dirを抽出します - チェック項目ごと(1~7):
- レイヤー 1: Grep/Glob でスキャンし、候補を見つけます
- レイヤー 2: 各候補の前後 20~50 行を読み込みます。チェック固有の重要な質問を適用し、確定/誤検出/コンテキスト不足に分類します
- 収集 -- 確定した所見について、重大度、場所、工数、推奨事項を収集します
references/audit_scoring.mdに従ってスコアを算出します- レポートを作成 -- メモリ上で作成し、
{output_dir}/ln-628--global.mdに書き込みます(単一の Write で原子的に書き込みます) - 概要を返却してコーディネーターに渡します
監査ルール
重大度の統一的な引き上げ: すべてのチェックで、支払い/認証/金融関連のコードに影響する所見は、他の要因にかかわらず CRITICAL に引き上げます。
1. 非同期処理/イベントループの競合(CWE-362)
内容: シングルスレッドの非同期コードで、await/yield 境界をまたいで共有状態が破損します。
レイヤー 1 -- Grep パターン:
| 言語 | パターン | Grep |
|---|---|---|
| JS/TS | await をまたぐ読み取り・変更・書き込み | \w+\s*[+\-*/]?=\s*.*await(例:result += await something) |
| JS/TS | 確認後の初期化における競合 | if\s*\(!?\w+\) の後、同じブロック内に \w+\s*=\s*await |
| Python | await をまたぐ読み取り・変更・書き込み | async def 内の \w+\s*[+\-*/]?=\s*await |
| Python | 非同期コード内のモジュールレベル共有状態 | モジュールレベルの \w+\s*= と、async def 内での変更 |
| すべて | ロックなしの共有キャッシュ | ロック/ミューテックスの近くにない、非同期関数内の `.set( |
レイヤー 2 -- 重要な質問:
- その変数は共有されていますか(モジュール/グローバルスコープ)、それともローカルですか?
- この await の地点で、2 つの非同期タスクが交互に実行される可能性はありますか?
- アクセスを保護するロック/ミューテックス/セマフォはありますか?
重大度: CRITICAL(支払い/認証) | HIGH(ユーザー向け) | MEDIUM(バックグラウンド)
安全なパターンとして除外: ローカル変数、const 宣言、単一の await(処理が交互に実行される可能性がない場合)。
工数: M
2. スレッド/ゴルーチンの安全性(CWE-366)
概要: 複数のスレッド/ゴルーチンから共有された可変状態に、同期せずにアクセスしています。
レイヤー 1 -- grep パターン:
| 言語 | パターン | grep |
|---|---|---|
| Go | mutex を使わないマップへのアクセス | sync.Mutex または sync.RWMutex のない構造体内の map\[.*\].*= |
| Go | ゴルーチンにキャプチャされた変数 | go func + 外側のスコープの変更される変数 |
| Python | スレッド内で変更されるグローバル変数 | 関数内の global\s+\w+ + 同じファイル内の threading.Thread |
| Java | スレッド間で共有される HashMap | synchronized|ConcurrentHashMap のない同じクラス内の HashMap + Thread|Executor|Runnable |
| Rust | マルチスレッド環境での Rc | 同じファイル内の Rc<RefCell + thread::spawn|tokio::spawn |
| Node.js | Worker Threads の共有状態 | Atomics を使わない可変アクセスを伴う workerData|SharedArrayBuffer|parentPort |
レイヤー 2 -- 重要な質問:
- この構造体/オブジェクトは実際にスレッド間で共有されていますか?(シングルスレッドのコードなら FP)
- mutex/ロックは埋め込み構造体またはインポートされたモジュールにありますか?(grep では見落とす可能性があります)
go funcは値としてキャプチャしていますか(安全)、それとも参照としてキャプチャしていますか(危険)?
重大度: CRITICAL(決済/認証) | HIGH(データ破損の可能性あり) | MEDIUM(内部処理)
安全なパターンの除外事項: ゴルーチンの開始前に init() または main() で使用する Go のマップ。Rust の Arc<Mutex<T>>(すでに安全)。Java の Collections.synchronizedMap()。
作業量: M
3. TOCTOU -- チェック時と使用時の競合(CWE-367)
概要: リソースの状態をチェックしてから使用しますが、チェックと使用の間に状態が変化する可能性があります。
レイヤー 1 -- grep パターン:
| 言語 | チェック | 使用 | grep |
|---|---|---|---|
| Python | os.path.exists() | open() | 同じ変数に対する os\.path\.exists\( と open\( が近接している |
| Python | os.access() | os.open() | os\.access\( と os\.open\(|open\( が近接している |
| Node.js | fs.existsSync() | fs.readFileSync() | existsSync\( と readFileSync\(|readFile\( が近接している |
| Node.js | fs.accessSync() | fs.openSync() | accessSync\( と openSync\( が近接している |
| Go | os.Stat() | os.Open() | os\.Stat\( と os\.Open\(|os\.Create\( が近接している |
| Java | .exists() | new FileInputStream | \.exists\(\) と new File|FileInputStream|FileOutputStream が近接している |
レイヤー 2 -- 重要な質問:
- チェックは制御フローに使われていますか(脆弱)、それともログ記録だけに使われていますか(安全)?
- チェックから使用までの一連の処理にロック/再試行はありますか?
- ファイルはアプリケーションが管理する一時ディレクトリにありますか(リスクは低め)?
- 攻撃者がファイルを差し替える可能性はありますか(シンボリックリンク攻撃)?
重大度: CRITICAL(セキュリティ上重要:権限、認証トークン、設定) | HIGH(ユーザー向けファイル操作) | MEDIUM(内部/バックグラウンド処理)
安全なパターンの除外事項: 再試行を伴う try/catch 内でのチェック。ログ記録/メトリクスのみを目的とするチェック。ファイルロックで保護されたチェックと使用。
作業量: S-M(チェックしてから使用するパターンを、直接使用+エラー処理に置き換える)
4. デッドロックの可能性(CWE-833)
概要: ロックを一貫性のない順序で取得する、またはブロッキング操作中にロックを保持します。
レイヤー 1 -- grep パターン:
| 言語 | パターン | Grep |
|---|---|---|
| Python | ネストされたロック | with\s+\w+_lock:(複数行:異なる2つのロックがネストされている) |
| Python | ループ内のロック | for.*: のループ本体内に \.acquire\(\) がある |
| Python | ロック + 外部呼び出し | \.acquire\(\) の後、解放前に await|requests\.|urllib がある |
| Go | defer によるアンロックの欠落 | 次の行に defer.*\.Unlock\(\) がない \.Lock\(\) |
| Go | ネストされたロック | 間に \.Unlock\(\) がない \.Lock\(\) の呼び出しが同じ関数内に2つある |
| Java | ネストされた synchronized | synchronized\s*\((複数行:異なるモニターを使用するブロックがネストされている) |
| JS | 非同期ミューテックスのネスト | await\s+\w+\.acquire\(\)(同じ関数内に異なるミューテックスが2つある) |
レイヤー 2 -- 重要な質問:
- これらは同じロック(再入可能=問題なし)ですか、それとも異なるロック(デッドロックのリスク)ですか?
- すべての呼び出し箇所でロックの取得順序は一貫していますか?
- ロック内の外部呼び出しにはタイムアウトがありますか?
重大度: CRITICAL(決済/認証) | HIGH(アプリがフリーズするリスク)
安全なパターンとして除外: 再入可能ロック(同じロックを2回取得)。明示的なタイムアウトが設定されたロック(asyncio.wait_for、tryLock)。
作業量: L(ロック取得順序の再設計)
5. 非同期コンテキストでのブロッキング I/O(CWE-400)
概要: 非同期関数またはイベントループのハンドラー内にある同期ブロッキング呼び出しです。
レイヤー 1 -- grep パターン:
| 言語 | ブロッキング呼び出し | Grep | 置き換え |
|---|---|---|---|
| Python | async def 内の time.sleep | async def 内の time\.sleep | await asyncio.sleep |
| Python | async def 内の requests.* | async def 内の requests\.(get|post|put|delete) | httpx または aiohttp |
| Python | async def 内の open() | async def 内の open\( | aiofiles.open |
| Node.js | fs.readFileSync(非同期処理内) | fs\.readFileSync|fs\.writeFileSync|fs\.mkdirSync | fs.promises.* |
| Node.js | execSync(非同期処理内) | 非同期ハンドラー内の execSync|spawnSync | promises を使用する exec |
| Node.js | 非同期処理内の同期暗号処理 | crypto\.pbkdf2Sync|crypto\.scryptSync | crypto.pbkdf2(コールバック) |
レイヤー 2 -- 重要な質問:
- これはホットパス(API ハンドラー)にありますか、それともコールドパス(起動スクリプト)にありますか?
- ブロッキング時間は長いですか(>100ms)?
- 正当な理由がありますか(例:起動時に小さな設定ファイルを同期読み込みする)?
重大度: HIGH(イベントループ/非同期コンテキストをブロック) | MEDIUM(軽微なブロッキング <100ms)
安全なパターンとして除外: if __name__ == "__main__" 内のブロッキング呼び出し(起動時)。初期化時の設定読み込みにおける readFileSync。小さな入力に対する同期暗号処理。
作業量: S-M(非同期の代替手段に置き換え)
6. リソースの競合(CWE-362)
概要: 複数の同時アクセス処理が、調整なしに同じリソースを奪い合います。
レイヤー 1 -- grep パターン:
| パターン | リスク | Grep |
|---|---|---|
| 同期なしの共有メモリ | データ破損 | SharedArrayBuffer|SharedMemory|shm_open|mmap があり、近くに Atomics|Mutex|Lock がない |
| 調整なしの IPC | メッセージの順序 | 同時実行されるループ内の process\.send|parentPort\.postMessage |
| ファイルへの同時追記 | 書き込みの混在 | 並列タスクから同じパスへの複数の appendFile|fs\.write |
レイヤー 2 -- 重要な質問:
- 複数の書き込み処理は実際に同時実行されますか?(順次実行なら安全です)
- OS レベルでのアトミック性は保証されていますか?(例:小さな書き込みに対する
O_APPEND) - 正確性を保つうえで順序は重要ですか?
重大度: HIGH(データ破損) | MEDIUM(順序の問題)
安全なパターンとして除外: 単一書き込み処理パターン。OS がアトミック性を保証する操作(小さなパイプ書き込み、O_APPEND)。順序保証のあるメッセージキュー。
作業量: M
7. プロセス間の競合と見えない副作用(CWE-362、CWE-421)
概要: 複数のプロセス、またはプロセスと OS が同じ排他的リソースにアクセスする状況です。共有 OS リソースに対する、分かりにくい副作用を伴う操作も含みます。
レイヤー 1 -- エントリーポイントを grep します:
| パターン | リスク | grep |
|---|---|---|
| クリップボードへの二重アクセス | 同じフローでの OSC 52 とネイティブクリップボードの併用 | 同じファイル内で osc52|\\x1b\\]52 と clipboard|SetClipboardData|pbcopy|xclip |
| サブプロセスと共有ファイル | 親プロセスと子プロセスが同じファイルに書き込む | 同じパスに対する spawn|exec|Popen と writeFile|open.*"w" |
| OS の排他的リソース | Win32 クリップボード、シリアルポート、名前付きパイプ | OpenClipboard|serial\.Serial|CreateNamedPipe|mkfifo |
| ターミナルエスケープシーケンス | stdout によってターミナルから OS へのアクセスが発生する | \\x1b\\]|\\033\\]|writeOsc|xterm |
| 外部クリップボードツール | 起動したプロセス経由でのクリップボードアクセス | pbcopy|xclip|xsel|clip\.exe |
レイヤー 2 -- ほかのどのチェックよりも、推論に依存します:
-
リソース一覧を作成します:
リソース 排他的か? アクセサー 1 アクセサー 2 同期処理あり? -
タイムラインを追跡します:
t=0ms operation_A() -> resource_X accessed t=?ms side_effect -> resource_X accessed by external process t=?ms operation_B() -> resource_X accessed again -> CONFLICT? -
重要な質問:
- 別のプロセス(ターミナル、OS、子プロセス)がこのリソースに同時にアクセスできますか?
- この操作は共有 OS リソースに見えない副作用をもたらしますか?
- 外部プロセスの処理が想定より遅い、または速い場合、何が起こりますか?
- ユーザーがこの操作を短時間に 2 回実行した場合、何が起こりますか?
深刻度: CRITICAL(同期処理なしで、排他的な OS リソースに 2 つのアクセサーがアクセス) | HIGH(ロックなしで、サブプロセスと共有ファイルを使用) | HIGH(推論によって見えない副作用を検出)
安全なパターンとして除外するケース: アクセサーが 1 つだけ。リトライ/バックオフのパターンがある。明示的な遅延/await によって操作を順番に実行している。
作業量: M-L(冗長なアクセス経路の削除が必要な場合があります)
スコアリングアルゴリズム
必読: references/audit_worker_core_contract.md と references/audit_scoring.md を読み込みます。
出力形式
必読: references/audit_worker_core_contract.md と references/templates/audit_worker_report_template.md を読み込みます。
references/audit_summary_contract.md に従って JSON サマリーを書き込みます。管理モードでは呼び出し元が runId と summaryArtifactPath の両方を渡します。スタンドアロンモードでは、ワーカーが共通コントラクトに従って、実行ごとのアーティファクトパスを生成します。
レポートを {output_dir}/ln-628--global.md に書き込み、category: "Concurrency" と以下のチェックを設定します:async_races, thread_safety, toctou, deadlock_potential, blocking_io, resource_contention, cross_process_races。
references/audit_summary_contract.md に従ってサマリーを返します。
summaryArtifactPath がない場合は、スタンドアロンのランタイムサマリーを .hex-skills/runtime-artifacts/runs/{run_id}/evaluation-worker/{worker}--{identifier}.json に書き込み、必要に応じて構造化出力にも同じサマリーを出力します。
Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/ln-628--global.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
重要なルール
必読: references/audit_worker_core_contract.md を読み込みます。
- 自動修正しない: 報告のみを行います。並行性の問題の修正には、人による慎重なレビューが必要です
- 2 層検出: レイヤー 1 の grep の後に、必ずレイヤー 2 の推論を適用します。コンテキストを分析せず、生の grep マッチだけを報告してはいけません
- 言語に応じた検出: 各チェックで、言語固有のパターンを使用します
- CRITICAL への統一的なエスカレーション: 決済/認証/金融関連コードの検出事項は、すべて CRITICAL とします
- 作業量を現実的に見積もる: S = 1 時間未満、M = 1~4 時間、L = 4 時間超
- 除外対象: テストファイル、シングルスレッドの CLI ツール、生成コードは対象外とします
完了の定義
必ずお読みください: references/audit_worker_core_contract.md を読み込みます。
- contextStore を解析しました(language、concurrency model、output_dir)
- 2 層の検出で 7 つのチェックをすべて完了しました:
- 非同期処理の競合、スレッドセーフ性、TOCTOU、デッドロックの可能性、ブロッキング I/O、リソース競合、プロセス間の競合
- 各候補に第 2 層の推論を適用しました(確認済み/誤検出/コンテキストが必要)
- 重要度、場所、作業量、推奨事項を含む検出結果を収集しました
-
references/audit_scoring.mdに従ってスコアを算出しました -
{output_dir}/ln-628--global.mdにレポートを書き込みました(単一の Write 呼び出しによるアトミックな書き込み) - コントラクトに従って概要を書き込みました
参照ファイル
- 2 層検出の方法論:
references/two_layer_detection.md - 監査出力スキーマ:
references/audit_output_schema.md
バージョン: 4.0.0 最終更新日: 2026-03-04