ln-652-transaction-correctness-auditor
ln-652-transaction-correctness-auditor について
データベーストランザクションの正確性、範囲、トリガーとの相互作用を監査する専門ワーカースキルです。コードは変更せず、重大度付きの指摘と適合スコアを出力します。
主な機能
- 01トランザクション境界とコミットの確認
- 02ロールバック処理の検査
- 03トリガーと通知動作の確認
- 04イベントの発行元と購読側の照合
- 05構造化レポートとスコアの作成
活用シーン
- 01コードベースのトランザクション処理を監査
- 02通知に影響するコミット漏れを検出
- 03範囲が広すぎる、または分割されたトランザクションを特定
MCP 対応
利用可能な場合、ファイルの読み取り・検索・編集にはhex-line MCPを優先し、参照チェーンや呼び出し経路の分析に有用な場合はhex-graphを使用します。MCPが利用不可または非対応の場合は組み込みツールに切り替えます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ levnikolaevich/ claude-code-skills --skill ln-652-transaction-correctness-auditorインストール後、Claude Code で/ln-652-transaction-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 ワーカー
データベースのトランザクションパターンについて、整合性、適用範囲、トリガーとの相互作用を監査する専門ワーカーです。
目的と範囲
- トランザクションの整合性を監査します(優先度:高)
- コミットパターン、トランザクション境界、ロールバック処理、トリガー/通知のセマンティクスを確認します
- 重大度、場所、作業量、推奨事項を含む構造化された指摘事項をファイルに書き込みます
- トランザクション整合性カテゴリのコンプライアンススコア(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、db_config(データベースの種類、ORM の設定、トリガー/通知パターン)、codebase_root、output_dir。
ドメイン対応: domain_mode と current_domain をサポートします。
参照チェーンや呼び出しパスによってトランザクション分析の精度が大きく向上する場合は、まず hex-graph を使用します。利用可能な場合、ローカルのコード/設定の読み取りにはまず hex-line を使用します。MCP が利用できない、未対応、またはインデックス化されていない場合は、組み込みの Read/Grep/Glob/Bash を使用して続行し、レポートにフォールバックしたことを記載します。
ワークフロー
検出ポリシー:2 層検出(候補のスキャン、その後のコンテキスト検証)を使用します。検証方法が曖昧な場合に限り、references/two_layer_detection.md を読み込みます。
-
contextStore からコンテキストを解析
- tech_stack、best_practices、db_config、output_dir を抽出します
- scan_path を決定します
-
トランザクション基盤を特定
- トリガーを含むマイグレーションファイル(
pg_notify、CREATE TRIGGER、NOTIFY)を探します - セッション/トランザクション設定(
expire_on_commit、autocommit、分離レベル)を探します - トリガーの影響を受けるテーブルを特定します
- トリガーを含むマイグレーションファイル(
-
コードベースをスキャンして違反を検出
- トリガーの影響を受けるテーブルへの UPDATE パスを追跡します
- トランザクション境界(begin/commit の範囲)を分析します
- コミット前後のエラー処理を確認します
-
重大度、場所、作業量、推奨事項とともに指摘事項を収集します
-
ペナルティアルゴリズムを使用してスコアを算出します
-
レポートを作成:
references/templates/audit_worker_report_template.mdに従って完全な Markdown レポートをメモリ上に作成し、単一の Write 呼び出しで{output_dir}/ln-652--global.mdに書き込みます -
概要を返す: コーディネーターに最小限の概要を返します(出力形式を参照)
監査ルール(優先度:高)
1. 中間コミットの欠落
内容: DB トリガー/NOTIFY がトランザクションのコミットに依存している場合に、コミットなしで UPDATE する
検出方法:
- ステップ 1: マイグレーションでトリガーを探します。
alembic/versions/、migrations/内でpg_notify|NOTIFY|CREATE TRIGGER|CREATE OR REPLACE FUNCTION.*triggerを検索します。- 抽出する情報:トリガー関数名、テーブル名、トリガーイベント(INSERT/UPDATE)
- ステップ 2: トリガーの影響を受けるテーブルを UPDATE するコードを探します。
- トリガーテーブルに関連する
repo.*update|session\.execute.*update|\.progress|\.statusを検索します。
- トリガーテーブルに関連する
- ステップ 3: 連続する更新の間に
commit()があるか確認します。- トリガーテーブルへの UPDATE がループ/連続処理内で複数回実行され、その間に
commit()がない場合、NOTIFY イベントは最終コミットまで遅延します。 - 中間コミットがないと、リアルタイムの進捗追跡が機能しなくなります。
- トリガーテーブルへの UPDATE がループ/連続処理内で複数回実行され、その間に
重大度:
- CRITICAL: NOTIFY/LISTEN ベースのリアルタイム機能(SSE、WebSocket)でコミットが欠落している
- HIGH: マテリアライズドデータを更新するトリガーでコミットが欠落している
例外: 中間状態を観測する必要のない単一のアトミック操作の場合、CRITICAL を MEDIUM に引き下げます。トランザクションのスコープが意図的であることを文書化している場合(ADR、アーキテクチャコメント)、重大度を 1 段階引き下げます。
推奨事項:
- 進捗の節目で
session.commit()を追加します(頻度を制限し、N%ごと、または T 秒ごとに実行します)。 - または、リアルタイム通知を DB トリガーから切り離します(Redis pub/sub、プロセス内イベント)。
工数: S-M(戦略的なコミットを追加するか、通知経路を再設計します)
2. トランザクションのスコープが広すぎる
内容: 遅い外部呼び出しを含む、無関係な操作が単一のトランザクションにまとめられている
検出方法:
async with session.begin()または明示的なトランザクションブロックを探します。- ブロック内に外部呼び出しが含まれているか確認します:
await httpx.、await aiohttp.、await requests.、await grpc. - ブロック内にファイル I/O が含まれているか確認します:
open(、.read(、.write( - パターン:同じトランザクション内に DB 書き込み、外部 API 呼び出し、別の DB 書き込みが含まれている
重大度:
- HIGH: トランザクション内で外部 HTTP/gRPC 呼び出しを実行している(ネットワーク遅延中に DB 接続を保持する)
- MEDIUM: トランザクション内でファイル I/O を実行している
推奨事項: トランザクションを分割します。サービス間の整合性には Saga/Outbox パターンを使用します。
工数: M-L(トランザクション境界を再構成します)
3. トランザクションのスコープが狭すぎる
内容: 論理的にアトミックであるべき操作が、複数のコミットに分割されている
検出方法:
- アトミックであるべき操作に対して、
session.commit()が複数回呼び出されている - パターン:親エンティティを作成してコミットし、子エンティティを作成してコミットする(単一のトランザクションにすべき)
- パターン:ステータスの更新と監査ログの作成が別々のコミットで行われている
重大度:
- HIGH: 親子エンティティの作成が別々のコミットになっている(失敗時に孤立するリスク)
- MEDIUM: 関連する更新が別々のコミットになっている(失敗時に状態が不整合になる)
推奨事項: async with session.begin() またはユニット・オブ・ワークパターンを使い、関連する操作を単一のトランザクションで囲みます。
工数: M(コミット境界を再構成します)
4. ロールバック処理の欠落
内容: 適切なエラー処理とロールバックなしで session.commit() を実行している
検出方法:
try/exceptブロックまたはコンテキストマネージャーの外にあるsession.commit()を探します。try内にsession.commit()があり、except内にsession.rollback()がない箇所を探します。- パターン:サービスメソッド内で単独の
await session.commit()を実行している - 例外:
async with session.begin()は自動的にロールバックするため安全です。
重大度:
- MEDIUM: ロールバックがない(失敗時にセッションが不整合な状態のままになる)
- LOW: コンテキストマネージャー使用時に明示的なロールバックがない(自動的に処理される)
推奨事項: async with session.begin() を使用して自動ロールバックするか、明示的な try/except/rollback パターンを追加します。
工数: S(コンテキストマネージャーで囲むか、エラー処理を追加します)
5. 長時間保持されるトランザクション
内容: 時間のかかる、またはブロッキングする処理中に開いたままのトランザクション
検出方法:
- スコープを計測します。トランザクションの開始からコミットまでの行数を数えます
begin()とcommit()の間に50行を超えるコードがある場合、フラグを立てます- トランザクション内に外部サービスへの
await呼び出し(ネットワーク遅延)がある場合、フラグを立てます - トランザクション内に
time.sleep()またはasyncio.sleep()がある場合、フラグを立てます
重大度:
- HIGH: 外部 API 呼び出し中もトランザクションが保持されています(接続プール枯渇のリスク)
- MEDIUM: トランザクションが50行を超えて続きます(ロジックが複雑で、ロック競合が発生する可能性が高い)
推奨事項: トランザクションの範囲を最小限にします。トランザクションを開始する前にデータを準備し、DB 操作の直後にコミットします
作業量: M(トランザクションの時間を最小限にするためにコードを再構成)
6. イベントチャネル名の整合性
内容: パブリッシャーのチャネル/トピック名が、サブスクライバーのチャネル/トピック名と一致しません
検出方法:
- ステップ 1: パブリッシャーのチャネル名を収集します(フェーズ 2 のトリガー検出を拡張します):
- マイグレーショントリガー:
pg_notify('channel_name', ...)の文字列引数、NOTIFY channel_nameを抽出します - アプリケーションコード:
src/、app/内で\.publish\(["']|\.emit\(["']|redis.*publish\(["']|\.send_to\(["']を Grep します - 抽出項目:
{channel_name, source_file, source_line, technology}
- マイグレーショントリガー:
- ステップ 2: サブスクライバーのチャネル名を収集します:
- PostgreSQL:アプリケーションコード内(マイグレーションだけでなく)で
LISTEN\s+(\w+)を Grep します - Redis:
src/、app/内で\.subscribe\(["']([^"']+)を Grep します - EventEmitter/WebSocket:ハンドラー/リスナーディレクトリ内で
\.on\(["']([^"']+)を Grep します - 抽出項目:
{channel_name, source_file, source_line, technology}
- PostgreSQL:アプリケーションコード内(マイグレーションだけでなく)で
- ステップ 3: パブリッシャーとサブスクライバーを相互照合します:
- 完全一致:
publisher.channel_name == subscriber.channel_name-> OK - 近似一致:Levenshtein 距離が2以下、または一方が他方の部分文字列 -> MISMATCH としてフラグを立てます
- 孤立したパブリッシャー:パブリッシャーにはチャネルが存在するが、サブスクライバーには存在しない -> ORPHAN としてフラグを立てます
- 孤立したサブスクライバー:サブスクライバーにはチャネルが存在するが、パブリッシャーには存在しない -> ORPHAN としてフラグを立てます
- 完全一致:
レイヤー 2 のコンテキスト分析(必須):
- チャネル名が共有設定定数または環境変数(例:
CHANNEL = os.environ["EVENT_CHANNEL"])に由来し、パブリッシャーとサブスクライバーの両方が同じソースを使う場合は、不一致ではありません - チャネルが動的なサフィックスパターン(例:
job_events:{job_id})を使用し、両側で同じテンプレートを使う場合は、孤立していません - パブリッシャーとサブスクライバーの検出対象からテストファイル(
**/test*/**、**/*.test.*)を除外します
重大度:
- CRITICAL: チャネル名が一致しません(近似一致:パブリッシャーは
job_eventsに送信し、サブスクライバーはjob_eventをリッスンしています) - HIGH: 孤立したパブリッシャー — イベントは送信されますが、消費されません(イベントが状態変更を伴う場合、データ損失のリスクがあります)
- MEDIUM: 孤立したサブスクライバー — リスナーは登録されていますが、パブリッシャーが見つかりません(デッドコードまたは将来の機能)
推奨事項:
- 不一致の場合:パブリッシャーとサブスクライバーで共有する単一の定数にチャネル名を統一します
- 孤立したパブリッシャーの場合:サブスクライバーを追加するか、未使用の NOTIFY/publish を削除します
- 孤立したサブスクライバーの場合:パブリッシャーを追加するか、使用されていないリスナーを削除します
作業量: S(タイプミスの修正/定数の追加)から M(不足しているサブスクライバー/パブリッシャーの設計)
スコアリングアルゴリズム
必ず読むこと: references/audit_scoring.md を読み込みます。
出力形式
必ずお読みください: references/templates/audit_worker_report_template.md を読み込んでください。
references/audit_summary_contract.md に従って JSON のサマリーを記述してください。管理モードでは、呼び出し元から runId と summaryArtifactPath の両方が渡されます。スタンドアロンモードでは、ワーカーが共通コントラクトに従って、実行スコープのアーティファクトパスを独自に生成します。
{output_dir}/ln-652--global.md に、category: "Transaction Correctness" とチェック項目 missing_intermediate_commits、scope_too_wide、scope_too_narrow、missing_rollback、long_held_transaction、event_channel_consistency を含むレポートを記述してください。
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-652--global.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
重要なルール
すでに読み込まれている references/audit_worker_core_contract.md を適用してください。
- 自動修正しない: 報告のみ行ってください
- まずトリガーを検出する: トランザクションパターンを分析する前に、必ずマイグレーションをスキャンしてトリガー/NOTIFY を検出してください
- ORM を考慮する: ORM のコンテキストマネージャーが自動ロールバックするか確認してください(
async with session.begin()は安全です) - テストトランザクションを除外する: 手動のコミット/ロールバックを行うテストフィクスチャーにはフラグを立てないでください
- データベース固有の挙動を考慮する: PostgreSQL の NOTIFY のセマンティクスは、MySQL のイベントスケジューラーとは異なります
完了の定義
すでに読み込まれている references/audit_worker_core_contract.md を適用してください。
- contextStore の解析に成功している(output_dir を含む)
- scan_path が決定されている
- マイグレーションからトリガー/NOTIFY のインフラストラクチャーを検出している
- 6 つすべてのチェックを完了している:
- 中間コミットの欠落、スコープが広すぎる、スコープが狭すぎる、ロールバックの欠落、長時間保持、イベントチャネルの一貫性
- 重大度、場所、工数、推奨事項を含む検出結果を収集している
- ペナルティアルゴリズムを使用してスコアを算出している
-
{output_dir}/ln-652--global.mdにレポートを記述している(Write の単一呼び出しでアトミックに書き込み) - コントラクトに従ってサマリーを記述している
参照ファイル
- 監査出力スキーマ:
references/audit_output_schema.md
バージョン: 1.1.0 最終更新日: 2026-03-15