NB: This Overview Has Been Generated By Copilot/AI
A single-document synthesis of the whole repository: purpose, architecture, layer designs, and embedded DL encodings. Written for consumption by another AI agent doing design review or extension work, and secondarily by humans. Compressed on purpose — see §0 for the DL notation used.
Generated from the repository state as of this writing. Where a layer’s content does not exist yet, this document says so explicitly rather than inventing it — see §3 for the authoritative state.
Each populated layer gets: purpose/scope, key design decisions (the why, not repeated across layers), a compressed DL encoding of every class/property, and an axiom index table. The DL encoding uses standard description-logic shorthand, not Turtle:
| Symbol | Meaning |
|---|---|
⊑ |
rdfs:subClassOf / rdfs:subPropertyOf |
⊓ |
conjunction (a class combines these parents/restrictions) |
∃r.C |
owl:someValuesFrom restriction on property r to class C |
=n r.C, ≥n r.C, ≤n r.C |
exact/min/max cardinality on r (range C where relevant) |
r⁻ |
owl:inverseOf |
Func, Asym, Irref, Trans |
property characteristics (Functional, Asymmetric, Irreflexive, Transitive) |
A ⊥ B |
owl:disjointWith / AllDisjointClasses |
dom/range |
rdfs:domain / rdfs:range |
A class with no restrictions listed is a bare class (no cardinality constraints of its own). “Mixin” means the class exists to be a subClassOf parent for domain classes defined in higher layers; it is rarely instantiated on its own. Every class and property below also carries an rdfs:comment (one-line definition) and an fnd:utility annotation (usage guidance) in the source; these are folded into the prose rather than repeated verbatim, to keep this document’s token footprint down. Consult the layer’s own README.md or spec/*.ttl for the exact annotation strings if needed.
LATTICE is a domain-neutral semantic framework (OWL + SHACL + SKOS) for representing governing instruments — contracts, protocols, agreements, policies, entitlement schemes, any document or system that defines obligations, eligibility conditions, and lifecycle behaviour — as structured, queryable, versioned RDF graphs.
It is the middle of a three-part picture:
mork/) and is domain-agnostic; ontology/mork/targets/ (currently empty) is where it would be configured to target LATTICE specifically, but MORK itself does not depend on LATTICE.ontology/spc/spec/spc.ttl, ~1227 lines; ontology/spc/README.md, ~1393 lines; plus an architecture note and a paper under ontology/spc/docs/). Its namespace was harmonised to the shared nebularis.org base under ADR-A62; its projection/ directory remains empty — no contract to Party or Behaviour exists yet. Integration as an orchestration substrate is deferred to Phase 4, per ADR-A62; treat it as a separately developed body of work pending projection authoring, not as part of the dependency graph below.| Layer | Kind | Models | Namespace prefix | Depends on |
|---|---|---|---|---|
| Foundation | Substrate | Identity/versioning, evidence, temporal scoping, governance status | fnd: |
— |
| Vocabulary | Substrate | Governed binding of external concept schemes into other layers’ properties | voc: |
Foundation |
| Quantification | Substrate | Declared value spaces, quantities, ordered values, bounds, ranges, conversion, granularity, recurrence | qnt: |
Foundation, Vocabulary |
| Party | Substrate | Actors, roles, role occupancy, participation groups, delegation | pty: |
Foundation, Vocabulary, Quantification |
| Eligibility | Substrate | Admissibility: conditions, unresolved questions, decisions | elg: |
Foundation, Vocabulary, Quantification, Party |
| Instrument | Applied domain ontology | Generic governing-document shape: Provision → Obligation → Qualifier | ins: |
Foundation, Vocabulary, Party, Eligibility |
| Behaviour | Substrate | State, transition, trigger, guard, effect | bhv: |
Foundation, Vocabulary, Quantification, Party, Eligibility, Instrument |
Dependency order, per ADR-A01:
foundation
└── vocabulary
└── quantification
└── party
├── eligibility
│ └── instrument
└── behaviour (imports instrument, eligibility, party, quantification)
Instrument is a first applied ontology on the substrates, not the only possible one — a different applied domain (device lifecycle, access-control entitlement, asset maintenance) could sit atop Instrument or replace it, composing with Party/Eligibility/Behaviour through its own projection/ contracts without touching the core layers.
Layer-crossing composition rules (stated once here, they recur throughout the layer sections below):
pty:RoleOccupancy).Per-layer template. Every layer directory follows the same structure, populated as needed:
<layer>/
├── README.md # literate spec: prose + fenced turtle-spec blocks == the T-box/R-box source of truth
├── spec/<layer>.ttl # compiled OWL, mechanically extractable from README.md's turtle-spec fences
├── shapes/
│ ├── structural.ttl # SHACL property shapes (local, per-instance)
│ ├── constraints.ttl # SHACL-SPARQL, whole-graph conditions (e.g. sh:in closed-world enums)
│ └── rules.ttl # SHACL-SPARQL rules materialising derived facts
├── vocab/<layer>-vocab.ttl # mechanism-intrinsic named individuals only, never business vocabulary
├── projection/<other-layer>.ttl # this layer's declared contracts to/from another layer
├── execution/ # generated runtime artefacts + regeneration docs (invalidation-policy.md etc)
├── ontology/examples/ # single-layer worked instances
└── test/ # this layer's own shape/rule tests
Literate-spec ⇄ compiled-ttl duality. A layer’s README.md is authoritative. Each class/property is documented once, with a Definition (→ rdfs:comment), a Utility paragraph (→ fnd:utility), and a fenced code block. Two fence tags matter: ` turtle-spec ` is genuine specification content, extracted in document order and concatenated with the layer's prefix block to produce `spec/<layer>.ttl`; `turtle-example ` is illustration only and is never extracted. This convention was tightened after an early extraction pass over Foundation’s document pulled in its own template illustration by mistake — worth knowing if you’re asked to regenerate a spec/*.ttl from its README, or vice versa (walk classes/properties, render rdfs:comment as Definition and fnd:utility as Utility). The two artefacts are designed not to drift apart under this discipline: drift can only happen if someone edits the rendered Markdown prose directly instead of the annotation value it came from.
vocab/ vs domain vocabulary — a hard boundary. vocab/ folders hold only small, mechanism-intrinsic enumerations (trigger kind, role type, composition-rule type) — closed-by-default sets that are part of how the mechanism works, not what a domain calls things. Actual business vocabularies (product codes, jurisdictions, currencies) never appear in this repository; ontology/vocabulary/’s SchemeContract mechanism is precisely how a downstream implementation supplies its own without touching core specs. If a proposed vocab/ addition is hard to justify as mechanism rather than domain, that difficulty is the signal.
Governance is separate from every layer it checks. ontology/governance/ (currently an empty scaffold — parity/, scheme-contracts/, shapes/, all .gitkeep only) is meant to run over the union graph, enforcing scheme-contract compliance, deprecation posture, and cross-layer parity in CI, rather than living inside any one module.
Two licences, split by content type. .ttl files and tools/ (the reference implementation, also currently empty) are MPL 2.0 — copyleft only on the modified file itself, no obligation on what you build atop it. .md files (docs, specs, layer READMEs) are CC BY-SA 4.0. Every file requires a one-line SPDX header as its first non-blank line (# SPDX-License-Identifier: MPL-2.0 or <!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->), checked by reuse lint in CI. spec/, shapes/, vocab/, projection/ never contain executable code — that boundary is CI-enforced too.
AI-assisted contributions are welcome but carry disclosure obligations (GENAI_CONTRIBUTION.md): a Generated-by: commit trailer, a PR-description provenance section, and — specific to this project, not derived from any licensing concern — a check that AI-drafted ontology content holds the same domain-neutral line as hand-drafted content. The stated risk: generative models drift toward heavily-represented training-data domains (insurance, lending) when asked for an unprompted example, which is exactly the kind of drift vocab/’s mechanism-vs-domain boundary and the cross-domain worked examples (ontology/examples/employment.ttl etc, currently empty placeholders) are designed to catch.
Namespace convention. Base https://www.nebularis.org/neuro-semantic/lattice/, one hash namespace per layer under that base (hash rather than slash namespaces, so every term in a layer resolves with one retrieval of that layer’s document). See the prefix table in §1.
Versioning convention. Every owl:Ontology document under ontology/ carries an owl:versionIRI following Semantic Versioning 2.0.0, one version per document (spec/<layer>.ttl and vocab/<layer>-vocab.ttl independently). The full MAJOR/MINOR/PATCH classification, the import-pinning cascade obligation, and the 2026-09-25 baseline reset to 0.2.0 are recorded in ADR-A86 and the ontology versioning policy — read the policy document before bumping any layer’s version.
Loading LATTICE, and consuming it from an applied ontology. ontology/catalog-v001.xml is an OASIS XML catalog mapping every ontology IRI and version IRI under ontology/ to its file by relative path, and every spec/ and vocab/ directory holds a stub catalog chaining to it, so Protégé and the OWL API load any document with its import closure from a checkout (ADR-A88). The catalogs are generated by mise run build:ontology-catalog and checked by mise run check:ontology-catalog. tools/ontology_catalog.py also loads an import closure into rdflib, which has no catalog support. An applied ontology pins a LATTICE commit (submodule, vendored copy or package), imports LATTICE by exact version IRI, and chains its own catalog to LATTICE’s with <nextCatalog catalog="<path>/ontology/catalog-v001.xml"/>. To upgrade, it moves the pin, lists the version IRIs that changed, updates its own owl:imports by the policy’s cascade checklist, and runs its own gate. Every LATTICE layer is at major version zero, so every bump is treated as potentially breaking. To check a checkout in Protégé, see Loading LATTICE in Protégé.
This is the section to read before recommending any change. What follows is the current state of the tree after Gates 1–6, including what is authored, what remains deferred, and what is intentionally out of scope.
| Layer / area | README (spec prose) | spec/*.ttl |
shapes/*.ttl |
vocab/*.ttl |
projection/*.ttl |
Status |
|---|---|---|---|---|---|---|
| Foundation | 434 lines, complete | 230 lines, complete | empty | empty (no individuals yet — Draft/Reviewed/Active/Superseded not declared) |
n/a | Fully specified T-box |
| Vocabulary | complete | 147 lines, complete | populated (structural.ttl, constraints.ttl; rules.ttl deliberately documents no rule per ADR-A85) |
n/a | n/a (contracts belong in consuming layers) | T-box specified. Binding conformance package verified (14/14 tests). Surface and Eligibility both resolve scoped bindings (tools/surface, ontology/eligibility/shapes/rules.ttl), verified against dedicated fixtures. |
| Quantification | 1277 lines, complete | 561 lines, complete | populated (constraints.ttl, rules.ttl, structural.ttl) |
populated | empty (.gitkeep only — imported by everything above it, imports nothing back) |
Fully specified T-box + shapes. Previously missing owl:Ontology header/imports fixed under ADR-A01/Gate 1. |
| Party | 359 lines, complete | 202 lines, complete | empty | 75 lines, 7 named individuals, complete | behaviour.ttl empty |
Fully specified T-box + vocab. Now also imports Quantification (ADR-A01/Gate 1). |
| Eligibility | authored | authored | populated (constraints.ttl, rules.ttl, structural.ttl) |
populated | populated (party.ttl, quantification.ttl) |
Authored in Gate 2. Includes baseline admission profiles, interval-containment fixtures, and rule/constraint surface. Concept inclusion and exclusion (ADR-A87), hierarchical match over a scheme without a hierarchy (elg:L14, ADR-A100), and evidence bindings over an applied ontology’s own properties (ADR-A91). tools/mork_compilers compiles every condition kind except Wildcard, and AllRequired/AnySufficient profiles, to SPARQL, SHACL, and SWRL (ADR-A89). Bound conditions with a claimed single-valued path (elg:singleValued) also compile to design-time OWL classes, checked for subsumption, satisfiability and overlap through the test-only reasoning harness (ADR-A90, ADR-A83). |
| Instrument | authored | authored | populated (constraints.ttl, rules.ttl, structural.ttl) |
populated | populated (party.ttl) |
Authored in Gate 2.5. Minimal applied ontology sufficient for Behaviour target binding and supersession constraints. |
| Behaviour | authored | authored | populated (constraints.ttl, rules.ttl, structural.ttl) |
populated | populated (eligibility.ttl, instrument.ttl, party.ttl, quantification.ttl) |
Authored in Gate 3. Includes transition, guard, effect, and Sequential allowance support. Proportional remains declared but rejected. |
| Governance | scaffold + cross-layer docs | n/a | scaffold | n/a | n/a | Partially authored. Governance policy lives in docs/GOVERNANCE.md; automated governance shapes remain future work. |
| MORK | 657 lines, narrative “for dummies” guide (not literate-spec format) | Mork.ttl 1888 lines + Mork.owl, complete and large |
empty | n/a | n/a | Fully specified, pre-existing/independent vocabulary — richer and older in style (OWL-API generated, SKOS-annotation-heavy) than the newer literate-spec layers |
Persistence (dal:) |
authored (README.md + docs/precedence-and-resolution.md + docs/aggregate-boundaries.md) |
authored (spec/persistence.ttl) |
authored (shapes/constraints.ttl, including two SHACL-level fixtures) |
n/a | n/a | Fully specified, with a working compiler. Cross-cutting substrate (§8a), not a layer. tools/persistence implements resolution, validation, capability self-check, boundary-shape walking, an 11-template Mustache library, and an injection corpus, all passing under mise check:persistence. |
| SPC | 1393 lines, complete | 1227 lines, complete | empty | empty | empty (.gitkeep only) |
Fully specified but unintegrated. Placeholder namespace (http://example.org/spc#), no projection contract to any layer. Also carries ontology/spc/docs/architecture.md plus a paper and two images. Integration is out of scope for the current Eligibility/Behaviour programme. |
Applied insurance domain (ontology/applied/insurance/) |
domain README present | none | none | none | n/a | Legacy contract module dropped (epic applied-insurance-reference decision D1, AIR-1.1): it did not parse as Turtle and nothing imported it, available at the insurance-contract-v0.2.0 and applied-insurance-shapes-v0.1.0 tags. peril/ has its properties, scheme declarations and shapes (AIR-2.1), with concepts to follow in Phase 2. common/, exposure/ and submission/ are planned by that epic’s Phases 1 to 6. claims/ and a new contract/ module are deferred (epic D2). |
Root ontology/examples/*.ttl (employment, lending-covenant, saas-subscription, clinical-trial) |
— | all four files 0 bytes | — | — | — | Not authored |
ontology/examples/insure-o/ |
authored | scaffolded | authored | authored | authored | Applied validation package in progress. Minimal insurance-style structural, behavioural, and scheme-binding examples are now present under the examples tree and reference the shared substrate without naming proprietary source constructs. |
docs/architecture/decisions/, docs/GOVERNANCE.md, docs/operational-guidance.md, docs/validation-and-test-plan.md, docs/architecture/conformance-levels.md, docs/architecture/technology-options.md |
— | — | — | — | — | Authored as programme guidance. ADR set populated through A01, A03–A15, A-C1, A-C2. Operational guidance, validation plan, derivation reference, conformance ladder, and deferred-scope note are present. |
tools/, scripts/ |
— | — | — | — | — | Empty (.gitkeep only) — no reference implementation, no compiler, no extraction tooling, no scaffold-lattice.sh despite CONTRIBUTING.md referencing it |
Practical implication for anyone extending this repository: Foundation, Vocabulary, Quantification, Party, Eligibility, Instrument, and Behaviour now form a coherent authored stack with documentation, shapes, projections, fixtures, and a shared conformance corpus. The main remaining semantic deferrals are Behaviour bhv:Proportional absorption and allowance-reset edge cases, both recorded explicitly in deferred-scope-and-boundaries.md. SPC is fully specified in isolation but unintegrated. The next substantive expansion work is therefore optional applied-layer authoring or a separate SPC integration programme, not completion of missing substrate basics.
fnd:)Four independent, composable mixin capabilities: persistent identity/versioning, evidential support, temporal scoping, governance status. Foundation’s own governance-status concept is a bare value, not a lifecycle with transitions — a downstream layer wanting triggers and guards around that value composes Behaviour on top of it.
fnd:Evidence ⊑ prov:Entity, fnd:assertedBy ⊑ prov:wasAttributedTo. Temporal scoping deliberately does not align with OWL-Time’s Instant/Interval apparatus (which would force validFrom/validTo to be individuals rather than plain xsd:dateTime literals) — a considered, reversible asymmetry, not an oversight.Governed god-class. A single class carrying all four capabilities would force every adopter to take all four; independent, non-disjoint mixins let a class pick exactly what it needs.GovernanceState open at T-box, closed via SHACL. OWL’s open-world assumption means the closed enumeration (Draft/Reviewed/Active/Superseded, not yet declared anywhere) belongs in shapes/constraints.ttl as sh:in over named individuals, not in the class definition itself.Annotation property: fnd:utility (concise usage explanation; carried by every term below)
Classes:
fnd:Version ⊑ =1 hasIdentity.PersistentIdentity
fnd:PersistentIdentity ⊑ ≥1 hasVersion.Version [hasVersion ≡ hasIdentity⁻]
fnd:Evidenced (mixin, no own restriction — target of hasEvidence)
fnd:Evidence ⊑ prov:Entity ⊓ ≥1 supports.Evidenced ⊓ =1 recordedAt.xsd:dateTime
fnd:TemporallyScoped ⊑ =1 hasTemporalScope.TemporalScope
fnd:TemporalScope ⊑ =1 validFrom.xsd:dateTime [validTo optional, ≤1]
fnd:Governable ⊑ =1 hasGovernanceState.GovernanceState
fnd:GovernanceState (bare; enumeration deferred to vocab/ + SHACL sh:in)
Disjointness:
AllDisjoint( Version, PersistentIdentity, Evidence, TemporalScope, GovernanceState )
Evidenced ⊥ Evidence
TemporallyScoped ⊥ TemporalScope
Governable ⊥ GovernanceState
Object properties:
hasIdentity : Version → PersistentIdentity, Func, inv(hasVersion)
hasVersion : PersistentIdentity → Version (inverse-functional, entailed)
supersededBy : Version → Version, Asym, Irref (NOT Transitive — walk the chain to reach latest)
hasEvidence : Evidenced → Evidence, inv(supports) (not Func — accumulates over time; no min — absent is normal)
supports : Evidence → Evidenced
assertedBy : Evidence → prov:Agent, ⊑ prov:wasAttributedTo
hasTemporalScope: TemporallyScoped → TemporalScope, Func
hasGovernanceState: Governable → GovernanceState, Func
Data properties:
recordedAt : Evidence → xsd:dateTime, Func
validFrom : TemporalScope → xsd:dateTime, Func, required
validTo : TemporalScope → xsd:dateTime, Func, optional
| Term | Kind | Key characteristics |
|---|---|---|
fnd:Version |
Class/mixin | hasIdentity = 1 |
fnd:PersistentIdentity |
Class | hasVersion ≥ 1 |
fnd:Evidenced |
Class/mixin | — |
fnd:Evidence |
Class | ⊑ prov:Entity; supports ≥ 1; recordedAt = 1 |
fnd:TemporallyScoped |
Class/mixin | hasTemporalScope = 1 |
fnd:TemporalScope |
Class | validFrom = 1 |
fnd:Governable |
Class/mixin | hasGovernanceState = 1 |
fnd:GovernanceState |
Class | open T-box; closed via SHACL |
hasIdentity/hasVersion |
Obj. prop. | Functional / inverse pair |
supersededBy |
Obj. prop. | Asymmetric, Irreflexive, not Transitive |
hasEvidence/supports |
Obj. prop. | inverse pair, not Functional |
assertedBy |
Obj. prop. | subPropertyOf prov:wasAttributedTo |
hasTemporalScope |
Obj. prop. | Functional |
hasGovernanceState |
Obj. prop. | Functional |
recordedAt, validFrom, validTo |
Data prop. | all Functional, xsd:dateTime |
A domain class from a higher layer (e.g. ins:Obligation, not defined in Foundation) composes mixins directly:
ins:Obligation ⊑ fnd:Version ⊓ fnd:Evidenced ⊓ fnd:TemporallyScoped
An ordinary populated instance does not take fnd:Governable — that mixin is for specification artefacts (a wording template, a SHACL shape) under review, not for ordinary contract facts.
⊑ prov:Entity, ⊑ prov:wasAttributedTo) are candidates for splitting into a separate optional import module — not built.GovernanceState’s four named individuals belong in vocab/foundation-vocab.ttl and are not yet declared anywhere in the repository — this is a real gap: nothing currently instantiates Draft/Reviewed/Active/Superseded, so any downstream layer or example that references fnd:Active (Vocabulary’s own worked example does exactly this) is using a forward reference to a term that does not exist yet.supersededBy (two versions being superseded must share one PersistentIdentity) belongs in shapes/constraints.ttl as SHACL-SPARQL, not attempted as an OWL property chain — not built.riot or rdflib over spec/foundation.ttl (and the other compiled .ttl files) is a real outstanding validation step, not merely optional polish.voc:)Governs how external, domain-specific concept schemes bind into other layers’ concept-valued properties, without those layers naming a domain concept directly. Builds on W3C SKOS, adding governed scheme-level versioning, a structural contract mechanism, and scoped, time-bounded bindings for contexts where the scheme differs or changes over time. Vocabulary does not resolve a fuzzy label to a concept (that is MORK’s job) — it defines the structural binding model and the inputs to resolution.
ConceptScheme is a fnd:Version; an individual skos:Concept gets no independent version thread — tracking meaning drift of one concept across scheme versions is left unaddressed.SchemeContract is structural only — never encodes what a scheme is about. It constrains which property, which scheme, and what governance state that scheme must hold; the aboutness is prose, supplied by whichever domain ontology extends the framework.SchemeContract extension.SchemeBinding connects one contract to one scheme edition, zero or more conjunctive opaque scopes, and one temporal scope. Multiple bindings are separate nodes because boundScheme is functional.boundScheme is the fallback when no binding applies, and a scopeless binding must agree with it when both exist.resolvedUnder to retain the binding that supplied its concept values. It is not re-resolved when current bindings change. Binding resolution, conflict, and provenance checks require SHACL-SPARQL or an equivalent reference implementation.Classes:
voc:ConceptScheme ⊑ skos:ConceptScheme ⊓ fnd:Version ⊓ fnd:Governable
voc:SchemeContract ⊑ fnd:Version ⊓ fnd:Governable ⊓ ≥1 constrainsProperty
voc:SchemeBinding ⊑ fnd:TemporallyScoped ⊓ =1 forContract.SchemeContract ⊓ =1 bindsScheme.ConceptScheme
voc:BindingScope (bare, opaque to Vocabulary; no individuals shipped)
Disjointness:
AllDisjoint( ConceptScheme, SchemeContract, SchemeBinding, BindingScope )
ConceptScheme ⊥ skos:Concept
Object properties:
constrainsProperty : SchemeContract → rdf:Property (punning — points at a property defined elsewhere)
requiresGovernanceState: SchemeContract → fnd:GovernanceState (disjunctive if multi-valued: any one value suffices; optional)
boundScheme : SchemeContract → ConceptScheme, Func (optional — unbound is the normal starting state)
forContract : SchemeBinding → SchemeContract, Func
bindsScheme : SchemeBinding → ConceptScheme, Func
bindingScope : SchemeBinding → BindingScope (optional, conjunctive when multi-valued)
resolvedUnder : any versioned record → SchemeBinding (one value per contract drawn on)
| Term | Kind | Key characteristics |
|---|---|---|
voc:ConceptScheme |
Class | ⊑ fnd:Version, fnd:Governable, skos:ConceptScheme; ⊥ voc:SchemeContract, voc:SchemeBinding, voc:BindingScope, skos:Concept |
voc:SchemeContract |
Class | ⊑ fnd:Version, fnd:Governable; constrainsProperty ≥ 1 |
voc:SchemeBinding |
Class | ⊑ fnd:TemporallyScoped; forContract = 1; bindsScheme = 1 |
voc:BindingScope |
Class | Opaque context marker; no individuals shipped |
voc:constrainsProperty |
Obj. prop. | dom SchemeContract, range rdf:Property |
voc:requiresGovernanceState |
Obj. prop. | dom SchemeContract, range fnd:GovernanceState; optional, disjunctive |
voc:boundScheme |
Obj. prop. | Functional; optional |
voc:forContract |
Obj. prop. | Functional; domain SchemeBinding, range SchemeContract |
voc:bindsScheme |
Obj. prop. | Functional; domain SchemeBinding, range ConceptScheme |
voc:bindingScope |
Obj. prop. | Domain SchemeBinding, range BindingScope; optional and conjunctive |
voc:resolvedUnder |
Obj. prop. | No domain; range SchemeBinding; historical resolution provenance |
# Authored once, alongside ins:hasPerilType's own definition (Instrument, not yet written):
ex:peril-contract a voc:SchemeContract ;
voc:constrainsProperty ins:hasPerilType ;
voc:requiresGovernanceState fnd:Active . # forward reference — fnd:Active not yet declared, see §4.6
# Bound later, independently, by a downstream implementation:
ex:acme-peril-codes-v2 a voc:ConceptScheme ;
fnd:hasIdentity ex:acme-peril-codes-identity ;
fnd:hasGovernanceState fnd:Active .
ex:peril-contract voc:boundScheme ex:acme-peril-codes-v2 .
ins:hasPerilType itself is never named in Vocabulary’s own spec — only in this illustration, demonstrating the contract mechanism constrains a property without ever knowing what it is about.
Scoped and temporal binding — two contexts can use different scheme editions, and one context can change edition without rewriting earlier records:
ex:job-family-contract a voc:SchemeContract ;
voc:constrainsProperty ex:hasJobFamily .
ex:north a voc:BindingScope .
ex:north-2026a a voc:SchemeBinding ;
voc:forContract ex:job-family-contract ;
voc:bindsScheme ex:north-v1 ;
voc:bindingScope ex:north ;
fnd:hasTemporalScope ex:jan-to-jul .
ex:north-2026b a voc:SchemeBinding ;
voc:forContract ex:job-family-contract ;
voc:bindsScheme ex:north-v2 ;
voc:bindingScope ex:north ;
fnd:hasTemporalScope ex:from-jul .
ex:offer-letter-117-v1 voc:resolvedUnder ex:north-2026a .
The example is illustrative and is not part of the extracted Vocabulary specification. A consumer supplies the active scopes and resolution time. It must reject equal-specificity conflicts rather than choosing an arbitrary scheme.
SchemeContract/ConceptScheme individuals belong in consuming layers and in ontology/governance/scheme-contracts/, not in this T-box.shapes/structural.ttl mirrors the OWL cardinality restrictions (forContract, bindsScheme, hasTemporalScope, hasIdentity, hasGovernanceState), and shapes/constraints.ttl adds four SHACL-SPARQL checks — temporal interval order, the context-independent form of an equal-specificity conflict (identical scope sets with overlapping validity), scopeless-binding/boundScheme agreement, and historical-provenance time (against a documented, non-normative vvp: validation-profile term; see that file’s header). Strict-superset precedence is genuinely context-dependent and is not a SHACL shape — it is implemented instead by the reference resolver in tools/vocabulary/ (vocabulary.resolver.resolve), which also raises a named conflict rather than choosing silently.boundScheme now resolve an applicable binding first: Surface’s compiler (tools/surface/src/surface/compile.py) calls vocabulary.resolve for a contract-bound population, given a new srf:activeBindingScope and the compiler’s resolution time, and Eligibility’s HierarchyWellFoundednessShape (ontology/eligibility/shapes/rules.ttl) checks every scheme a contract could resolve to (boundScheme or any SchemeBinding). Verified against ontology/surface/examples/employment-job-family-scoped.ttl and a synthetic scoped-only cycle fixture, respectively.mise run check:vocabulary passes 14/14, python -m unittest surface.test_surface -q passes 62/62, and mise run check:python-root passes 77/77 plus Phase 8 conformance, all run in the working Python environment.pty:)Actor, Role, and the reified qualified-relation individual (Role Occupancy) connecting them, scoped and time-bound; Participation Groups with shares/composition rules; Delegation between an accountable role and a performing one — all built on that reification. Imports Foundation + Vocabulary; imported by Instrument, Eligibility, Behaviour. Upward references (an Obligation’s obligor/obligee, an Effect populating a contingent occupancy, a Guard testing a delegation’s scope) are deliberately left to the higher layer’s own projection/ files — Party never depends upward.
RoleOccupancy has no property pointing back at what it’s scoped to (no withinInstrument ranging over ins:Instrument) — that would create an upward dependency Party cannot have. Scoping is established entirely from the referencing (higher-layer) side.occupiedBy optional, inRole required — the formal mechanism for contingent role occupancy: a role designed into an instrument from the outset, unoccupied until some triggering event binds an actor.GroupMembership), not a property on RoleOccupancy. Share is a property of participating in a specific group; putting it directly on the occupancy would be ambiguous if one occupancy ever belonged to more than one group. GroupMembership reifies participation the same way RoleOccupancy itself reifies Actor-in-Role.Role and CompositionRule are open at T-box, closed-by-default in vocab/party-vocab.ttl. “Closed” = closed-by-default, extensible by a downstream implementation supplying its own named individuals plus a correspondingly extended/overridden SHACL shape — not a permanent ceiling.Delegation carries no formal scope property — formalising one would either duplicate Eligibility’s mechanism or create an upward dependency. Delegation states only that a performing occupancy discharges an accountable one; whether performance is within scope is composed on top by Eligibility.Actor and Role are bare classes — no Foundation mixins, no internal structure; a domain adds whatever identification fields it needs via subclassing.Classes:
pty:Actor (bare)
pty:Role (bare; open T-box, closed-by-default in vocab/party-vocab.ttl)
pty:RoleOccupancy ⊑ fnd:Version ⊓ fnd:Evidenced ⊓ fnd:TemporallyScoped ⊓ =1 inRole.Role
pty:ParticipationGroup ⊑ fnd:Version ⊓ fnd:Evidenced ⊓ =1 hasCompositionRule.CompositionRule ⊓ ≥1 hasParticipant.GroupMembership
pty:CompositionRule (bare; open T-box, closed-by-default in vocab/party-vocab.ttl)
pty:GroupMembership ⊑ =1 memberOccupancy.RoleOccupancy ⊓ =1 memberOf.ParticipationGroup ⊓ =1 share.xsd:decimal
pty:Delegation ⊑ fnd:Evidenced ⊓ fnd:TemporallyScoped ⊓ =1 delegatesFrom.RoleOccupancy ⊓ =1 delegatesTo.RoleOccupancy
Disjointness:
AllDisjoint( Actor, Role, RoleOccupancy, ParticipationGroup, GroupMembership, Delegation )
Object properties:
occupiedBy : RoleOccupancy → Actor, Func (optional — unset = designed-in-but-unfilled, the contingent-occupancy state)
inRole : RoleOccupancy → Role, Func, required
memberOccupancy : GroupMembership → RoleOccupancy, Func, required
memberOf : GroupMembership → ParticipationGroup, Func, required, inv(hasParticipant)
hasParticipant : ParticipationGroup → GroupMembership (entailed inverse; typically populated by query, not asserted directly)
hasCompositionRule: ParticipationGroup → CompositionRule, Func, required
delegatesFrom : Delegation → RoleOccupancy, cardinality 1 per Delegation individual, NOT globally functional (an accountable occupancy may have several Delegations over time/in parallel)
delegatesTo : Delegation → RoleOccupancy, cardinality 1 per Delegation individual, NOT globally functional (one performer may discharge several accountable occupancies)
Data properties:
share : GroupMembership → xsd:decimal, Func (proportion, e.g. 0.40 for 40% — not an absolute amount; add a separate property for fixed amounts)
Named individuals (vocab/party-vocab.ttl — baseline, extensible):
Roles: pty:Obligor, pty:Obligee, pty:Guarantor, pty:Accountable, pty:Performing
CompositionRules: pty:SeveralOnly, pty:JointAndSeveral
Role individuals and their intent: Obligor/Obligee are the direction-of-obligation pair (Obligee doubles as the role a contingent occupancy is typed with once eventually filled). Accountable/Performing are the two sides of Delegation (delegatesFrom always points at an Accountable occupancy, delegatesTo always at a Performing one). Guarantor backs another occupancy’s obligation, becoming answerable on that occupancy’s default — but has no mechanism of its own yet: it needs Instrument’s Obligation and a Behaviour trigger together (contingent liability activating on default), and is flagged as the least mechanically complete individual in the baseline.
Composition-rule individuals: SeveralOnly — each member’s exposure independently capped, a defaulting member’s shortfall is simply unmet, does not redistribute. JointAndSeveral — any member may be called for the full obligation, with a right of recourse against the others afterward (the group’s internal contribution accounting is a separate concern this rule does not resolve).
| Term | Kind | Key characteristics |
|---|---|---|
pty:Actor |
Class | bare |
pty:Role |
Class | bare, open-T-box/closed-by-default |
pty:RoleOccupancy |
Class | Version, Evidenced, TemporallyScoped; inRole = 1 |
pty:ParticipationGroup |
Class | Version, Evidenced; hasCompositionRule = 1; hasParticipant ≥ 1 |
pty:CompositionRule |
Class | bare, open-T-box/closed-by-default |
pty:GroupMembership |
Class | bare; memberOccupancy, memberOf, share each = 1 |
pty:Delegation |
Class | Evidenced, TemporallyScoped; delegatesFrom, delegatesTo each = 1 |
occupiedBy |
Obj. prop. | Functional; optional |
inRole |
Obj. prop. | Functional; required |
memberOccupancy |
Obj. prop. | Functional; required |
memberOf / hasParticipant |
Obj. prop. | inverse pair; memberOf Functional+required |
share |
Data prop. | Functional; xsd:decimal; proportion |
hasCompositionRule |
Obj. prop. | Functional; required |
delegatesFrom / delegatesTo |
Obj. prop. | not globally Functional; = 1 per Delegation |
Six classes mutually disjoint. No owl:Alignments section — Party introduces no external-vocabulary dependency (unlike Vocabulary/SKOS or Foundation/PROV-O); everything here is LATTICE-internal or reuse of Foundation’s mixins.
Several liability — three occupancies sharing one obligation, none liable beyond its own share:
ex:group-1 a pty:ParticipationGroup ; pty:hasCompositionRule pty:SeveralOnly .
ex:occ-a a pty:RoleOccupancy ; pty:inRole pty:Obligor ; pty:occupiedBy ex:syndicate-a .
ex:mem-a a pty:GroupMembership ; pty:memberOccupancy ex:occ-a ; pty:memberOf ex:group-1 ; pty:share "0.40" .
# occ-b/mem-b (0.35), occ-c/mem-c (0.25) follow the same pattern.
Note what is absent: nothing here says which obligation the group fulfils — that reference (ins:fulfilledBy or similar) is declared from Instrument’s side, in Instrument’s own projection file, pointing at the group.
Contingent occupancy + delegation split:
ex:third-party-occ a pty:RoleOccupancy ; pty:inRole pty:Obligee . # inRole set, occupiedBy unset
# Later, a Behaviour Effect (not Party's own mechanism) adds:
# ex:third-party-occ pty:occupiedBy ex:claimant-x .
ex:sponsor-occ a pty:RoleOccupancy ; pty:inRole pty:Accountable .
ex:cro-occ a pty:RoleOccupancy ; pty:inRole pty:Performing .
ex:delegation-1 a pty:Delegation ;
pty:delegatesFrom ex:sponsor-occ ; pty:delegatesTo ex:cro-occ .
ontology/party/spec/party.md §4 should be tightened to describe CompositionRule and Role as closed-by-default-and-extensible consistently (currently one is stated more strongly “closed” than the vocab document’s own §4 implies).Guarantor’s activation mechanism is now expressible through the authored Instrument and Behaviour layers, but it is not yet illustrated by a dedicated cross-layer fixture.sh:in constraint enumerating the baseline Role/CompositionRule individuals (and the pattern for a downstream implementation extending or overriding it) belongs in shapes/constraints.ttl — not built for any layer.Eligibility, Behaviour, and Instrument are now authored. What remains useful here is not a reconstruction of their scope from forward references, but a concise statement of the boundary lines that still matter when extending them:
Instrument (ins:) — remains the first applied ontology on top of the substrates: the generic shape of a governing document, with Party-facing bindings declared in its own projection surface. Future extension work here is applied-ontology elaboration, not substrate completion.
Eligibility (elg:) — remains the admissibility layer for conditions, questions, and decisions. Future work here is profile growth, additional strategy families, or applied-layer bindings, not a missing baseline mechanism.
Behaviour (bhv:) — remains the state, transition, trigger, guard, and effect layer. Its current extent surface is intentionally narrow: Sequential allowance handling is usable, while Proportional and reset edge cases remain explicitly deferred pending the prerequisites recorded in deferred-scope-and-boundaries.md.
Governance — runs over the union graph (not a layer instances live in), enforcing scheme-contract compliance, deprecation posture, cross-layer parity, in CI. ontology/governance/scheme-contracts/ is explicitly where authored voc:SchemeContract individuals for cross-cutting concerns would live; ontology/governance/parity/ presumably checks that sibling layers (e.g., all six) maintain structural parity in how they apply the shared per-layer template.
SPC — is not green-field, but it is still unintegrated with the LATTICE stack. Treat it as adjacent authored work that requires namespace harmonisation, projection contracts, and a conformance story before it joins the dependency picture.
Recommendation for an agent asked to author one of these layers: follow the literate-spec convention exactly (§2) — write the README.md first with Definition/Utility pairs and turtle-spec/turtle-example fencing, then extract spec/<layer>.ttl mechanically — rather than writing the compiled Turtle directly, to stay consistent with how Foundation/Vocabulary/Party were built and keep the two artefacts from the outset in the non-drifting relationship §2 describes.
mrk: / Mork.ttl :)MORK predates the newer literate-spec layers stylistically — it is a large (1888-line), OWL-API-generated, SKOS-annotation-heavy vocabulary (skos:definition, skos:scopeNote, skos:example used as de facto documentation, rather than the fnd:utility convention). It is functionally independent of LATTICE’s own layers; LATTICE is one possible mapping target for it, not a dependency.
MORK addresses the n × m data-integration problem (n sources × m consumers, every change touching all of them) by giving every source-to-ontology alignment a first-class, typed graph representation instead of ad hoc ETL code. Three separated layers, each changing at a different rate:
mrk:DataMapping individuals connecting intent to specific target classes/properties/individuals, stratified by which OWL box they touch: T-Box (exactTBoxMatch/broadTBoxCategoryMatch/narrowTBoxCategoryMatch — “this creates/references a class”), A-Box (exactABoxMatch and broad/narrow variants — “this creates/references an individual”), R-Box (exactRBoxMatch/inverseRBoxMatch and broad/narrow variants — “this creates/references a property/relation”). Ordering is derived automatically from this stratification: T-Box before A-Box before R-Box.Compilation boundary — the core architectural commitment: the LLM is never invoked at runtime for anything but proposing intent/mapping nodes. Everything downstream of a validation gate (structural SHACL checks, GCI/disjointness consistency checks, type-safety checks against the target ontology) is deterministic — compilation, artefact generation, execution. This buys reproducibility (same validated graph → same artefacts regardless of LLM variance), auditability (every artefact traces back through mapping → intent → original source text), and composability (independently generated mapping fragments compose because they share this algebraic structure).
skos:Concept
⊑ mrk:DataConcept ⊓ ∃conceptScheme.TaxonomyScheme # abstract concept to be mapped
⊑ mrk:DataMapping ⊓ ∃mappingScheme.MappingScheme # captures a mapping; usually skos:note-annotated with rationale
⊑ mrk:Datum # explicit individuation of a DataConcept in a target OntologicalScheme
⊑ mrk:DeferredContext # placeholder axiom another DataMapping must reference via an object property
⊑ mrk:Hypothesis ≡ ∃(hypothesisMapping⁻).DataMapping # a mapping supplying supporting evidence for another
⊑ mrk:IndexedMapping
⊑ mrk:Lookup ⊓ ∃dataRef.xsd:string # base data → named individual; dataRef = source path
⊑ mrk:UncertainMapping
⊑ mrk:Digraph (deprecated — use compositeBroaderMapping/compositeNarrowerMapping instead)
mrk:Representation
⊑ mrk:IdentifiableElement ⊓ ∃identifier.xsd:string
⊑ mrk:Entity # an entity in a source representation scheme, marked with its native identifier
⊑ mrk:Membership # by convention, only subclassed, never instantiated directly
mrk:Interpolation ≡ ∃interpolationComponent.DataMapping ⊓ ∃interpolationTemplate.xsd:string
⊑ skos:OrderedCollection # positional template ("$1, $2, ...") over an ordered set of component mappings
mrk:MappingScheme ⊑ skos:ConceptScheme # captures mappings from a RepresentationScheme to an OntologicalScheme
mrk:RepresentationScheme, mrk:OntologicalScheme, mrk:TaxonomyScheme — the three source/target scheme kinds
mrk:OwlAxiom
⊑ mrk:DeferredConceptIRI, DeferredClassDefinition, DeferredObjectPropertyDefinition,
DeferredDataPropertyDefinition, DeferredIndividualDefinition, DeferredABoxReference
# placeholders for axioms a mapping proposes creating, referenced before they formally exist —
# needed because instances of owl:ObjectProperty in an RDF triple's object position are disallowed
# by some processing environments (e.g. owlapi); resolved via owl:sameAs once materialised.
mrk:OwlClass, mrk:OwlObjectProperty, mrk:OwlDataProperty # T-box/R-box element wrappers
mrk:Array, mrk:Collection ⊑ (mrk:OrderedCollection | mrk:UnorderedCollection), mrk:CollectionElement, mrk:AnonymousElement
mrk:Attribute, mrk:Association, mrk:Chaining, mrk:Composition, mrk:Objectification # structural pattern vocabulary for source schema shapes
mrk:SerializationFormat ⊒ mrk:JSON, mrk:XML, mrk:YAML
mrk:WeightedMatch # base for confidence-carrying match assertions
Box-stratified match properties (each with broad/narrow/exact variants):
{exact,broad,narrow}TBoxCategoryMatch, {exact,broad,narrow}ABoxCategoryMatch,
{exact,broad,narrow}RBoxCategoryMatch, inverseRBoxMatch
exactTBoxMatch / exactABoxMatch / exactRBoxMatch — direct create-or-reference
broadCategoryMatch / narrowCategoryMatch — generic (stratum-agnostic) hierarchical match
broadConceptRole / narrowConceptRole, broadNavigableConceptRole / narrowNavigableConceptRole
Composition / DAG-building operators:
compositeNarrowerMapping, compositeBroaderMapping, compositeNarrowerTemplate, compositeBroaderTemplate
broaderApplicative — apply sub-mappings within a parent mapping's output context
deferredMapping — this mapping cannot finish until another completes
templateMapping / identityTemplateMapping / templateClassMapping — reusable pattern, instantiated per source
hypothesisMapping — supporting-evidence relation between mappings
dependentMapping, siblingMapping, relatedMapping, placeholderMapping, indicativeMapping, possibleMatch, partialMatch,
missingOrUnrelatedMatch, incompleteMapping
Confidence / weighting:
weightedBroader, weightedNarrower, weighting — carries the 0–100 confidence score; effective confidence
down a dependency chain = local_confidence × min(child_confidences) (see §8.4)
Structural/lexical/semantic evidence:
lexicalMatch, semanticMatch, structuralMatch, pathMatch, digraphMatch (deprecated path), digraphOf
Data access / value shaping:
dataRef, dataInline, data, path, reference, template, identifier, name,
conceptId, conceptName, conceptIRI, conceptFQNameTemplate, conceptNameTemplate, conceptShortNameTemplate,
individualIRI, individualName, externalPropertyValue, collectionElementScalarValue, orderedItems, uniqueItems, itemsConstrained
Scheme / membership plumbing:
conceptScheme, mappingScheme, ontologicalScheme, representationScheme, hasConcept, hasMapping, memberOf, memberProperty,
mappingFor, mappingIndex, mappingRecommendation, representationOf, representedAs, relatedProperty
Assertion-generation (drive the compiler's SHACL/SWRL/RML output):
assertsPropertyDomains, assertsPropertyRanges, propertyMappingAssertions, referenceDataMapping, referenceDataPath
Governance annotations:
mappingNote, userDeclined
Category-theoretic framing (profunctors, Galois connections; the README is explicit that using MORK never requires understanding this maths, only trusting what it proves):
ε(t) ≈ K·exp(−(1+d′)·t / (K·ln K)) — fraction of fields still needing help decays with mapping-run count t, community acceleration factor d′, vocabulary size K.Semantica (referenced, not present here) is positioned as handling data acquisition — ingestion, normalisation, entity extraction, dedup — which MORK deliberately does not address; MORK owns schema modelling, ontological alignment, artefact generation, and AI-output governance. The stated integration point is an adapter layer between Semantica’s entity-extraction output and MORK’s mapping pipeline — not built, not this repository’s concern. The ingestion vision refines this for document-scale ingestion: the model authors MORK content directly, and Semantica-like services supply grounding and memory behind interfaces LATTICE owns.
MORK’s vocabulary is real and complete (Mork.ttl), but its narrative document (README.md) is aspirational in tone throughout (“Our convergence theorem,” “should be proven theorems,” “we hope to see”) — treat the mathematical claims in §8.4 as design intent the vocabulary was built to support, not as verified, benchmarked properties of a running system. There is no tools/ implementation of the compiler, validator, or agents described in Part 6 of the README anywhere in this checkout. If asked to assess MORK’s maturity: the T-box is production-ready as a vocabulary; the pipeline, agents, and convergence guarantees are unimplemented specification.
dal:)ontology/persistence is a cross-cutting substrate, not a layer in the dependency table in §1: it targets classes, graphs, and shapes by IRI reference only, imports nothing from Foundation through Behaviour, and none of them import it back. It sits alongside MORK and Surface as infrastructure every layer can be configured through without any layer depending on it.
The patterns in rdf-sparql-patterns-guide.md (uniqueness, ordering, concurrency, and their combination) are a menu, not a selection mechanism. LATTICE ships as a framework: an adopter takes some or all of it and decides, per class or per deployment of their own applied ontology, which of the guide’s patterns apply. ontology/persistence is that selection mechanism, and tools/persistence (a design-time-only compiler, no store SPI, no live backend) turns a selection into generated SPARQL.
Six independently scopable dimensions (aggregate boundary, concurrency, ordering grain, receipt model, meta topology, uniqueness), five scope kinds ranked by whether resolving them needs reasoning (dal:GraphPatternScope, dal:NamespaceScope, dal:ClassScope, dal:ShapeScope, dal:EquivalentClassScope, only the last of which needs one), and a fixed per-dimension precedence algorithm: highest dal:priority wins, non-reasoning beats reasoning at a tie, any further tie is a compile-time refusal. Full design: persistence-profile-substrate.md; governing decisions: ADR-A78, ADR-A79, ADR-A80.
A substrate ontology (Behaviour, Party, and so on) never binds a dal:DataAccessProfile to its own classes. Authority over how a shared class is persisted belongs to whichever applied ontology deploys it, expressed by scoping to that deployment’s graph pattern, which structurally outranks a bare class-level scope. ontology/persistence/shapes/constraints.ttl’s SharedClassProfileWarningShape flags the anti-pattern (a bare dal:ClassScope targeting a class outside its own namespace) as a SHACL warning, not a hard rejection.
Implemented, not aspirational: ontology/persistence/spec/persistence.ttl and shapes/constraints.ttl are real OWL/SHACL, tools/persistence is a working Python compiler with a passing test suite (mise check:persistence) covering the resolver, validator, capability self-check, boundary-shape walker, an 11-template library, an injection corpus, determinism, and full compile→instantiate→parse round trips. platform/housekeeping (ADR-A80) is a separate, not-yet-built unit: its contracts and configuration model are designed, its execution engine is explicitly deferred alongside the store SPI (proposed A75).
These recur across the layer sections above and are the load-bearing joints of the whole design — worth having in one place for quick recall:
Version, Evidenced, TemporallyScoped, Governable) are designed to be combined à la carte on a domain class defined elsewhere (ins:Obligation ⊑ Version ⊓ Evidenced ⊓ TemporallyScoped, deliberately not ⊓ Governable — see §4.5).RoleOccupancy reifies Actor-in-Role; GroupMembership reifies occupancy-in-group; Delegation reifies accountable-discharged-by-performing. Each of these could in principle have been a direct property; each was reified instead because the relation itself needed to survive change, carry evidence, or scope a share value unambiguously.projection/ file. No lower layer (Foundation, Vocabulary, Party) ever names a class or property from a higher layer (Instrument, Eligibility, Behaviour). A lower layer’s document may illustrate with a higher-layer term (always under an ins:/ex: prefix explicitly marked as “not part of this layer’s own namespace”), but never specifies against it.RoleOccupancy can exist with inRole set and occupiedBy unset — the shared representation for “designed into the instrument from the outset, filled later by an event.” What fills it is a Behaviour Effect, never a Party-layer mechanism itself.vocab/ baselines are closed-by-default, not closed-permanently. Both pty:Role/pty:CompositionRule and (by the same reasoning, though only stated explicitly for the latter) any future layer’s mechanism-intrinsic vocab are meant to be extended by a downstream implementation supplying additional named individuals plus a correspondingly extended/overridden SHACL shape — never by a PR against this repository.SchemeContract decouples “this property needs governed values” from “here is the scheme.” The two can be authored months apart by different parties; nothing in the mechanism requires the scheme to exist when the contract is declared.“Hash identities” are intended to make LATTICE’s versioned RDF graphs reproducible, cacheable, and auditable. They answer different questions and must not be collapsed into one digest.
The current repository does not implement this model yet. Foundation currently provides the semantic building blocks for identity and versioning:
fnd:PersistentIdentity represents the continuing thing.fnd:Version represents one state of that thing.fnd:hasIdentity links a version to its persistent identity.fnd:supersededBy links one version to its successor.For example, an obligation edited after a contract change should receive a new ins:Obligation version, linked to the same persistent identity. It must not be mutated in place. The planned hashing model extends this with deterministic identities for authored content and derived outputs.
| Identity | Question answered | Typical use |
|---|---|---|
| Semantic content hash | Did the meaning-bearing declaration change? | Detecting semantic changes and deciding which semantic caches are invalid |
| Generation/profile identity | Were these outputs produced under the same compiler, evaluator, registry, validation, and IRI-binding configuration? | Determining whether two derived products are interchangeable |
| Build artefact hash | Did regeneration produce the same bytes or graph? | Checking deterministic compilation and detecting accidental edits |
| Runtime state hash | Is this execution or replay at the same state and position? | Replay verification, event-log comparison, and operational state reconciliation |
The planning documents sometimes call all four “hash identities”, but generation identity is conceptually a profile identity. It may be represented by a versioned identifier or digest rather than being treated as semantic content itself.
This is computed from a canonical representation of the meaning-bearing declaration. For Eligibility, that includes the dimensions and constraints that actually affect admission. For Behaviour, it includes declarations such as transitions, triggers, guards, activation policies, effect payloads, and target bindings.
The canonicalisation contract is intended to remove irrelevant representation differences, including:
The important optimisation is wildcard elision. If a newly added dimension is unconstrained for an existing profile, its wildcard value is omitted from that profile’s canonical form. Adding the dimension therefore leaves existing semantic hashes unchanged. A profile changes its hash only when it actually uses the new dimension.
The planned elg:Unsourced marker is deliberately not elided. It distinguishes “explicitly unconstrained” from “we never supplied this value”. It still admits everything, but it participates in the hash and can fail governance when the dimension is runtime-critical.
The semantic hash is therefore about meaning, not deployment. Two deployments with identical declarations but different generated property IRIs can have the same semantic hash.
A semantic hash alone is insufficient for reusing a derived artefact. The same declarations may be compiled using different:
Those differences can produce incompatible outputs even when the declarations mean the same thing.
The planned cache rule is:
cache valid = semantic content hash + generation/profile identity
This preserves the benefit of stable semantic hashes without claiming that outputs from different compiler configurations are interchangeable.
This identifies the generated result itself, such as:
A deterministic generator should produce the same artefact hash from the same semantic input and generation identity. If the hash changes unexpectedly, the implementation or serialisation process changed.
This is distinct from the semantic hash. A harmless compiler or serialisation change may alter the artefact hash without changing the declaration’s meaning.
This applies to execution rather than static declarations. It represents a state snapshot or replay position, potentially including:
Runtime hashing supports deterministic replay. Two executions that differ only in wall-clock timestamps or storage addresses may still be equivalent if those values are excluded from the comparison projection. Differences in queue order or final state should not be ignored because they can change behaviour.
The intended lifecycle is:
The design explicitly rejects in-place mutation of authored Instrument nodes. A Behaviour effect such as StructureWrite or Reparameterisation should create a new version or derived node, link it to the execution as evidence, recompute the structural or semantic hash, and identify dependent derived products for invalidation. Withdrawal is represented through supersession or inactivity, not by deleting triples.
The broader A-12 proposal also classifies derived products, including inferred statements, validation results, materialisations, projections, indexes, generated artefacts, compiled evaluators, and decision or execution records. Each product should record:
That authority declaration matters because a materialised or projected statement must not automatically outrank its source. It may be advisory, a reproducible cache, operationally authoritative, or externally authoritative and synchronised.
The attached plans point toward a Foundation-level extension, roughly involving:
fnd:DerivedArtefactfnd:derivedFromfnd:GenerationProfiletools/ or a later compilation areaFoundation now declares fnd:DerivedArtefact, fnd:DerivationRun and fnd:DerivationKind, aligned with PROV-O, and uses PROV-O’s own derivation links rather than a fnd:derivedFrom (ADR-A92). Surface’s derived records subclass it. Hash properties, canonicalisation and invalidation remain Surface’s own (srf:, tools/surface), and a shared Foundation generation-profile class is not planned.
One significant migration consequence is already called out. When the canonicalisation contract changes, every affected semantic or structural hash changes, so the derived estate requires a planned full rehash and regeneration. After that cutover, wildcard elision provides the intended steady-state benefit: adding an unused dimension should not invalidate existing profiles or their derived artefacts.
Ranked by what would most unblock further work, not by section order:
fnd:GovernanceState’s four named individuals (Draft, Reviewed, Active, Superseded) in vocab/foundation-vocab.ttl. Currently a real gap, not a stylistic one — Vocabulary’s own worked example already forward-references fnd:Active, and any populated graph using governance status today has nothing to actually point at..ttl through an actual OWL/RDF parser (riot/Apache Jena or rdflib). Every layer’s own “Open Items” section flags this as unverified, checked only by manual review — a cheap, high-value validation pass before any of it is treated as load-bearing.shapes/constraints.ttl for Foundation and Party before extending either layer further — both documents defer specific, named closed-world constraints (the GovernanceState enumeration, the Role/CompositionRule sh:in baseline, the supersededBy same-identity check) to a SHACL layer that does not exist in any layer yet.CompositionRule/Role with party-vocab.ttl’s own, more precise “closed-by-default, extensible” framing (§6.6) — a small textual fix, not a design change.applied-ontology-readiness, ADRs A-83 and A-86 to A-96 Accepted). Clean examples, versioning guarantees, the import catalog, concept and profile compilation, evidence bindings, the Foundation derived-artefact contract and PROV-O alignment are implemented. The design-time OWL backend (ADR-A90) and its checks run through the ADR-A83 reasoning harness. The Quantification and Instrument extensions (ADRs A-93 to A-96) are implemented. See the status record.