Rendered from docs/decisions/0013-linkml-and-shacl-as-substrate.md in the Headwater corpus. Every document on this half of the site is typed by the taxonomy the descriptor names: corpus.json.

Q13 — LinkML and SHACL as substrate

Context

One evaluation settles this with Q6 and Q9. Two worked examples supply the substance underneath, on LinkML and on SHACL.

What the worked examples established, and what does not change. LinkML already ships three of the twenty research-derived changes: SKOS mapping slots, PROV slot_uri alignment, and recommended as advisory severity. Its designates_type is our heterogeneous-shelf discriminator. The boundary is not structural against governance. LinkML, SHACL and JSON Schema all validate one instance against a shape. Everything else that Headwater does is a property of the whole graph, or of the corpus over time. SHACL reaches the graph layer that LinkML cannot, and every interesting constraint there is embedded SPARQL that nobody reads because a generator wrote it.

Two objections recorded here were withdrawn, and three survive. The error-message objection fell to sh:message interpolation, and the SPARQL-engine objection fell to embeddable Rust engines. Line numbers, remediation and fixability still do not survive the RDF round trip, and spec 4 needs all three.

Decision

The ownership half of the leaning survives untouched, and the architecture around it does not. Headwater owns the language, and standard formats come out of it. But LinkML is not the substrate, and it is not the compiler either. It is the last of six sibling emitters, and the one with the weakest case.

Emitters never chain, and that is now measured rather than feared. The open-question entry already named the chaining trap, and framed it as a loss of the graph layer. The stronger fact sits inside LinkML's own shape layer. Its SHACL generator does not translate any_of or equals_string_in, which LinkML itself expresses (HW-EVAL-adjacent-work §N.5). A chained pipeline inherits every loss of every hop and declares none of them. So every emitter reads the resolved lock and the graph directly.

The staging order, and why LinkML is last.

Order Emitter Ships when Consumer
1 JSON Schema for front matter first release the adopter's own editor, through a language server
2 Native graph JSON first release the solution corpus of Q9, and any local tool
3 SHACL a named external consumer asks a validation stack with no Headwater installation
4 RDF and SKOS the same trigger knowledge-organization tooling
5 OKF the same trigger LeanCTX, and whatever reads its bundles
6 LinkML the same trigger LinkML's own fan-out to OWL, Pydantic and SQL

Consequences

Only the first two pay off with no external adopter, and that is the whole reason for their position. The title of the open-question entry is what hid the answer. It named LinkML and SHACL together and put LinkML first, which made a pipeline look natural. Once emitters may not chain, LinkML stops being the route to anything else. It becomes a sibling whose distinctive value is a fan-out that nobody has asked for.

SPDX 3.0 is the observed application of the model-first half, at standards scale. One model yields an OWL ontology with SHACL restrictions, a JSON-LD context, and a JSON Schema, all derived rather than authored in parallel.

exportable_as is a set, with a partition rule and an equivalence bar. Spec 12 owns the rules. A check declares a set of emitter targets, and none is the common value. The exported and unexported sets partition the check registry, and the engine generates both. A target may appear only when the emitted constraint catches exactly what the native check catches, which a differential test establishes. The declaration travels with the artifact, because a consumer who copies an export copies its limits too. OGC API and STAC ship that convention already (HW-EVAL-adjacent-work §N.6).

The export is for three things, and the list is unchanged. External validation to a declared depth. LinkML's generator fan-out, of which JSON Schema is the immediately useful part and now arrives without LinkML. And a differential-testing oracle, which is the admission test for any claim of coverage.

The engine still never runs on SHACL's validation machinery, and the disqualifications hold for any authoring surface. SHACL defines conformance as "no validation results" and has no notion of completeness. Nothing in SHACL checks that a projection represents the corpus. Source positions and fixability do not survive the round trip. Document-body, corpus-scope and temporal checks never reach the graph at all.

The OKF half is not a separate question, and the open-question entry misfiled it. Q13 separated OKF from the substrate question correctly. One is about the TBox and the other about the ABox, and to conflate them imports weight that the smaller decision does not carry. What it failed to notice is that the native graph export is an ABox emitter too, and Q6 owns it. So OKF is a second ABox emitter beside the native one, on identical terms. It reads the graph, declares a loss set, and emits a census.

That placement makes the standing worry concrete rather than hypothetical. OKF's own conformance check is four advisory warnings, so a consumer that validates a bundle verifies almost nothing about it. The census is the answer, because it is the emitter's own account of what it dropped, checked where the emitter runs. OKF carries unrecognized front-matter keys through a parse-emit cycle untouched, so Headwater facets ride along under a headwater_* prefix and the loss set stays small.

Counter-evidence, still standing. OpenGEO declines RDF, OWL and SHACL for a neighboring problem. TrustGraph chose the whole standards stack and ships it. The staging order is what respects both. Nothing standards-based is refused, and nothing is built before a consumer exists.