Unit ID: applied-ontology-readiness
Status: Proposed, awaiting human review before implementation
Trigger: human request, 2026-09-25
Sketch: applied-ontology-readiness.md
Status record: applied-ontology-readiness.md
ADRs: A-87,
A-88,
A-89,
A-90,
A-91,
A-92,
and the ADR-A86 addendum.
All Proposed.
Close gaps AO1 to AO13 from the sketch, in three phases. Phase A changes no semantics. Phase B extends the Eligibility compilers. Phase C extends Foundation, Surface, Executable, Quantification and Instrument. No slice starts before the ADR it names is ratified. Phase A slices AOR-2 and AOR-3 are detailed to implementation level. Phase B slices are detailed to module, file and test-case level. Phase C slices are outlined and are detailed when their ADRs are drafted.
docs/developer/validation/applied-ontology-readiness-<slice>.md, updates
the status record and docs/developer/INDEX.md, and edits any normative
document it contradicts in the same slice.spec/*.ttl as data, so sh:targetClass reaches subclass instances, with
pySHACL advanced=True and inference="none".ADRs A-87 to A-92 (Proposed), the ADR-A86 addendum, the sketch, this
plan, the status record, the ADR catalogue rows, and INDEX.md entries. L0.
Gate: human review of the ADRs and of the open questions in the sketch.
Invariant: every Eligibility example validates with no violation and no warning. The declaration warning targets conditions that match candidates directly (ADR-A87 item 4).
Depends on: ADR-A87 ratified. Sketch open questions 1 and 2 answered.
Changes:
ontology/eligibility/examples/hierarchical-match.ttl
ex:hierarchical-condition gains elg:requiredConcept ex:fire, preceded
by a comment: # Removing elg:requiredConcept raises
elg:ConceptConditionDeclarationShape (sh:Warning), because the condition
would state nothing to match against.ex:hierarchical-profile declares elg:matchStrategy
elg:HierarchicalMatch, elg:compatibilityOperation elg:AllRequired and elg:wildcardSemantics
elg:NoWildcard, following the interval example’s convention (open
question 1). This clears three pre-existing elg:ConditionShape
violations.ex:decision gains elg:usesOperationalProfile ex:reference-profile,
with ex:reference-profile a elg:OperationalProfile. This clears the
pre-existing L8 violation.elg:constrainedByContract to a voc:SchemeContract bound to a
voc:ConceptScheme holding the three concepts.elg:candidateValue until AOR-5 introduces
elg:candidateConcept.ontology/eligibility/examples/condition-taxonomy.ttl
skos: prefix and four concepts: ex:full-time,
ex:part-time (an employment basis), ex:tier-standard,
ex:tier-premium (a subscription tier).ex:exact-condition gains elg:requiredConcept ex:full-time.
ex:set-condition gains elg:requiredConcept ex:tier-standard,
ex:tier-premium. Each carries the comment from change 1.ontology/eligibility/examples/interval-containment.ttl
ex:decision-1 gains elg:usesOperationalProfile as in change 1. Its
declaration warning on ex:profile-a is cleared by change 4, not by
giving the profile a concept.ontology/eligibility/shapes/constraints.ttl and its mirror in
ontology/eligibility/README.md §7: the first sh:sparql of
elg:ConceptConditionDeclarationShape adds
FILTER NOT EXISTS { $this elg:hasCondition ?member }. The two blocks stay
identical.eligibility/spec 0.3.0 → 0.3.1 (PATCH, a shape brought into line
with documented intent), in spec/eligibility.ttl and the README header.
Cascade to every importer of lattice/eligibility/0.3.0:
eligibility/vocab/eligibility-vocab.ttl, instrument/spec/instrument.ttl
and README, behaviour/spec/behaviour.ttl and README,
applied/capacity/spec/applied_capacity_execution_spec_capx_Version2.ttl.
The enumeration is re-run before and after editing.tools/test_eligibility_examples.py (pytest, rdflib and pySHACL, both
existing root dependencies).mise.toml: new task check:eligibility-examples (folded into
check:ontology-catalog on 2026-09-25, which runs every tools/test_*.py)
(python -m pytest tools/test_eligibility_examples.py -q), added to the
aggregate check.tools/README.md lists the new test.Examples declare no owl:Ontology, so changes 1 to 3 carry no version impact.
Test cases:
| ID | Given / When / Then | Level | +/- |
|---|---|---|---|
| AOR2-01 | hierarchical-match.ttl / validated / no results |
L1 | + |
| AOR2-02 | condition-taxonomy.ttl / validated / no results |
L1 | + |
| AOR2-03 | interval-containment.ttl / validated / no results |
L1 | + |
| AOR2-04 | hierarchical-match.ttl without ex:hierarchical-condition’s required concept / validated / exactly one declaration warning, focused on that condition |
L1 | - |
| AOR2-05 | as AOR2-04 for ex:exact-condition |
L1 | - |
| AOR2-06 | as AOR2-04 for ex:set-condition |
L1 | - |
| AOR2-07 | a profile with elg:hasCondition and a concept match strategy, no concepts / validated / no declaration warning |
L1 | + |
| AOR2-08 | a condition with SetMembership, no concepts, no elg:hasCondition / validated / one declaration warning |
L1 | - |
| AOR2-09 | a condition whose excluded concept lies outside every required concept / validated / one elg:ReachableExclusionShape warning |
L1 | - |
| AOR2-10 | the shape in constraints.ttl and the README §7 block / parsed / isomorphic |
L3 | + |
One command: mise run check:ontology-catalog (originally check:eligibility-examples).
Also run: mise run check:ontology-versioning, and
grep -rl 'lattice/eligibility/0.3.0' ontology tools returns nothing.
Artefacts to inspect: the three example diffs and their comments.
Adversarial probe: revert change 4 and show AOR2-03 and AOR2-07 fail.
Non-coverage: other layers’ examples (a repository-wide example check is a
candidate follow-up), and compiled evaluation of the examples (AOR-5, AOR-6).
Estimate: 80k tokens.
Invariant: a version IRI identifies one content, and CI enforces it.
Depends on: ADR-A86 and its addendum ratified.
Changes:
tools/ontology_version_check.py fails for a document under a spec/ or
vocab/ directory, or under ontology/applied/*/spec/, that declares
owl:Ontology without owl:versionIRI. Examples and test fixtures stay
exempt (nine MORK example and test documents today).tools/test_ontology_version_check.py turns the manual mutation probe
recorded by ontology-semantic-versioning into tests..github/workflows/platform.yml: the Python job checks out with
fetch-depth: 0 and runs
python tools/ontology_version_check.py --base-ref origin/main.docs/architecture/ontology-versioning-policy.md: the cascade checklist
applies to every bump, and the propagation rule from addendum item 1 is
added to “What changes the number”.ontology/surface/execution/job-family/ are
regenerated with the Surface CLI from ontology/surface/examples/employment-job-family.ttl,
with the produced_at recorded in their manifest, so they import
lattice/surface/0.3.0. The regeneration command is recorded in the status
record.Test cases: content changed with version unchanged is flagged (-).
Content and version changed together pass (+). An untouched file passes (+).
A spec/ document without a version IRI is flagged (-). An example document
without one passes (+). A document that gains owl:Ontology in the change
without a version IRI is flagged (-). The job-family modules import only IRIs
declared in the tree (+, checked by AOR-4’s tool once it exists, by grep until
then). All L1.
One command: python -m pytest tools/test_ontology_version_check.py -q.
Non-coverage: changing ontology IRIs (addendum item 4).
Estimate: 90k tokens.
Invariant: every LATTICE document loads with its import closure from a checkout, with no machine-specific configuration (ADR-A88).
Depends on: ADR-A88 ratified. AOR-3 (job-family imports fixed).
Changes:
tools/ontology_catalog.py with three commands. write generates
ontology/catalog-v001.xml (every ontology IRI and version IRI declared
under ontology/, relative paths, external imports listed explicitly) and
the directory stubs. check fails on drift, on an import target with no
entry, and on an entry whose file does not declare its IRI. closure loads
a document’s import closure into an rdflib graph through the catalog.catalog-v001.xml files are replaced by generated stubs.
The mork/spec catalog’s Mork.owl mapping is kept as an entry if
Mork.owl still exists.tools/test_ontology_catalog.py.mise.toml: build:ontology-catalog and check:ontology-catalog, the
latter added to the aggregate check. CI runs the check.docs/architecture/ontology-architecture.md §2 gains a “Consuming LATTICE
from an applied ontology” paragraph: pin a commit, chain the catalog with
nextCatalog, upgrade by the ADR-A86 cascade checklist, treat every bump as
potentially breaking at major version zero, run the consumer’s own gate.docs/architecture/ontology-versioning-policy.md: regenerating the catalog
is a step of every bump.Test cases: every import in the tree resolves (+). A removed catalog entry
is reported (-). An entry pointing at a file that declares a different IRI is
reported (-). A hand edit to the catalog is reported as drift (-). The closure
of behaviour/spec/behaviour.ttl loads and contains a term from each of its
transitive imports (+). A fixture applied ontology in a temporary directory,
with its own catalog chaining to LATTICE’s by relative path, loads its closure
(+). Generation is byte-identical across two runs (L2, +). A Protégé load of
one spec document through its stub (manual, recorded in the VP, and the
ADR-A88 open question).
One command: mise run check:ontology-catalog.
Non-coverage: serving documents at their IRIs.
Estimate: 140k tokens.
All Phase B slices touch tools/mork_compilers and at most one ontology
layer. Each adds cases to test/conformance/ so ADR-A28 parity covers them.
Each depends on AOR-2 and on the ADRs named.
| Slice | Scope | Modules | Depends on | Level | Estimate |
|---|---|---|---|---|---|
| AOR-5 | elg:candidateConcept. IR concept plan for ExactMatch and SetMembership with required and excluded concepts. SPARQL backend. Examples migrated from candidateValue. Eligibility MINOR with cascade |
ontology/eligibility, tools/mork_compilers |
A-89 | L1, L2 | 150k |
| AOR-6 | HierarchicalMatch in the IR. Scheme resolution through tools/vocabulary with explicit instant and scope. QueryTime closure in SPARQL. The ADR-A87 decision table, including L11 |
tools/mork_compilers |
AOR-5, and the temporal-binding-consumer-hardening Finding 1 decision |
L1, L2 | 180k |
| AOR-7 | Expanded closure. SHACL and SWRL backends for concept plans. exe:ConceptMatchPlan and the diagnostic vocabulary. Executable MINOR |
tools/mork_compilers, ontology/mork |
AOR-6 | L1, L2 | 180k |
| AOR-8 | Profile aggregation for AllRequired and AnySufficient on all three backends. DimensionConsistent refused with a diagnostic |
tools/mork_compilers |
AOR-7 | L1, L2 | 130k |
| AOR-9 | elg:EvidenceBinding, elg:EvidenceStep, elg:aboutSubject. The IR reads candidates through bindings. Eligibility MINOR with cascade |
ontology/eligibility, tools/mork_compilers |
A-91, AOR-8 | L1, L2 | 180k |
| AOR-10 | OWL backend: hierarchy and condition classes, exe:OwlArtefact, sibling-disjointness option |
tools/mork_compilers, ontology/mork |
A-90, AOR-9, the path encoding decision, and the ADR-A83 harness | L1, L4 | 170k |
| AOR-11 | Profile classes and the subsumption, satisfiability and overlap checks through the harness CLI | tools/mork_compilers |
AOR-10 | L4 | 150k |
Test-case outline for Phase B. Each slice’s VP carries, as applicable:
Undetermined, checked over the generated rules (-)Undetermined carrying a diagnosticEach Phase B slice’s single command is mise run check:python-root until a
check:mork-compilers task exists. AOR-5 adds that task (running
python -m pytest tools/mork_compilers -q) and wires it into check.
Each slice is gated on the ADR named, drafted 2026-09-25. Each is an ontology change with the ADR-A86 cascade. Test cases are fixed when the ADR is ratified.
| Slice | Scope | Decision | Version impact | Estimate |
|---|---|---|---|---|
| AOR-12 | fnd:DerivedArtefact, fnd:DerivationRun, derivation kinds in Foundation vocab. srf:DerivedArtefact alignment. Carries the ADR-A91 step-list lift if accepted by then |
A-92 | Foundation, Surface MINOR. Foundation cascades to every layer | 200k |
| AOR-13 | Executable aligned directly to PROV-O, without importing Foundation (ADR-A92 item 3 as rewritten) | A-92 | Executable MINOR | 90k |
| AOR-14 | Derived rate spaces (sketch AO10) | A-93 | Quantification MINOR, cascades | 150k |
| AOR-15 | Calendar binding through qnt:UnitContract (AO11) |
A-94 | Quantification MINOR, cascades | 150k |
| AOR-16 | Alternative bounds stated per unit (AO12) | A-95 | Quantification MINOR, cascades | 120k |
| AOR-17 | ins:inProvision no longer functional (AO13) |
A-96 | Instrument MINOR, cascades | 60k |
AOR-14 to AOR-16 land as one Quantification change, cascading once (human decision, 2026-09-25). AOR-16 includes the compiler work that selects required intervals by the candidate’s unit.
| Document | Change | Slice |
|---|---|---|
docs/architecture/decisions/ |
A-87 to A-92, A-86 addendum, catalogue | AOR-1 |
docs/architecture/decisions/ |
Phase C ADRs | AOR-14 to AOR-17 |
ontology/eligibility/README.md |
shape mirror and version (AOR-2), new terms (AOR-5, AOR-9) | AOR-2, AOR-5, AOR-9 |
docs/architecture/ontology-versioning-policy.md |
propagation rule, catalog step | AOR-3, AOR-4 |
docs/architecture/ontology-architecture.md |
§2 consumer paragraph (AOR-4), §3 status rows, §11 items | AOR-4 onwards |
ontology/mork/README.md, tools/mork_compilers docs |
new plans, backends, closure modes | AOR-5 to AOR-11 |
ontology/foundation/README.md, ontology/surface/README.md |
new and aligned terms | AOR-12 |
| eligibility-compiler status | deferred items marked as carried here | AOR-5 |
| surface outstanding items §1.3, §3.1 | closed on AOR-12 | AOR-12 |
docs/developer/INDEX.md, status record |
every slice | all |
Root README.md, docs/architecture/solution-design-specification.md, data-architecture.md, ux-design.md |
checked, no change planned. No new directory is introduced | none |
Phase A closes when AOR-2 to AOR-4 are signed off and mise run check is
green with the new tasks included. Phase B closes when AOR-5 to AOR-11 are
signed off and the shared conformance corpus covers every concept strategy and
both evaluable compatibility operations. Phase C slices close individually.
| Phase | Estimate |
|---|---|
| A (AOR-1 to AOR-4) | 460k, of which AOR-1 about 150k |
| B (AOR-5 to AOR-11) | 1.14M |
| C (AOR-12 to AOR-17) | 770k plus ADR drafting, about 40k per ADR |
Estimates cover agent input and output for authoring and one round of fixes from human-reported failures. Actuals are recorded in the status record.