Skip to content

compliance: run SHACL for rule tests now that shaclgen translates rules (after linkml/linkml#3990) #39

Open
linkml/linkml
#3990

Description

@jdsika

Status (2026-10-13): folded into linkml#3990 (fork #20): the three rule tests run SHACL, IMPLEMENTS where gen-shacl translates the rule and INCOMPLETE for invalid instances of rules it skips. The extra presence-implies-value compliance test is not included. Close when it merges.

What

The compliance suite skips SHACL in all three rules tests of tests/linkml/test_compliance/test_boolean_slot_compliance.py. So docs/generators/dashboard.md shows ❓ for SHACL under Precondition rules, Precondition combos and Value presence in rules.

shaclgen translates rules since linkml#3451 (boolean guard, exclusive value). linkml#3989 adds presence-implies-value, inheritance and open_world, and linkml#3990 adds the compositional translation. This calls for a test-only PR after linkml#3990.

Reproduction

uv run pytest tests/linkml/test_compliance/test_boolean_slot_compliance.py -rs -q \
  -k "shacl and (test_preconditions or test_value_presence_in_rules)"
SKIPPED [10] ...:2167: shaclgen does not support rules yet
SKIPPED [12] ...:2383: shaclgen does not support rules yet
SKIPPED [8] ...:2636: shaclgen does not support boolean expressions yet

This is what SHACL would decide at linkml#3990 (c89faac06), validating as check_data does (ShaclValidationPlugin, RDF from rdflib_dumper):

Test / schema Rule operators sh:sparql SHACL vs expected
test_preconditions any_of/none_of of equals_number 0 6 valid agree; 4 invalid accepted
combos if0then0 equals_number 0 2 valid agree; 0-10 accepted
combos no_preconditions, no_postconditions one side missing 0 3 valid agree
combos ifAthenB equals_string 1 AA rejected
combos Disjunctive exactly_one_of of bounds 0 11-1 accepted
combos if1or2then3or4 any_of of equals_number 0 11 accepted
combos ifAorBthenCorD any_of of equals_string 0 2 valid agree; AA accepted
test_value_presence_in_rules (both multivalued) value_presence PRESENT→ABSENT, ABSENT→PRESENT 2 8/8 agree

main and linkml#3989 emit no sh:sparql for any of these. Minimal check, which prints invalid, valid, valid, invalid:

from linkml.validator import Validator
from linkml.validator.plugins.shacl_validation_plugin import ShaclValidationPlugin

presence = lambda slot, p: {"slot_conditions": {slot: {"value_presence": p}}}
schema = {
    "id": "http://example.org/vp", "name": "vp", "default_prefix": "ex", "default_range": "string",
    "prefixes": {"ex": "http://example.org/", "linkml": "https://w3id.org/linkml/"},
    "imports": ["linkml:types"],
    "classes": {"C": {"attributes": {"s1": {}, "s2": {}}, "rules": [
        {"preconditions": presence("s1", "PRESENT"), "postconditions": presence("s2", "ABSENT")},
        {"preconditions": presence("s1", "ABSENT"), "postconditions": presence("s2", "PRESENT")},
    ]}},
}
for inst in ({}, {"s1": "x"}, {"s2": "x"}, {"s1": "x", "s2": "x"}):
    v = Validator(schema=schema, validation_plugins=[ShaclValidationPlugin(closed=True)])
    print(inst, "valid" if not list(v.iter_results(inst, "C")) else "invalid")

Harness behaviour

check_data validates nothing when expected_behavior is INCOMPLETE, NOT_APPLICABLE or FALSE_POSITIVE.

  • Both precondition tests expect INCOMPLETE for every framework except JSON Schema and OWL.
  • test_value_presence_in_rules expects INCOMPLETE for the invalid instances of every framework except JSON Schema.

Deleting the skips alone gives 30 passes, but only the 4 valid value_presence instances are actually validated. Setting SHACL to IMPLEMENTS in all three gives 22 passes and 8 failures: exactly the "accepted" cases above.

Plan

  • test_value_presence_in_rules: delete the skip; SHACL IMPLEMENTS for all instances.
  • test_preconditions_combos: delete the skip. SHACL IMPLEMENTS for ifAthenB and every valid instance, and INCOMPLETE for the invalid instances of rules shaclgen skips (equals_number, exactly_one_of, slot-level any_of).
  • test_preconditions: delete the skip. SHACL IMPLEMENTS for valid instances, which guards against false positives, and INCOMPLETE for invalid ones.
  • Add a presence-implies-value test across CORE_FRAMEWORKS:
    • targets: string, an enum without meanings, an enum with meanings;
    • instances: allowed, other, absent target, absent guard;
    • a subclass instance, and open_world;
    • expectations: SHACL IMPLEMENTS, since all agree at c89faac06. A target whose range holds neither strings nor booleans makes shaclgen skip the rule with a warning, so INCOMPLETE there.

Notes

Acceptance

  • No "does not support rules yet" / "boolean expressions yet" SHACL skip remains in the three rule tests.
  • uv run pytest tests/linkml/test_compliance/test_boolean_slot_compliance.py -k shacl passes with the expectations above.
  • After uv run pytest tests/linkml/test_compliance/ --with-output && uv run python scripts/generate_dashboard.py, docs/generators/dashboard.md shows SHACL ✅ for Value presence in rules and ⚠️ for Precondition rules / Precondition combos, instead of ❓.

Activity

  1. changed the title [-]compliance: run SHACL for rule tests now that shaclgen translates rules (after #3990)[/-] [+]compliance: run SHACL for rule tests now that shaclgen translates rules (after linkml/linkml#3990)[/+] on Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions