Coverage & gaps
The mapping's own discipline is "bind only what exists" — a schema location with no sound ontology predicate is left in a gap register, never force-bound to a plausible-looking term. This page is that register, plus the vocabulary needed to read it correctly.
Layer 1, layer 2, and GAP
The mapping's build contract (CONTRACT.md) defines three tiers:
- Layer 1 — provenance-anchored. Every schema leaf that some
opda:predicate's owndct:sourcecitation names, inverted back into a mapping rule. Authoritative and unambiguous — the mapping's "sound AND complete" claim applies to layer 1 only. - Layer 2 — shared/collapsed leaves. Semantically the same shared property
(e.g. a supplier name, an address part) but not itself a
dct:sourcetarget. Mapped best-effort, with an explicit coverage report — never silently claimed complete. - GAP. A schema location, or an ontology resource, with no sound counterpart on the other side. Expected and logged, not a completeness failure — the alternative (force-binding a plausible-but-wrong predicate) is the one thing this mapping is designed never to do.
This mapping's own gap register (gap-register.json /
build/final-gap.json) tracks schema↔ontology mapping gaps. The GAP register
on Ontology → Known issues tracks a completely
different thing — which overlay profiles bind which Category-G leaves. Same
name, two unrelated pipelines; don't conflate a figure from one with the other.
The current figure
As of 2026-07-05, 466 of 469 domain-module ontology resources are mapped or
removed for cause — 99.4% (source/03-standards/rml/build/final-gap.json,
regenerate with python3 build/final_scope2.py — see
Running & validating). The 3 remaining are:
| Term | Kind | Domain → Range | Why it stays unmapped |
|---|---|---|---|
opda:founds | ObjectProperty | Relator → Role | UFO Role/Relator connectives asserting an alternate encoding of a fact the mapping already captures via co-typing (e.g. ?s a opda:Seller directly) + opda:roleNotation. There is structurally no distinct Role node for these edges to target under this ontology's chosen encoding — not an oversight, a standing exclusion rule for upper-ontology/structural-pattern terms. |
opda:playedBy | ObjectProperty | Role → Organisation | |
opda:plays | ObjectProperty | Organisation → Role |
This is the outcome of a long gap-closing effort, not a static number: earlier points in
the same effort recorded 465/472 (98.5%) and 459/472 (97.2%). Three resources
(UPRNSuccessionEvent, AssuranceLevel, inspireFeatureId)
were removed outright late in that effort, confirmed to have zero basis anywhere in the
schema corpus — not merely unpopulated in the tracked fixtures — which is why the
denominator moved from 472 to 469. Full session-by-session detail:
ADR-0057's Amendments.
Why 469, not 8,458
The canonical PDTF data dictionary has 8,458 leaf records. It is tempting to divide the mapping's coverage by that number instead — this project tried exactly that, twice, in the same session that closed the last few gaps, and both attempts were wrong for the same reason: the raw dictionary was never the ontology's target coverage scope. It is the mechanical supply an upstream curation pass (Category A–G, ODR-0022) consumes, not a checklist the ontology must equal. That curation's completed output — 469 domain-module resources — is the correct, complete denominator; 8,458 (or the ~7,810 / ~2,164 "still to map" figures briefly proposed before the error was caught) measures the wrong thing entirely.
Honest non-mapping, worked
Two real leaves illustrate the discipline of leaving a gap rather than force-binding it:
-
propertyPack.priceInformation.price(the headline asking price) has no sound predicate to bind to.opda:soldPrice/opda:listPrice/opda:estimatedPriceare allopda:Valuation-domain comparable prices, andopda:priceis a separate, Category-D fixtures amount — none mean "this property's current asking price." It stays a gap; closing it needs a genuine ontology addition (e.g. a newopda:askingPrice), not a mapping change. -
propertyPack.connectivity.broadband.supplieris not thedct:sourceof any predicate either, but it is semantically the sharedopda:supplierproperty used elsewhere — so it's mapped as layer 2, best-effort, rather than left in the gap register.
Comments
Loading comments…
Sign in to post a comment