SHACL becomes interesting when an ontology is no longer only a vocabulary. At that point the question is not "did we model the domain well enough?" It is "which RDF does this system accept, and who broke the contract?"
That is the production job for SHACL.
An ontology gives names to classes and properties. OWL can describe meaning and support inference. SHACL is the layer that says whether a data graph satisfies the shapes the system expects. The SHACL 1.2 Core specification defines validation as checking a data graph against a shapes graph and producing validation results. That sounds dry until the first producer ships RDF that is valid and operationally unusable.
A policy control without an owner. A component without a supplier. An evidence item with a string where the contract expects an IRI. The vocabulary can still be fine. The data is not fit to ingest.
The shape is part of the contract
Production teams often treat shapes as documentation with better syntax. That is too weak. A shape file is contract code.
If a property shape adds sh:minCount 1, yesterday's optional value became required. If it tightens sh:datatype, an integration that sent a plain string can start failing. If it adds sh:class, inferred or asserted types now matter to acceptance. If it uses sh:closed, extra properties that used to pass through the system can be rejected unless they are explicitly ignored.
None of those changes remove a vocabulary IRI. They still change the production contract.
That is the point I was making in Schema evolution in production ontologies: backward compatibility is not only about whether terms still exist. A SHACL change can break a producer while the ontology diff looks harmless.
Put validation in CI
The useful SHACL artifact is not the shapes file. It is the validation report attached to a gate.
For a small system, that gate can be simple. Run something like pySHACL or Apache Jena SHACL against fixture graphs before merge. Keep one known-good graph, one invalid graph per common producer failure, one graph from the previous release, and one graph with inferred types if validation depends on entailment.
The important part is that failure leaves evidence. The SHACL validation report model includes sh:conforms, validation results, severity, focus node, result path, source shape, source constraint component, and message. A Boolean result is useful to block the build. It is not enough to debug the break. The review needs to show which node failed, which path failed, and which shape made the decision.
That changes the conversation. Instead of "the ontology team says this producer is wrong", the artifact says "this producer emitted ex:evidence123 without the required ex:hasControl path under shape version X." That is reviewable and repeatable.
This is where SHACL earns its keep. Governance notes can say every evidence item needs a control. A shape with a CI report proves whether the graph obeys that rule.
Choose the gate deliberately
SHACL can run in more than one place.
Pre-merge fixture tests catch contract changes before they land. Producer contract tests catch integrations that drift before they hit the shared graph. Batch ingest validation catches bad files at the boundary. Transaction-time validation catches bad writes at commit. RDF4J documents SHACL validation during commit(), and Jena documents both command-line validation and a Fuseki SHACL endpoint.
The strongest gate is not always the first one to deploy. Transaction-time validation can be expensive on large graphs. Some systems should start with deltas, batch windows, or producer-specific fixtures before enforcing every write. That is not a reason to leave the contract informal. It is a reason to choose the gate with an owner and a failure path.
The validation environment also needs to be pinned. SHACL Core allows processors to validate over entailments, but processors do not all support every entailment regime. If the graph only conforms after RDFS or OWL inference, the CI job has to say which engine, which version, and which inference settings produced the report.
Test the tests
SHACL does not prove that the graph is true. It proves that the graph satisfies the contract the shapes express.
That distinction matters. A conforming graph can still be stale. It can still encode a weak model. It can still use a formally valid identifier for the wrong real-world thing. SHACL is not a replacement for domain review or inference design.
It can also become a second ontology if the team lets domain meaning drift into shapes instead of modelling it in the vocabulary. That is not an argument against SHACL. It is an argument for reviewing shapes with the same discipline as ontology changes.
The shapes themselves need tests. The SHACL 1.2 Overview points to SHACL-SHACL shapes graphs for validating SHACL shapes graphs. Tools such as pySHACL expose meta-SHACL checks for that reason. If the production contract lives in shapes, then malformed shapes are production bugs.
I like SHACL most when it is boring. A shapes graph, a fixture set, a pinned validator, and a stored validation report. Not a modelling manifesto. Not a governance memo. Just the acceptance contract for graph data, running before bad data gets authority.