Skip to content

ADR-0031: Entity types, not entity kinds — de-overloading 'kind'

ADR-0031: Entity types, not entity kinds — de-overloading ‘kind’

Status: accepted (2026-07-04)

Supersedes: partially supersedes ADR-0028 — the wire key naming only (from.kindfrom.entity_type; has_link.kindlink_type). ADR-0028’s decision stands in full: QuerySpec is the wire surface, IR-2 stays kernel-internal, the flat-v2 where grammar and its staging discipline are unchanged.

Context

The word kind was overloaded. The LLD (§20) always names the modeled type of an entity an entity type (defineEntityType, EntityType | Interface link targets, “entity types conform structurally”) and reserves “kind” for the kind constructor — the closed set of nine value shapes (text, numeric, categorical, … the layer-1 primitive a trait’s value is built from). But the code drifted: EntityKindDecl, entity_kinds, kind_id, EntityKindId, EntityRef.kind — using “kind” for the entity type, colliding head-on with KindConstructor (the constructor) inside the same files, and with a third, orphaned vinxi-value::ValueKind. A late glossary rewrite compounded it, defining “Entity / Entity Kind” on the one page that declares itself “authoritative over any conflicting page” — inverting the LLD’s own vocabulary.

The ratified query wire inherited the collision: ADR-0028 §v0 serves from (kind | kinds | interface), where kind means entity type.

This ADR is the naming half of the ontology-depth design (docs/superpowers/specs/2026-07-04-ontology-palantir-depth-design.md, R1/R10); the value-type layer (R2) and YAML authoring (R8) are tracked separately.

Decision

The modeled type of an entity is an entity type. “kind” is reserved for the kernel constructor layer. Concretely:

  • Document format & code: EntityTypeDecl, entity_types, entity_type_id, EntityTypeId, EntityRef.entity_type, snapshot entity_type() / type_conforms(); link endpoints source_type / LinkTarget::Types; the amendment/derivation/alert fields entity_type_id / root_type / from_type / alert_type.
  • Query wire (partial supersession of ADR-0028): from.kindfrom.entity_type (one key, accepting a single string or an array — the pre-existing union shape, unchanged); has_link.kindlink_type (it names a link type). The response envelope field kindIdentityTypeId. Grammar, flat-v2 shape, conformance discipline, and the IR-2-internal ruling are untouched.
  • The glossary is corrected to “Entity / Entity Type”; this ADR adjudicates the self-declared-authoritative page in favour of the LLD vocabulary.
  • The constructor layer keeps “kind” for now (KindConstructor, the {"kind": …} trait-value tag). Its rename to value_kind, and the vocabulary value_kind → value_type → trait → entity_type, land with the value-type-layer track (a later ADR under the same spec). Ambient, non-entity senses of “kind” (statement_kind, job_kind, dataset_kind, event EntityChangeKind, …) are unaffected.

Consequences

  • The rename is breaking across the document format, the query wire, migration SQL, the truth-log subject strings, and the provisional TS client. It was executed clean-slate (spec R9): no persisted universe or database was preserved, so no serde aliases, dual-read, or in-place data migration exist — dev environments drop and reinstall.
  • The six repo reality packages were migrated to the new format in the same slice, and a new validate() guard rejects a declaration-free document (the failure mode where an old-format document deserializes silently-empty because every section is #[serde(default)]).
  • Two closed “kind” vocabularies remain by design, but they no longer collide in naming: the value-kind constructor layer (kernel-owned, nine shapes) and the ambient record categories. The entity sense is gone.
  • A follow-on ADR completes the constructor-layer rename to value_kind and introduces the value-type layer; until then, “kind constructor” in canon still reads as Kind* in code — a known, scheduled inconsistency.