Introduction

This document defines some basic relations and types, to be used in ddot.it. Ddot.it itself is relation agnostic and can be used with any relations, including those defined in RDF.

There are only two built-in relations, representing syntax shortcuts from the parsing layer: Relation text (for text annotating a triple, after the ,, marker) and Relation links to / is linked from (the default relation for the untyped link shortcut ....).

Monotonicity

Ddot.it is a monotonic modelling language, and the relations defined here preserve that.

Monotonic means: adding a statement can never invalidate a conclusion already drawn. Whatever a reasoner infers from a set of triples it still infers after more triples arrive; inference only ever adds, it never retracts. The formal statement is that if a knowledge base entails some fact, then every superset of that knowledge base entails it too.

This follows from the language being positive: there is no way to write a negation, so no statement can contradict another. A monotonic language cannot produce contradictions — the worst that can happen is that it infers something you consider wrong, which is a modelling error, not a logical one.

The practical payoff: triples from different files, authors and tools can simply be merged. No statement can invalidate another, so there is no ordering, no precedence and no conflict resolution to define. Every relation in this document is designed to keep that guarantee — see for instance how cycles in has subtype collapse into same as instead of being an error.

RDFS, OWL and CDS are monotonic in the same way. Languages with negation, defaults or a closed-world assumption are not: there, a later statement can withdraw an earlier conclusion.

Syntax

  • In this document, foo, bar and baz are variables.

  • We use this syntax to present some triples above the line as Given from which we deduce the Inferred triple below the line.

    Given / Inferred
    ... given triples here ...
    ___________________________________
    ... inferred triples here
  • Self-Referential: To make ddot.it self-sufficient, the relations in this document are defined using the relations in this document. This is common practice.

Declaration Conventions

Every built-in in this document is declared with the same shape, so that a tool can load the vocabulary without special-casing:

  1. Canonical names are spelled out. A built-in block always uses the canonical relation name (has alias, not alias; same as, not is same as). Alternative spellings appear only as ..has alias.. values.

  2. Both sides of a pair are declared. A relation and its inverse each get their own block with their own has type, has supertype, has inverse and uri.

  3. Hierarchies point upwards only. A built-in block states has supertype, never has subtype; each entry names its parent, so the full tree is the union of those edges. Only the three roots — entity for types, related and has property for relations — state no has supertype at all.

  4. Symmetric relations are their own inverse. For a relation of type symmetric relation the has inverse triple is implied and therefore not stated.

  5. Every built-in has a uri in the ddot.it namespace (see Relation prefix).

  6. This document is authoritative; the .ddot file is derived. ddot-it-vocabulary.ddot next to this file is the machine-readable twin of the built-in blocks below. It is generated from this document, never edited by hand, and CI asserts the two agree:

    ./check-vocabulary.sh            # verify; non-zero exit on mismatch
    ./check-vocabulary.sh --update   # accept the current output as the new baseline

    So a built-in is changed here, and the .ddot file is regenerated. If the two ever disagree, this document wins and the .ddot file is stale.

  7. Only built-ins are machine-readable. The document turns ddot.it parsing off immediately below the title block with an https://ddot.it/off command, and each built-in block switches it back on with https://ddot.it/on and off again straight after. Everything else — prose, link: macros, the Given / Inferred rules, the Example blocks and the CDS migration table — is therefore never parsed. Indexing this file with a ddot.it tool yields exactly the built-in triples and nothing else:

    ddot index -f vocabulary.ddot --ext adoc site/spec/

    The commands are written inside AsciiDoc comments (// https://ddot.it/off), so they steer the parser without showing up in the rendered document. This relies on two properties, both now guaranteed by the Parse Specification: pre-parse commands are recognised anywhere on a line, so the leading // does not hide them; and the reader is a plain ddot.it parser working on the raw file, which is what the ddot index invocation above uses. A host-aware AsciiDoc parser that discarded comment lines would lose this steering, which is why such parsers SHOULD preserve pre-parse commands found in host comments.

Top-Level Types

We can use Relation has type / has instance to assign subjects a type. Additionally, we can use Relation has subtype / has supertype to define type hierarchies. So what are the root / top-most elements in the ddot.it type hierarchy?

Diagram
Figure 1. Top-Level Types, to be used with has type

Type entity

The absolute root type. Everything in ddot.it is an Relation has instance or Relation has subtype / has supertype of this type.

Built-in
entity ..has type.. entity
..has type.. type
..uri.. https://ddot.it/vocabulary/2026-07-20#entity

entity has no supertype — it is the root. Its subtypes thing and value state the edge from their side, see below.

It carries two types, and both are wanted. entity ..has type.. type says the same thing thing, value and type say about themselves: it is a type, usable as the object of a Relation has type / has instance. entity ..has type.. entity says it is also an instance of itself, which follows from being the root — everything, types included, is an entity. Neither triple contradicts the other; in a monotonic language they simply both hold.

Types thing and value

Motivation

Ddot.it has only one datatype: string. So it cannot distinguish between, let’s say 42 being the age of someone or it being the identifier for a chemical compound. Everything is just an Type entity.

Type thing

We define thing to be all entities that are object-like, physical or imaginary concepts that can be named. In RDF, these are URIs or Blank Nodes.

Built-in
thing ..has type.. type
..has supertype.. entity
..uri.. https://ddot.it/vocabulary/2026-07-20#thing
Type value

We define value to be all entities that have no identity on their own. These are merely used to describe other entities. In RDF, these are the Literals.

Built-in
value ..has type.. type
..has supertype.. entity
..uri.. https://ddot.it/vocabulary/2026-07-20#value

Types type and relation

Type type

The "mother of all types" is the type type — the super-type of all types. It is its own type.

Built-in
type ..has type.. type
..has supertype.. thing
..uri.. https://ddot.it/vocabulary/2026-07-20#type
Type relation

All relations have the type relation.

Built-in
relation ..has type.. type
..has supertype.. type
..uri.. https://ddot.it/vocabulary/2026-07-20#relation

Linking with Mathematical Relations

Some relations have mathematical properties that let a reasoner infer further triples. Ddot.it models these properties as types of relations, so they are stated with the ordinary has type relation.

Type symmetric relation

The type symmetric relation is the type of all mathematically symmetric relations.

Given / Inferred
aaa ..fooRel.. bbb
fooRel ..has type.. symmetric relation
___________________________________
bbb ..fooRel.. aaa
Built-in
symmetric relation ..has type.. type
..has supertype.. relation
..uri.. https://ddot.it/vocabulary/2026-07-20#symmetric-relation

Type transitive relation

The type transitive relation is the type of all mathematically transitive relations.

Given / Inferred
aaa ..fooRel.. bbb
bbb ..fooRel.. ccc
fooRel ..has type.. transitive relation
___________________________________
aaa ..fooRel.. ccc
Built-in
transitive relation ..has type.. type
..has supertype.. relation
..uri.. https://ddot.it/vocabulary/2026-07-20#transitive-relation

Usage in Formal Systems and Inference

For formal systems, such as rule and inference engines, a crucial question is: Are these two entities the same or different logical entities? To make using ddot.it easier, many relations define aliases that are alternative names denoting the same concept.

Relation has inverse

Motivation

Often relations form natural pairs, depending on their direction. A Person works for a Company. In the other direction, a Company employs a Person. So works for and employs express the same fact, but stated from a different perspective. For many use cases, the distinction should be ignored. Like in OWL, ddot.it allows to explicitly state the inverse relation of a relation.

Given / Inferred
a ..ppp.. b
ppp ..has inverse.. qqq
_____________________________________
b ..qqq.. a
ppp ..has type.. relation
qqq ..has type.. relation
Built-in
has inverse ..has type.. relation
..has type.. symmetric relation
..has supertype.. related
..uri.. https://ddot.it/vocabulary/2026-07-20#has-inverse

Syntax for Inverse Relations On The Fly

Given any relation foo, you can use ^foo to state a triple like "the other way round". Formally, the ^ syntax only works as the first character in a relation name. It’s the same character used by the SPARQL query language for the same effect.

Given / Inferred
a ..^foo.. b
_____________________________________
b ..foo.. a
foo ..has type.. relation
^foo ..has type.. relation
foo ..has inverse.. ^foo
^foo ..has inverse.. foo

And you can always give ^foo a better Relation label.

Spec

^ does not nest. Only the first character is the operator; everything after it is the relation name, taken literally. So ^^foo is not a double inverse — it is a relation whose name happens to be ^foo, i.e. the inverse of the relation named ^foo. There is no cancellation rule and no ^foo. If you want the forward relation, write foo.

^ binds the whole name, prefix included. ^foaf:knows is the inverse of the relation foaf:knows; the ^ is not part of, and does not interact with, the prefix mechanism. It is never written foaf:^knows.

Relation has type / has instance

Relation has type

aaa ..has type.. Caraaa is an instance of the type Car. The inverse is has instance; the supertype is has tag, because typing is a refinement of tagging.

has type ..has type.. relation
..has supertype.. has tag
..has inverse.. has instance
..uri.. https://ddot.it/vocabulary/2026-07-20#has-type
..has alias.. hasType
The a shortcut

In N3 (and other RDF syntaxes), the built-in a expresses typing, e.g. (ex:Berlin, a, ex:City). To keep ddot.it self-documenting, the canonical name is has type, so we write Berlin ..has type.. City. But typing with just a is convenient, so a is declared to be replaced by has type: an editor may substitute the one for the other, and a reasoner treats both as the same relation.

Built-in
a ..is replaced by.. has type
Relation has instance

The inverse of has type: Car ..has instance.. aaa whenever aaa ..has type.. Car.

Typing is a refinement of tagging: has instance is a subtype of is tag of. So aaa ..has type.. Car implies aaa ..has tag.. Car, which lets type-browsing and tag-browsing share one user interface.

has instance ..has type.. relation
..has supertype.. is tag of
..has inverse.. has type
..uri.. https://ddot.it/vocabulary/2026-07-20#has-instance
..has alias.. hasInstance

Relation has subtype / has supertype

Relation has subtype

Types assigned with has type are inherited along this relation. The inverse is has supertype.

Example

The type Vehicle has the more specialised type Car: Vehicle ..has subtype.. Car.

aaa ..has type.. Car
Vehicle ..has subtype.. Car

infers

aaa ..has type.. Vehicle

So if we know something is a Car, then it also must be a Vehicle. It does not work the other way round.

has subtype ..has type.. relation
..has type.. transitive relation
..has supertype.. has detail
..has inverse.. has supertype
..uri.. https://ddot.it/vocabulary/2026-07-20#has-subtype
..has alias.. subtype
Relation has supertype
has supertype ..has type.. relation
..has type.. transitive relation
..has supertype.. has context
..has inverse.. has subtype
..uri.. https://ddot.it/vocabulary/2026-07-20#has-supertype
..has alias.. supertype
Which one do I write?

has type and has subtype are deliberately not the same relation, and the difference is member-versus-set:

Write When Example

has type

the subject is one thing that belongs to a category

myCar ..has type.. Car

has subtype

the subject is a category of things

Vehicle ..has subtype.. Car

It is tempting to merge them, since one transitive relation would give inheritance for free — myCar isa Car, Car isa Vehicle, done. Three things are lost by doing so, and they are why ddot.it keeps both:

  1. Member and set stay distinguishable. Merged, Sportscar and myCar would sit under Car identically, and "how many cars are there" would stop having an answer.

  2. RDF round-trips. has type maps to rdf:type and has subtype to rdfs:subClassOf; these are distinct in RDF, and the CDS & Standards Alignment maps to RDFS, OWL, SKOS and WordNet throughout.

  3. Membership stays non-transitive. A member of a set is not a member of that set’s members. has subtype is transitive; has type is not.

What ddot.it does not require is a strict separation of class and instance: an entity may carry both, and several built-ins do (see entity, which is both a type and an instance of itself). Punning is allowed; merging the two relations is not.

Cycles

If has subtype forms a cycle, all participants of the cycle are considered to be the same entity (same as). This is exactly what the RDFS specification also states. This is the logicians' solution to "nothing is forbidden".

A linter should show such cycles, as they are rarely intentional.

Top-Level Relations

The relation hierarchy has two roots, because ddot.it relations do two different jobs:

related

connects a thing to a thing. Both ends have an identity of their own, so the link is worth following in either direction.

has property

attaches a value to a thing. The value end has no identity of its own; it merely describes the thing.

Every other relation in this document is a subtype of one of these two.

Each root is paired with a type that marks which family a relation belongs to — relation and property respectively (see A type and a relation, in parallel with relation / related). The root is the relation you inherit from; the type is what you are.

Diagram
Figure 2. Overview
Reading the diagram
  • Each box holds a relation and its inverse as forward / inverse. The upper name is a has subtype of its parent’s upper name; the lower name likewise on the inverse side. So one arrow A <|-- B states both B.forward has supertype A.forward and B.inverse has supertype A.inverse.

  • The symmetric relations (related, has similar, same as) are their own inverse, so they carry a single name.

  • has property is the second root and carries a single name for the opposite reason: its inverse exists but is not worth naming — see A type and a relation, in parallel with relation / related.

  • An arrow A <|-- B means: a statement using B also holds for A (via relation inheritance).

  • «symmetric» and «transitive» mark relations of that type; on a pair, the marker applies to both directions.

  • Typing (has instance / has type) is deliberately a refinement of tagging, which is itself a refinement of annotation. This mirrors Fig. 4.5 of the source thesis (see Relation has instance).

  • has subtype / has supertype refine has detail / has context: a subtype is a special kind of detail. The type hierarchy they build is shown in Top-Level Types.

An undirected link connecting foo and bar, with no further claim about how they are related. The weakest link ddot.it offers. The root of all relations between things.

related ..has type.. relation
..has type.. symmetric relation
..uri.. https://ddot.it/vocabulary/2026-07-20#related
..has alias.. is related to
..has alias.. hasRelated

Relation property

foo ..property.. barbar is a value that describes foo. The weakest such statement ddot.it offers, and the root of all value-carrying relations.

Because the object is a value, stating a property also tells us what kind of entity sits on each end — this is how ddot.it recovers the thing / value distinction that its single string datatype cannot express:

Given / Inferred
aaa ..ppp.. vvv
ppp ..has type.. property
___________________________________
aaa ..has type.. thing
vvv ..has type.. value
No named inverse

property and its subtypes deliberately have no has inverse. The inverse direction is well defined — "which entities carry this value?" — but the value end is not an entity you navigate from, so naming a relation for it would only invite people to model values as things.

Where the inverse is genuinely needed, the ^ syntax supplies it without a name: ^property, ^label, ^grade always exist and can be given a Relation label locally.

A type and a relation, in parallel with relation / related

The value-carrying family is described by two built-ins, exactly mirroring how the thing-to-thing family works:

Family Top-level relation Type

between things

related

relation

value-carrying

has property

property

property is a type: it marks a relation as one that attaches a value. has property is the relation at the root of that family, the one every value-carrying relation has as its supertype. Writing label ..has type.. property says what kind of relation label is; writing label ..has supertype.. has property places it in the relation hierarchy. Both are declared, just as has subtype declares both ..has type.. transitive relation and ..has supertype.. has detail.

Type property
property ..has type.. type
..has supertype.. relation
..uri.. https://ddot.it/vocabulary/2026-07-20#property
Relation has property
has property ..has type.. relation
..has type.. property
..uri.. https://ddot.it/vocabulary/2026-07-20#has-property
..has alias.. hasProperty
A identifying relation is always a subtype of property: it carries a value that happens to pin down its subject. This is declared, as identifying relation ..has supertype.. property in its built-in block — and both ends are now types, so the edge sits wholly inside the type hierarchy.
Diagram
Figure 3. The built-in properties

label and text are defined under Content Management Relations, uri and prefix under Linking with the Semantic Web, the remaining six under Provenance.

Identity: Same or Different?

Some core relations.

Relation has similar

foo and bar are similar, without any claim that they are the same. Weaker than same as, stronger than related.

has similar ..has type.. relation
..has type.. symmetric relation
..has supertype.. related
..uri.. https://ddot.it/vocabulary/2026-07-20#has-similar
..has alias.. is similar to
..has alias.. hasSimilar

has similar is symmetric but not transitive. From a ..has similar.. b and b ..has similar.. c nothing follows about a and c. That is what makes it the safe target for importing fuzzy links such as skos:closeMatch or WordNet’s similar to — see the alignment tables.

Relation same as

foo and bar refer to the same concept. Neither one is the main name — compare is alias of, which does distinguish.

same as ..has type.. relation
..has type.. symmetric relation
..has type.. transitive relation
..has supertype.. has similar
..uri.. https://ddot.it/vocabulary/2026-07-20#same-as
..has alias.. is same as

Relation has alias / is alias of

Relation has alias

bar ..has alias.. foofoo is an alternative name for bar, which stays the main one.

has alias ..has type.. relation
..has supertype.. has similar
..has inverse.. is alias of
..uri.. https://ddot.it/vocabulary/2026-07-20#has-alias
..has alias.. alias
Relation is alias of

Like same as, but with a clear main concept: foo is the alternative name, bar is the one to keep. This is like a sym-link.

The inverse is has alias.

is alias of ..has type.. relation
..has supertype.. has similar
..has inverse.. has alias
..uri.. https://ddot.it/vocabulary/2026-07-20#is-alias-of

Relations is replaced by / replaces

foo ..replaces.. barfoo supersedes bar. Both remain distinct entities; use same as if they are in fact the same thing.

Usage in Interactive Tools (Editors)

In an editor, when a user types a string aaa marked as aaa ..is replaced by.. bbb, the editor should replace aaa directly with bbb. This is how the a shortcut for has type is defined.

is replaced by ..has type.. relation
..has supertype.. has similar
..has inverse.. replaces
..uri.. https://ddot.it/vocabulary/2026-07-20#is-replaced-by
..has alias.. replacedBy
..has type.. transitive relation

replaces ..has type.. relation
..has supertype.. has similar
..has inverse.. is replaced by
..uri.. https://ddot.it/vocabulary/2026-07-20#replaces
..has type.. transitive relation

Type identifier and Relation identifying relation

Type identifier

We define identifier to be a subtype of Type value, used in a relation of type Type identifying relation.

Built-in
identifier ..has type.. type
..has supertype.. value
..uri.. https://ddot.it/vocabulary/2026-07-20#identifier
Type identifying relation

An identifying relation carries a value, which uniquely identifies subjects.

Given / Inferred
a ..rel.. q
b ..rel.. q
rel ..has type.. identifying relation
_____________________________________
a ..same as.. b
q ..has type.. identifier
a ..has type.. thing
b ..has type.. thing
Built-in
identifying relation ..has type.. type
..has supertype.. relation
..has supertype.. property
..uri.. https://ddot.it/vocabulary/2026-07-20#identifying-relation

Order

Relations has next / has previous

Relations has next

A sequence. foo ..has next.. bar places foo earlier than bar. Both directions are transitive, so a chain of steps yields the full ordering.

has next ..has type.. relation
..has type.. transitive relation
..has supertype.. links to
..has inverse.. has previous
..uri.. https://ddot.it/vocabulary/2026-07-20#has-next
..has alias.. has after
..has alias.. hasAfter
Relation has previous
has previous ..has type.. relation
..has type.. transitive relation
..has supertype.. is linked from
..has inverse.. has next
..uri.. https://ddot.it/vocabulary/2026-07-20#has-previous
..has alias.. has prev
..has alias.. has before
..has alias.. hasBefore

Linking

Linking, like in hyper-text, is the most basic way of a directed relation in ddot.it.

This relation is also one of the relations built into ddot.it parsing. It is used as the implicit relation of an untyped link, written …​. or .. ...

If the empty relation shortcut is used as in

  • s....o (no space) or its variant

  • s.. ..o (with spaces),

    then there is no relation name given. Emitters omit the relation (the event’s type field) for such untyped links; consumers default a missing relation to links to (see Triple Events).

links to ..has type.. relation
..has supertype.. related
..has inverse.. is linked from
..uri.. https://ddot.it/vocabulary/2026-07-20#links-to
..has alias.. has target
..has alias.. hasTarget
..has alias.. ^is linked from
Relation is linked from

The inverse of links to. Its alias has source is the name used in CDS.

is linked from ..has type.. relation
..has supertype.. related
..has inverse.. links to
..uri.. https://ddot.it/vocabulary/2026-07-20#is-linked-from
..has alias.. has source
..has alias.. hasSource
..has alias.. ^links to

See also parsing.

Hierarchies

Relations has detail and has context

foo ..has detail.. barbar elaborates or refines foo. Read the other way, foo is the context in which bar makes sense.

Built-in
has detail ..has type.. relation
..has supertype.. links to
..has inverse.. has context
..uri.. https://ddot.it/vocabulary/2026-07-20#has-detail
..has alias.. hasDetail

has context ..has type.. relation
..has supertype.. is linked from
..has inverse.. has detail
..uri.. https://ddot.it/vocabulary/2026-07-20#has-context
..has alias.. hasContext

The relations has detail/has context are not transitive, unlike has part below, which is a more specific relation. A detail of a detail is not automatically a detail of the whole.

Relations has part and is part of

foo ..has part.. barbar is a component of foo. Both directions are transitive: a part of a part is a part of the whole.

has part ..has type.. relation
..has type.. transitive relation
..has supertype.. has detail
..has inverse.. is part of
..uri.. https://ddot.it/vocabulary/2026-07-20#has-part
..has alias.. hasPart

is part of ..has type.. relation
..has type.. transitive relation
..has supertype.. has context
..has inverse.. has part
..uri.. https://ddot.it/vocabulary/2026-07-20#is-part-of
..has alias.. isPartOf
Tags propagate to parts

A tag on a whole applies to each of its parts:

Given / Inferred
aaaPart ..is part of.. bbbWhole
bbbWhole ..has tag.. cccTag
___________________________________
aaaPart ..has tag.. cccTag
Example
Engine ..is part of.. Car
Car ..has tag.. mechanical
__________________________
Engine ..has tag.. mechanical

Going Meta

Relations has annotation / annotates

bar ..annotates.. foobar is a remark, comment or note about foo. The annotation is a first-class entity, so it can itself be annotated, tagged or typed.

annotates ..has type.. relation
..has supertype.. links to
..has inverse.. has annotation
..uri.. https://ddot.it/vocabulary/2026-07-20#annotates
..has alias.. has annotation member
..has alias.. hasAnnotationMember

has annotation ..has type.. relation
..has supertype.. is linked from
..has inverse.. annotates
..uri.. https://ddot.it/vocabulary/2026-07-20#has-annotation
..has alias.. hasAnnotation
Annotating a triple rather than an entity is what the ,, meta part is for. See parsing.

Relation has tag / is tag of

Relation has tag

foo has the tag bar. A tag is usually a single term. Sometimes multiple words are also used.

has tag ..has type.. relation
..has supertype.. has annotation
..has inverse.. is tag of
..uri.. https://ddot.it/vocabulary/2026-07-20#has-tag
..has alias.. tag

Tags are not transitive. A tag on a tag says nothing about the tagged entity.

Relation is tag of

The inverse of has tag: bar ..is tag of.. foo whenever foo ..has tag.. bar. Declared separately so that the tag side of the pair has a name and a URI of its own.

is tag of ..has type.. relation
..has supertype.. annotates
..has inverse.. has tag
..uri.. https://ddot.it/vocabulary/2026-07-20#is-tag-of
..has alias.. has tag member
..has alias.. hasTagMember

Content Management Relations

Relation label

foo ..label.. bar sets the visible label of foo to bar. The semantic layer therefore gives every node an id and a label, the latter defaulting to the id string. Tools that display the knowledge graph show the label and hide the relabelled id. Only the use as a triple relation is defined here. What a tool then does with a label — showing it in place of the id, using it for search, exporting it — belongs to higher layers, and this document says nothing about it.

label ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#label
..has alias.. has label
Why separate id from label

Splitting the two makes a graph written in one file easier to change. These two graphs have the same structure and the same displayed names:

Alice ..knows.. Bob
Bob ..knows.. Carol
a ..knows.. b
b ..knows.. c
a ..label.. Alice
b ..label.. Bob
c ..label.. Carol

The first is more ddot.it-ish and is the right default. The second is easier to maintain while the naming is still in flux: a name is corrected in one place instead of at every occurrence, and the ids stay stable, so nothing else in the graph has to be touched.

The distinction matters only in downstream tools that support labels. At graphinout.com, incoming graph data — ddot.it syntax included — is first converted to Connected JSON (CJ), which has label support, and then to the requested target format.

In previous versions of ddot.it, this was modelled as a command (!!label), documented on its own page at https://ddot.it/label. It is now an ordinary relation and is defined here; the command and its page are gone. !!label in a relation slot is still lexed as a command (command syntax is registry-free) and carries no command semantics — see corpus case 15-label.

Relation text

This relation is one of the relations built into ddot.it parsing. It carries the free text of a ,, meta that holds no triple (MetaTextInline / MetaTextBlock). Used as an ordinary relation (foo ..text.. some content) it assigns free-form content to a subject — the same relation, written explicitly rather than produced by the ,, shorthand.

When parsing meta-text, as in s..p..o,, meta-text, this is reported as the triple event meta: [{"type":"text","to":"meta-text"}]. A meta pair uses the same type/to keys as the triple event itself, and the collector keeps those keys — one key vocabulary across both layers.

text ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#text
..has alias.. has text
..has alias.. has content

Linking with the Semantic Web

Ddot.it should be compatible with semantic web / linked open data standards. The triple structure fits exactly, and even the triple-meta parts map to upcoming RDF 1.2 specs (see Primer or Spec). The "base layer" of these standards, The Resource Description Framework (RDF), mandates that resource identifiers are URIs. For that reason, we give every ddot.it relation a URI via ddot.it uri.

Relation uri

Built-in
uri ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#uri

If an entity has several URIs, all of them denote the same entity.

Relation prefix

Built-in
prefix ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#prefix

Additionally, because URIs are visually quite ugly and have a repetitive part, it’s common practice in most syntaxes to abbreviate the reoccurring URI prefix. Ddot.it does the same.

Effect
  • For any string starting with a sequence foo:bar in

    • subject (foo:bar ..y.. z)

    • relation (x ..foo:bar.. z), or

    • object (x ..y.. foo:bar),

  • where we also have the triple foo .. prefix .. baz,

  • we infer a similar string with the prefix resolved into its namespace

    • subject (bazbar ..y.. z)

    • relation (x ..bazbar.. z), or

    • object (x ..y.. bazbar).

In practice, baz is usually something like https://example.com/ns/v3/.

The ddot.it Namespace

We also state as a built-in:

Built-in
ddot ..prefix.. https://ddot.it/vocabulary/2026-07-20#

Provenance

In this section we define some common relations to be used in the meta part of a triple (after the ,, marker). All of them take a value as object; all dates and times are ISO 8601 strings.

Relation source uri

The file or web resource a triple was collected from — maybe only for debugging, maybe always. The URI should name the source file and should locate the source lines in the # fragment, e.g. file:///home/me/notes.adoc#L12-L14.

source uri ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#source-uri
..has alias.. sourceUri

Relation collected

When the triple was collected, as an ISO 8601 date-time.

collected ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#collected
..has alias.. collected at

Relations valid since / valid until

valid since is the date from which the triple holds — a kind of "first collected". valid until is the date after which it no longer holds; if it is missing, the triple is still valid.

valid since ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#valid-since
..has alias.. validSince

valid until ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#valid-until
..has alias.. validUntil

Relation last modified

When the source document was last changed. Used on the source, not on the triple:

Example
notes.adoc ..has type.. source
..last modified.. 2026-10-09T09:13:59
Built-in
last modified ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#last-modified
..has alias.. lastModified

source ..has type.. type
..has supertype.. thing
..uri.. https://ddot.it/vocabulary/2026-07-20#source

Relation grade

How much a triple can be trusted. The object is one of unreviewed, reviewed or manual.

An unreviewed triple is a tool’s guess and should be treated as disposable. A tool that re-runs its matcher is expected to drop the ..grade.. unreviewed triples it previously emitted. Never store an author’s intent as an auto-link.

Dropping those triples does not violate monotonicity. Monotonicity is a property of inference over one knowledge base state: no statement present can invalidate a conclusion drawn from the others. Regenerating a derived file is a lifecycle operation on the inputs — the tool is not retracting a conclusion, it is producing a new set of triples to reason over. The same distinction applies to editing any source file: deleting a line changes the input, not the logic.
grade ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#grade

unreviewed ..has type.. grade value
..uri.. https://ddot.it/vocabulary/2026-07-20#unreviewed
reviewed ..has type.. grade value
..uri.. https://ddot.it/vocabulary/2026-07-20#reviewed
manual ..has type.. grade value
..uri.. https://ddot.it/vocabulary/2026-07-20#manual

grade value ..has type.. type
..has supertype.. value
..uri.. https://ddot.it/vocabulary/2026-07-20#grade-value
In CDS some triple provenance was modelled by using relations. This is now superseded by using grade. The migration is as follows:
Table 1. Migration from CDS
CDS ddot.it
a ..hasManualLinkTarget.. b
a....b ,, ..grade.. manual
b ..hasManualLinkSource.. a
a....b ,, ..grade.. manual
a ..hasAutoLinkTarget.. b
a....b ,, ..grade.. unreviewed
b ..hasAutoLinkSource.. a
a....b ,, ..grade.. unreviewed

Cardinality

How many values a relation may carry. Ddot.it borrows the model from ECore, which expresses cardinality as bounds rather than as a separate construct.

Bounds are written as two separate properties[1] , each taking a plain integer:

Person ..has address.. Address ,, ..min cardinality.. 1 ;; ..max cardinality.. 3

An omitted max cardinality means unbounded. There is no * or -1 sentinel: saying nothing is how "no upper limit" is said.

Relation cardinality

For the common case where a relation carries exactly n values, cardinality sets both bounds at once.

Given / Inferred
rel ..cardinality.. nnn
___________________________________
rel ..min cardinality.. nnn
rel ..max cardinality.. nnn
Built-in
min cardinality ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#min-cardinality
..has alias.. lowerBound
max cardinality ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#max-cardinality
..has alias.. upperBound
cardinality ..has type.. relation
..has type.. property
..has supertype.. has property
..uri.. https://ddot.it/vocabulary/2026-07-20#cardinality

Types required, single valued and multi valued

Three named shorthands cover almost every practical case. They are relation types, declared the same way as symmetric relation and transitive relation, and they describe the relation itself rather than one triple that uses it.

Given / Inferred
rel ..has type.. required
___________________________________
rel ..min cardinality.. 1
Given / Inferred
rel ..has type.. single valued
___________________________________
rel ..max cardinality.. 1
Built-in
required ..has type.. type
..has supertype.. relation
..uri.. https://ddot.it/vocabulary/2026-07-20#required
single valued ..has type.. type
..has supertype.. relation
..uri.. https://ddot.it/vocabulary/2026-07-20#single-valued
multi valued ..has type.. type
..has supertype.. relation
..uri.. https://ddot.it/vocabulary/2026-07-20#multi-valued
multi valued infers nothing, and that is deliberate. Being unbounded is the default — it is what an absent max cardinality already means — and ddot.it is monotonic, with no way to state "there is no maximum" as a constraint that would forbid one being added later. multi valued is therefore documentation: it says the author considered the bound and meant it to be open. Its counterpart single valued does infer, because max cardinality 1 is a positive statement.
Table 2. The four common combinations
UML ddot.it Shorthand Meaning

0..1

..max cardinality.. 1

single valued

Optional single value

1..1

..min cardinality.. 1 ;; ..max cardinality.. 1

required + single valued

Exactly one

0..*

(nothing)

multi valued

Any number, including none

1..*

..min cardinality.. 1

required + multi valued

At least one

Summary

Type Hierarchy

The has subtype tree, rooted at entity. Each entry links to its definition.

Relation Hierarchy

The has supertype forest, mirroring the overview diagram in Top-Level Relations and Fig. 4.5 of the source thesis. There are two trees: related for relations between things, and has property for relations carrying a value. Each entry links to its definition; the inverse relation is shown in parentheses. s marks symmetric and t transitive relations.

Relations between things
Relations carrying a value

None of these has a named inverse; use ^ if you need one (see A type and a relation, in parallel with relation / related). Each also carries ..has type.. property.

Versioning

This vocabulary is versioned independently of the ddot.it syntax specification.

Version number

The title carries a semantic version (currently 1.1.0):

  • Major — a built-in was removed or its meaning narrowed, so previously valid data may now be wrong.

  • Minor — built-ins were added, or aliases and supertypes were added without invalidating existing data.

  • Patch — wording, examples and typo fixes only; no triple changed.

Namespace date

Every built-in URI lives in a dated namespace, currently https://ddot.it/vocabulary/2026-07-20# (see prefix). The date changes only on a major version, so minor and patch releases keep every existing URI resolvable. Consumers should therefore pin the namespace, not the version number.

Changes

Because a minor release only ever adds built-ins, a consumer that ignores relations it does not know stays correct across minor upgrades. The per-release list of changes is kept in the Ddot.it changelog.

This is a property of the release policy, not the same thing as the monotonicity of the language itself. Both point the same way — nothing is ever taken back — but a major release may remove a built-in, whereas monotonicity holds for every version of ddot.it.

1. Do not write a range like 1..3 as a single value. It parses where it stands, because a meta object may contain .. — but the same string used as a subject silently misparses: 1..3 ..has type.. cardinality reads as subject 1, relation 3. Two bounds avoid the trap entirely.