Unit ID: ontology-semantic-versioning
Status: Proposed, awaiting human review before implementation
Trigger: human request, 2026-09-25
Sketch: ontology-semantic-versioning.md
Status record: ontology-semantic-versioning.md
ADR: ADR-A86, Proposed
Every owl:Ontology document under ontology/ carries an ungoverned
owl:versionIRI, or none, with no documented rule for when it changes. This
unit adopts SemVer 2.0.0 for ontology documents (ADR-A86), documents the
MAJOR/MINOR/PATCH classification for a human or agentic contributor to apply,
resets every in-scope document to one common baseline, and adds a narrow
mechanical check that a version literal actually moved when content did. It
does not build an automatic change-classifier, does not touch shapes/*.ttl
or projection/*.ttl versioning independence, and does not change what any
layer’s ontology says.
ADR-A86
(Proposed) records: SemVer 2.0.0 per owl:Ontology document; spec/*.ttl and
vocab/*.ttl remain independently versioned; the PATCH/MINOR/MAJOR mapping
table; import-pinning retained as-is with a same-change cascade obligation;
the 0.2.0 baseline reset target; and the versionIRI base-URI normalisation
bundled into that same reset. No implementation slice below starts until this
ADR, the mapping table, the versioning unit, and the baseline number are
confirmed at ratification.
docs/architecture/decisions/README.md index updated with the A-86 row.docs/developer/INDEX.md updated with this unit’s entry, in the same shape
as the vocabulary-temporal-binding entry it sits alongside.docs/traceability/matrix.csv for ADR-A86 and
each invariant in the sketch, once slices are numbered against test/check
IDs (Slice 4 introduces the first checkable one).docs/architecture/ontology-versioning-policy.md:
vocabulary-temporal-binding’s MINOR addition,
and a worked hypothetical MAJOR narrowing) kept as illustrations.owl:Ontology document; how
shapes//projection/ changes map onto that).grep -rl
"owl:imports.*<layer-namespace>" ontology/ (or the literal pattern each
layer’s README already uses) to enumerate every importer, and update all
of them, plus their README turtle-spec sources, in the same change.turtle-spec block; tools/literate_extract.py propagates
it to spec/*.ttl/vocab/*.ttl — never hand-edit the generated file’s
owl:versionIRI independently of its README source) versus the
directly-authored layers (Persistence, Surface, MORK, SPC, applied
ontologies), where the generated file is the source.CONTRIBUTING.md “Where new content belongs” gains a short cross-reference
to the new policy document, next to the existing vocab/ boundary note.docs/architecture/ontology-architecture.md §2 (“Namespace convention”)
gains a one-paragraph cross-reference to the new policy document; no other
content in that file changes as part of this unit.A single mechanical pass across every document the sketch’s inventory table names:
Mork.ttl and spc.ttl their first owl:versionIRI.applied/insurance/contract.ttl’s owl:versionIRI 0.1.1 and
owl:versionInfo "3.5.1" into one signal (the ADR’s recommendation:
owl:versionIRI is authoritative; owl:versionInfo, if kept at all, states
the same value as a human-readable label, never a second number).
Confirm at ratification whether owl:versionInfo is dropped or kept.owl:versionIRI base URI for every core layer currently
missing the lattice/ segment (Foundation, Vocabulary, Quantification,
Party, Eligibility, Instrument, Behaviour, Surface — both spec and
vocab artefacts) to https://www.nebularis.org/neuro-semantic/lattice/<layer>/<version>
(and the equivalent <layer>-vocab pattern, base corrected the same way).
Leave applied/insurance/contract.ttl’s distinct namespace family alone
pending the open question in the sketch.0.2.0 (pending
ratification of that number).turtle-spec block and regenerate via tools/literate_extract.py, not by
hand-editing spec/*.ttl/vocab/*.ttl directly — the existing README⇄spec
drift check depends on that discipline holding.owl:imports statement (README source and generated file
alike) that names one of the bumped IRIs by its old version, in the same
change — enumerate with the checklist from deliverable 2 before starting,
not after.tools/repository_topology_check.py)
that, given a base ref and the working tree, flags any in-scope .ttl file
whose triples differ from the base ref but whose owl:versionIRI literal
is unchanged. Wired as mise run check:ontology-versioning (or folded into
topology:links/topology:preflight if that proves the better home —
confirm at Slice 4 planning, not before).| Slice | Scope | Test level | Gate | Status |
|---|---|---|---|---|
| 1 | ADR-A86, sketch, plan, status record, ADR-index and INDEX.md entries | L0 | Human review of the mapping table, versioning unit, and 0.2.0 baseline number |
Done |
| 2 | ontology-versioning-policy.md, CONTRIBUTING.md and ontology-architecture.md §2 cross-references |
L0 | mise run topology:links finds no broken cross-reference; a second reader can classify a change using only the new document |
Done |
| 3 | Baseline reset (version numbers, base-URI normalisation, owl:imports cascade, per-layer changelog notes) |
L0, L3 | Every affected README’s turtle-spec block still extracts cleanly (tools/literate_extract.py --check); every owl:imports target IRI resolves to a document that exists in the tree; reuse lint still passes |
Done, with one recorded deviation (see status record) |
| 4 | The “changed but not bumped” check, wired into mise |
L0 | The check fires against a fixture with content changed and version literal held constant, and stays silent against a fixture with both changed together (mutation probe) | Done |
Slice 3 touched every file the sketch’s inventory named plus one additional
reference-implementation constant (tools/surface/src/surface/namespaces.py)
discovered while enumerating importers. See the
status record for the full
account, including the one place this slice deviated from the plan’s literal
text (it did not run tools/literate_extract.py in write mode, because doing
so would have overwritten large amounts of unrelated, already-drifted content
that predates this unit).
The single command, once Slice 4 lands:
mise run check:ontology-versioning
Until then, Slices 1–3 validate via mise run topology:links, tools/literate_extract.py --check
(run per affected layer), and reuse lint, all of which already exist.
owl:imports
pinning (flagged in the ADR as a live open question, not decided here).owl:Ontology/owl:versionIRI identity for shapes/*.ttl or
projection/*.ttl.applied/insurance/contract.ttl’s namespace family — resetting its version
number and reconciling its two version signals, yes; moving it into the
lattice/ namespace tree, not decided here.docs/architecture/solution-design-specification.md, docs/GOVERNANCE.md,
the root README.md, and GENAI_CONTRIBUTION.md were checked and contain no
ontology-version-specific mechanism this unit must synchronise. This remains
an explicit assumption for human review, not a claim the files are
permanently out of scope.