Physical — deployment

    Three-graph CI gate

    Three-graph CI gate

    The three-graph gate enforces ODR-0004 §3a’s five-part class / shape / annotation separation contract across the committed corpus. The contract says: classes, shapes, and annotations live in different graphs; no graph contains material that belongs to another. The gate runs five SHACL-AF queries against the emitted directory and fails on any violation.

    What the gate enforces

    The five separation rules per ODR-0004 §3a:

    1. No sh:NodeShape triples in class graphs — opda-classes.ttl, opda-<module>.ttl × 6, and opda-vocabularies.ttl MUST NOT carry SHACL shape declarations.
    2. No owl:Class triples in shape graphs — opda-shapes.ttl and opda-<module>-shapes.ttl × 6 MUST NOT carry class declarations.
    3. No owl:imports triples in shape graphs — shape graphs are pure constraint material; imports live in the TBox graphs.
    4. No dct:references <https://w3id.org/dpv/…> triples in class graphs — DPV co-annotation is a reference-not-import concern (per ADR-0012) confined to -annotations.ttl files.
    5. Foundation meta-shapes only in opda-shapes.ttl — Cat 3 NoIdentityOverride, Cat 5 MetaShapeOverShapeGraph, and the three-rule interface contract meta-shapes live in the foundation shape graph; per-module shape graphs carry per-module shapes only.

    Command

    opda-gen ci-three-graph --ontology-dir source/03-standards/ontology

    Default --ontology-dir resolves to source/03-standards/ontology/ relative to the OPDA repo root (per the _default_ontology_dir() walker in tools/opda-gen/src/opda_gen/cli.py).

    Expected output on success:

    three-graph CI: PASS (all 5 checks)

    Expected output on failure (per violation):

    THREE-GRAPH VIOLATION: <description of which rule and where>

    Exit code: 0 on PASS, 1 on any violation.

    Workflow definition

    The gate runs inside .github/workflows/ontology-byte-identity.yml as the Three-graph CI test step:

    - name: Three-graph CI test
      working-directory: tools/opda-gen
      run: opda-gen ci-three-graph --ontology-dir ../../source/03-standards/ontology

    It runs immediately after Byte-identity diff so any byte-identity failure short-circuits before the separation check (an emitter regression often surfaces as a byte-identity violation before it surfaces as a separation violation).

    Implementation

    The test body lives in tools/opda-gen/src/opda_gen/ci/three_graph_test.py. It loads each TTL via rdflib, runs five filter queries, and returns a list of violation strings (empty list = PASS).

    The CLI wrapper at tools/opda-gen/src/opda_gen/cli.py prints each violation to stderr prefixed with THREE-GRAPH VIOLATION: and exits 1.

    Failure mode

    A typical violation looks like:

    THREE-GRAPH VIOLATION: opda-property.ttl contains 3 sh:NodeShape triples (rule 1)

    Investigation order:

    1. Identify the offending triples via grep -n 'sh:NodeShape' source/03-standards/ontology/opda-property.ttl.
    2. Determine whether the triples should move to opda-property-shapes.ttl (correct destination per ODR-0004 §3a) or be removed entirely (if they’re spurious).
    3. Fix the emitter source — most likely a constraint definition leaked from the shape emitter into the module emitter.
    4. Re-emit (opda-gen emit), confirm byte-identity, re-run ci-three-graph.

    The three-graph gate is the ontology-engineering analogue of a “no import * from "private/internal/sql"” lint: it preserves the architectural boundary that makes the three derived consumer profiles (opda-validation, opda-ui, opda-inference) composable.

    Source ODR + ADR

    Comments

    Loading comments…