Skip to content

canonical-schema: L1 node coverage gaps (comments, local variables, enum constants, call-node richness) #40

Description

@sinha108

Problem

canonical-schema.md under-specifies several node fields that every analyzer already produces, so each language is inventing its own names (or silently dropping the data). Discovered doing a field-by-field v1→v2 comparison while migrating codeanalyzer-java to schema v2 (codellm-devkit/codeanalyzer-java#180, epic codellm-devkit/.github#42).

Sibling of #39, which covers the same class of problem for entrypoint/CRUD enrichment. This issue covers the core L1 node vocabulary.

Gap Keystone today Evidence from analyzers
Comments / docstrings no comment vocabulary anywhere codeanalyzer-python v2 has comments: List[PyComment] on module/class/callable; Java v1 has Comment on nearly every node and its Neo4j schema declares a docstring property on JType/JCallable/JField/…
Local variables silent codeanalyzer-python v2 has local_variables: List[PyVariableDeclaration] on callable; Java v1 has Callable.variableDeclarations
Enum constants / type members silent (type lists only callables{} + fields{}) Java v1 has Type.enumConstants; TS models enums as their own type kind
Call-node richness call body node is only { callee, arguments } Java v1's CallSite carries 14 more fields (receiver_expr, receiver_type, argument_types, argument_expr, callee_signature, is_static_call, is_constructor_call, access flags). The Python pilot did not lose these — it emits body call nodes and keeps a parallel rich call_sites[]. So the canonical shape as written forces a data loss that no analyzer actually wants, and the one v2 implementation quietly worked around it
Parameter modifiers param = { name, type, span, is_variadic? } Java v1 has ParameterInCallable.modifiers (final)
code_start_line silent codeanalyzer-python v2 has code_start_line; Java v1 has codeStartLine
is_implicit silent Java v1 has Callable.isImplicit (compiler-generated default constructors)
Record components silent Java v1 has Type.recordComponents (with defaultValue, isVarArgs) — arguably language-specific, but worth a ruling (fields? params? own list?)

The pattern is the same one the parity clause exists to prevent: the shared vocabulary is silent, so analyzers coin their own names (or lose the data), and the SDK cannot model the concept once.

Scope boundary

This issue decides and documents the canonical vocabulary in
skills/designing-cldk-changes/references/canonical-schema.md (plus consequent notes in
neo4j-projection.md / schema-contract.md). It does not implement anything in an analyzer or
SDK — those are follow-ups per repo. Entrypoint/CRUD enrichment is #39, not here.

Goals

  • Decide canonical comment/docstring representation: a comments[] node list, a single docstring, or "recover from module.source only" — and on which node kinds
  • Decide whether local variables are a first-class callable field (pilot precedent) or subsumed by L3 body statements
  • Decide enum constants (and other type members) — new node kind under fields{}, own list, or language-additive
  • Resolve the call-node richness question: enrich the canonical call node, sanction a parallel call_sites[], or explicitly declare the detail out of scope (and accept that framework/CRUD finders need receiver_type)
  • Rule on the small ones: parameter.modifiers, code_start_line, is_implicit, record components
  • For each: state the Neo4j projection consequence, and the migration for analyzers already emitting a divergent shape

Caveats and known risks

  • Several of these interact with the "absent = no fact" and "no per-callable code" conventions — e.g. dropping comments is defensible because module.source is retained, but then docstrings are not addressable/queryable, which matters for LLM/RAG consumers.
  • Enriching the call node duplicates data that L4's actual_in/actual_out vertices partly express; the ruling should say which is authoritative.
  • Whatever is chosen, at least one shipped analyzer migrates: Java v1 and the Python v2 pilot differ here today.

Definition of done

  • canonical-schema.md covers each row above (field name, shape, placement, Neo4j projection).
  • Migration notes exist for the divergent shapes already shipped (Java v1, Python v2 pilot).
  • Follow-up issues filed on the affected analyzer/SDK repos.

Metadata

Metadata

Assignees

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