Found while validating python-sdk's new flows_to/slice verbs (python-sdk#270, PR python-sdk#297) end-to-end against 1.1.0. Audit corpus: the python-sdk cldk/ package at -a 4 — 758 callables, 29,562 ddg edges, 5,031 spanned body vertices.
1. The interprocedural port layer is an island
Observed ddg edge patterns across the entire corpus (src-class → dst-class):
| pattern |
count |
| stmt → stmt |
24,825 |
| entry → stmt |
4,737 |
| anything touching a port (actual_in/actual_out/formal_in/formal_out) |
0 |
Port wiring: 2,673 formal_in ports — 0 with outgoing ddg; 2,431 formal_out ports — 0 with incoming ddg. Meanwhile the app level emits 1,961 param_in + 1,788 param_out edges and per-call summary edges between those same ports.
So the SDG is two disconnected graphs: a statement-level ddg, and a port lattice (actual_in → formal_in, formal_out → actual_out, actual_in → actual_out) nothing flows into or out of. Consequences for any consumer:
flows_to(def_stmt, callee_formal) can never find a path — an end-to-end "this value reaches that parameter" witness is inexpressible; only port-to-port segments work.
- Return-value flow (
x = f(y) → uses of x) dies at actual_out.
- Inside the callee, parameter flow is carried by
@entry → stmt var edges, duplicating what formal_in → stmt should carry — so entering via param_in dead-ends at formal_in.
Missing edge classes (the fix checklist):
Note: codeanalyzer-typescript already emits stmt → formal_out under the same schema (verified on its L4 sample), so the vocabulary supports this today — no schema change needed, emission only.
2. Every call vertex is off the CFG spine
1,781 of 5,031 spanned body vertices are touched by zero cfg edges — and all 1,781 are kind: call. A slice(edges=("cfg",)) or any cfg-reachability walk never visits a call site. If calls are intended as dataflow satellites of their statement, that design deserves a schema note; otherwise they should sit on the spine (stmt → call → next or a stmt —contains→ call link).
Minimal repro: any 2-function project at -a 4 (the python-sdk tests/resources/cpg/py-a4.json "pyfix" sample exhibits every one of these). Related: #112 (persist max_level in the Neo4j emit).
Found while validating python-sdk's new
flows_to/slice verbs (python-sdk#270, PR python-sdk#297) end-to-end against 1.1.0. Audit corpus: the python-sdkcldk/package at-a 4— 758 callables, 29,562 ddg edges, 5,031 spanned body vertices.1. The interprocedural port layer is an island
Observed ddg edge patterns across the entire corpus (src-class → dst-class):
Port wiring: 2,673
formal_inports — 0 with outgoing ddg; 2,431formal_outports — 0 with incoming ddg. Meanwhile the app level emits 1,961param_in+ 1,788param_outedges and per-callsummaryedges between those same ports.So the SDG is two disconnected graphs: a statement-level ddg, and a port lattice (
actual_in → formal_in,formal_out → actual_out,actual_in → actual_out) nothing flows into or out of. Consequences for any consumer:flows_to(def_stmt, callee_formal)can never find a path — an end-to-end "this value reaches that parameter" witness is inexpressible; only port-to-port segments work.x = f(y)→ uses ofx) dies atactual_out.@entry → stmtvar edges, duplicating whatformal_in → stmtshould carry — so entering viaparam_indead-ends atformal_in.Missing edge classes (the fix checklist):
def stmt → actual_in:k(argument binding at the call site)actual_out → use stmt(return-value binding)formal_in:k → first-use stmts(or re-root the parameter's entry edges at the port)return stmt → formal_outNote: codeanalyzer-typescript already emits
stmt → formal_outunder the same schema (verified on its L4 sample), so the vocabulary supports this today — no schema change needed, emission only.2. Every
callvertex is off the CFG spine1,781 of 5,031 spanned body vertices are touched by zero cfg edges — and all 1,781 are
kind: call. Aslice(edges=("cfg",))or any cfg-reachability walk never visits a call site. If calls are intended as dataflow satellites of their statement, that design deserves a schema note; otherwise they should sit on the spine (stmt → call → nextor astmt —contains→ calllink).Minimal repro: any 2-function project at
-a 4(the python-sdktests/resources/cpg/py-a4.json"pyfix" sample exhibits every one of these). Related: #112 (persist max_level in the Neo4j emit).