Repository navigation
A SHACL shape gives a property the domain and range it does not declare - #1001
Merged
WaylandYang merged 2 commits intoSep 29, 2026
Merged
Conversation
Signed-off-by: dada-yan <BinjunYann@gmail.com>
WaylandYang
approved these changes
Sep 29, 2026
WaylandYang
left a comment
Contributor
There was a problem hiding this comment.
Approving. Thanks @Maya-Kid.
Reviewed at df75d62. What I checked:
- Only the gaps are filled. A declared
rdfs:domain/rdfs:rangewins, side by side, and a test pins it. - Blank nodes stay contained. Only
sh:path,sh:classandsh:datatypeare kept for a blank subject, the blank object sits in a field nothing else reads, and the triple count is unchanged. The members of ansh:orlist are kept too but never reached, since no node shape lists them undersh:property. - What is not read is said, in the code and in the tests, and still shows up in the report.
The UCO table answers what I was going to ask: 549 datatype properties imported where there were 2, and the 30 left over each have a reason. The 13 with xsd:hexBinary / xsd:base64Binary look like a small follow-up of their own if you want it.
This was referenced Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
For #923, as suggested there.
UCO states its constraints as SHACL shapes rather than as
rdfs:domain/rdfs:range, so its properties arrive at import with almost no domains. A datatype property without a domain is skipped at import. This change reads the shapes.Problem
rdfs:domain/rdfs:range, and from schema.org'sdomainIncludes/rangeIncludes.observable:AccountAuthenticationFacet a owl:Class, sh:NodeShape ; sh:property [ sh:path observable:passwordType ; sh:datatype xsd:string ] ; sh:targetClass observable:AccountAuthenticationFacet .no_domain). On the merged UCO, 561 of the 579 datatype properties are skipped for this reason, and only 2 would be imported.read_triplesdrops every triple whose subject is a blank node.Change
Keeping the shape triples. In
crates/utopia-ingest/src/ontology_rdf.rs,read_triplesnow keeps the three triples a property shape needs (sh:path,sh:class,sh:datatype) when their subject is a blank node. It records a blank-node object in a new field that only the shape pass reads. Every other blank-node triple is dropped as before, andtriplesstill counts only triples whose subject is an IRI.Reading the shapes.
shape_signaturesreadsnode shape sh:property property shape:sh:path, when that path is an IRI;sh:targetClass, or the node itself when it is both a class and ash:NodeShape(SHACL's implicit class target);sh:classorsh:datatype.Declarations win.
projectuses these only where the property declares no domain or range of its own.domainIncludesis.ranges_union), as withrangeIncludes.Not read. Each of these is noted in the code:
sh:targetSubjectsOfandsh:targetObjectsOf, which do not name a class;sh:orandsh:node.The report.
sh:targetClass,sh:property,sh:path,sh:classandsh:datatypeare no longer reported as not projected. The other SHACL predicates still are.The record. In
docs/decisions/0001-ontology-import-and-governance.md, decision 13 now says where a signature comes from when a property declares none, and a revision entry records the change.None of the five bundled packs mentions SHACL, so their projection is unchanged.
Verification
Run in containers on a Linux host: Rust 1.98.1 and PostgreSQL 16 with pgvector.
New tests (
ontology_rdf::shape_tests)One Turtle snippet covers each form:
sh:targetClassand blank-node property shapes carryingsh:classandsh:datatype;sh:NodeShapewithoutsh:targetClass;rdfs:domain/rdfs:range, which wins over the shape;sh:or,sh:targetSubjectsOf, and a path to a property the file does not declare;On dev with only the new tests, three of the four fail. The one that passes is the test that a declared domain and range win: it pins that a shape never overrides a declaration.
This branch
cargo fmt --all --checkandcargo clippy --locked --workspace --all-targets -- -D warningsare clean.UTOPIA_TEST_REQUIRE_PDFTOTEXT=1 cargo test --locked --workspacepasses: 1297 passed, 0 failed. This includes the projection tests against the bundled packs.UCO 1.5.0 through the import preview
The 18 Turtle files under
ontology/were merged by concatenation; they have no labelled blank nodes and no relative IRIs, so that is a valid merge. The import plan that the preview returns was run into an empty base, on dev and on this branch:xsd:hexBinaryorxsd:base64Binary, which the importer does not map today;core:informalType, a super-property that no shape constrains.observable:passwordTypegetsAccountAuthenticationFacet → xsd:string.core:hasFacetgetsUcoObject → Facet.core:namegets all eight classes that constrain it.sh:orover datatypes;