Skip to content

Design Decisions — The Rationale Behind Every Modelling Choice

When you build an ontology for enterprise architecture, dozens of choices have long-term consequences: OWL or JSON Schema? Validation in OWL axioms or SHACL? Punning or clean separation? Get them wrong and you inherit inference bugs, brittle tooling, and queries that silently return wrong answers.

This document captures the key modelling decisions behind Linked.Archi as numbered decision records (DD-N) — each with the decision, the rationale, and the alternatives rejected. Use it to understand why the ontologies look the way they do, or as a reference when you hit the same choices in your own metamodel.


DD-1: Metamodel as Ontology — Architecture Languages in RDF

Decision: Represent architecture metamodels using OWL ontologies and related semantic web resources rather than UML profiles, XML schemas, or custom formats.

Rationale: An architecture metamodel can be expressed as the abstract syntax of a domain-specific modelling language. A metamodel defines the language for expressing a model — it provides the types, relationships, and constraints for a modelling language within a particular domain. Representing it in RDF lets us assign each layer of the language to the formalism suited to it:

  • OWL — formal semantics for the core concepts and their logical relationships (the meta-language for defining them)
  • SKOS — controlled vocabularies and taxonomies for classifying and organizing architecture elements
  • SHACL — structural validation and governance constraints (closed-world)
  • SPARQL — standard query language for traversing the resulting graph

The result is a single integrated graph offering machine-interpretable precision, vocabulary-level interoperability, SPARQL queryability, and the ability to generate stakeholder-specific views from one source of truth.

Trade-off: Higher learning curve for teams unfamiliar with semantic web technologies. Mitigated by the minimal OWL profile (DD-2) and comprehensive documentation.


DD-2: Minimal OWL Profile with SHACL Constraints

Decision: Use only a small subset of OWL for vocabulary semantics, and delegate all closed-world constraints to SHACL.

Rationale: The most common modelling failure mode is treating OWL axioms as if they were closed-world constraints. OWL operates under the Open World Assumption — the absence of a statement does not mean it is false. SHACL provides the closed-world validation that governance requires.

What OWL handles:

  • Class and property declarations
  • Simple hierarchies (rdfs:subClassOf, rdfs:subPropertyOf)
  • Property typing (owl:ObjectProperty vs owl:DatatypeProperty)
  • Modularization (owl:imports)
  • Documentation metadata

Retained inference — a short, deliberate list where the entailment is wanted:

  • Subsumption (rdfs:subClassOf/rdfs:subPropertyOf) — relied upon by SHACL shapes (which target superclasses) and by query generalization
  • Transitivity on compositional properties (hasPart/partOf) — part-of chains resolve automatically
  • Inverse pairs (e.g. hasPart/partOf) — bidirectional traversal without asserting both triples
  • Functionality where a property is single-valued (e.g. prefVisNotation)
  • owl:sameAs — admitted only as a documented exception for confirmed cross-source identity merges (see DD-11, identity correspondence vs. merge); the default cross-source link is the non-inferential skos:exactMatch

Everything else — cardinality, disjointness, value restrictions, equivalence used as constraint — is expressed in SHACL, not OWL.

What SHACL handles:

  • Cardinalities (sh:minCount, sh:maxCount)
  • Required properties
  • Value constraints (sh:datatype, sh:class, sh:pattern, sh:in)
  • Closed shapes
  • Cross-field and conditional rules

Why not RDFS-only: Keeping minimal OWL buys property typing that tools understand (WIDOCO, WebVOWL), better documentation generation, and a smoother Protégé authoring workflow.

Clarification — Is this still an ontology, or just a schema?

Minimizing OWL raises a fair question: if constraints live in SHACL and only a thin layer of OWL remains, is the result still an ontology, or has it become a schema? The answer is that it remains an ontology, and the question conflates two separable ideas bundled under the word "ontology":

  1. Shared, explicit conceptualisation with formal identity. Concepts have globally-resolvable IRIs, explicit definitions, and a vocabulary other modules import and extend — so a bs:Component means the same thing wherever it appears. A schema (XSD, DDL, JSON Schema) defines the shape of valid documents within one system; it is local and closed, and its meaning does not travel. Linked.Archi has the former property throughout.
  2. A subsumption/classification structure with inference. The ontologies carry an is-a hierarchy over which subsumption is computed and relied upon (see the retained-inference list above). A schema has no notion of "every X is automatically a Y." Linked.Archi keeps this.
  3. Rich logical (DL) axiomatisation — restrictions, disjointness, cardinality-as-entailment, property chains. This is what the minimal profile deliberately declines.

Linked.Archi builds ontologies in senses (1) and (2) while declining most of (3). That is not "an ontology degraded into a schema" — it is a lightly-axiomatized ontology that relocates constraints rather than removing them. A schema's defining job is to constrain structure; those constraints are fully present here, expressed in SHACL — the layer designed for the closed-world validation that governance requires and that OWL's open-world axioms handle badly. (SHACL exists precisely because OWL was being misused as a schema language.)

So the division of labour is: OWL/RDFS carries meaning, identity, and classification — what ontologies are uniquely good at; SHACL carries constraint and validation — what schemas are good at. Calling the result "just a schema" mistakes the validation layer for the whole artifact. (DD-5 makes the complementary point structurally: RDFS+OWL sits at the M3 layer — the layer that defines ontologies — so the substrate is ontological by construction.)

The concession. Declining DL axiomatization does give up automated consistency checking and rich DL inference (necessary-and-sufficient classification, disjointness-based contradiction detection, property-chain entailment). The inference Linked.Archi relies on is the bounded list above — subsumption plus a few property characteristics — not full DL reasoning. Inference claims elsewhere in the documentation should stay within that boundary.


DD-3: ISO 42010 Alignment for Core Concepts

Decision: Align core ontology concepts with ISO/IEC/IEEE 42010 (Architecture Description).

Rationale: ISO 42010 provides a well-established conceptual framework for architecture description that is framework-agnostic. By aligning with it:

  • The core ontology is not biased toward any specific EA framework
  • Concepts like System, Architecture, Model, Viewpoint, View, Stakeholder, and Concern have precise, standardized meanings
  • The distinction between Architecture (abstract, inherent to a system) and Architecture Description (work product) is preserved
  • Multiple frameworks (TOGAF, DoDAF, Zachman, ADMIT) can be mapped to the same foundation

Core aligns with ISO 42010 as its conceptual basis and deliberately does not ground in a foundational (upper) ontology — see DD-4 for that decision and the alternatives considered.


DD-4: No Foundational Ontology — Lightweight Domain Core Instead

Decision: Do not ground arch:core in a foundational (upper) ontology such as BFO, DOLCE, UFO, or GIST. Instead, arch:core is a lightweight domain core ontology for enterprise architecture, aligned with ISO/IEC/IEEE 42010 (DD-3) and neutral across EA frameworks. Core plays the upper-ontology role, but concretely it is a domain reference ontology (or "core ontology" / "foundational layer") within the Linked.Archi hierarchy (everything imports it; nothing domain-specific lives in it) without being a foundational ontology in the BFO/DOLCE sense.

Rationale:

  • Consistency with the minimal-OWL profile (DD-2). Foundational ontologies — especially BFO and DOLCE — are heavily axiomatized in OWL-DL (disjointness, restrictions, the constraint-style axioms DD-2 deliberately declines). Importing one and then running a minimal-OWL/SHACL profile is self-defeating: either we pull in axioms we have chosen not to use, or we import the ontology and ignore its axioms, which forfeits the rigor that was the point of grounding.
  • Accessibility. A core premise of the project is lowering barriers to adoption. Requiring foundational-ontology literacy to extend a module contradicts that goal.
  • Open- vs closed-world. Foundational ontologies assume open-world DL reasoning; Linked.Archi validates closed-world via SHACL (DD-2). Grounding in a DL-heavy foundation reintroduces the OWA mismatch the profile exists to avoid.
  • EA-framework neutrality, not category neutrality. Core needs to be neutral across ArchiMate, TOGAF, Zachman, etc. — a domain neutrality. It does not need to be neutral across all categories of existence (endurant/perdurant, object/process), which is what a foundational ontology provides and what EA modelling does not require.
  • Practitioner expectation. No ArchiMate or TOGAF practitioner models against BFO. Grounding there optimizes for the academic-ontology audience at the expense of the practitioner audience the project targets.

Alternatives considered:

Foundational ontology Why not adopted as the grounding
BFO Heavily axiomatized OWL-DL; realist endurant/occurrent commitments; conflicts directly with the minimal-OWL profile and the accessibility goal.
DOLCE Rich descriptive/cognitive axiomatization; same DL-weight and learning-curve objections as BFO.
UFO The most relevant — UFO has been used to analyze and repair ArchiMate's semantic ambiguities (see companion note). Its analyses inform our concept definitions, but importing UFO axiomatically reintroduces DL weight and OWA reasoning we have declined.
GIST The closest genuine alternative — Semantic Arts' minimalist upper ontology for the enterprise (~100 classes/properties), using everyday business concepts rather than philosophical primitives. It is minimalist in concept count, but it is still DL-axiomatized: it uses fine-grained disjointness at the top level so a reasoner detects inconsistency. Two reasons we did not build on it: (a) that disjointness-based DL reasoning is exactly the constraint-style OWL the minimal profile declines (DD-2); (b) grounding EA notations in GIST's generic primitives pulls toward GIST's reduce-to-essentials philosophy, which is in tension with our notation-fidelity goal (we preserve each notation's specific standardized types, not collapse them). ISO 42010 was preferred as the anchor because it is an architecture-description standard at our actual layer (DD-3). GIST's minimalism nonetheless validates the lightweight approach core takes.

Consequences:

  • We forgo principled interoperability with other foundationally-grounded ontologies (e.g. BFO-based biomedical ontologies) and the automated consistency-checking a DL-rich foundation enables. This is accepted: those benefits serve cross-domain academic interoperability, not the EA-practitioner use case.
  • Core's category choices are justified by ISO 42010 and EA practice rather than by a foundational ontology. Where finer ontological distinctions matter, UFO-based analyses inform definitions without being imported (see companion note).
  • "Upper ontology" is reserved for its technical meaning; core is described as the foundational layer / domain core, never as "an upper ontology," to avoid the category claim it does not make.

