Skip to content

fix(dataflow): connect the L4 SDG port layer to the statement ddg - #116

Merged
rahlk merged 1 commit into
mainfrom
fix/issue-115-l4-port-wiring
Jul 27, 2026
Merged

fix(dataflow): connect the L4 SDG port layer to the statement ddg#116
rahlk merged 1 commit into
mainfrom
fix/issue-115-l4-port-wiring

Conversation

@rahlk

@rahlk rahlk commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Closes #115.

Part 1 — port wiring. The SDG assembler builds the statement ↔ port binding edges (def stmt → actual_in, actual_out → callsite, formal_in → first use, return → formal_out) into the IR's extra_edges, and the old v1 program_graphs projection emitted them — the v2 emission dropped them, so the port lattice was an island and no end-to-end flows_to walk could cross a call. emit_l4 now emits them on each callable's ddg with prov:["reaching-defs"] — the label codeanalyzer-typescript already ships, keeping the prov vocabulary keystone-shared (ssa = L3 syntactic, points-to = L4 alias delta, reaching-defs = L4 port bindings). Deduplicated, deterministic, endpoint-guarded, idempotent under cache reuse; strictly additive so L3 ⊆ L4 holds.

Part 2 — call anchoring. Nested call vertices (y = f(x)) stay off the CFG spine by design (dataflow satellites); from L3 they carry parent = the enclosing statement's local — the same anchoring actual_in/actual_out use. Sanctioned null → value refinement at L2→L3 (mirrors callee: null → id); bare-call statements share their key with the CFG node and are untouched. Both decisions recorded in .claude/SCHEMA_DECISIONS.md.

Tests: 9 new regression tests (test/test_v2_l4_ports.py) covering all four binding classes, additivity vs the ssa set, endpoint hygiene, idempotency, and both parent cases; the conformance validator's L4 prov set gains reaching-defs.

Gate: full suite green — 198 passed, 6 skipped in 6m13s.

Propagation: same bug (3 of 4 classes) filed against the TS analyzer as codellm-devkit/codeanalyzer-typescript#81; python-sdk pin bump + py-a4.json golden regeneration tracked via codellm-devkit/python-sdk#276.

The SDG assembler wires the binding edges — def stmt → actual_in,
actual_out → callsite, formal_in → first use, return → formal_out — into
the IR's extra_edges, and the old v1 program_graphs projection emitted
them; the v2 emission dropped them, leaving the port lattice an island no
end-to-end flows_to walk could cross.

emit_l4 now emits the DDG-typed extra edges onto each callable's ddg
tagged prov=['reaching-defs'] (the label codeanalyzer-typescript ships
for its port-routing edges, keeping the prov vocabulary keystone-shared),
deduplicated, deterministically ordered, endpoint-guarded, and idempotent
under cache reuse. CDG-typed extras stay unemitted — actual vertices
already carry that containment in parent.

Nested call vertices (y = f(x)) are likewise anchored: from L3 they carry
parent = the enclosing statement's local id, a sanctioned null → value
refinement at L2→L3 mirroring callee null → id at L1→L2. Bare-call
statements share their key with the CFG node and are untouched.

Conformance now admits the third L4 prov value; both decisions are
recorded in .claude/SCHEMA_DECISIONS.md.
@rahlk
rahlk merged commit 310d292 into main Jul 27, 2026
@rahlk
rahlk deleted the fix/issue-115-l4-port-wiring branch July 27, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

L4 graph completeness: SDG port layer is disconnected from the statement ddg; call vertices sit off the CFG spine

1 participant