ln-628-concurrency-correctness-auditor について
非同期処理の競合、スレッド安全性、デッドロック、ブロッキング I/O、リソース競合、プロセス間競合を調べるコードベース監査用スキルです。候補のスキャン後にコンテキストを検証し、問題、推奨事項、スコアを出力します。
主な機能
- 01非同期競合とスレッド安全性の問題検出
- 02TOCTOU リスクとデッドロックの特定
- 03非同期コンテキスト内のブロッキング I/O 検出
- 04リソース競合とプロセス間競合の確認
- 05コンプライアンススコアとレポートの作成
活用シーン
- 01並行アクセス時の共有状態リスクの確認
- 02非同期処理におけるブロッキング呼び出しの調査
- 03ファイルや OS リソースへの並行アクセスの評価
MCP 対応
コードの読み取りと検索には hex-line を優先し、データフローや呼び出し経路の分析が並行性の判断に役立つ場合は hex-graph を使用します。MCP が利用できない場合は組み込みツールに切り替えます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ levnikolaevich/ claude-code-skills --skill ln-628-concurrency-correctness-auditorインストール後、Claude Code で/ln-628-concurrency-correctness-auditorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/audit_output_schema.mdaudit_scoring.mdaudit_summary_contract.mdaudit_worker_core_contract.mdmcp_integration_patterns.mdmcp_tool_preferences.mdtwo_layer_detection.mdreferences/templates/audit_worker_report_template.md詳細
パス: ファイルパス(
references/、../ln-*)は、このスキルディレクトリを基準とした相対パスです。
並行処理の正確性監査担当(L3 ワーカー)
タイプ: L3 ワーカー
並行処理の正確性、非同期処理の危険性、プロセス間のリソースアクセスを監査する専門ワーカーです。
目的と範囲
- 並行処理を監査します(カテゴリ 11:高優先度)
- 7 つのチェック項目:非同期処理の競合、スレッドセーフティ、TOCTOU、デッドロック、ブロッキング I/O、リソース競合、プロセス間の競合
- 2 層で検出します。grep で候補を見つけ、エージェントがコンテキストを推論します
FIX_RACE、FIX_DEADLOCK、またはCONTROL_ASYNC_SIDE_EFFECTを出力します- コンプライアンススコア(X/10)を算出します
入力
必須の読み込み: references/audit_worker_core_contract.md と references/mcp_tool_preferences.md を読み込みます。
ツールポリシー:ホストの AGENTS.md が対象範囲外の独立したサブエージェントとして実行される場合があるため、ファイルの読み取り、検索、編集では、まず hex-line MCP を使用してください。MCP の動作が不明な場合に限り、references/mcp_integration_patterns.md を読み込みます。
contextStore で次の情報を受け取ります:tech_stack、best_practices、codebase_root、output_dir。
データフローや呼び出し経路の分析によって並行処理の検出結果が大きく改善される場合は、まず hex-graph を使用します。ローカルコードの読み取りでは、利用可能な場合、まず hex-line を使用します。MCP が利用できない、未対応、またはインデックス化されていない場合は、組み込みの Read/Grep/Glob/Bash を使用して続行し、レポートにフォールバックしたことを記載します。
ワークフロー
検出ポリシー:2 層の検出(候補のスキャン、続いてコンテキストの検証)を使用します。検証方法が不明確な場合に限り、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_scoring.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 ツール、生成コードは対象外としてください
- 対象範囲: 並行処理の正確性のみを監査してください。ライフサイクルの準備状況、レイヤーの責務、ローカルなコードスタイルは監査しないでください。
- 対応必須: すべての検出事項に
FIX_RACE、FIX_DEADLOCK、またはCONTROL_ASYNC_SIDE_EFFECTのいずれかを使用してください。
完了の定義
すでに読み込まれている references/audit_worker_core_contract.md を適用します。
- contextStore を解析済み(language、concurrency model、output_dir)
- 2 層検出を用いて 7 つすべてのチェックを完了済み:
- async races、thread safety、TOCTOU、deadlock potential、blocking I/O、resource contention、cross-process races
- 各候補に第 2 層の推論を適用済み(confirmed / FP / needs-context)
- severity、location、effort、action、recommendation とともに検出結果を収集済み
-
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