Skip to content

Identity

The natural key

Identity is the structured key (lang, module, symbol, disambiguator?). It is compared component-wise, never by parsing a rendered string. Uniqueness is per model union: no two entities share (lang, module, symbol, disambiguator).

Component Role
lang language id, frozen per profile (java, ts, clj, …)
module the owning module’s path. A module names itself here, with an empty symbol
symbol the path below the module — dots for nesting; empty only for a module
disambiguator optional: file:line:column for anonymous entities (lambdas, impl blocks), param:/local: markers for sub-members; absent when the symbol is already unique. For Java invocables the erased-FQN parameter list is part of symbol, not of this component. The COLUMN is load-bearing: one line can start several nameless entities, and without it they collapse into one id

Rendered ids

A rendered idjava:com.acme.order/OrderService.bill(com.acme.order.Order), produced by core’s renderId as <lang>:<module>[/<symbol>][#<disambiguator>] — is a display projection: written into v1 files and shown to users, and never parsed.

Because the id is a projection it must not lose information, so / and # are reserved: a module may contain neither, a symbol may not contain #, and a present disambiguator is non-empty. Under those rules rendering is injective — two distinct keys can never produce one id.

A module names itself rather than its parent: the alternative renders the package java:com.acme.order as java:com.acme/order and needs a fabricated java module to place the stub package java:java.util.

Identity is multi-declaration tolerant: one key may be declared in several places (TypeScript declaration merging, C# partial classes).

Canonical order

Sort by natural key, component by component, a missing disambiguator before any present one. It belongs to the model, not to an encoding: it is what makes snapshot diffs reviewable and extractor cross-validation meaningful. It is deliberately not the same as sorting the rendered ids as strings, where / and . are ordinary characters.

References

Every reference between concepts (edge endpoints, parent, children, attachedTo, declaredType, candidates) identifies an entity by its natural key. The v1 file format spells each of those as the rendered id string; the model.jsonl encoding uses file-scoped integer surrogates. A surrogate is not identity and never crosses a file boundary.

SourceAnchor

The evidence concept: where in the source a fact was observed.

Attribute Type Meaning
file string path of the CodeFile, relative to the analyzed root
span [int, int] [startLine, endLine], 1-based, inclusive

Relations: attached to entities (via the TSourceAnchor trait) and to edges (directly). Anchors on edges are what make every dependency claim auditable.

Space

TypeScript-family concept: which declaration space(s) an entity occupies.

Value Meaning
type exists only at type-check time (TS interface, type) — dependencies on it are erased at runtime
value exists at runtime

An entity may occupy both (a TS class). Optional attribute; only meaningful in profiles that declare it.

CodeFile

A source file. Not reified as a first-class entity in most profiles — it appears as anchor.file values and in TModule.definedIn. It becomes an explicit node only where a language has file-level dependencies (PHP FileInclude edges).

Worked example

{
  "id": "java:com.acme.order/OrderService.bill(com.acme.order.Order)",
  "kind": "method",
  "traits": ["TNamed", "TInvocable", "TWithParameters", "TWithLocalVariables",
             "TWithInvocations", "TWithAccesses", "TTypedEntity", "TChildOf",
             "TSourceAnchor"],
  "name": "bill",
  "signature": "bill(com.acme.order.Order)",
  "declaredType": "java:com.acme.billing/Invoice",
  "parent": "java:com.acme.order/OrderService",
  "anchor": { "file": "OrderService.java", "span": [15, 22] }
}

The id is the rendering of the natural key:

Component Value
lang java
module com.acme.order
symbol OrderService.bill(com.acme.order.Order)
disambiguator (absent — the symbol is already unique)

The id’s parameter types are erased fully-qualified names, not simple names: archive(java.util.List) and archive(com.acme.order.legacy.List) are legal Java overloads that both render as archive(List) under simple names, so one method would vanish from the model with no error.

Why identity is a key and not a string: Identity.

Last updated on