Skip to content

Running QC checks and building a release locally

This page documents how to run ELMO's quality-control checks and build a release artefact from the command line, without Docker. The standard ODK release workflow uses Docker (./run.sh make …); use that approach when you want to produce an officially-versioned release. The commands below use a local robot.jar and are useful for fast iteration during editing — running checks in seconds rather than spinning up a container.


Prerequisites

Requirement Notes
Java 11+ Java 22 is confirmed to work; run java -version to check
robot.jar Located at C:/Users/Tim Alamenciak/Documents/TReK/Racoon/ROBOT/robot.jar; version 1.9.7
Python 3 Required for editing TSV templates; run python --version to check
Git Bash (Windows) All commands below assume a Bash-compatible shell

All commands must be run from the src/ontology/ directory unless noted otherwise:

cd path/to/elmo/src/ontology

For convenience, set a shell alias so you don't have to type the full jar path:

alias robot='java -jar "C:/Users/Tim Alamenciak/Documents/TReK/Racoon/ROBOT/robot.jar"'

The remaining examples on this page use robot for brevity.


1. Rebuild components from ROBOT templates

Run this whenever you have edited a .tsv template file and need to regenerate the corresponding OWL component before checking or releasing.

Interventions component

robot template \
  --prefix 'ELMO: https://w3id.org/elmo/elmo_' \
  --template ../templates/interventions.tsv \
  --output components/interventions.owl

Ecosystems component

robot template \
  --prefix 'ELMO: https://w3id.org/elmo/elmo_' \
  --template ../templates/ecosystems.tsv \
  --output components/ecosystems.owl

CAS component

cas.owl is maintained by hand in Functional Syntax — no rebuild step is needed. Edit components/cas.owl directly.


2. Pre-processing step

Several checks operate on a pre-processed version of the edit file. Regenerate it after any change:

robot convert \
  --catalog catalog-v001.xml \
  --input elmo-edit.owl \
  --format ofn \
  --output tmp/elmo-preprocess.owl

This step is also the first thing make reason does, so it will be run automatically if you use the make targets below.


3. Quality-control checks

3.1 Reasoning (unsatisfiable class check)

Runs ELK over the full ontology (all components + imports) and fails if any class becomes unsatisfiable.

make -f elmo.Makefile reason
robot reason \
  --catalog catalog-v001.xml \
  --input tmp/elmo-preprocess.owl \
  --reasoner ELK \
  --equivalent-classes-allowed all \
  --exclude-tautologies structural \
  --output test.owl && rm test.owl

Expected output: no output on success (exit code 0). Any ERROR line means an unsatisfiable class was found; use the explain target (§ 3.5) to investigate.


3.2 OBO-format quality report

Runs the ROBOT report command over the merged ontology and writes a TSV to reports/elmo-edit.owl-obo-report.tsv.

make -f elmo.Makefile report
robot merge \
  --catalog catalog-v001.xml \
  --input elmo-edit.owl \
  report \
  --output reports/elmo-edit.owl-obo-report.tsv

Interpreting the output

The report prints a summary line like:

ERROR:      14
WARN:       37
INFO:       65
Category Expected count Notes
ERROR on ELMO terms 0 Any error here needs to be fixed
WARN on ELMO terms ≤ 3 Two pre-existing duplicate_exact_synonym on ecosystem types 3620108/3620109; one expected duplicate_label_synonym on merged term 3620037
ERROR on imported terms 14 All multiple_labels on GO/IAO/oboInOwl — artefact of slim import labels; safe to ignore
WARN on imported terms 33 missing_definition + 1 annotation_whitespace Artefacts of import slimming; safe to ignore

3.3 SPARQL validation checks

Checks five structural rules against the pre-processed ontology:

make -f elmo.Makefile verify

This runs the three diagnostic queries (missing-definitions, missing-labels, none-definitions) and writes CSV results to reports/.

# Structural integrity checks (5/5 should PASS)
robot verify \
  --catalog catalog-v001.xml \
  -i tmp/elmo-preprocess.owl \
  --queries \
    ../sparql/owldef-self-reference-violation.sparql \
    ../sparql/iri-range-violation.sparql \
    ../sparql/label-with-iri-violation.sparql \
    ../sparql/multiple-replaced_by-violation.sparql \
    ../sparql/dc-properties-violation.sparql \
  -O reports/

# Diagnostic queries (produce CSV reports, do not fail the build)
robot merge \
  --catalog catalog-v001.xml \
  --input elmo-edit.owl \
  query --format csv \
    --query ../sparql/missing-definitions.sparql reports/missing-definitions.csv \
    --query ../sparql/missing-labels.sparql      reports/missing-labels.csv \
    --query ../sparql/none-definitions.sparql    reports/none-definitions.csv

Expected output: all five structural checks should print PASS … 0 violation(s). The diagnostic query results in reports/ should be empty (header row only) for a clean ontology — the only exception is missing-definitions.csv, which will always list the root metadata node ELMO_0000000.


3.4 DOSDP pattern validation

Validates the design-pattern TSVs against their YAML schemas:

dosdp validate -i elmo-edit.owl \
  --infile ../patterns/definitions.tsv \
  --template ../patterns/definitions.yaml

3.5 Explain an unsatisfiable class

If reasoning fails and you need to understand why a class is unsatisfiable:

make -f elmo.Makefile explain CLASS="https://w3id.org/elmo/elmo_3620001"

The explanation is written to reports/explanation.md.

robot explain \
  --catalog catalog-v001.xml \
  --input tmp/elmo-preprocess.owl \
  --reasoner ELK \
  --axiom "SubClassOf(<https://w3id.org/elmo/elmo_3620001> owl:Nothing)" \
  --explanation reports/explanation.md

4. Running all checks together

To replicate the full CI suite as closely as possible without Docker, run the checks in this order:

# From src/ontology/

# 1. Rebuild any templates you have changed
robot template --prefix 'ELMO: https://w3id.org/elmo/elmo_' \
  --template ../templates/interventions.tsv --output components/interventions.owl
robot template --prefix 'ELMO: https://w3id.org/elmo/elmo_' \
  --template ../templates/ecosystems.tsv   --output components/ecosystems.owl

# 2. Pre-process
robot convert --catalog catalog-v001.xml \
  --input elmo-edit.owl --format ofn --output tmp/elmo-preprocess.owl

# 3. Reason
robot reason --catalog catalog-v001.xml \
  --input tmp/elmo-preprocess.owl --reasoner ELK \
  --equivalent-classes-allowed all --exclude-tautologies structural \
  --output test.owl && rm test.owl

# 4. Structural SPARQL checks
robot verify --catalog catalog-v001.xml \
  -i tmp/elmo-preprocess.owl \
  --queries \
    ../sparql/owldef-self-reference-violation.sparql \
    ../sparql/iri-range-violation.sparql \
    ../sparql/label-with-iri-violation.sparql \
    ../sparql/multiple-replaced_by-violation.sparql \
    ../sparql/dc-properties-violation.sparql \
  -O reports/

# 5. Quality report
robot merge --catalog catalog-v001.xml --input elmo-edit.owl \
  report --output reports/elmo-edit.owl-obo-report.tsv

5. Building a release (without Docker)

!!! warning "Prefer Docker for official releases" The ODK Docker workflow (./run.sh make prepare_release -B) is the canonical method for producing versioned release artefacts because it pins tool versions and runs the full pipeline including pattern compilation. Use the steps below only when Docker is unavailable or for quick local testing of release outputs.

5.1 Prepare a release branch

git checkout main && git pull
git checkout -b release-$(date +%Y-%m-%d)

5.2 Rebuild all components

robot template --prefix 'ELMO: https://w3id.org/elmo/elmo_' \
  --template ../templates/interventions.tsv --output components/interventions.owl
robot template --prefix 'ELMO: https://w3id.org/elmo/elmo_' \
  --template ../templates/ecosystems.tsv   --output components/ecosystems.owl

5.3 Run all QC checks

Follow the steps in § 4 and confirm everything passes before proceeding.

5.4 Build the base release file

The base release includes only ELMO-authored axioms (no imports merged in):

robot merge \
    --catalog catalog-v001.xml \
    --input elmo-edit.owl \
  annotate \
    --ontology-iri "https://w3id.org/elmo/elmo" \
    --version-iri "https://w3id.org/elmo/elmo/releases/$(date +%Y-%m-%d)/elmo-base.owl" \
    --annotation owl:versionInfo "$(date +%Y-%m-%d)" \
  convert --format owl --output ../../elmo-base.owl

# OBO and JSON variants
robot convert --input ../../elmo-base.owl --format obo  --output ../../elmo-base.obo
robot convert --input ../../elmo-base.owl --format json --output ../../elmo-base.json

5.5 Build the full release file

The full release adds inferred axioms from the reasoner:

robot merge \
    --catalog catalog-v001.xml \
    --input elmo-edit.owl \
  reason \
    --reasoner ELK \
    --equivalent-classes-allowed all \
    --exclude-tautologies structural \
  annotate \
    --ontology-iri "https://w3id.org/elmo/elmo" \
    --version-iri "https://w3id.org/elmo/elmo/releases/$(date +%Y-%m-%d)/elmo-full.owl" \
    --annotation owl:versionInfo "$(date +%Y-%m-%d)" \
  convert --format owl --output ../../elmo-full.owl

robot convert --input ../../elmo-full.owl --format obo  --output ../../elmo-full.obo
robot convert --input ../../elmo-full.owl --format json --output ../../elmo-full.json

5.6 Commit, push and open a pull request

cd ../..   # back to repo root
git add elmo-base.owl elmo-base.obo elmo-base.json \
        elmo-full.owl elmo-full.obo elmo-full.json \
        src/ontology/components/
git commit -m "Release $(date +%Y-%m-%d)"
git push -u origin release-$(date +%Y-%m-%d)

Then open a pull request on GitHub and follow the review steps described in the Release Workflow.

5.7 Tag the release on GitHub

Once the PR is merged to main, create a GitHub release as described in Release Workflow § Create a GitHub release. Use the date as the tag, prefixed with v — e.g. v2026-03-18.


6. SPARQL query reference

All queries live in src/sparql/.

File Purpose Used in
owldef-self-reference-violation.sparql Flags definitions that reference their own class make verify / CI
iri-range-violation.sparql Flags annotation values that should be IRIs but are literals make verify / CI
label-with-iri-violation.sparql Flags labels that contain raw IRIs make verify / CI
multiple-replaced_by-violation.sparql Flags deprecated terms with more than one replaced_by make verify / CI
dc-properties-violation.sparql Flags missing required Dublin Core properties make verify / CI
missing-definitions.sparql Lists ELMO classes without IAO:0000115 make verify (diagnostic)
missing-labels.sparql Lists ELMO classes without rdfs:label make verify (diagnostic)
none-definitions.sparql Lists ELMO classes whose definition is literally "None" make verify (diagnostic)
basic-report.sparql General class statistics SPARQL exports
class-count-by-prefix.sparql Counts classes grouped by IRI prefix SPARQL exports
synonyms.sparql Exports all synonym annotations SPARQL exports
obsoletes.sparql Lists deprecated/obsolete terms SPARQL exports
edges.sparql Exports parent-child edges SPARQL exports

Run any query ad hoc with:

robot merge --catalog catalog-v001.xml --input elmo-edit.owl \
  query --format csv \
  --query ../sparql/QUERYNAME.sparql results.csv

7. Quick-reference card

# Rebuild a template component
robot template --prefix 'ELMO: ...' --template ../templates/FOO.tsv --output components/FOO.owl

# Pre-process
robot convert --catalog catalog-v001.xml --input elmo-edit.owl --format ofn --output tmp/elmo-preprocess.owl

# Reason
robot reason --catalog catalog-v001.xml --input tmp/elmo-preprocess.owl --reasoner ELK \
  --equivalent-classes-allowed all --exclude-tautologies structural --output test.owl && rm test.owl

# Structural checks
robot verify --catalog catalog-v001.xml -i tmp/elmo-preprocess.owl \
  --queries ../sparql/owldef-self-reference-violation.sparql \
            ../sparql/iri-range-violation.sparql \
            ../sparql/label-with-iri-violation.sparql \
            ../sparql/multiple-replaced_by-violation.sparql \
            ../sparql/dc-properties-violation.sparql \
  -O reports/

# Quality report
robot merge --catalog catalog-v001.xml --input elmo-edit.owl \
  report --output reports/elmo-edit.owl-obo-report.tsv

# Explain an unsatisfiable class
robot explain --catalog catalog-v001.xml --input tmp/elmo-preprocess.owl --reasoner ELK \
  --axiom "SubClassOf(<IRI> owl:Nothing)" --explanation reports/explanation.md

Or use the make shortcuts defined in src/ontology/elmo.Makefile:

make -f elmo.Makefile reason
make -f elmo.Makefile report
make -f elmo.Makefile verify
make -f elmo.Makefile explain CLASS="https://w3id.org/elmo/elmo_XXXXXXX"