Skip to content

Migrate to canonical schema v2: can:// ids, statement-level CPG, identity-only edges #179

Open

Description

@rahlk

Is your feature request related to a problem? Please describe.

Parent: codellm-devkit/.github#35 · Roadmap: docs/design/roadmap.md (candidate 9) Identity grammar spec: can-uri-service-segment.md · codellm-devkit/.github#39

Skeleton — bodies to be filled in by the maintainer.

codeanalyzer-java is the only analyzer still on schema 1.1.0, and the only one whose shape canonical v2 explicitly forbids rather than merely differs from.

  • No can:// ids. Python and TypeScript both emit them; Java does not.
  • No statement-level nodes in the Neo4j projection. schema.neo4j.json declares 16 labels — JApplication, JCompilationUnit, JType, JCallable, JCallSite, JField, JParameter, JVariable, JAnnotation, JComment, JCrudOperation, JCrudQuery, JEnumConstant, JInitializationBlock, JPackage, JRecordComponent — and none is a body/statement node. Deferred deliberately in .claude/SCHEMA_DECISIONS.md Callable signature and patch for expression resolution failure #9: "Statement-level CPG (CFGNode etc.) stays a follow-up." This is that follow-up.
  • Dependence edges are callable→callable. J_CONTROL_DEP / J_DATA_DEP / J_HEAP_DATA_DEP connect JCallable to JCallable (SCHEMA_DECISIONS.md Callable signature and patch for expression resolution failure #9), where canonical v2 places cfg / cdg / ddg at statement→statement on the callable.
  • Rich edges. The emitted shape drives python-sdk's JGraphEdges, whose source and target are full JMethodDetail objects rather than node ids (cldk/models/java/models.py:517-523). Canonical v2's expansion rubric: "Never: … add a rich-edge variant."

Describe the solution you'd like

  • can://<service>/<lang>/<file>/<type>/<sig> ids, with Java's signatureOf() pinned (generics, overloads, <init>) — note the service segment is outermost and there is no <app> segment (spec D1/D2); the app-name CLI option becomes --service, same default (input directory name)
  • Statement-level body nodes in both projections, on the settled body-node model
  • cfg / cdg / ddg / summary re-anchored from callable→callable to statement→statement
  • Identity-only edges — endpoints are ids, no nested callables
  • SCHEMA_VERSION 1.1.0 → 2.1.0 (not 2.0.0 — Java emits no can:// id today, so it lands directly on the service-segment grammar and never has to migrate off 2.0.0), with .claude/SCHEMA_DECISIONS.md updated
  • Passes the shared conformance suite (Shared conformance suite: check every analyzer against canonical v2 .github#38) and the projection-parity gate (Projection-parity gate: prove analysis.json and the Neo4j graph agree .github#37)

Describe alternatives you've considered

Not stated in the original issue.

Additional context

Scope boundary

Brings the analyzer's emitted contract to canonical v2. Does not change python-sdk's Java models — that is codellm-devkit/python-sdk#309, and it is blocked on this issue, not the reverse. Does not settle the entrypoint vocabulary (JEntrypoint marker + is_entrypoint), which is a separate design session.

Caveats and known risks

  • WALA node identity is SSA instruction order, not AST source spans (SCHEMA_DECISIONS.md Update excluding signature-related files #5): node_id 0 is a synthetic ENTRY, then SSA instructions by iindex. Canonical v2 addresses sub-callable nodes by @line:col. These do not map cleanly — WALA nodes are SSA instructions, not AST regions, and source lines come from ECJ/CAst positions with a -1 sentinel when unavailable. This is the hard part of the issue and may force either a Java-specific local-id form recorded in SCHEMA_DECISIONS.md, or a change to the canonical grammar. It should be raised in the contract spec (Extract and freeze the canonical schema v2 contract from codeanalyzer-python .github#36), not discovered during implementation.
  • CFG edge kinds are derived, not labelled by WALA (SCHEMA_DECISIONS.md Update main.yml #6) — true/false by successor order, loop_back by iindex comparison. Deterministic but approximate; carry the documentation forward rather than silently absorbing it.
  • No SUMMARY edges today (SCHEMA_DECISIONS.md Add thrown exceptions to callable info in symbol table #7) — WALA computes HRB summaries lazily inside Slicer.
  • This is a breaking change for every python-sdk consumer of JGraphEdges. It must ride one migration with codeanalyzer-python 3.0.0 and the SDK, per the epic's release plan.
  • TODO

Definition of done

  • TODO — exact conditions. At minimum: the conformance suite and parity gate both pass, and no JGraphEdges-shaped rich edge remains in the emitted contract.

Activity

  1. rahlk commented on Aug 7, 2026

    @rahlk
    CollaboratorAuthor

    Folding the can:// service segment into this migration rather than filing a separate issue,
    since Java has not emitted a can:// id yet and would otherwise implement the old grammar and
    immediately migrate off it.

    Spec: can-uri-service-segment.md · coordination codellm-devkit/.github#39 · siblings codellm-devkit/codeanalyzer-python#123, codellm-devkit/codeanalyzer-typescript#91.

    What changed in the body above — two goal lines:

    - can://<lang>/<app>/<file>/<type>/<sig>
    + can://<service>/<lang>/<file>/<type>/<sig>      # service outermost, <app> collapsed into it
    
    - SCHEMA_VERSION 1.1.0 → 2.0.0
    + SCHEMA_VERSION 1.1.0 → 2.1.0
    

    Java is the cheapest repo in this change: Python and TypeScript have to rewrite live ids
    (83 and 34 references), while Java has none, so it lands on the final grammar first time. The
    app-name CLI option becomes --service, defaulting to the input directory name.

    Two things this does not touch, flagged for the maintainer rather than silently edited:

    1. The caveat "It must ride one migration with codeanalyzer-python 3.0.0 and the SDK, per the
      epic's release plan"
      now looks stale. There is no codeanalyzer-python 3.0.0 — the
      service-segment change was taken as an in-place amendment to v2 (2.0.0 → 2.1.0, spec D3),
      on the grounds that no consumer holds a can:// id today. Whether Java's migration still
      needs to ride a single train with Python and the SDK is a release-plan question that predates
      this spec and is yours to settle.

    2. The WALA local-id problem in the caveats — SSA iindex order versus canonical @line:col —
      is untouched and remains the hard part of this issue. That caveat says it should be raised in
      the contract spec Extract and freeze the canonical schema v2 contract from codeanalyzer-python .github#36. It still should; the service segment sits above
      the callable line and does not interact with sub-callable identity either way.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions