Skip to content

v2 Stage 3: L3 intraprocedural CFG/CDG/DDG (syntactic) #73

Closed

Description

@rahlk

Part of #69.

Stage 3 — L3 intraprocedural CFG/CDG/DDG (syntactic)

Branch: feat/v2-stage3-l3

Deliverables:

  • dataflow/identity.py — the (signature, int node_id) ↔ (can:// callable-id, ordinal-id) bijection; consumed by both emitters.
  • Populate body with statement nodes + @entry/@exit; emit cfg/cdg/ddg edge lists on each callable, re-targeting the existing cfg/dominance/defuse kernels through the identity map.
  • Split the current PDG rows into cfg/cdg/ddg; add a syntactic-only DDG mode (textual interference, oracle bypassed, prov:["ssa"]).
  • CLI: --graphs cfg,dfg,pdg scoping; --graph-field-depth at L3+; sdg requires -a 4 (flag error otherwise).
  • Neo4j: PyCFGNode keyed by ordinal id; PY_DDG gains prov.
  • Migrate test/test_dataflow_{cfg,dominance,defuse,pdg,scc,cpg,slicing}.py to v2 ids.

Files: dataflow/{identity,builder,defuse}.py, core.py, __main__.py, neo4j/project.py, dataflow tests.

Gate: intraprocedural backward slice == hand-computed set exactly (over ordinal ids); assert_conformant(..., 3) incl. no dangling cfg/cdg/ddg; L2 ⊆ L3.

Expand into full bite-sized tasks with superpowers:writing-plans at stage start.

Activity

  1. rahlk commented on Jul 7, 2026

    @rahlk
    ContributorAuthor

    Two forward-risks surfaced by the Stage 1 whole-branch review that Stage 3 must handle:

    1. Cross-level cache body-leak (correctness). The analysis cache stores the full Analysis (bodies + edge lists) and _file_unchanged keys only on content hash / mtime / size — not on analysis_level, and populate_l1_body/assign_ids add to body but never clear it. Harmless at L1 (only call nodes populate body), but once Stage 3 fills body with statements + @entry/@exit + cfg/cdg/ddg, a subsequent lower-level run reusing the cache would leak higher-level content into lower-level output — breaking level purity / the L1⊆…⊆L4 monotonicity gate. Fix: key the cache by analysis_level (or clear regenerated body/edge collections on reuse).
    2. Re-enable the Neo4j CPG overlay (_project_program_graphs is currently disabled + dead-references the dissolved program_graphs field) on the v2 tree, and close the latent dual :PySymbol constraint (id + signature) before Neo4j is exercised.
  2. rahlk commented on Jul 7, 2026

    @rahlk
    ContributorAuthor

    Additional Stage-3 tracking (from the Stage 2 whole-branch review): when re-enabling the Neo4j projection, reconcile a classification-precedence asymmetry — reidentify_call_graph (JSON) resolves declared-first (sig_to_id wins) while _call_endpoint (Neo4j) resolves external-first (external_symbols wins). Inert today (a symbol is either project-declared or external, never both), but make them consistent so JSON and Neo4j can't disagree on an endpoint id if that invariant ever weakens. Track alongside the latent dual :PySymbol (id + signature) uniqueness constraint.

  3. rahlk commented on Jul 15, 2026

    @rahlk
    ContributorAuthor

    Landed on main via the stacked v2 chain (PR #88 → merge d477207) and released as v1.0.0 (schema_version 2.0.0).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions