Skip to content

Resolve and follow owl:imports (import closure) when loading a project #229

Description

@JohnRDOrazio

Summary

OntoKit currently treats a project as a single self-contained RDF file. owl:imports triples are parsed but never followed: consistency_service.py only uses them to derive "external" namespaces so that dangling-reference checks skip imported terms (consistency_service.py ~L332). Nothing loads the imported ontology, so classes and properties defined in an import are invisible to the class tree, the detail panel, the linter, the indexer and the consistency checks.

This blocks the modular ontology layout planned for the CatholicOS ontologies (see ontologies-project): a small shared upper module (ontology-core, BFO 2020 + a CCO slice) imported by per-discipline modules (ontology-biblical, ontology-liturgical-calendar, …), with ontology-semantic-canon as an aggregator that imports all of them. In that layout every editable file has an owl:imports and the parent classes a curator needs to subclass live in the imported file.

Current behaviour

  • OntologyService.load_from_git / load_from_storage parse one file into one rdflib.Graph (ontology.py ~L740, ~L775).
  • owl:imports objects are treated as opaque namespace prefixes for the purposes of consistency checks only.
  • A module that declares rdfs:subClassOf cco:Person (defined in an import) shows the parent as an unresolved IRI with no label, no tree position, and no ability to browse it.

Proposed behaviour

  1. Resolve the import closure when a project is loaded. Resolution order, mirroring what Protégé and ROBOT do:
    1. a catalog-v001.xml (OASIS XML Catalog) next to the ontology file in the same repo, mapping import IRIs to local paths — this is the de facto standard and what ROBOT/ODK emit;
    2. a local path in the same repo if the IRI resolves to a file there;
    3. HTTP fetch of the IRI (content-negotiated), with the result cached by IRI + owl:versionIRI / ETag.
      Transitive imports are followed with cycle detection.
  2. Keep imported axioms distinct from local axioms. Load imports into separate named graphs (or a ConjunctiveGraph/Dataset) rather than merging into the project graph, so that:
    • the editor never writes imported triples back to the project file;
    • the class tree can show imported terms read-only (greyed / badge "imported from …");
    • semantic diff, PRs and change events only ever see local triples.
  3. Use the closure everywhere it matters: class tree and parent resolution, label lookup for IRIs, linter, consistency checks (replace the namespace-skip heuristic with "term is defined in the closure"), indexer/embeddings (opt-in, since importing BFO/CCO would otherwise flood search results).
  4. Surface failures — an import that cannot be resolved should appear as a project-level warning, not a silent gap.

Out of scope for this issue

  • Editing imported ontologies from within the importing project (they are read-only by design).
  • Reasoning over the closure (separate issue).
  • MIREOT/SLME extraction of import slices — that is a build-time concern (ROBOT) in the ontology repos, not an OntoKit concern.

Notes

  • rdflib does not resolve owl:imports on its own; owlready2 does (via onto_path) but OntoKit is rdflib-based, so this needs to be implemented in the service layer.
  • Suggested test fixture: a two-file project (core.ttl defining :Person, module.ttl importing it and declaring :Apostle rdfs:subClassOf :Person) plus a catalog-v001.xml, asserting that :Person appears as the labelled parent of :Apostle in the tree and that saving module.ttl does not write :Person's axioms into it.

Activity

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