References:


DD-5: MOF↔OWL Equivalence — Why RDF Can Represent Any MOF-Based Modelling Language

Decision: Linked.Archi treats RDFS+OWL as the M3 (meta-metamodel) layer, functionally equivalent to OMG's Meta Object Facility (MOF). Any MOF-based modelling language (UML, BPMN, SysML, etc.) can be faithfully represented as an OWL ontology. The OMG Ontology Definition Metamodel (ODM, formal/2014-09-02) provides the formal mapping rules.

Context — The Four-Layer Architecture:

Both the OMG and W3C stacks use a four-layer metamodel architecture:

Layer   OMG Stack                    W3C Semantic Web Stack
─────   ─────────                    ──────────────────────
M3      MOF                          RDFS + OWL
        (defines metamodels)         (defines ontologies)

M2      UML, BPMN, SysML, OWL        OWL ontology (e.g., uml-onto.ttl)
        (all defined using MOF)      (defined using OWL classes/properties)

M1      UML model instances          RDF individuals
        (conform to M2)             (typed with M2 classes)

M0      The real world               The real world

In Linked.Archi, RDFS/OWL is the foundational layer. Modelling languages like UML, BPMN, and ArchiMate are expressed as OWL ontologies (M2), and model instances are RDF individuals typed with those classes (M1). The OMG four-layer framing is used for didactic continuity with OMG-trained colleagues — structurally, the W3C stack is flatter because RDFS is reflective (rdfs:Class rdf:type rdfs:Class) and does not require a separate meta-meta tier.

The ODM Mapping Rules:

The OMG Ontology Definition Metamodel (ODM) defines the formal correspondence between MOF and OWL constructs:

MOF Construct (M3) OWL/RDFS Construct (M3) ODM Reference Notes
UML::Package owl:Ontology Annex D.3.2 Namespace and modularization
UML::Class owl:Class Annex D.3.3 Direct correspondence
UML::Generalization rdfs:subClassOf Annex D.3.3 Direct correspondence
UML::Property (attribute) owl:DatatypeProperty Annex D.3.4 Structural features of classifiers
UML::Property (reference) owl:ObjectProperty Annex D.3.4 Navigation between classifiers
UML::Association (binary) owl:ObjectProperty Annex D.3.5 Binary associations map to property pairs
UML::AssociationClass owl:Class + functional properties Annex D.3.6 N-ary associations become classes
UML::Multiplicity owl:minCardinality / owl:maxCardinality Annex D.3.7 Cardinality restrictions
UML::Enumeration owl:oneOf or SKOS Annex D.3.9 SKOS as primary (DD-7), plus owl:oneOf where the source spec closes the value set (UML-DD-12)

Where MOF and OWL/SHACL Diverge:

Concern MOF OWL/RDFS Linked.Archi Resolution
World assumption Closed — what's not stated is false Open — absence of a statement is not denial SHACL provides closed-world validation (DD-2)
Associations First-class binary constructs with named ends, navigability, multiplicity Properties — simpler, no named ends Three-declaration qualified relationship pattern (DD-10)
Constraints Built-in (multiplicity, ordered, unique) No built-in constraints SHACL shapes (DD-2)
Reflexivity MOF is defined in terms of itself RDFS is reflexive; OWL avoids it for decidability Not relevant for Linked.Archi's minimal OWL profile
Serialization XMI (XML-based) RDF (Turtle, JSON-LD, N-Triples) Turtle as primary format

_ In Linked.Archi we use SHACL shapes for constraints (DD-2) _

Why This Matters for Linked.Archi:

This equivalence is the theoretical foundation for the entire project. Because OWL sits at the same M3 layer as MOF:

  1. Any MOF-based modelling language (UML, BPMN, SysML, CWM) can be represented as an OWL ontology
  2. Models conforming to those languages become RDF individuals — queryable, linkable, validatable
  3. Multiple modelling languages can coexist in the same knowledge graph because they share the same M3 substrate
  4. Cross-language queries are possible because all models are RDF triples regardless of their source language

This is not a theoretical claim — it is demonstrated by the BPMN ontology (derived from OMG XMI/CMOF), the UML ontology (following ODM mapping rules), and the ArchiMate ontology (mapped from the Open Group specification).

References:


DD-6: No Punning — OWL Classes and SKOS Taxonomies Stay Separate

Decision: Do not use OWL 2 punning (same IRI as both class and individual, or class and property). Use OWL class hierarchies for formal semantics and SKOS concept schemes for lightweight classification, linked via annotation properties.

Rationale: Punning is tempting in enterprise architecture because ArchiMate involves element types (meta-level) and model elements (instance-level), plus cross-cutting classifications (active/passive, internal/external, layers). Reusing the same IRI for multiple roles seems convenient but creates predictable problems:

  • Under OWL 2 Direct Semantics, punned views are interpreted independently — no logical bridge exists between them. Modellers expect cross-level entailments that do not happen.
  • Mainstream tools (Protégé, visualization tools, SPARQL endpoints) handle punning inconsistently — duplicate UI entries, broken annotation display, ambiguous query results.
  • Integration across heterogeneous stacks (RDFS inferencing, SHACL validation, rule engines, partial OWL RL) amplifies semantic mismatches.
  • SPARQL under OWL Direct Semantics entailment requires variable typing that makes meta-queries awkward or illegal.

The Linked.Archi approach instead:

  • OWL class hierarchies for formal semantics that reasoners understand (e.g., arch:ActiveStructureElement rdfs:subClassOf arch:Element — so instances inherit the classification)
  • SKOS concept schemes for lightweight faceted classification (by layer, aspect, exposure) linked to OWL classes via owl:AnnotationProperty — queryable in SPARQL, ignored by DL reasoners
  • No same-IRI reuse across entity categories — separate namespaces/patterns for classes, properties, individuals, and taxonomy concepts

This follows the OWL 2 specification's own guidance: use annotations when information should not contribute to logical consequences.

Clarification — SKOS annotation properties on OWL classes:

Using skos:prefLabel, skos:definition, skos:altLabel, and skos:scopeNote on owl:Class declarations is explicitly permitted and does NOT constitute punning. These properties are typed as owl:AnnotationProperty in the SKOS OWL vocabulary — they attach lexical metadata to any resource without altering its logical role. An owl:Class carrying a skos:prefLabel does not become a skos:Concept.

Clarification — Taxonomy skos:narrower pointing at OWL class IRIs:

The taxonomy files (e.g., archimate3.2-tax.ttl) use skos:narrower to reference OWL class IRIs directly as leaf nodes:

:BusinessLayer
    a             skos:Concept ;
    skos:narrower am:BusinessActor, am:BusinessRole, am:BusinessProcess . . . .

Under strict RDFS entailment, skos:narrower has rdfs:range skos:Concept — so this would infer am:BusinessActor rdf:type skos:Concept, creating implicit class-individual punning. Linked.Archi accepts this pragmatically because:

  1. No RDFS materialization is run on taxonomy files — the entailment regime is minimal OWL (DD-2), not RDFS closure. The rdf:type skos:Concept triple is never materialized.
  2. The purpose is tool consumption — modelling tools read skos:narrower to populate palettes and navigation trees. They do not run RDFS inference on the taxonomy.
  3. rdfs:seeAlso is the explicit bridge — each SKOS grouping concept (e.g., amtax:BusinessLayer) carries rdfs:seeAlso am:BusinessLayerElement to link the navigational concept to its OWL class counterpart without range-based entailment.
  4. OWL 2 Direct Semantics treats annotation assertions independently — even if a tool loads both files, the class and individual interpretations remain in separate semantic domains under Direct Semantics.

The leaf-level skos:narrower references are a pragmatic shortcut for tool interoperability. If strict RDFS-entailment environments are targeted, replace direct class references with dedicated skos:Concept individuals per leaf and link them to the OWL class via rdfs:seeAlso.

What remains prohibited:

  • Explicitly declaring am:BusinessProcess a owl:Class, skos:Concept — this is intentional punning
  • Using the same IRI as both owl:ObjectProperty and owl:Class
  • Relying on cross-category entailments that depend on punned interpretations being logically connected

References:


DD-7: SKOS for Taxonomies and Classification

Decision: Use SKOS concept schemes for classifying model concepts rather than OWL class hierarchies.

Rationale: SKOS provides:

  • Multiple independent classification dimensions (by layer, by aspect, by domain) without multiple inheritance issues
  • Navigation aids for modelling tools (palette generation, filtering)
  • Controlled vocabularies with preferred/alternative labels
  • Broader/narrower relationships that are explicitly navigational, not ontological

The ArchiMate taxonomy, for example, classifies elements both by layer (Business, Application, Technology) and by aspect (Active Structure, Passive Structure, Behaviour) — two orthogonal dimensions that would be awkward to model as OWL class hierarchies.

The closed enumeration pattern

Where a source specification fixes a value set and no adopter may extend it, the values get an OWL identity in addition to their SKOS one. The shape is always the same four parts:

  1. An owl:Class for the enumeration, closed with owl:oneOf over its values.
  2. Each value declared in the same file as owl:NamedIndividual, typed by that class, and also a skos:Concept.
  3. skos:broader and skos:inScheme on each value, pointing at a grouping concept in the module's taxonomy.
  4. The reciprocal skos:narrower from that grouping concept, which is what tools read to build pickers and palettes.
## in the ontology
mod:Ring a owl:Class ;
    owl:oneOf ( mod:Adopt mod:Trial mod:Assess mod:Hold mod:Retire ) .

mod:Adopt a owl:NamedIndividual, mod:Ring, skos:Concept ;
    skos:prefLabel "Adopt"@en ;
    skos:broader   modtax:Rings ;
    skos:inScheme  <https://meta.linked.archi/mod/tax#> .

## in the taxonomy
modtax:Rings a skos:Concept ;
    skos:narrower mod:Adopt, mod:Trial, mod:Assess, mod:Hold, mod:Retire .

SKOS remains the primary mechanism and carries the labels, definitions, notation symbols and navigation; the OWL layer carries typing and closure, so a property can name the enumeration as its range and SHACL can reject a member of the wrong set. Modules using the pattern: frameworks/TIME/ (dispositions, ratings, lifecycle states), frameworks/tech-radar/ (rings, quadrants, movements) and modelingLanguages/uml/ (the nine UML Enumerations — see UML-DD-12).

Value sets that adopters are expected to extend — environment types, domain tags, organisation-specific states — stay pure SKOS and belong in a reference-data document instead, where they can be replaced without touching the metamodel.


DD-8: domainIncludes / rangeIncludes Instead of rdfs:domain / rdfs:range

Decision: Use arch:domainIncludes and arch:rangeIncludes (modelled after schema:domainIncludes) for relationship guidance, reserving rdfs:domain/rdfs:range for cases where inference is genuinely desired.

Rationale: In RDFS/OWL, rdfs:domain and rdfs:range are inference axioms, not constraints. Stating rdfs:domain :Node on a property means "anything that uses this property is inferred to be a :Node" — which is often not the intended behaviour.

arch:domainIncludes / arch:rangeIncludes serve as guidance for modelling tools (e.g., relationship wizards that propose valid connections) without triggering unintended inference. Actual constraints are implemented in SHACL.

Relationship to SHACL: SHACL does not read rdfs:domain, rdfs:range, arch:domainIncludes, or arch:rangeIncludes — it defines its own constraints independently via sh:class, sh:targetClass, and sh:node. However, the interaction between entailment and SHACL is real and must be understood:

Mechanism Layer Effect
rdfs:domain / rdfs:range RDFS inference Infers type — "anything using this property IS a X" (open world)
arch:domainIncludes / arch:rangeIncludes Annotation Suggests valid types — for tooling hints, documentation, relationship wizards
sh:class, sh:targetClass, sh:node SHACL validation Validates — "if this property is used, the value MUST be a X" (closed world)

SHACL shapes declare their own sh:class and sh:targetClass directly — they are the enforcement layer. The arch:domainIncludes/arch:rangeIncludes annotations are the documentation and tooling layer. Neither depends on the other at runtime.

The entailment interaction: While SHACL itself does not read domain/range declarations, SHACL operates on whatever graph it receives — including materialized inferences. If RDFS entailment runs before SHACL validation (as it does in engines like GraphDB or Stardog with reasoning enabled), the materialized triples affect which shapes fire:

  • rdfs:subClassOf transitivity means a shape targeting am:ActiveStructureElement fires on am:BusinessActor instances — this is desired behaviour and is the reason Linked.Archi uses class hierarchies for aspect/layer classification (see AM-DD-1).
  • rdfs:domain/rdfs:range inference would cause undesired behaviour: any resource using a property with rdfs:domain :Node would be inferred as :Node, causing shapes targeting :Node to fire on unexpected instances.

This is the key distinction: rdfs:subClassOf entailment is intentional and relied upon by SHACL shapes (they use rdf:type/rdfs:subClassOf* property paths). Domain/range entailment is unintentional and would pollute the type graph. By using annotation properties (arch:domainIncludes/arch:rangeIncludes) instead of rdfs:domain/rdfs:range, the type graph remains clean — only explicit rdf:type assertions and rdfs:subClassOf inheritance determine which shapes apply to which instances.

For a deeper treatment with examples, trade-off analysis, and practical implications for SPARQL and validation pipelines, see the Domain & Range Guide.


DD-9: ModelConcept as Base Class (Not Direct Use of owl:Class)

Decision: Introduce arch:ModelConcept as the base class for all architecture model concepts rather than using owl:Class or rdfs:Resource directly.

Rationale: Architecture model concepts need to:

  • Be presented in different contexts with specific visual notations
  • Be understood correctly by stakeholders (not just machines)
  • Be available in a modelling palette for architects to use
  • Have restrictions defined by the architecture framework
  • Carry governance metadata (ownership, master data source)

These requirements are specific to architecture modelling and would be lost if using generic RDF/OWL constructs directly. ModelConcept provides the semantic anchor for all of this.


DD-10: Clean Separation of Predicates and Relationship Resources

Decision: Relationship types are standard owl:ObjectProperty declarations. Relationship occurrences that need identity, metadata, or lifecycle management are instances of arch:QualifiedRelationship subclasses. The two are bridged by arch:unqualifiedForm (schema-level mapping) and rdf:reifies (RDF 1.2 instance-level bridge).

Rationale: Architecture models need two views of every relationship:

  1. A direct predicate for graph traversal — ex:AppSvc1 am:serves ex:BizProc1 — enabling SPARQL property paths, reasoning, impact analysis, and simple queries
  2. A first-class resource for architecture management — a QualifiedRelationship instance carrying provenance, confidence, lifecycle state, view context, approval status, and supporting multiplicity (multiple distinct edges between the same pair)

Earlier iterations of the core ontology used a metaclass pattern (arch:Relationship rdfs:subClassOf rdf:Property) and OWL 2 punning to make relationship types serve both roles simultaneously. The current design moves away from this: relationship types are plain owl:ObjectProperty, and the qualified form is a separate class hierarchy under arch:QualifiedRelationship.

Three complementary representations are emitted for every relationship:

  1. Direct triplesource vocab:serves target — for SPARQL traversal
  2. Qualified predicatesource vocab:qualifiedServes relationshipNode — for navigation to the full resource
  3. Qualified relationship resource — carries all metadata: labels, provenance, lifecycle, etc.
  4. rdf:reifies — bridges the direct triple to the resource (RDF 1.2)

This separation is cleaner because:

  • Relationship types as standard owl:ObjectProperty work consistently across all reasoners and tools — no punning edge cases
  • Qualified relationship resources are genuine architectural objects, not reification workarounds — they can be the source or target of other relationships (higher-order modelling)
  • The schema mapping (arch:unqualifiedForm) is explicit and validatable via SHACL
  • RDF 1.2 rdf:reifies provides the standardized bridge, replacing the older rdf:Statement-based approach
  • Multiple distinct reifiers for the same proposition are supported — essential when the same logical relation appears in different contexts (current vs target state, observed vs inferred)

The pattern adopts and extends the PROV-O qualified relation pattern:

PROV-O Linked.Archi Role
prov:EntityInfluence arch:QualifiedRelationship Base class for qualified nodes
prov:influencer / prov:entity arch:source / arch:target Source and target elements
prov:unqualifiedForm arch:unqualifiedForm Schema-level mapping
prov:qualifiedInfluence Type-specific qualified property Navigates source → qualified node
(no equivalent) rdf:reifies (RDF 1.2) Bridges direct triple to resource

Anti-patterns to avoid:

  • Do not treat relationship occurrences as predicates — relationship type is a predicate, relationship occurrence is a resource
  • Do not use arch:unqualifiedForm on instance data — it is a schema-level mapping
  • Always emit the unqualified triple alongside the qualified resource — consumers doing analytics need the direct predicate

References:


DD-11: Identity Mechanism — Correspondence vs. Merge

Decision: Use skos:exactMatch as the default mechanism for cross-source correspondence. Reserve owl:sameAs for a documented subset of cases where the two IRIs are confirmed to be the same individual and a full property merge is wanted. Record which mechanism was used, and why, alongside the link itself — see DD-27 for the reconciliation graph and the shape of a recorded link.

Context: When the same real-world system appears in two sources (e.g. a Backstage bs:Component and an ArchiMate am4:ApplicationComponent), the graph needs a way to relate the two nodes so cross-source queries can span them. Two RDF mechanisms are available, and they make different claims.

Rationale:

  • skos:exactMatch asserts interchangeability for retrieval/mapping without asserting logical identity. It carries no OWL entailment, so the everyday query path stays reasoner-free (consistent with the minimal-OWL profile, DD-2); the linked nodes keep their native types; and the link is revocable without touching source data.
  • owl:sameAs asserts the nodes are one individual and triggers a complete, bidirectional property merge under reasoning. It is powerful where genuine identity holds, but unforgiving — a wrong sameAs silently corrupts all downstream queries — and it pulls OWL entailment into the common path.
  • Decision rule (substitutability): if a reasoner could safely replace one IRI with the other everywhere, forever, the nodes are one entity → owl:sameAs. Otherwise → skos:exactMatch. Most EA cross-source links fail the substitutability test, because notations model the same system at different granularities and concerns, so correspondence is the right default and merge the exception.

Consequences:

  • Cross-source queries traverse skos:exactMatch explicitly (one extra hop); they do not get an automatic property pool. This is accepted as the cost of keeping the link inspectable and inference-free.
  • The two mechanisms must not be mixed silently: a query written for one will miss links made with the other. Hence one default per deployment (skos:exactMatch), with owl:sameAs confined to a recorded subset.
  • Identity decisions are authored and reviewed, never inferred by converters (see the reconciliation method in Bridging Architecture Silos).

DD-12: Versioned Namespace IRIs

