You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
canonical-schema.md (the keystone) mandates "No dangling endpoints — every src/dst references node ids" in the Edges section, but gives no vocabulary for a call whose target is outside the project (JDK / library / builtin). Every analyzer has to resolve this to satisfy the invariant, and the keystone's own worked example quietly violates it:
Analyzer / keystone
out-of-project call target today
Keystone
silent — no external_symbols, no @external id. The worked call_graph example points a Go call at dst: "can://go/myapp/src/fnv.go/New64()" — a stdlib target dressed as a plain source-file id, which dangles under the keystone's own no-dangling rule (there is no fnv.go node in the tree).
codeanalyzer-java (v2, L2)
coined an external_symbols{} map at application scope, keyed by an @external can-id (can://java/<app>/@external/<binary-type>/<sig>, valued {kind, signature, declaring_type}); a call_graphdst may be such a key, which is how no-dangling is met for library targets. Ledger D19; homing is opt-in behind --external-calls (default off = v1 parity), D24.
codeanalyzer-typescript / -python
no L2 external representation yet — both will need one, and will coin it incompatibly unless the keystone rules.
This is the same parity-clause failure #39 (entrypoint/CRUD) and #40 (L1 node fields) exist to prevent — a shared concept the keystone is silent on, so one analyzer coins it and the others (and the SDK) cannot model it once. It surfaced at L2 (the edge overlay) rather than L1.
Decide and document the canonical vocabulary for out-of-project call targets in skills/designing-cldk-changes/references/canonical-schema.md (and any consequent notes in neo4j-projection.md / schema-contract.md). This does not implement it in any analyzer or SDK — those are follow-ups per repo — and it adds no detection capability.
Goals
Decide the canonical representation of an out-of-project call target: the Java precedent (an external_symbols{} map at application scope, keyed by an @external id, valued {kind, signature, declaring_type}) vs. any alternative — and state explicitly that a call_graphdstmay be an external_symbols key, which is how the no-dangling invariant is satisfied for such targets.
Fix the worked call_graph example (the Go fnv.New64 target) to use the chosen representation, so the keystone stops contradicting its own no-dangling rule.
Specify the @external id grammar in the id section — can://<lang>/<app>/@external/<binary-type-name>/<erased-sig> — and document @ as the reserved marker for non-file id slots (already used for synthetic body-node tags). Rule on binary vs source spelling: Java puts the binary name (java.util.Map$Entry) in the id for exactness/joinability and the dotted form in declaring_type, so consumers never parse the id.
Decide whether external homing is mandatory or optional in the canonical output. Java made it opt-in (--external-calls, default off, for v1 parity); with it off, external targets are dropped and no-dangling holds trivially. Rule on whether the default max_level-2 payload should carry externals.
Note that prov is per-language open vocabulary (the keystone already says so): Java's L2 values are ["declared", "rta"]; record that each analyzer documents its own prov set.
(Neo4j) decide whether an external symbol gets its own node family/label in the projection, or is folded into the existing callable node family.
Definition of done
canonical-schema.md defines the out-of-project call-target vocabulary, the @external id grammar, and the dst-may-be-external rule; the worked example no longer dangles.
The decision is reflected (or a follow-up filed) for each analyzer and the SDK, and for the Neo4j projection.
Problem
canonical-schema.md(the keystone) mandates "No dangling endpoints — everysrc/dstreferences node ids" in the Edges section, but gives no vocabulary for a call whose target is outside the project (JDK / library / builtin). Every analyzer has to resolve this to satisfy the invariant, and the keystone's own worked example quietly violates it:external_symbols, no@externalid. The workedcall_graphexample points a Go call atdst: "can://go/myapp/src/fnv.go/New64()"— a stdlib target dressed as a plain source-file id, which dangles under the keystone's own no-dangling rule (there is nofnv.gonode in the tree).external_symbols{}map at application scope, keyed by an@externalcan-id (can://java/<app>/@external/<binary-type>/<sig>, valued{kind, signature, declaring_type}); acall_graphdstmay be such a key, which is how no-dangling is met for library targets. Ledger D19; homing is opt-in behind--external-calls(default off = v1 parity), D24.This is the same parity-clause failure #39 (entrypoint/CRUD) and #40 (L1 node fields) exist to prevent — a shared concept the keystone is silent on, so one analyzer coins it and the others (and the SDK) cannot model it once. It surfaced at L2 (the edge overlay) rather than L1.
Discovered while implementing Java's L2 v2 call graph (codellm-devkit/codeanalyzer-java#181, epic codellm-devkit/.github#42). Java is shipping the
external_symbols/@externalshape now and will align once this is decided.Scope boundary
Decide and document the canonical vocabulary for out-of-project call targets in
skills/designing-cldk-changes/references/canonical-schema.md(and any consequent notes inneo4j-projection.md/schema-contract.md). This does not implement it in any analyzer or SDK — those are follow-ups per repo — and it adds no detection capability.Goals
external_symbols{}map at application scope, keyed by an@externalid, valued{kind, signature, declaring_type}) vs. any alternative — and state explicitly that acall_graphdstmay be anexternal_symbolskey, which is how the no-dangling invariant is satisfied for such targets.call_graphexample (the Gofnv.New64target) to use the chosen representation, so the keystone stops contradicting its own no-dangling rule.@externalid grammar in the id section —can://<lang>/<app>/@external/<binary-type-name>/<erased-sig>— and document@as the reserved marker for non-file id slots (already used for synthetic body-node tags). Rule on binary vs source spelling: Java puts the binary name (java.util.Map$Entry) in the id for exactness/joinability and the dotted form indeclaring_type, so consumers never parse the id.--external-calls, default off, for v1 parity); with it off, external targets are dropped and no-dangling holds trivially. Rule on whether the defaultmax_level-2 payload should carry externals.provis per-language open vocabulary (the keystone already says so): Java's L2 values are["declared", "rta"]; record that each analyzer documents its ownprovset.Definition of done
canonical-schema.mddefines the out-of-project call-target vocabulary, the@externalid grammar, and thedst-may-be-external rule; the worked example no longer dangles.