dev.idiolect.vocab

A community-published vocabulary. Two compatible shapes are supported:

  1. The legacy single-relation tree (actions + top + world), where every entry declares its direct subsumers and the world pins the inference discipline.
  2. The typed multi-relation knowledge graph (nodes + edges), where every node is first-class and edges carry a relation slug.

Authors choose either. Consumers normalize the legacy tree to the graph form at access time by lifting each actionEntry to a node and each parents entry to a subsumed_by edge. New vocabularies should prefer the graph shape; the tree stays valid for backward compatibility and remains the right shape for pure subsumption hierarchies.

The graph shape is modelled after pub.chive.graph.{node,edge}, so cross-vocabulary translation, SKOS-style broader_than/narrower_than mappings, and external-id alignment (Wikidata, ROR, ORCID, ...) are first-class.

Source: lexicons/dev/idiolect/vocab.json · Rust: idiolect_records::Vocab · TS: @idiolect-dev/schema/vocab · Fixture: idiolect_records::examples::vocab

Top-level shape

FieldTypeRequiredNotes
namestring (≤128)yesHuman-readable name.
descriptionstring (≤4000 graphemes)noNarrative description.
worldenumyesclosed-with-default / open / hierarchy-closed. Default subsumption discipline.
defaultRelationat-urinoPointer to the relation-kind node consumers should treat as canonical when no relation is specified.
topstring (≤256)noIdentifier of the vocabulary's top action under subsumed_by. Required when actions is populated and world=closed-with-default.
actionsarray (≤4096) of actionEntrynoLegacy tree shape.
nodesarray (≤4096) of vocabNodenoGraph shape.
edgesarray (≤16384) of vocabEdgenoGraph shape.
supersedesat-urinoPrior vocabulary this one replaces.
occurredAtdatetimeyesPublication timestamp.

The world discipline

A closed-enum field naming how undeclared identifiers are treated:

SlugBehavior
closed-with-defaultEvery undeclared id is subsumed by top and nothing else. The natural default for hierarchical taxonomies.
openUndeclared ids are incomparable to every declared id. Right when the vocab is one community's view of an open-ended space.
hierarchy-closedOnly the declared edges exist. Strictest; appropriate when the vocabulary is a closed enumeration.

The slug is closed enum: it is meta-policy on the inference engine, not a domain term, so extending it would change runtime semantics. Per-relation overrides live on the relation node's metadata.

The actionEntry (legacy tree)

FieldTypeRequiredNotes
idstring (≤256)yesStable action identifier.
parentsarray of stringsyesDirect subsumers. Empty for top.
classstring (≤256)noIdentifier of the attitudinal composition this action instances.
descriptionstring (≤500 graphemes)noOptional human-readable description.

The vocabNode (graph form)

FieldTypeRequiredNotes
idstring (≤256)yesStable slug. Used as edge endpoint.
kindopen enumnoconcept / relation / instance / type / collection.
kindVocabvocabRefnoVocab the kind slug resolves against.
subkindUriat-urinoPointer to another node typing this node's subkind.
labelstring (≤500)noPrimary human-readable label (SKOS prefLabel).
alternateLabelsarray (≤50)noSKOS altLabel.
hiddenLabelsarray (≤50)noSKOS hiddenLabel: searchable, not displayed.
descriptionstring (≤2000 graphemes)noSKOS definition.
scopeNotestring (≤2000 graphemes)noSKOS scopeNote: usage guidance.
examplestring (≤2000 graphemes)noSKOS example.
historyNotestring (≤2000 graphemes)noSKOS historyNote.
editorialNotestring (≤2000 graphemes)noSKOS editorialNote.
changeNotestring (≤2000 graphemes)noSKOS changeNote.
notationstring (≤500)noSKOS notation: non-text identifier.
externalIdsarray (≤20) of externalIdnoMappings to external knowledge bases.
statusopen enumnoproposed / active / deprecated.
relationMetadatarelationMetadatanoOWL Lite property characteristics. Required for kind: relation.

vocabNode.kind

SlugMeaning
conceptA SKOS concept; the typical case.
relationThis node represents a relation type. Edges with this slug reference this node.
instanceAn individual; a specific entity.
typeA metaclass; a type-of-types.
collectionA SKOS Collection. Members linked via member_of edges.

The vocabEdge

FieldTypeRequiredNotes
sourcestringyesSource node id.
targetstringyesTarget node id.
relationSlugstringyesRelation slug. References a relation-kind node.
metadataunknownnoEdge metadata, free-form.

OWL Lite property characteristics

A relation-kind node carries metadata declaring algebraic properties:

PropertyMeaning
symmetric
asymmetric
transitive
reflexive for all in scope
irreflexive for all in scope
functional
inverseFunctional
inverseOfPointer to the inverse relation node.
worldPer-relation override of the vocabulary-level world.

Contradictions (symmetric+asymmetric, reflexive+irreflexive) are caught at validation time. Functional / inverse-functional violations are caught at edge-walk time. VocabGraph::validate walks the asserted edges and emits one violation per inconsistency.

SKOS Core annotations

The full annotation set on every concept node:

FieldSKOS counterpart
labelprefLabel
alternateLabelsaltLabel
hiddenLabelshiddenLabel
descriptiondefinition
scopeNotescopeNote
exampleexample
historyNotehistoryNote
editorialNoteeditorialNote
changeNotechangeNote
notationnotation
externalIds[]exactMatch / closeMatch / broadMatch / narrowMatch / relatedMatch

External-id mappings

Each externalId carries:

SubfieldTypeNotes
systemstringKnowledge-base identifier (wikidata, ror, orcid, lcsh, ...).
idstringIdentifier in that system.
matchenumexact / close / broader / narrower / related.

External ids enable cross-system translation. A consumer holding two vocabs with wikidata:Q4116214 external ids can match the nodes across the vocabs even when the slugs differ.

Backward compatibility

The lifting from tree to graph form is mechanical:

Tree elementGraph element
actionEntryvocabNode { id, kind: "concept" }
Each parent in actionEntry.parentsvocabEdge { source = entry.id, target = parent, relationSlug: "subsumed_by" }
actionEntry.class (when present)vocabEdge { source = entry.id, target = class, relationSlug: "instance_of" }
topThe unique node with no outbound subsumed_by edge.

A vocab record with both actions and nodes/edges populated is interpreted as the union after lifting. This is the transition shape; new vocabularies should prefer pure graph form.

Example (graph form)

{
  "$type": "dev.idiolect.vocab",
  "name": "vote-stances",
  "description": "Default deliberation vote stances.",
  "world": "open",
  "nodes": [
    { "id": "agree",    "kind": "concept", "label": "Agree" },
    { "id": "disagree", "kind": "concept", "label": "Disagree" },
    { "id": "pass",     "kind": "concept", "label": "Pass" },
    { "id": "polar_opposite_of",
      "kind": "relation",
      "label": "Polar opposite of",
      "relationMetadata": { "symmetric": true, "irreflexive": true }
    }
  ],
  "edges": [
    { "source": "agree",
      "target": "disagree",
      "relationSlug": "polar_opposite_of" }
  ],
  "occurredAt": "2026-04-19T00:00:00.000Z"
}

Concept references