Decision: Include version numbers in ontology namespace IRIs (e.g., https://meta.linked.archi/core#).

Rationale: Enables:

  • Multiple versions to coexist in the same triplestore
  • Explicit owl:imports of specific versions
  • Clear provenance tracking
  • Backward compatibility management via owl:priorVersion

DD-13: Metamodel as Manifest (Separate from Ontology)

Decision: A Metamodel (arch:Metamodel) is a separate resource from the ontology that defines model concepts. The metamodel is a manifest that aggregates all constituent resources — the model concepts ontology, SHACL shapes, derivation rules, viewpoints, taxonomy, deliverable templates, reference data, reference models, and presentation contexts — via composition properties.

Rationale: A modelling language is more than just an ontology of elements and relationships. It includes validation rules (SHACL), derivation rules, viewpoint definitions, taxonomies (SKOS), deliverable templates, reference data, and presentation contexts. These are separate concerns maintained in separate files.

The metamodel manifest provides:

  • A single entry point for tools to discover all resources that make up a modelling language
  • Clean separation of concerns — each file has one job
  • Independent versioning and maintenance of each resource
  • The ability for simple metamodels to be just an ontology (the ontology can type itself as arch:Metamodel) while complex ones use a separate manifest

Pattern:

# The manifest (archimate3.2-metamodel.ttl)
ammm:ArchiMate3.2
    a                              arch:Metamodel ;
    arch:basedOnFramework          ammm:ArchiMateFramework ;
    arch:modelConcepts             <https://meta.linked.archi/archimate3/onto#> ;
    arch:formalRules               amsh:, amelsh:, ampsh: ;
    arch:derivationRules           amderiv: ;
    arch:architectureViewpoints    amvp: ;
    arch:conceptClassification     <https://meta.linked.archi/archimate3/tax#> ;
    arch:viewpointLibrary          amvp:ViewpointCatalog ;
    arch:hasDeliverableTemplate    ammm:ArchitectureDefinitionDocument ;
    arch:referenceData             ammm:ArchiMateReferenceData ;
    arch:referenceModels           ammm:ArchiMateReferenceModels ;
    arch:presentationContextScheme ammm:ArchiMatePresentationContexts .

# A model conforms to the metamodel
ex:MyModel
    a                             arch:Model ;
    arch:modelConformsToMetamodel ammm:ArchiMate3.2 ;
    arch:deliverableTemplateUsed  ammm:ArchitectureDefinitionDocument .

For simple metamodels (e.g., Backstage, C4), the ontology can still type itself as arch:Metamodel directly — no separate manifest needed. The manifest pattern is for when the metamodel aggregates multiple files.

References:

  • ArchiMate 3.2 metamodel: modelingLanguages/archimate/3.2/archimate3.2-metamodel.ttl (reference implementation)

DD-14: Default Namespace Prefix and Ontology Header Convention

Decision: Every Linked.Archi ontology file declares @prefix : pointing to its own namespace IRI, and includes a standard header block with vann:preferredNamespaceUri, vann:preferredNamespacePrefix, owl:versionIRI, and owl:imports.

Pattern:

@prefix :        <https://meta.linked.archi/{name}#> .
@prefix arch:    <https://meta.linked.archi/core#> .
@prefix owl:     <http://www.w3.org/2002/07/owl#> .
@prefix vann:    <http://purl.org/vocab/vann/> .
@prefix dc:      <http://purl.org/dc/elements/1.1/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix cc:      <http://creativecommons.org/ns#> .
@prefix skos:    <http://www.w3.org/2004/02/skos/core#> .

<https://meta.linked.archi/{name}#>
    a                             owl:Ontology ;
    owl:imports                   <https://meta.linked.archi/core#> ;
    cc:license                    "http://creativecommons.org/licenses/by/4.0/" ;
    vann:preferredNamespaceUri    "https://meta.linked.archi/{name}#" ;
    vann:preferredNamespacePrefix "{prefix}" ;
    dc:title                      "..."@en ;
    dc:description                "..."@en ;
    dcterms:created               "YYYY-MM-DD"^^xsd:date ;
    dcterms:modified              "YYYY-MM-DD"^^xsd:date ;
    dc:publisher                  "Linked.Archi"@en, <https://linked.archi> ;
    owl:versionIRI                <https://meta.linked.archi/{name}/{version}#> ;
    owl:versionInfo               "{version}"@en ;
.

Rationale:

  1. @prefix : — The default namespace prefix enables concise element declarations (:BusinessActor instead of am:BusinessActor within the file). It also serves as the canonical signal for tooling (WIDOCO, the build script, Protégé) to identify the ontology's own namespace.

  2. vann:preferredNamespaceUri + vann:preferredNamespacePrefix — Machine-readable namespace metadata. Used by documentation generators, prefix registries, and the build pipeline as a fallback when @prefix : is not present.

  3. owl:imports — Explicit dependency declaration. Every modelling language and extension imports arch:core. Tools can resolve the full dependency chain.

  4. Standard metadatadc:title, dc:description, dcterms:created, dcterms:modified, cc:license, dc:publisher, owl:versionIRI, owl:versionInfo ensure every ontology is self-describing and discoverable.

Consistency rule: All ontology files (*-onto.ttl) in core/, extensions/, modelingLanguages/, and frameworks/ must follow this convention. Files that don't (e.g., BPMN sub-ontologies, legacy TOGAF/Zachman files) should be updated to conform.

Tooling dependency: The doc generator (.scripts/.tools/generate-docs.sh) extracts the ontology name from @prefix : to determine the output directory. Ontologies without this declaration are skipped. The fallback reads vann:preferredNamespaceUri.


DD-15: Source-Scoped Graphs for Converted Models

Decision: A converted model is emitted as a set of named graphs under a deterministic template. The semantic content is partitioned by input, the curated model has a graph of its own, geometry is separate, and provenance describes each of the others.

{base}{notation}/{modelId}/graph/semantic/{repo}/{path}   facts lifted from one input
{base}{notation}/{modelId}/graph/semantic                 the same, unpartitioned: a single-input model
{base}{notation}/{modelId}/graph/model                    the curated model
{base}{notation}/{modelId}/graph/views                    geometry
{base}{notation}/{modelId}/graph/provenance               PROV-O about all of the above

The model-level semantic view is the union of the per-source graphs and graph/model. A store configured with a union default graph gets it without further work; graph/semantic/* is the pattern to union. Reach a per-source graph through ?g prov:wasDerivedFrom ?source rather than by composing its name — the depth under graph/ is not fixed.

Rationale: The partition makes the graph the unit of provenance, which is what two questions require. "Give me every triple this input produced" is a single GRAPH clause. "Which source asserted this fact" is unanswerable at resource level as soon as two inputs contribute to one resource: the resource then carries two prov:wasDerivedFrom values and nothing pairs a value with the statement it explains. Two descriptors declaring one component produce bs:lifecycleState bs:Production and bs:Experimental on that component, both sources named and the pairing lost.

The curated model is separated for the same reason in reverse: the arch:Model resource, its metamodel conformance, its folder tree and the ordering nodes come from no input at all. They are the converter's own construction, so they belong in their own graph with their own provenance, whose input is the diagram index.

Membership is asserted, not implied by the graph. Every arch:ModelConcept carries arch:partOfModel to its model, in the same graph as the concept. Without it, partitioning the semantic content would destroy model membership, and membership would be unavailable in TURTLE, RDFXML and NTRIPLES, which are supported outputs. Membership does not run through the folder chain: a folder is a presentation device, nearer a view than the model's semantics, and routing membership through it would make membership depend on folder policy.

Where the semantic/views line falls. Around geometry. The arch:View resource is an arch:ModelConcept and sits in the semantic content; views holds only arch-vis: nodes, links, points and bounds. That is what makes geometry droppable on its own — the larger part of an ArchiMate model by triple count — without losing the diagrams or their names.

Run identifiers do not appear in graph IRIs. A graph IRI names what the graph holds, so a re-conversion replaces it in place. Revision history belongs to version control: the repository holds every prior state, git log over the output directory is the lineage, and a commit-derived run timestamp makes an unchanged input at an unchanged commit produce a byte-identical graph, so the diff is reviewable. It also keeps the union current: with run-scoped graph IRIs and nothing dropped, a union returns every historical value of every property.

A graph is named after the input file, not after the file at a commit. The prov:Entity describing the input keeps its revision, because it identifies bytes at a revision and accumulating one node per revision is what gives an aggregate its history. A graph is not that — it holds the current facts from a file, and a later run replaces it. Keying the graph on the commit as well would make a re-collection that moved one file's commit write a second graph beside the first, and a union would then return that file's facts once per revision it had ever been read at.

Pattern:

<M/graph/semantic/group-order-service/catalog-info-yaml> {
    <M/element/component/default/order-service>
        a bs:Component, arch:Element, arch:ModelConcept ;
        arch:partOfModel  <M> ;
        skos:prefLabel    "Order Service"@en ;
        bs:lifecycleState bs:Production .
}

<M/graph/model> {
    <M> a arch:Model ;
        arch:modelConformsToMetamodel bsmm:BackstageCatalog ;
        dcterms:title "Service Catalogue" .
    <M/folder/Elements> a arch:Folder ; dcterms:isPartOf <M/folder> ;
        schema:itemListElement [ a schema:ListItem ; schema:position 1 ;
                                 schema:item <M/element/component/default/order-service> ] .
}

<M/graph/provenance> {
    <M/graph/semantic/group-order-service/catalog-info-yaml>
        a prov:Bundle ;
        prov:wasGeneratedBy  <{base}provenance/run/9c2f1e04> ;
        prov:wasDerivedFrom  <{base}provenance/source/group-order-service/4f2c1ab8e0d1/catalog-info-yaml> ;
        prov:generatedAtTime "2026-08-29T09:03:11Z"^^xsd:dateTime ;
        dcterms:conformsTo   bsmm:BackstageCatalog .

    <M/graph/model> a prov:Bundle ;
        prov:wasGeneratedBy <{base}provenance/run/9c2f1e04> ;
        prov:wasDerivedFrom <{base}provenance/source/group-models/1a2b3c4d5e6f/catalog-index-yaml> .

    <{base}provenance/run/9c2f1e04> a prov:Activity ;
        prov:used <{base}provenance/source/group-order-service/4f2c1ab8e0d1/catalog-info-yaml> ,
                  <{base}provenance/source/group-models/1a2b3c4d5e6f/catalog-index-yaml> .
}

A graph is typed prov:Bundle and not also prov:Entity. PROV-O makes prov:Bundle a subclass of prov:Entity, so the second type adds nothing a reasoner needs, and it would place every graph in ?s a prov:Entity, which is the pattern that enumerates a run's inputs. The repository node is typed prov:Collection alone for the same reason.

Alternatives rejected:

Alternative Why not
One semantic graph per model A fact cannot be attributed to the input that produced it where two inputs contribute to one resource.
Per-source graphs that restate the facts, the semantic graph staying per model Works, at roughly a 50% increase in quads. The facts then exist twice, which the partition avoids entirely. Held as the fallback where per-concept graph routing is impractical in a converter.
RDF 1.2 reification of each fact Exact and non-duplicating, at roughly a 94% increase in quads, and those triples survive flattening so Turtle grows too. Requires SPARQL 1.2 to query. Revisit when store support is ordinary.
Membership via dcterms:isPartOf through the folder chain One triple would complete it, but it makes model membership depend on folder policy, and folders are presentation. arch:partOfModel exists and says exactly this.
Run identifiers in graph IRIs Accumulates every revision in the union, so "the current value" stops being answerable without a curated list of active graphs. Version control already holds history.
One prov:Bundle per run wrapping everything A bundle separates provenance about provenance; it does not give per-input attribution, which is the requirement. Bundles are used here to describe each graph, which is the other thing they are for.

Consequences:

  • Graph count grows with input count: a model built from 200 files gets 200 semantic graphs. A model built from one input keeps the unpartitioned graph. That is not a flag but a consequence of the rule — partitioning one input would name a graph after the only file there is.
  • The graphs compose into a model only if the store unions them. That is configuration, and it is load-bearing rather than convenient.
  • Under Turtle, RDF/XML and N-Triples the per-fact attribution is lost. arch:partOfModel survives, so the model is still reassemblable, and the bundle descriptions survive too, so "what did this run write, and from what" remains answerable. What goes is the ability to bind a graph variable from a triple.
  • provenance is reserved as a top-level segment under {base} (DD-29).
  • A lifter that is not one of the published converters is expected to emit arch:partOfModel on every model concept it produces. Nothing else recovers membership once the graph boundary is gone.

Where a graph cannot be attributed. Geometry is not partitioned: it comes from one input, and no consumer has asked to attribute it. Where a converter receives geometry by file name alone, with no path to locate it in a repository, its views graph is left undescribed rather than described as derived from the wrong input.

Open questions. Three points remain under review, none of which changes the layout:

  • Whether prov:Bundle is the right class for a graph of domain facts. PROV-O defines a bundle as a named set of provenance descriptions, so the usage is common practice but a stretch; dcat:Dataset is the alternative. The choice is one type triple per graph and cheap to revise.
  • Whether a graph should carry a canonical hash over its contents (RDFC-1.0), so that "did this graph change" is answerable without a diff.
  • Whether a source entity should also be typed dcat:Distribution. It is a retrievable representation of a dataset, which is what the class means, and dcat:downloadURL would reconcile DD-16's preference for URLs with the path literal used here.

References:

  • DD-16 — schema-level provenance
  • DD-27 — layer discipline
  • DD-28 — derived triples
  • DD-29 — reserved segments
  • Converters — output conventions and downloads

DD-16: Source Attribution and Provenance — dcterms:source + prov:wasDerivedFrom

Scope: This record governs schema-level provenance — an ontology, class or taxonomy concept derived from a published specification or foundational text. Provenance for converted model instances is DD-15; provenance for rule-derived relationships is DD-28. See DD-27 for how the three layers coexist in one graph.

Decision: Use both dcterms:source and prov:wasDerivedFrom (or prov:hadPrimarySource) on ontology headers to declare derivation sources. They are complementary, not competing. Use dcterms:source consistently everywhere — never the legacy dc:source.

Rationale: The two properties solve overlapping but distinct problems:

  • dcterms:source is a flat, bibliographic statement: "this resource is derived from that one." It's what tooling ( Protégé, LOV, WIDOCO) picks up and displays as "sources." No commitment to a process model — no agents, activities, or timestamps. Use on both ontology headers AND individual OWL classes (to link each entity to its spec section).

  • prov:wasDerivedFrom is part of PROV-O's derivation chain. It says the same thing semantically ("entity B was generated from entity A") but plugs into a richer graph: you can attach a prov:Activity (the act of generating the ontology), a prov:Agent (the author or tool), prov:generatedAtTime, etc. If you ever need to answer "how, when, and by whom was this ontology produced from source X?", prov:wasDerivedFrom is the anchor.

  • prov:hadPrimarySource (subproperty of prov:wasDerivedFrom) is specifically meant for "the original document this content traces back to." Specifications (TOGAF, ArchiMate, BPMN, UML) and foundational research (Kotusev's books/papers) are textbook primary sources.

Pattern:

<my-ontology>
    a                     owl:Ontology ;
    dcterms:source        <https://pubs.opengroup.org/togaf-standard/architecture-content/chap02.html> ;
    prov:wasDerivedFrom   <https://pubs.opengroup.org/togaf-standard/architecture-content/chap02.html> ;
    prov:hadPrimarySource <https://pubs.opengroup.org/togaf-standard/architecture-content/chap02.html> ;
.

For book-form sources without stable URIs, mint source entities typed as bibo:Book and prov:Entity:

@prefix bibo:    <http://purl.org/ontology/bibo/> .
@prefix prov:    <http://www.w3.org/ns/prov#> .
@prefix dcterms: <http://purl.org/dc/terms/> .

<my-ontology>
    a                   owl:Ontology ;
    dcterms:source      :AuthorYear ;
    prov:wasDerivedFrom :AuthorYear ;
.

:AuthorYear
    a                 bibo:Book, prov:Entity ;
    dcterms:title     "Book Title"@en ;
    dcterms:creator   "Author Name" ;
    bibo:isbn13       "9780000000000" ;
    bibo:edition      "2nd" ;
    dcterms:date      "2021" ;
    dcterms:publisher "Publisher Name" ;
.

When to use which:

Property Use for Consumed by
dcterms:source All derivation sources (URLs preferred) WIDOCO, LOV, Protégé, documentation generators
prov:wasDerivedFrom Same sources, when traceability matters PROV-aware tools, provenance queries
prov:hadPrimarySource The canonical specification or foundational text Provenance audits, lineage tracking
rdfs:seeAlso Related but non-derivation references (older versions, community pages, alternative formats) General discovery

Note on literals. URLs are preferred as dcterms:source values here because schema-level sources are published, dereferenceable specifications. A file in a repository is not identified by a URL, so instance provenance (DD-15) splits the identity of a source file across four predicates:

Fact Predicate Form
which repository dcterms:isPartOf IRI, target typed prov:Collection
where in it dcterms:source path literal
which revision dcterms:identifier commit identifier literal
which bytes schema:sha256 digest literal

A path alone identifies a file only relative to a repository, which is why the repository is a statement rather than a prefix of a URL. The browsable, commit-pinned URL is reachable as prov:alternateOf — an assertion that the two IRIs denote the same document — with rdfs:seeAlso retained for human use. The divergence is therefore narrower than "literal versus URL": a URL-valued assertion about the source does exist, just not on dcterms:source. Both usages are valid, since dcterms:source has no enforced range, but a query written for one will not find the other. Scope source queries by graph, and prefer prov:alternateOf where a dereferenceable IRI is wanted.

Anti-patterns:

  • Using dc:source (legacy namespace) — always use dcterms:source instead
  • Using schema:citation for derivation sources — citations are for "how to cite this resource", not "where this resource came from"
  • Omitting dcterms:source and relying only on PROV — most tooling won't find it

Trade-off: Slight redundancy between dcterms:source and prov:wasDerivedFrom pointing to the same URI. This is acceptable — the two serve different consumer ecosystems and the duplication is minimal.

Element-Level Source Attribution

When the source specification has section-level anchors, individual OWL classes carry more specific provenance:

Property Purpose on elements
dcterms:source Specific section URL with fragment identifier — canonical derivation link
prov:wasQuotedFrom Same URL with fragment — indicates skos:definition was quoted verbatim from that section
rdfs:seeAlso Alternative format URLs with fragment for the same section (singlepage, PDF, etc.)
:MyElement
    a                  owl:Class ;
    skos:prefLabel     "My Element"@en ;
    dcterms:source     <https://spec-publisher.org/spec/chap09.html#sec-My-Element> ;
    prov:wasQuotedFrom <https://spec-publisher.org/spec/chap09.html#sec-My-Element> ;
    rdfs:seeAlso       <https://spec-publisher.org/spec/chap09.html#sec-My-Element>,
                       <https://spec-publisher.org/spec.singlepage/#sec-My-Element> ;
    skos:definition    '''...exact text from the spec definition box...'''@en ;
    skos:scopeNote     '''...explanatory prose following the definition...'''@en ;
.

Rules for element-level attribution:

  • Do NOT repeat the generic ontology-level URL on classes — only use more specific section URLs
  • skos:definition MUST contain the exact formal definition from the spec (the normative definition text)
  • skos:scopeNote contains the explanatory prose that follows the definition
  • Remove figure/example references from scope notes (e.g., "Figure 4-3 shows...")
  • Convert section cross-references to local class links (e.g., "(see :Plateau)" instead of "see Section 12.2.3")
  • Remove spec-internal reference markers (e.g., [G211], [REF-42])
  • arch:domainIncludes / arch:rangeIncludes go on properties only, NEVER on classes

DD-17: Stakeholder as Both Core Concept and Element

Decision: arch:Stakeholder is both a core ontology concept (affecting metamodel design) and a subclass of arch:Element (usable in models).

Rationale: Stakeholders directly affect how the architecture description is organized and thus impact the metamodel itself. At the same time, stakeholders need to appear in architecture models (e.g., ArchiMate motivation views). Making Stakeholder a subclass of Element allows the same instance to serve both roles, benefiting analysis and inference.


DD-18: ReferenceModel as Subclass of Metamodel

Decision: refa:ReferenceModel extends arch:Metamodel.

Rationale: Reference models primarily contain abstract concepts defined as classes — they are type-level artifacts. While they may contain individuals (universals common to a set of concepts, or abstract tropes used as derivation sources), the primary content is definitional.

When reference model concepts are used for derivation, prov:wasDerivedFrom should reference the original concept, maintaining traceability.


DD-19: Force Over Driver for Architecture Decision Influences

Decision: Name the class ad:Force rather than "Driver" or "Motivation" for influences on architecture decisions.

Rationale: "Force" is more generic and encompasses all influences on architecture decisions. "Driver" collides with ArchiMate's Driver concept (which has a more specific meaning). "Motivation" is also a Force but not generic enough. The name aligns with the software architecture literature (Bass, Clements, Kazman) where "architectural forces" is the established term.


DD-20: Presentation Context Scheme for Stakeholder-Specific Views

Decision: Introduce arch:presentationContextScheme to group visual notations and templates by stakeholder audience.

Rationale: The same architecture knowledge needs different visual representations for different audiences (C-Level, Business, DevOps, Architects, Security, Data Management). Rather than creating separate models, presentation contexts act as "themes" that select appropriate visual notations, templates, and abstraction levels from the same underlying knowledge graph.


DD-21: Abstract vs Concrete Elements (ABB/SBB)

Decision: Use arch:isAbstract boolean property to distinguish Architecture Building Blocks (ABBs) from Solution Building Blocks (SBBs).

Rationale: ABBs are abstract, used for modelling patterns, reference architectures, or high-level architectures. SBBs are concrete, used for actual architecture solutions and exist in CMDBs, ITSM solutions, and architecture landscape repositories. This distinction is critical for governance and portfolio management.


DD-22: [Moved] ArchiMate-Specific Decisions

ArchiMate-specific design decisions have been moved to doc/guide/archimate/design-decisions.md. This keeps the repo-wide design decisions document focused on decisions that apply to ALL Linked.Archi ontologies.

Each modelling language module may have its own design-decisions.md for language-specific choices. The repo-wide decisions in this document apply as defaults unless a module-specific decision overrides them.


DD-23: Enumerated State Vocabularies as Named Individuals

Decision: Model closed state vocabularies — lifecycle states, decision states, assessment statuses — as named individuals of a state class, attached with a plain owl:ObjectProperty. Do not declare the property owl:FunctionalProperty, and do not close the value set with owl:oneOf. Enforce "at most one state, drawn from this list" in SHACL with sh:maxCount 1 and sh:in.

Pattern:

:DecisionState a owl:Class ;
    skos:prefLabel "Decision State"@en .

:decisionState a owl:ObjectProperty ;      # not owl:FunctionalProperty
    rdfs:domain :Decision ;
    rdfs:range  :DecisionState .

:Proposed a :DecisionState ;
    skos:prefLabel  "Proposed"@en ;
    skos:altLabel   "Open"@en ;
    skos:definition "The decision has been raised but not yet settled."@en .
ex:DecisionShape a sh:NodeShape ;
    sh:targetClass ad:Decision ;
    sh:property [
        sh:path     ad:decisionState ;
        sh:maxCount 1 ;
        sh:in       ( ad:Proposed ad:Accepted ad:Rejected ad:Deprecated ad:Superseded ) ;
    ] .

Rationale: Three separate choices, each following from the minimal OWL profile (DD-2).

Individuals rather than string literals. A state individual has an IRI, so it can carry skos:prefLabel, skos:altLabel, and skos:definition, be translated, be mapped to an external vocabulary with skos:exactMatch, and be dereferenced in the published documentation. A literal "Proposed" carries none of that, and a typo in it is indistinguishable from a new value.

No owl:FunctionalProperty. A functional property asserts that the subject has at most one value — but under the Open World Assumption a reasoner does not read that as a constraint to check. Given a decision that carries two states, it entails owl:sameAs between the two state individuals. The reasoner silently merges Proposed and Accepted into one thing rather than reporting an error, and the merge then propagates through every query touching either. The declaration that looks like data quality enforcement actively destroys data quality. This is DD-2's general argument applied to a specific, easy-to-get-wrong case.

No owl:oneOf on the state class. Enumerating the class members closes the vocabulary in OWL, which prevents a downstream organization from adding a state its governance process needs (UnderReview, Delegated) without editing the published ontology. The value set is a governance constraint on our data, not a logical truth about the class, so it belongs in a shape a consumer can replace.

Alternatives considered:

Alternative Why not adopted
String literal values (arch:lifecycleState "Current") No labels, no definitions, no translation, no mapping to external vocabularies, and no way to distinguish a typo from a new value. Still present in some example models; not the pattern for new assets.
owl:FunctionalProperty on the state property Entails owl:sameAs between state individuals on any multi-valued data error, merging distinct states instead of flagging the error. Used by timefw:lifecycleState in the TIME framework — a divergence that predates this record.
owl:oneOf enumeration on the state class Closes the vocabulary against downstream extension. Used by timefw:AssessmentStatus — same divergence.
Triple-typing individuals as owl:NamedIndividual, :StateClass, skos:Concept Appropriate where the asset set has a taxonomy file to place the concepts in, as TIME does with timetax:AssessmentStatuses. Unnecessary where the states live in the ontology file alone, and it invites a second, competing home for the same vocabulary.

Consequences:

  • Nothing enforces single-state at the OWL layer. The guarantee exists only where a SHACL shape is actually written and run, so an asset set using this pattern should ship a *-shapes.ttl with the sh:maxCount 1 + sh:in property shape. arch-decision does not yet have one; the constraint is documented in skos:scopeNote on ad:decisionState and in the Extensions Guide until it does.
  • The state property carries only the current value. Where a full transition history matters, record it with prov:wasRevisionOf on successive versions of the subject, or with dcterms:modified for the last-changed timestamp.
  • The TIME framework diverges on two of the three points above. It is internally consistent and validated, so it is left as-is rather than migrated; new state vocabularies follow this record.

References: arch:ArchitectureState (core/core-onto.ttl) and ad:DecisionState (extensions/arch-decision/arch-decision-onto.ttl) are the reference implementations. The SHACL side of this record lives in extensions/arch-decision/arch-decision-shapes.ttl, where adsh:DecisionShape closes the state vocabulary with sh:maxCount 1 and sh:in. See also DD-2 for the minimal OWL profile and the OWL/SHACL division of labour, DD-6 on keeping OWL classes and SKOS concepts separate, and DD-7 for when a vocabulary belongs in a taxonomy file instead.


DD-24: skos:prefLabel is the Canonical Label; Notation Name Attributes are Retained Source Data

Decision: skos:prefLabel, carrying a language tag, is the one canonical human-readable label across every Linked.Archi metamodel. Notation ontologies additionally retain their source name attribute — bpmn:name and its equivalents — verbatim, as a plain xsd:string. The two are not alternatives. Converters emit both.

ex:t1 a bpmn:ServiceTask ;
    bpmn:name      "Charge card" ;      # source attribute, verbatim, xsd:string
    skos:prefLabel "Charge card"@en .   # canonical label, rdf:langString

Consequences for converter authors:

skos:prefLabel notation name attribute
Required yes, wherever the notation's own shape says so should be retained
Datatype rdf:langString — language tag mandatory plain xsd:string
Multiplicity one per language single-valued
Read by tooling yes — docs, palettes, templates, SPARQL, SHACL no
Layer canonical, cross-notation serialization-level fact

An untagged literal does not satisfy any notation's label shape — they all assert sh:datatype rdf:langString. "Charge card" fails; "Charge card"@en passes. This is the most common reason a converter's output fails validation while looking correct to a human reader.

Rationale.

Why keep the notation attribute at all. It is not merely a duplicate. In BPMN, 34 classes carry bpmn:name and only 7 of them are aligned to arch:Element. For the other 27 — Error, Signal, Interface, Operation, Resource, PartnerEntity, CorrelationKey, InputSet, DataInput, LaneSet, MessageFlow and the rest — bpmn:name is the only name-bearing property, and no core shape reaches them because they are not architecture elements. Removing it would either leave them nameless or force skos:prefLabel onto bookkeeping nodes, which then pollutes every label-based query. The attribute is also one of roughly 200 generated from the source metamodel alongside bpmn:id and bpmn:text; the same "it overlaps something in core" argument would remove those too, at which point the ontology stops being a faithful mapping of the specification.

Why not bridge them with rdfs:subPropertyOf. Asserting bpmn:name rdfs:subPropertyOf skos:prefLabel looks like it would make notation-native names satisfy the core rule. It does not. The entailed skos:prefLabel inherits the plain xsd:string datatype, so a correctly named element still fails — the violation simply moves from sh:MinCountConstraintComponent to sh:DatatypeConstraintComponent, reported against a label that is present and looks fine. The relationship between the two properties is policy, documented on the property itself, not an inference.

Why the label rule is notation-owned and not in core. There is deliberately no core label shape. arch:Element means "a node in a model", and several notations have nodes that are legitimately unnamed: BPMN Gateway and Event subtypes, ArchiMate AndJunction and OrJunction, BPMN TextAnnotation and Group (which carry text rather than a name), and bpmndi:BPMNDiagram (whose name the spec makes optional, which is why there is no core arch:View rule either). Those constructs are genuine elements — they have identity, they render on diagrams, they belong in element counts — so excluding them from arch:Element to satisfy a label rule would misstate the model. Being an element and being required to carry a name are separate questions, and only the notation knows the answer to the second.

Each metamodel therefore states its own rule in its own shapes, listing the classes that must be named with plain sh:targetClass: bpmnsh:RequiredNameShape, am4elsh:ArchiMateElementShape, amelsh:ArchiMateElementShape, c4sh:C4ElementLabelShape, strsh:StructurizrElementLabelShape, bssh:BackstageElementLabelShape, and the per-class shapes in BPMN Lite.

Two mechanisms were tried and rejected. sh:severity sh:Warning on a core shape does not help: under SHACL a report conforms only when it contains no results at all, so downgrading severity reclassifies output without making the graph conform, and RDF4J's ShaclSail does not distinguish severities either. An arch:labelOptional annotation with a sh:sparql exemption does not help either: SPARQL-based constraints see only the data graph, so whether the exemption is visible depends on how the consumer assembles data and schema graphs — the same fragility the rule was meant to remove.

A notation shape must not target arch:Element. In a merged multi-notation graph that applies one notation's naming policy to every other notation's elements. Target the metamodel's own classes. Abstract domain or layer roots are usually the concise way to do it, and they give you a natural place to leave connectors out: ArchiMate's junctions are declared rdfs:subClassOf arch:Element directly rather than under any domain root, so targeting the 10 domain roots in 4.0 (or 7 layer roots in 3.2) covers every named element and exempts the junctions without listing 59 classes.

Related: see DD-21 on abstract classes, and the alignment axioms in modelingLanguages/bpmn/linkedarchi-bpmn-onto.ttl for a worked example of choosing element roots deliberately rather than at the metamodel root — aligning a notation's abstract metamodel root makes every serialization artefact an architecture element.

Where alignment axioms live. Declare rdfs:subClassOf arch:Element and rdfs:subClassOf arch:QualifiedRelationship on the classes themselves, in the metamodel's own ontology file. Do not put them in a separate alignment document. A sidecar is not reachable through the ontology's owl:imports, and SHACL and RDF tooling does not dereference imports, so a consumer loading the published ontology namespace gets the classes with no connection to the core model at all — and the axioms that decide what counts as an architecture element end up being the one part of the metamodel with no generated documentation.


DD-25: One arch:Framework IRI per Language Family

Decision: A modelling language has exactly one arch:Framework individual, minted in a namespace that carries no version. Every version's manifest points arch:basedOnFramework at it, and version detail lives on the arch:Metamodel individual via owl:versionInfo.

## modelingLanguages/archimate/archimate-framework.ttl — above the 3.2/ and 4.0/ directories
amfw:ArchiMateFramework a arch:Framework ;
    skos:prefLabel "ArchiMate"@en .          # the language, not a release

## archimate3.2-metamodel.ttl
ammm:ArchiMate3.2 arch:basedOnFramework amfw:ArchiMateFramework ; owl:versionInfo "3.2" .
## archimate4-metamodel.ttl
am4mm:ArchiMate4  arch:basedOnFramework amfw:ArchiMateFramework ; owl:versionInfo "4.0" .

Problem it solves. arch:modelConformsToMetamodel ranges over arch:Metamodel, and each version publishes its own instance. That part is right and useful: a model conforms to ArchiMate 3.2, not to ArchiMate in general. The hop that should group the versions is arch:basedOnFramework — and every manifest declared it, pointing at a Framework individual minted in that manifest's own namespace. archimate3/metamodel#ArchiMateFramework and archimate4/metamodel#ArchiMateFramework were two IRIs for the same language, related by nothing, each carrying a version in its skos:prefLabel.

So the natural query returned nothing, whichever of the two IRIs you picked:

SELECT ?model WHERE {
  ?model arch:modelConformsToMetamodel/arch:basedOnFramework amfw:ArchiMateFramework .
}

and had to be written as an enumeration that grows with every release:

SELECT ?model WHERE {
  VALUES ?mm { ammm:ArchiMate3.2 am4mm:ArchiMate4 }
  ?model arch:modelConformsToMetamodel ?mm .
}

There was no fallback either: no prov:wasRevisionOf, owl:priorVersion, dcterms:isVersionOf or owl:backwardCompatibleWith linked the two metamodels, and core/common-tax.ttl has no grouping concept for them.

No new predicate was needed. arch:basedOnFramework already means "the Framework this Metamodel is a version of". It was simply being pointed at a per-version resource. The version-bearing labels — "ArchiMate 3.2" on a Framework — are the tell that the individual had been understood as a per-version thing rather than as the thing versions are of.

Rejected alternatives. Keeping the per-namespace individuals and relating them with skos:exactMatch, or linking the metamodels with prov:wasRevisionOf. Both leave the consumer walking a property path over an unbounded chain instead of taking one hop, and both grow as releases accumulate — which is the cost the enumeration already had.

Deprecation, not deletion. The old IRIs were published, so they stay, with owl:deprecated true and owl:sameAs to the new one. They are not typed arch:Framework any more, so ?fw a arch:Framework returns one ArchiMate framework rather than three. Retyping them would trade a broken query for a misleading one.

Where the boundary falls. A profile of a language shares the language's framework. BPMN Lite is a thinner reading of BPMN, not a different notation, so bpmn-lite/metamodel#BPMNLite points at bpmn/metamodel#BPMNFramework; what distinguishes Lite from the full suite belongs on the metamodel, which is where a consumer chooses between them anyway. Languages whose namespace already carries no version — UML, C4, Backstage, EDGY — needed only their labels de-versioned, since the IRI was already correct.

Framework IRI Metamodels reached in one hop
archimate/framework#ArchiMateFramework ArchiMate3.2 (3.2), ArchiMate4 (4.0)
bpmn/metamodel#BPMNFramework BPMN2 (2.0.2), BPMNLite
uml/metamodel#UMLFramework UML2 (2.5.1)
edgy/metamodel#EDGYFramework EDGY23 (23)

Consequences:

  • The language-level and the version-level question are both answerable, and each in one hop: follow arch:basedOnFramework for the language, read arch:modelConformsToMetamodel for the release.
  • A skos:prefLabel on an arch:Framework must not contain a version. Put it in owl:versionInfo on the arch:Metamodel.
  • Single-version languages should still draw the distinction. It costs nothing while latent, and ArchiMate is what happens when it is not drawn: by the time a second version exists, the wrong IRI is already published.
  • Frameworks in frameworks/ (TOGAF, Zachman, UAF, DoDAF and the rest) still mint their Framework individual in their own single namespace. That is correct while each has one version, and the same rule applies when one gains a second.

DD-26: Lifted Records Are Judged on What the Source Format Holds

Decision: A shape must be satisfiable by a record lifted from the formats converters actually read. Where a source format cannot carry the structure a shape asks for, the obligation is made conditional on evidence present in the data — never on the record's provenance, and not by lowering the severity to sh:Info.

The case that prompted it. adsh:AcceptedDecisionSelectionShape required ad:hasSelectedOption on every ad:Accepted decision. That is right for a record authored in this vocabulary, where options are first-class resources. It cannot be met by a record lifted from a document-based ADR — MADR, Nygard, or a Structurizr !adrs block — which is a title, a status, a date and a Markdown body. The options considered are prose under a heading. There is nothing in the graph to point the property at, and no way to derive one without parsing free text and guessing which heading names the outcome. A converter that minted an ad:Option from the decision title to silence the shape would be inventing model content, and asserting that alternatives were weighed when the graph has no idea whether they were.

So every correctly converted accepted ADR reported one violation with no action available. That is worse than no check: it teaches consumers to ignore the shape set, which costs more than the check gains.

The fix — condition on evidence in the data. The obligation now fires only where the record holds candidates to choose from:

adsh:AcceptedDecisionSelectionShape
    sh:or (
        [ sh:not [ sh:property [ sh:path ad:decisionState ; sh:hasValue ad:Accepted ] ] ]
        [ sh:property [ sh:path ad:hasSelectedOption ; sh:minCount 1 ] ]
        [ sh:property [ sh:path ad:hasAlternative    ; sh:maxCount 0 ] ]   # nothing to select from
    ) ;
.

A record that lists alternatives and names no outcome is still a violation — that is the record the check exists for. A record with no options at all is silent about whether options were weighed, which under the Open World Assumption is the honest reading: the answer to "was an option selected" for a prose ADR is unknown, not no. Rationale is still required, by adsh:AcceptedDecisionRationaleShape.

Rejected — sh:Info. Lowering the severity drops the check for authored records too, where it is a genuine structural error. It also misuses the convention: sh:Info marks divergence that is legitimately ambiguous in the data, as bssh:KindTypeAlignmentShape does for a retained bs:kind disagreeing with rdf:type, where a mis-mapped lift and a deliberate retyping are indistinguishable. An accepted decision that lists candidates and names no outcome is not ambiguous.

Rejected — accepting the rationale as the escape. Allowing ad:justificationDocument to stand in for ad:hasSelectedOption under-fixes and over-exempts at once. It under-fixes because a Nygard or MADR body lifted into ad:justification as a literal still fails, so it exempts one converter's output rather than the class of problem. It over-exempts because attaching a design document then silences the record that lists alternatives and names no outcome. Rationale is evidence of why; a selected option is what was decided. Two shapes, two questions.

Rejected — a lift marker as the condition. Converters should record the lift, using prov:wasDerivedFrom and the surrounding PROV activity per DD-15. No shape may depend on it. Two reasons: that provenance belongs in the provenance graph (DD-15), where a validator run over the semantic graphs cannot see it, so conformance would depend on how a consumer assembled the graph; and gating a check on "a converter produced this" lets any converter silence any check by declaring itself one. A record authored by hand whose options live in a linked design document is the same artifact and is judged the same way.

Consequences:

  • When adding a shape, ask what the formats in scope can actually express. A constraint no lift can satisfy will be met by converters ignoring the shape set, not by better data.
  • Where two shapes cover related ground, they must agree about what a valid record looks like. The selection and rationale shapes disagreed about document-based ADRs — one accepted the document as sufficient, the other could not be satisfied at all.
  • Conformance fixtures should include a lifted record, not only an authored one. examples/extensions/decisions-example.ttl carries :ADR-063 for this: state, related concepts and the body as a schema:CreativeWork, with no options. It is what structurizr2linkedarchi emits, and the arch-decision profile fails if that stops passing.
  • Severity still means what it did: sh:Violation for a malformed record, sh:Warning for an incomplete one, sh:Info for divergence the data cannot adjudicate.

DD-27: Three Provenance Layers, Distinguished by Graph and by Activity

Decision: Linked.Archi records provenance at three granularities using the same PROV-O predicates. Consumers distinguish them by the named graph, and where the graph is unavailable, by the activity the derivation went through — never by the predicate, and never by the subject's type alone.

Layer Subject types Predicates Graph Authored by Record
Specification → ontology owl:Ontology, owl:Class dcterms:source, prov:wasDerivedFrom, prov:hadPrimarySource, prov:wasQuotedFrom the asset file's own graph ontology maintainer, by hand DD-16
Source artifact → model arch:Model, arch:View, arch:Element, arch:QualifiedRelationship, ad:Decision prov:wasGeneratedBy, prov:wasDerivedFrom, prov:qualifiedDerivation; on the graph, prov:Bundle with prov:wasDerivedFrom …/graph/provenance describes …/graph/semantic/{source} converter DD-15
Derivation rule → relationship arch:QualifiedRelationship prov:wasGeneratedBy, prov:wasDerivedFrom, a confidence annotation …/graph/derived SHACL rule engine DD-28

Why one predicate across three layers. PROV-O's derivation is deliberately granularity-neutral. Minting arch: terms per layer would fragment a standard vocabulary for no semantic gain and break PROV-aware tooling.

Why the subject's type is not sufficient. Rows two and three share arch:QualifiedRelationship. A relationship lifted from a catalogue descriptor and a relationship inferred by an ArchiMate derivation rule are both qualified relationships carrying prov:wasDerivedFrom. Only the graph, or the activity, separates them.

The graph is the primary discriminator. With source-scoped semantic graphs, a lifted fact sits in …/graph/semantic/{source}, an inferred one in …/graph/derived, and a curated one in …/graph/model. The layer is readable from the graph IRI without dereferencing anything.

The activity is the graph-independent discriminator. Converter output carries the qualified derivation form, whose prov:hadActivity names the conversion run. A rule engine should do the same, naming its rule-application activity. That survives flattening to Turtle, where the graph boundary does not.

# Wrong: returns ontology-from-spec, model-from-file and edge-from-rule together
SELECT ?x ?src WHERE { ?x prov:wasDerivedFrom ?src }

# Right, in a quad store: scope by graph
SELECT ?model ?src WHERE {
    GRAPH ?g { ?model prov:wasDerivedFrom ?src }
    FILTER(STRENDS(STR(?g), "/graph/provenance"))
}

# Right, in flattened Turtle: scope by the activity that performed the derivation
SELECT ?concept ?src WHERE {
    ?concept prov:qualifiedDerivation [ prov:entity ?src ; prov:hadActivity ?act ] .
    ?act a prov:Activity ; prov:wasAssociatedWith ?agent .
    ?agent schema:name "backstage2linkedarchi" .
}

Note prov:entity, lowercase — the property, not the prov:Entity class.

Requirement on derivation-rule assets. For the third layer to be separable in a flattened graph on the same terms, a derived relationship should carry prov:qualifiedDerivation with prov:hadActivity naming the rule application, alongside the confidence value it already carries. Without it, a Turtle consumer has no way to exclude inferred edges.

The reconciliation layer. Cross-source identity links (DD-11) are a fourth kind of claim: authored rather than derived, and about two model resources rather than about an artifact. They live in their own graph, {base}graph/reconciliation, with the mechanism and the authorship recorded per link. The correspondence itself is a skos:exactMatch or owl:sameAs triple; the record about it is an RDF 1.2 reifying resource over that triple, following the qualified-relationship bridge of DD-10:

<…/graph/reconciliation> {
    bs-ex:PaymentProcessor skos:exactMatch am-ex:PaymentProcessor .

    <…/reconciliation/link-0042>
        a                    prov:Entity ;
        rdf:reifies          <<( bs-ex:PaymentProcessor skos:exactMatch am-ex:PaymentProcessor )>> ;
        prov:wasAttributedTo <…/agent/architect-a> ;
        prov:generatedAtTime "2026-08-27T10:02:00Z"^^xsd:dateTime ;
        skos:scopeNote       "Substitutability test failed; correspondence only."@en .
}

The reified triple carries the mechanism, so DD-11's requirement to record which of skos:exactMatch and owl:sameAs was used is met by the record itself rather than by a separate property. Identity decisions are authored and reviewed, never emitted by converters.


DD-28: Rule-Derived Triples Land in Their Own Graph

Decision: Triples produced by SHACL derivation rules are written to {base}{notation}/{modelId}/graph/derived, never into the semantic graphs.

Rationale: The rules annotate each derived relationship with prov:wasGeneratedBy, prov:wasDerivedFrom and a confidence value. Those annotations are only actionable if a consumer can also exclude derived content wholesale — for a count, a diff, or a validation run that must see asserted facts only. A resource-level annotation cannot do that cheaply; a graph boundary can, with FROM NAMED or DROP GRAPH. It also keeps re-derivation idempotent: clear the graph and re-run, with no retraction logic against asserted content.

Converters assert derivation per relationship as well as per model, so a qualified relationship carrying prov:wasDerivedFrom may be either lifted or inferred. The graph is therefore the discriminator between the two (DD-27). If derived relationships land in a semantic graph, asserted and derived become indistinguishable after a merge, which defeats the confidence and PROV annotations the rules carry.

Consequences:

  • A consumer wanting the full picture queries the union, which is the default graph in most stores. A consumer wanting asserted facts only scopes to the semantic graphs.
  • Tooling that materializes into a store-local graph should map that local name to this template when the results are published.
  • The confidence annotation remains required. The graph answers "is this derived"; the confidence value answers "how much weight does the rule claim".

DD-29: Reserved Top-Level Segments Under the Base IRI

Decision: The base IRI of a published dataset is partitioned by first path segment. Notation slugs (archimate, bpmn, plantuml, c4, leanix, backstage, and any further notation) occupy that space. Two segments are reserved and may not be used as a notation slug: provenance, which holds the content-addressed provenance nodes, and graph, which holds the dataset-wide graphs that belong to no single model.

{base}provenance/source/{repo}/{sha}/{path}
{base}provenance/commit/{sha}
{base}provenance/person/{digest}
{base}provenance/run/{token}
{base}provenance/agent/{digest}
{base}provenance/derivation/{repo}/{sha}/{path}/{run}

{base}graph/reconciliation

Per-model graphs are not affected: they sit under {base}{notation}/{modelId}/graph/…, where graph is a segment of a model IRI rather than of the base (DD-15).

Rationale: Provenance nodes are identified by their content, not by the model that happened to read them. Placing them under a model or a notation would turn one file at one revision into several unrelated subjects, and one conversion run into one activity per model — neither of which is answerable in an aggregate. A file read by two models has to be one node for "everything derived from this file" to be a question at all. The reconciliation graph is reserved for the same reason from the other direction: an identity link relates two models, so it belongs to neither.

The node kinds are second-level rather than reserved individually. source, commit, run, agent, person and derivation sit under provenance, because reserving six further words among the notation slugs would leave "is this a notation or a node kind?" unanswerable from the IRI.

Consequences:

  • Adding a notation requires checking its slug against this list. The check is trivial and the failure is not: a notation named provenance or graph would collide silently with platform nodes in the same namespace.
  • Provenance nodes are shared across models and runs, but statements about them are still written into each model's own provenance graph, so a single graph remains a complete description of that model's lineage.

Conformance Principles

Principles derived from the design decisions above. Use as a quick reference for conformance reviews of new or updated ontology files.

P-1: No arch:Relationship class

The arch:Relationship class has been removed from the core ontology. Relationship types are standard owl:ObjectProperty declarations. No file should declare instances or subclasses of arch:Relationship.

Check: grep -r "arch:Relationship" core/ extensions/ modelingLanguages/ examples/ should return zero hits ( excluding deprecated files and comments).

P-2: No rdf:Statement dependency

arch:QualifiedRelationship does not extend rdf:Statement. No property should be declared as rdfs:subPropertyOf rdf:subject, rdf:object, or rdf:predicate. The bridge to the direct triple is rdf:reifies ( RDF 1.2), not old-style reification.

Check: No rdfs:subClassOf rdf:Statement or rdfs:subPropertyOf rdf:subject/rdf:object/rdf:predicate in any active ontology file.

P-3: Schema-level vs instance-level mapping

arch:unqualifiedForm is a schema-level annotation property used on class and property definitions to declare which unqualified predicate a qualified form corresponds to. It must not appear on instance data. At the instance level, the unqualified predicate is available via rdf:reifies.

P-4: Three-declaration pattern for relationship types

Every relationship type in a metamodel should produce three declarations:

  1. Unqualified predicateowl:ObjectProperty (e.g., am:serves)
  2. Qualified classrdfs:subClassOf arch:QualifiedRelationship with arch:unqualifiedForm pointing to the predicate (e.g., am:Serving)
  3. Qualified predicateowl:ObjectProperty with rdfs:range pointing to the qualified class and arch:unqualifiedForm pointing to the unqualified predicate (e.g., am:qualifiedServes)

See DD-10 for rationale and the Relationship Modelling Guide for full examples.

P-5: No OWL 2 punning for relationship types

Do not use the same IRI as both an owl:ObjectProperty and an owl:Class. The old pattern of declaring a relationship type as a arch:Relationship (making it simultaneously a property and an instance of a class) is retired. Use separate IRIs for the predicate and the qualified class.

P-6: arch:source and arch:target are standalone properties

arch:source and arch:target are standard owl:ObjectProperty declarations on arch:QualifiedRelationship. They have no rdfs:subPropertyOf relationship to rdf:subject or rdf:object.

P-7: Always emit the direct triple

Consumers doing analytics, SPARQL traversal, and reasoning depend on the direct triple. When producing model data, always emit the unqualified triple alongside the qualified resource. The qualified resource alone is not sufficient.

P-8: Always emit a language-tagged skos:prefLabel

skos:prefLabel is the canonical label and must carry a language tag — "Charge card"@en, not "Charge card". A notation's own name attribute (bpmn:name and equivalents) is retained source data and does not satisfy the label requirement. Emit both. See DD-24.

P-9: Align everything that is a node to arch:Element, including unnamed constructs

arch:Element means "a node in a model". Routing gateways, events and junctions are nodes: they have identity, they render on diagrams, they belong in element counts, so they are arch:Element. Whether they must carry a name is a separate question, answered by the metamodel's own label shape. Do not exclude a construct from arch:Element to dodge a naming rule.

Do not align a notation's abstract metamodel root either — bpmn:BaseElement and its equivalents make every serialization artefact an architecture element and inflate every element count. Align the roots that are genuinely model nodes.

P-10: Each metamodel owns its own label rule, and never targets arch:Element

core-shapes.ttl carries no label shape. Every metamodel with a shapes graph declares which of its classes must be named, using plain sh:targetClass against its own classes. Targeting arch:Element would apply that notation's naming policy to every other notation in a merged graph. Abstract domain or layer roots are usually the concise target set, and they leave connectors out naturally.