gitnexus-pdg-query について
gitnexus-pdg-queryは、GitNexusのプログラム依存グラフをクエリし、結果を解釈するスキルです。`pdg_query`の開発や、制御条件と変数の流れを調べる開発者向けです。
主な機能
- 01制御依存のクエリ
- 02定義から使用箇所への追跡
- 03早期リターンのガード検出
- 04PDGクエリ結果の解釈
- 05PDGレイヤー不足の診断
活用シーン
- 01文を制御する条件の確認
- 02関数内の変数の流れの追跡
- 03`pdg_query`のレビューや拡張
- 04空のクエリ結果の調査
MCP 対応
GitNexusの`pdg_query` MCPツールと、`controls`および`flows`モードについて説明します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ abhigyanpatwari/ gitnexus --skill gitnexus-pdg-queryインストール後、Claude Code で/gitnexus-pdg-queryを入力して読み込まれたか確認します。
詳細
GitNexus による PDG クエリサーフェス
pdg_query MCP ツールと、それが読み取る制御依存/データ依存エッジ — オプトインの --pdg プログラム依存レイヤー — に関する専門知識です。gitnexus/src/mcp/local/local-backend.ts(_pdgQueryImpl)や pdg_query ツール定義に触れる前、または pdg_query の結果を説明する際に、これを読んでください。
使用すべき場面
- 「この文はどのような条件で実行されますか?」(ガード述語)。
- 「この変数は関数内のどこを流れますか?」(def→use)。
- ガード節の発見(早期リターンガード — #559 のヒューリスティックを包含します)。
pdg_query/ CDG / REACHING_DEF の読み取りパスの拡張またはレビュー。- 空の、または予想外の
pdg_query結果のデバッグ。
階層化された基盤(ビルド順)
pdg_query は、taint が実行されるのと同じグラフ上で実行されます。各レイヤーは --pdg の背後でオプトインです。デフォルトの analyze 実行ではそれらは一切記録されません(バイト単位で同一)。
L1 CFG per-function basic blocks + control-flow edges (M1 #2081)
L2 REACHING_DEF GEN/KILL def→use data dependence (pure solver) (M2 #2082)
L5 CDG Ferrante control dependence (post-dominators) (M5 #2085)
3 つすべては、単一の CodeRelation テーブル内の BasicBlock → BasicBlock エッジです(type プロパティでキー付けされます)。Function → BasicBlock エッジは存在しません。
2 つのモード
pdg_query({ mode: 'controls', target })— CDG。アンカーされた関数について、各エッジは、制御する述語ブロック → 依存ブロック +label内の分岐の向き('T'= 述語の true/成立アーム、'F'= false/フォールスルー)です。早期リターン/throw ブロックへのエッジはguard: trueとフラグ付けされます。pdg_query({ mode: 'flows', target, variable? })— REACHING_DEF の def→use エッジ。variableは 1 つのバインディングに絞り込みます。
target は必須です — ファイルパス、またはシンボル/関数名(context() と同様に解決されます)。アンカーなしのモードはありません(以下を参照)。
修正されたガード節の Cypher
RFC #567 §2 の形式([:CDG {label:'F'}])は、書かれたままでは実行されません。エッジは単一の CodeRelation テーブルの type プロパティの値であり、分岐の向きは reason にあり、label カラムにはありません:
MATCH (pred:BasicBlock)-[r:CodeRelation {type: 'CDG'}]->(dep:BasicBlock)
WHERE dep.text STARTS WITH 'return' OR dep.text STARTS WITH 'throw'
RETURN pred.startLine, r.reason AS branch, dep.startLine, dep.text
r.reason は、述語が早期終了に到達するために取った向きです。if (!ok) return; の場合、return は述語の true アーム('T')に乗り、保護された本体は false アーム('F')に乗ります — 極性はガードに依存するため、一方の向きをハードコードしないでください。
注意点(特に重要なもの)
- 常にアンカーされ、LIMIT で境界付けられます。 LadybugDB には rel-property インデックスがないため、アンカーされていない
[:CDG*]/[:REACHING_DEF*]パススキャンは無制限になります。pdg_queryはtargetを必須とし、ページを境界付けます。生のcypher呼び出し元は、ファイル id-prefix またはシンボルスパンで自らアンカーする必要があります。 - BasicBlock↔シンボルの結合は再構築されます。
Function→BasicBlockエッジはありません。ブロックはその id-prefix(BasicBlock:<file>:<fnStartLine>:…)と、シンボルのスパン内のstartLineによって照合されます。BasicBlock のstartLineは 1 始まりである一方、シンボルノードのstartLine/endLineは 0 始まりであるため、両方の境界が+1シフトされます([symStart+1, symEnd+1])。上限の+1は関数の最終行にあるガード/def/use を保持し、下限の+1は直接上の行にある隣接関数のブロックを除外します。同一行/ネストされた関数は粗くアンカーされます。 - PDG レイヤーがない ⇒ エラーではなく注記。 リポジトリが
--pdgでインデックスされていない場合、ツールは{ results: [], note: "no PDG layer …" }を返します(RepoMeta.pdg.maxCdgEdgesPerFunction/maxReachingDefEdgesPerFunctionに対する低コストのメタプローブ)。 - CDG ラベルは M5/M6 では二値です。 すべての
switch-case アームは'T'です。case ごとの条件はまだ区別されません。 - 手続き内のみ。 関数をまたぐフローは taint の領域です(
explain)。
フォークせず、ミラーする
_pdgQueryImpl は _explainImpl の前半部分(WAL ラッパー、メタのレイヤーなしプローブ、limit 検証、resolveSymbolCandidates によるアンカー)を、TAINTED の代わりに CDG/REACHING_DEF で置き換えたものです — そして taint のパスコーデック / 手続き間 TAINT_PATH の仕組みは一切持ちません。それらの共有ヘルパーを再利用してください。再実装しないでください。