open-ontologies

fabio-rovaiMIT活跃维护

用基础设施即代码的方式管理生产环境本体,支持变更前评估影响范围、变更后回滚,并生成审计员可复核的形式化证明。

Plan, apply and roll back changes to a production ontology, with a blast radius report and a proof an auditor can re-check.

v2.1.0发布于 2026-10-23 22:38 UTC2,870star +29 / 7 天323fork同步于 2026-11-11 05:40 UTC

怎么上手

由 README 提炼,执行前请确认
curl -LO https://github.com/fabio-rovai/open-ontologies/releases/latest/download/open-ontologies-x86_64-unknown-linux-gnu
chmod +x open-ontologies-x86_64-unknown-linux-gnu && mv open-ontologies-x86_64-unknown-linux-gnu /usr/local/bin/open-ontologies
硬件要求按 README 说明

README 未说明显存或 GPU 要求;提供 macOS Apple Silicon 与 Linux x86_64 预编译二进制,Docker 镜像仅支持 linux/amd64,Apple Silicon 需加 --platform linux/amd64 模拟运行。

支持 Apple Silicon有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

用 Rust 单二进制管理生产本体变更,先看影响半径再应用,并给出可复核的证明

用基础设施即代码的方式管理生产环境本体,支持变更前评估影响范围、变更后回滚,并生成审计员可复核的形式化证明。

核心能力

  • 用 plan/apply/drift/certify/rollback 组成变更闭环
  • 输出 blast radius 报告与风险评分,暴露文本 diff 看不到的后果
  • 生成推导证书,用 oo-cert 离线复核且无需本工具
  • Lean 4 检查器可拒绝伪造推导并指出失效规则
  • 内置 MCP 服务,可接入 Claude 等客户端调用 onto_* 工具

容易踩的坑

从源码构建需 Rust 1.88+,且部分工具依赖 embeddings、plugins、postgres/duckdb 等可选 Cargo feature,缺失时直接报错;serve 命令是走 stdin/stdout 的 JSON-RPC MCP 服务,在终端里看起来像卡住,属正常现象;Docker 镜像只有 linux/amd64,Apple Silicon 上不加 --platform linux/amd64 会跑不起来

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v2.1.0
  1. v2.1.0最新正式版2026-10-23 · 2026-10-23 22:38 UTC

    Fixed

    • shacl, enforce, unpack and monitor exit non-zero on a failing verdict (#323, reported by @noahgift). They printed conforms: false, an error-severity violation, certificate_refused or a blocking watcher and exited 0, so open-ontologies shacl shapes.ttl || exit 1 passed on the data it exists to catch. Codes are 0 pass, 1 fail, 2 not determined (conforms: null, or no checker re-ran the certificate), and each command's --help lists them. plan and drift now exit 1 on an error, as lint does.

    • Preserve carriage returns and CRLF text when importing dataframe rows into the Python engine.

    • Report non-object JSON from a configured Python certificate checker as unchecked instead of raising an attribute error.

    • Preserve RDF literal datatypes when comparing Python KGCL graph changes, while retaining lexical label and annotation values.

    • Python: keep anonymous blank-node identities stable when diffing identical RDF text in OntologyEngine.diff and kgcl_diff; identical inputs remain parsed and validated.

    • Python: serialize RDF triple-term values in SELECT, CONSTRUCT and DESCRIBE query results instead of raising AttributeError; ordinary scalar values remain unchanged.

    • Python: accept reported blank-node graph names when selecting asserted graphs for Horn reasoning; preserve ordinary graph-name forms and inferred-graph refusal.

    • A module that skipped at collection did not fail the strict Python leg. The entry that added python/tests/conftest.py says collection-time skips "are caught too, through pytest_collectreport". They were seen and not failed: the hook rewrote report.outcome, and that never reached the exit status. MEASURED on pytest 9.0.3 and 9.1.1, under OO_REQUIRE_FIXTURES=1, with one passing test and one module that skips at collection: 1 passed, 1 skipped, exit 0. Four files in the strict leg skip that way — test_shacl.py, test_shacl_vacuous.py, test_align.py and test_vocab_check.py — so the leg stayed green if their extras went missing. The hook now records the skip, and pytest_sessionfinish fails the run. python/tests/test_conftest_collection_skip.py holds it, with a control run without the variable.

    • owl-dl classifies Pizza exactly as HermiT does, and says when it is not complete. On the canonical pizza.owl it returned no subsumptions and 143 undetermined classes; it now returns HermiT 1.4.3's 500 subsumptions and its two unsatisfiable classes, none wrong. The changes, each measured against HermiT: absorption of non-atomic left-hand sides (domains, ∀r⁻ rules, binary rules), dependency-directed backjumping, subsumers read off each class's satisfiability model instead of one tableau per pair of classes, owl:disjointWith absorbed as A ⊓ B ⊑ ⊥ (disjointness with owl:Thing never fired before), anywhere blocking, and parsing of owl:AllDisjointClasses, owl:disjointUnionOf and owl:equivalentProperty, which were skipped in silence. Over 120 ORE 2015 files across the el, dl and pure_dl tracks there is no wrong subsumption and no wrong unsatisfiability claim.

    • An unrecognised restriction such as owl:hasSelf was read as ⊤, so Narcissist ≡ ∃loves.Self made every class a subclass of Narcissist. It is now an opaque name, which is sound in both positions.

    • A subsumption test that ran out of budget was dropped as if refuted, and the run still reported complete: true; it is now counted in subsumption_agent.undetermined and named in budget_exhausted_in.

    • complete now requires that every axiom was modelled. Each owl-dl run reports search_finished and constructs_not_modelled, which now include owl:hasSelf, property disjointness, owl:AllDifferent and restrictions on datatype properties.

    • align reads SKOS. It read owl:Class only, so a pure SKOS taxonomy produced zero candidates and said nothing about why. A skos:Concept is now aligned

  2. v2.0.12026-09-28 · 2026-09-28 08:52 UTC
    查看更新说明

    Fixed

    • A request sent before initialize no longer ends the MCP server (#260). rmcp's handshake reads messages itself until it sees initialize, answers a pre-initialize ping and turns away everything else (rmcp-1.4.0/src/service/server.rs:191 and :200), so serve returned ExpectedInitializeRequest, main.rs:1867 propagated it with ?, and the client read the exit as EOF while waiting on its own initialize. One line was enough: a client whose first message was {"jsonrpc":"2.0","id":1,"method":"server/discover","params":{}} never got as far as the handshake. That same request one message later is answered -32601 by rmcp's default on_custom_request and costs nothing, so arrival order was the whole difference between a reply and a dead process. The stdio transport is now wrapped: a pre-initialize request is answered with a JSON-RPC error, -32601 for an unknown method so the reply matches what the post-handshake path already returns and -32600 for a known MCP method sent out of order, and a pre-initialize notification is dropped. Nothing changes after initialize. Measured on both rmcp versions in the registry, 1.4.0 and 1.8.0: unguarded, both reject the reported byte sequence; guarded, both complete the handshake, so the version bump was not the fix it looked like.
  3. v2.0.02026-09-21 · 2026-09-21 23:59 UTC
    查看更新说明

    A major number because the engine now answers three questions it could not answer before, and because every checker it ships can say which binary it is.

    Added

    • A crosswalk's match type is checked, not asserted. crosswalk-certify reasons over each side alone, translates the entailed ancestors through the mapping itself, and reports the tightest SKOS predicate the evidence supports. An exactMatch the entailments do not support comes back downgraded with the reason. Output is valid SSSOM with extra columns, so existing tooling reads it unchanged.
    • What cannot map is named. A source term with no row, and an ancestor with no image in the target, both travel in the same file. That second case is the one that disappears from every crosswalk export today.
    • A contradiction probe. The translated claims are carried into the target and reasoned over. A clash means the target denies what the mapping carried in, which is a disagreement and not a granularity gap.
    • Modules that reason alone, with k-of-n promotion. Each module keeps its own store, so two contexts may disagree without either becoming inconsistent. A fact earns "true everywhere" when k of n modules entail it independently. The report states that agreement is a count and not a proof.
    • A numeric certificate. oo-matcert recomputes a matrix product from the definition and discharges MatCert.mul_of_check. Integers only, in core Lean, under the no-dependency rule. Freivalds is offered as an O(n²) opinion with its bound printed, and the floating-point path reports a tolerance and names no theorem, because a proof over the reals says nothing about IEEE-754.
    • Every checker names the binary that is running (#204). --version and a checker block carrying the name, the Lean toolchain and the SHA-256 of the file the process is running from, matchable against the release SHASUMS.txt.
    • The certified token says which artefact was accepted (#164). It carries the digest of the inputs the accepting run was handed, and is no longer Copy.
    • The verified SHACL evaluator is reachable from the command line (#203).
    • The SHACL compiler names what it ignores (#206), instead of discarding sh:severity and sh:message in silence.
    • Ten clash fixtures with near-miss twins (#160), so every detector is exercised by a graph written to trip it and a control that must stay clean.

    Changed

    • The release refuses a tag that does not carry the version it claims, and refuses to publish a binary whose status disagrees with its tag. Eleven historical tags did not, including v1.6.0, which reports 1.5.0.
    • The try page uses the palette of the figures beside it.
    • The front-page graph uses the width of its panel, and no two labels overlap.

    Fixed

    • Cargo.toml said 1.5.0 under the v1.6.0 tag (#248).
    • Two tests raced over shared files; one wrote a script while a sibling forked, which Linux answers with ETXTBSY.
    • The HQDM panel heading overlapped the right column in browsers whose fonts render wider than Chrome's.
  4. v1.6.02026-09-21 · 2026-09-21 02:39 UTC
    查看更新说明

    Added

    • The release ships the checkers. oo-cert, oo-horn, the first-order resolution checker and oo-lrat are built for x86_64-unknown-linux-gnu and published as release assets, with their digests in SHASUMS.txt and build provenance attested alongside the engine. Until now the release carried the engine and not the thing that checks it, so "hand the reviewer a proof they can check" required that reviewer to install elan and build Lean first.
    • The hosted demo runs the whole loop. web/try induces an ontology from a sheet, then lets a visitor add one line to it, reasons, writes a certificate, has oo-cert accept it, and then forges one conclusion and hands the same checker the same premises. Measured on the bundled staff.csv: one rdfs:subClassOf gives 14 derivations, oo-cert exits 0 with OOCert.certificate_sound, and the forged copy exits 1 naming rdfs9.
  5. v1.5.02026-09-20 · 2026-09-20 22:45 UTC
    查看更新说明

    1.4.0 and 1.4.1 were tagged without a section of their own; their entries are among the ones below, which cover everything since 1.3.0. New in this tag:

    Added

    • One sheet in, one ontology out. onto_induce (and induce in batch) reads one data sheet and induces an OWL class with typed properties, a SHACL shape the rows satisfy by construction, and a loading mapping, with a sentence of evidence per induced statement. Cardinality is a shape and never owl:FunctionalProperty; observed ranges are reported, never constrained; numbered columns are one multi-valued property. The row loader now mints a cell outside its datatype's lexical space as a plain string, so an ill-typed literal cannot slip past sh:datatype. (#233)
    • web/try/, the "try it here" page: one function running the pinned release binary in batch mode; drop a sheet, read the evidence, edit a cell, re-check. (#233)
    • A verified first-order resolution calculus, lean/Fo, and oo-fores. onto_fol_prove sends OWL 2 RL ontologies to the prover as clauses, translates Vampire's refutation into the certificate format and has it checked: the ninth verdict word refutation_certified rests on Fo.unsat_of_check. (#224, #225, #226, #227; decision 0005, second addendum)
    • A verified LRAT checker, lean/Lrat and oo-lrat, so a SAT solver's unsat is a proof and not an opinion; picosat traces are translated to LRAT. (#222)
    • mu, the tenth verdict word. A goal that puts in class position a term the ontology never uses as a class is returned unasked before any prover runs, with the term, its position and what the file does call it. (#232)
    • The checker names the theorem. A Certified token carries the theorem the checker printed, never the caller's guess. (#220)
    • HQDM audited, both shipped renderings, drawn side by side with the evidence recomputed by a test; the second panel intersects this engine's undetermined set with HermiT's list. (#219, #230)
    • The front-page figure reads its prover run and has a sixth beat for the unasked question. (#229)

    Changed

    • SHACL: a node shape's own value constraints are evaluated against the focus node for all four target forms (W3C core suite: pass 35 → 61, fail 17 → 15). (#231)
    • CI installs hnswlib with --no-cache and HNSWLIB_NO_NATIVE=1; the cross-runner built-wheel cache was the source of the python job's SIGILL. (#223)
    • Windows: the fake checker used by the verdict tests survives cmd.exe's quoting. (#220)

    Added

    • A module carries a theorem; a slice carries a measurement. onto_module_extract computes a syntactic locality module over a signature: ⊥, ⊤ or the iterated ⊥⊤*, the standard OWL API algorithm. Unlike onto_segment_retrieve, whose loss then has to be measured by onto_closure_diff, a locality module CANNOT lose an entailment over its signature, and the difference is a theorem rather than a metric (Cuenca Grau, Horrocks, Kazakov and Sattler, JAIR 31, 2008). That theorem is CITED and is not machine-checked, nothing under lean/ being about locality, so the report names a paper and never a Lean theorem, and the_module_report_never_names_a_lean_theorem asserts that over the serialised report. What can be checked is the consequence: verify_out_dir reasons the ontology and the module to a fixpoint through the existing closure diff and reports every conclusion over the signature the module does not reach, which must be none. Measured on benchmark/reference/pizza-reference.owl: 238 of 1,345 axioms and 510 of 2,332 triples, nothing unclassified, and zero of the 2,583 differences lost over the signature. The locality test is written per axiom type and an axiom that cannot be classified is INCLUDED rather than dropped, since any M' with M ⊆ M' ⊆ O keeps the coverage property; the kinds and counts are in the payload so a small module and an unreadable one cannot render the same. The nega

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    One triple. Nothing added, nothing removed, blast radius zero. 901 consequences that were not there before.

    $ printf 'load base.ttl\nplan proposed.ttl\n' | open-ontologies batch -
    #   the whole change:  ex:hasParent rdfs:domain ex:Person
    
    added_classes         0
    removed_classes       0
    blast_radius          0 triples affected
    risk_score            low
                          ────────────────────────────────────────────
    conservativity        not_conservative_under_rule_table
    new consequences      901          rule table owl-rl, in 0.04s
    

    Each number from a shape diff tells you that this change is safe. But the change gave a new type to each individual that the property already had. The tool closes this gap. A text diff cannot show you the gap. The change is one correct line, and the text diff is one line long.

    Then give the reviewer the proof. The run writes a certificate. A different person re-verifies months later. That person needs no instance of this software and no network. The command is oo-cert asserted.tsv derivations.tsv. The exit code is 0, and the theorem OOCert.certificate_sound covers the result.

    The checker also refuses a forged proof. Write a false conclusion into the derivation file. The same checker exits 1 and names the rule that does not hold. This is the red edge in the figure above. This refusal, and not the headline, is the part that survives examination.

    This is not an ontology editor. Use Protégé to draw class hierarchies. You run Open Ontologies on the change, before the change goes to production.

    The tool is like Terraform, and this is on purpose. But the plan checks what a change means and what it breaks, not only its text. A text diff is git diff, and you have git diff already.

    You do not need a JVM. You do not need Protégé. The engine speaks MCP to Claude, to Cursor, and to other clients of that protocol.

    See the engine at work

    Three triples go in, and three triples come out. A person asserted only that ex:Northwind is in a sanctioned jurisdiction. The engine derived the need for enhanced due diligence. A different person can check that derivation. That person does not have to trust you, or this engine, or the model that wrote the ontology.

    Watch the last seconds. Somebody forges one conclusion, and leaves the two premises exactly as they were. The same checker refuses the conclusion and names the rule. oo-horn printed each line in that terminal for the fixtures in tests/fixtures/horn/supplier/. A test runs the checker again. The test fails if the figure and the checker do not agree.

    With a proof, and without a proof

    An ordinary reasonerOpen Ontologies
    The answerNorthwind needs enhanced due diligencethe same answer
    Why the answer holds"the reasoner says so"a certificate that names each rule and each premise
    Who can check the answera second implementation can agree, and some reasoners give an explanation. No verified checker accepts either oneanybody, with a checker that shares no code with the engine
    If the engine has a defecta second implementation can disagree. Then you know only that one of the two is wrongthe checker refuses the answer, exit 1
    If a person edits the outputyou cannot find the editthe checker refuses it, and names the line and the rule
    If a rule was yours, not the standard'sthe report is the samea different verdict word, and a test holds that word
    What an auditor receivesa screenshota file that the auditor can check again
    Guarantee on an unsatisfiability answerassertednone, and the tool says so

    If the tool measures a property, the tool says measured. If a prover gives an opinion, that opinion never takes the vocabulary of the checker. Read what the tool proves, and what it does not prove.

    What the tool does

    CapabilityWhat you get
    Reason over OWL and RDFSMaterialised inferences and a derivation certificate that a proved checker accepts
    Use your own rulesSWRL, RIF Core or a Horn table, evaluated, with a verdict word that says the rules were yours
    Validate against SHACLA report from an evaluator with a measurement against the W3C suite, not an assertion of success
    Ask if something is satisfiableA finite model, replayed and checked, and not only a yes
    Ask if something is inconsistentA refutation, if one is certifiable. If not, an honest opinion from the engine
    Retrieve a slice for RAGEntailment preservation for each claim, because 99% coverage can still lose the one triple that mattered
    Change an ontology in productionPlan, blast radius, risk score, locked IRIs, apply, monitor, drift, rollback
    Load real dataCSV, JSON, XML, YAML, XLSX, Parquet, PostgreSQL and DuckDB into RDF
    Give the problem to a proverTPTP, CLIF, SMT-LIB and LADR from one translation. The tool names and counts what it cannot export
    Work from an assistantAn MCP server, so Claude or Cursor operates all of it in conversation

    Run the checker yourself

    The repository holds the three files. The output shows only the important fields.

    $ cd lean && lake build            # builds the checkers, core Lean 4, no Mathlib
    $ F=../tests/fixtures/horn
    
    $ lake exe oo-horn check $F/builtin_rules.tsv $F/asserted.tsv $F/good.tsv
    {"ok":true,"verdict":"entailed","theorem":"OOCert.entails_of_builtin_horn",
     "means":"every conclusion is true in every model of the asserted graph"}
    
    $ lake exe oo-horn check $F/builtin_rules.tsv $F/asserted.tsv $F/bad_conclusion.tsv
    {"ok":false}                        # one IRI in the conclusion changed. exit 1.
    
    $ lake exe oo-horn check $F/user_rules.tsv $F/asserted.tsv $F/good.tsv
    {"ok":true,"verdict":"entailed_under_supplied_rules","theorem":"OOCert.horn_certificate_sound"}
    

    The third line is the important one. The inference is the same. But you wrote one of the rules. Thus the rule is an assumption that the certificate carries, and it is not a fact that the certificate establishes. The verdict word changes. A test fails if that word stops changing.

    flowchart LR
      E["Untrusted engine<br/>Rust, or the pure-Python one"] -->|certificate| C["Verified checker<br/>core Lean 4"]
      I["Isabelle/HOL<br/>independent second kernel"] -.->|same bytes| C
      C -->|built-in rules| A["entailed"]
      C -->|your rules| B["entailed_under_supplied_rules"]
      C -->|forged| X["refused, exit 1"]
    

    Run the tool on your own ontology

    The repository ships those fixtures. Now do the same steps with a file that you write. These steps take one minute.

    mkdir /tmp/oo-demo && cd /tmp/oo-demo
    cat > coffee.ttl <<'EOF'
    @prefix ex:   <http://example.org/> .
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    
    ex:Espresso rdfs:subClassOf ex:Coffee .
    ex:Coffee   rdfs:subClassOf ex:Drink .
    ex:myCup    a               ex:Espresso .
    EOF
    
    export OPEN_ONTOLOGIES_STORAGE_MODE=persistent          # in-memory by default, see below
    open-ontologies --data-dir /tmp/oo-demo/store load coffee.ttl
    open-ontologies --data-dir /tmp/oo-demo/store reason --profile rdfs --certificate ./cert
    

    Three triples go in, and three triples come out. The cup is a Coffee. The cup is a Drink. Espresso is a subclass of Drink. Each RDFS reasoner can do this much. The directory that the run wrote is the difference.

    lake exe oo-cert /tmp/oo-demo/cert/asserted.tsv /tmp/oo-demo/cert/derivations.tsv
    {"ok":true,"asserted":3,"derivations":3,"theorem":"OOCert.certificate_sound"}
    

    Now tell the checker a lie. Keep the premises, and forge one conclusion. The forged conclusion says that the cup is a Beer:

    cp -r /tmp/oo-demo/cert /tmp/oo-demo/forged
    sed -i '' 's|example.org/Drink>\t<http://example.org/myCup>|example.org/Beer>\t<http://example.org/myCup>|' \
      /tmp/oo-demo/forged/derivations.tsv     # GNU sed: drop the '' after -i
    lake exe oo-cert /tmp/oo-demo/forged/asserted.tsv /tmp/oo-demo/forged/derivations.tsv
    
    {"ok":false,"asserted":3,"derivations":3,"first_rejected":2,"rule":"rdfs9",
     "conclusion":"<http://example.org/myCup> <...#type> <http://example.org/Beer>",
     "premises":["<http://example.org/myCup> <...#type> <http://example.org/Coffee>",
                 "<http://example.org/Coffee> <...#subClassOf> <http://example.org/Drink>"]}
    

    The exit code is 1. The output gives the number of the bad line. It names the rule. It also shows the premises, so that you can see that the premises do not support the conclusion.

    What the proof contains

    The proof is two tab-separated files. For the run above, the two files are 1.3 KB. asserted.tsv holds your claims:

    <ex:myCup>      <rdf:type>          <ex:Espresso>
    <ex:Coffee>     <rdfs:subClassOf>   <ex:Drink>
    <ex:Espresso>   <rdfs:subClassOf>   <ex:Coffee>
    

    derivations.tsv holds one line for each step. Each line gives the rule, then the conclusion, then the premises for that conclusion.

    rdfs9    <ex:myCup> <rdf:type> <ex:Coffee>              <ex:myCup> <rdf:type> <ex:Espresso>        <ex:Espresso> <rdfs:subClassOf> <ex:Coffee>
    rdfs11   <ex:Espresso> <rdfs:subClassOf> <ex:Drink>     <ex:Espresso> <rdfs:subClassOf> <ex:Coffee> <ex:Coffee> <rdfs:subClassOf> <ex:Drink>
    rdfs9    <ex:myCup> <rdf:type> <ex:Drink>               <ex:myCup> <rdf:type> <ex:Coffee>          <ex:Coffee> <rdfs:subClassOf> <ex:Drink>
    

    That is the full proof. It needs no model, no network and no vendor.

    A checker reads each line. For each line, the checker derives the conclusion again from the premises of that line, under the rule that the line names. The checker then confirms that each premise is asserted, or that an earlier line concluded it. Anybody can write such a checker. This checker has a soundness theorem.

    Who checks the certificate, and when

    The certificate is a file. Thus the person who holds the file can check it, at any time that they choose.

    WhoWhenWhat they run
    You, in the loopat each run, before you trust an answerlake exe oo-cert, next to the reasoner
    A reviewerwhen a change landsthe same command in CI, on the artefact that the run wrote
    An auditor, months laterlong after the engine moved onthe same command, on the archived files
    A different agentwhen it receives a claim from an agent that it does not trustthe same command, before it acts on the claim

    The tool streams nothing, and the tool calls no home server. The engine and the checker share bytes on a disk, and they share no protocol. This is what makes the last two rows possible. An auditor who checks a claim next year needs the two files and a Lean build. That auditor does not need an instance of this software.

    The certificate records a digest of the assertions that the run used. The file asserted.sha256 holds that digest, next to the two other files. A holder of a store runs certificate-check <dir>. The command reads the digest, computes the same digest from the store, and reports whether the two agree.

    That answer has a limit, and the command states the limit. A digest binds a certificate to bytes. It does not bind a certificate to a state of the world. A store that changed and then changed back gives the same answer. The type-level form of this work is decision 0010, and that work is open.

    One case needs a word, because you will meet it. reason writes its inferences into the store by default. A check after such a run finds more triples in the store than the certificate lists. The report names that cause, and it does not call the store a different graph. It says different graph only when a triple in the store is not a conclusion of the run.

    Two defaults can cause you trouble. First, storage is in-memory, unless you set OPEN_ONTOLOGIES_STORAGE_MODE=persistent. Thus a load and then a reason starts from an empty store, and certifies nothing. The tool gives a warning, and you can miss that warning easily. Second, --data-dir is a flag and not an environment variable. Thus a demonstration without that flag writes into ~/.open-ontologies, next to your real work.

    The discipline behind this work has a cost, and the discipline has earned that cost: what the rules are, and what each rule caught.

    Three claims that used to travel on trust

    Three claims, each one checked against a real run

    A crosswalk states a match type. Nothing checked that statement. The engine now reasons over each side alone. It compares what each side entails, through the mapping itself. It then reports the tightest match type the evidence supports.

    An exactMatch that the entailments do not support comes back downgraded. The report gives the reason. It also names every term the crosswalk does not carry. That second list is the one that disappears from most crosswalk files. The output is valid SSSOM, so your tools read it today.

    The check compares where two terms sit in their hierarchies. It does not compare what the terms mean. Two sibling terms under one mapped parent look the same to it. So it can refute a match type, and it never makes a claim stronger. A parent that the mapping does not carry is a gap, and the report names it. A row with nothing to compare says so and is not certified.

    A second question is sharper than a downgrade. The engine carries the translated claims into the target and reasons again. A clash means the target denies what the mapping carried in. That is a disagreement, and a person must settle it. Run it with crosswalk-probe.

    Contexts can disagree. Birds fly. Penguins are birds, and penguins do not fly. One graph that holds both is inconsistent, and this engine finds the clash. Each module reasons alone instead. A fact earns "true everywhere" when k modules of n entail it.

    A number can now carry a certificate. oo-matcert recomputes a matrix product from the definition. It prints MatCert.mul_of_check when it accepts. Integers only, and that is the condition for the sentence to hold. Freivalds costs less and gives a probability, so it stays an opinion with its bound printed. Floating point reports a tolerance, because a proof over the real numbers says nothing about IEEE-754.

    open-ontologies batch plan.json   # crosswalk-certify, crosswalk-probe, modules --threshold k, matcert
    open-ontologies crosswalk-probe source.ttl target.ttl mapping.tsv   # exits 1 on a clash
    

    What the tool proves

    You askYou get backChecked against
    Reason over OWLA derivation certificateOOCert.certificate_sound
    Reason with rules that you wroteA certificate, and a different verdict wordOOCert.horn_certificate_sound
    Is this satisfiableA finite modelDl.satisfiable_of_checkModel
    Is the model of a solver realThe model, replayedFol.satisfiable_of_check
    Is this inconsistentA refutationOOCert.refutation_sound
    Does this data fit the shapesA validation reportShacl.validate_spec
    Does a retrieval slice still support the answerPreservation for each claimOOCert.certificate_sound

    A retrieval slice with 99% coverage can lose the one triple that an answer needs. A slice with 60% coverage can keep each claim that matters. Coverage is a proxy, and the proxy rises as the slice grows.

    Thus a retriever that you tune on coverage learns to fetch more, and not to fetch the correct triples. Entailment preservation is the property that you want. The tool can decide that property here, and it gives one certificate for each claim. See decision 0007.

    A measurement of the loss is the second-best answer. The best answer is a subset that can lose nothing. onto_module_extract computes such a subset. It computes a syntactic locality module over a signature. Each entailment of the full ontology over those terms is also an entailment of the subset.

    That guarantee is a theorem of Cuenca Grau, Horrocks, Kazakov and Sattler, JAIR 31 (2008). The tool CITES that theorem, and no machine checks it here. No file under lean/ is about locality, and the report says exactly that.

    The report names no theorem of this project. It offers a measurement instead. It reasons over the ontology and over the module to a fixpoint. It then reports each conclusion over the signature that the module does not reach. On the pizza ontology of this repository, the module is 238 of 1,345 axioms.

    The run lost zero conclusions out of 2,583 differences. onto_conservative_check uses the same machinery for the lifecycle. It answers one question: does the addition of these axioms change any consequence over the names that the ontology already used? See decision 0011.

    Install

    # macOS (Apple Silicon)
    curl -LO https://github.com/fabio-rovai/open-ontologies/releases/latest/download/open-ontologies-aarch64-apple-darwin
    chmod +x open-ontologies-aarch64-apple-darwin && mv open-ontologies-aarch64-apple-darwin /usr/local/bin/open-ontologies
    
    # Linux (x86_64)
    curl -LO https://github.com/fabio-rovai/open-ontologies/releases/latest/download/open-ontologies-x86_64-unknown-linux-gnu
    chmod +x open-ontologies-x86_64-unknown-linux-gnu && mv open-ontologies-x86_64-unknown-linux-gnu /usr/local/bin/open-ontologies
    
    # Docker
    docker pull ghcr.io/fabio-rovai/open-ontologies:latest
    
    # From source (Rust 1.88+)
    cargo build --release --features embeddings,plugins,sql
    

    For Intel macOS, for native Windows and for other systems, read docs/quickstart.md and docs/windows.md.

    The Docker image is for linux/amd64 only, so on Apple silicon run it under emulation with docker run --rm -i --platform linux/amd64 ghcr.io/fabio-rovai/open-ontologies:latest.

    The serve command starts an MCP server. That server speaks JSON-RPC on stdin and stdout. Thus, at start, the server looks as if it stopped, while it waits for a client. This behaviour is correct. From a terminal, use the CLI subcommands instead, for example open-ontologies validate <file.ttl>.

    Connect the tool to Claude

    For Claude Code, add this block to ~/.claude/settings.json. For Claude Desktop, add the block to ~/Library/Application Support/Claude/claude_desktop_config.json:

    {
      "mcpServers": {
        "open-ontologies": {
          "command": "/path/to/open-ontologies",
          "args": ["serve"]
        }
      }
    }
    

    Start the client again, and the onto_* tools are available. For Cursor, for Windsurf, for Zed and for VS Code, read docs/quickstart.md.

    Stars

    What the box contains

    One loop: plan a change, apply the change, watch for drift, certify what the engine derived, and rollback when the change was wrong. That loop is the whole of this front page, and that loop is the purpose of the tool.

    The other parts have their own documentation and their own code. They are alignment, embeddings, PDDL planning, clinical crosswalks, the plugin marketplace and CIVeX. docs/tool-reference.md lists them one time, and this page does not list them. A large list of features is not the argument.

    Some tools need an optional Cargo feature, and they return an error without that feature. Four tools need embeddings. Two tools need plugins. Two tools need postgres or duckdb. The release binaries have embeddings and plugins, so they lack only the two tools that need postgres or duckdb. The GHCR image also has sql, which turns on postgres and duckdb, so it carries all eight tools.

    The Python package open-ontologies-lite also reasons now. It reasons in pure Python, and it needs no Rust toolchain. The same Lean binaries check its certificates. The package is a second engine. The lack of trust in that engine costs nothing, because the warrant was never in the engine.

    tools/horn_differential.py runs both engines and the Lean checker over each RDF document in the repository. The two engines are not independent. They run the same algorithm over the same rule table, and the comments in the Python cite the Rust by file and by line. Thus their agreement is strong evidence against a transcription error, and it is almost no evidence against a shared misreading of a W3C rule. The independent leg is the Lean checker. The tool prints that caveat next to its agreement count at each run. docs/lean-certificates.md also states the caveat as a limitation.

    With those parts, the repository holds a marketplace of 33 standard ontologies, clinical crosswalks, semantic embeddings and a lineage audit trail. It also holds a desktop Studio, with a virtualized ontology tree, an AI chat panel and an inspector in the style of Protégé. You need no JVM. You need no Protégé.

    Documentation

    TopicLink
    Quickstartdocs/quickstart.md
    Architecturedocs/architecture.md
    Derivation certificates and the Lean checkersdocs/lean-certificates.md
    Which axioms a conclusion rests on, and provenance semiringsdocs/explanation.md
    What the Lean proofs assume about the Rustdocs/trusted-computing-base.md
    Aeneas at the Rust and Lean boundary: what it proves, and what it costsdocs/aeneas-boundary.md
    Which gates a green CI tick randocs/ci-gates.md
    First-order export, TPTP and Common Logicdocs/first-order-export.md
    Each reasoning system, and why the project used or refused itdocs/reasoning-systems-inventory.md
    Design decisions, one rule for each filedocs/decisions/
    SHIQ reasoningdocs/reasoning.md
    Schema alignmentdocs/alignment.md
    Data pipelinedocs/data-pipeline.md
    Ontology lifecycledocs/lifecycle.md
    Locality modules and conservative extensionsdocs/modules-and-conservativity.md
    Semantic embeddingsdocs/embeddings.md
    Clinical crosswalksdocs/clinical.md
    IES supportecosystem · alignment · SPARQL examples
    Benchmarksdocs/benchmarks.md
    Determinism and corrected resultsdocs/determinism.md
    Windowsdocs/windows.md
    ContributingCONTRIBUTING.md

    Open Ontologies for teams

    The engine in this repository has an MIT licence, and it keeps that licence. The engine does not give you a place for the evidence. You need a place that keeps certificates. You need a review of each change to an ontology, before that change ships. You need an auditor who can check an answer again, months later, with no installation.

    We build tesseractsemantics.com for that purpose. If a wrong answer from your ontologies has a cost, a conversation is worth your time.

    Stack

    Rust edition 2024, one binary, no JVM. Oxigraph 0.5 for RDF and for SPARQL 1.1. rmcp for MCP over streamable HTTP. SQLite for state, for lineage and for feedback. Lean 4 v4.33.1 for the checkers, core Lean only, no Mathlib.

    Tauri 2, React 19 and Tailwind 4 for the Studio. The full table is in docs/architecture.md.

    Citation

    • Open Ontologies: Tool-Augmented Ontology Engineering with Stable Matching Alignment. Fabio Rovai, 2026. arXiv:2605.09184
    • CIVeX: Causal Intervention Verification for Language Agents. Fabio Rovai, 2026. arXiv:2605.09168

    CITATION.cff holds machine-readable metadata. It also operates the "Cite this repository" button of GitHub.

    Language of this page

    This page follows the writing rules of ASD-STE100 Simplified Technical English. The rules are one idea for each sentence, the active voice and simple tenses. A descriptive sentence has a maximum of 25 words. A paragraph has a maximum of 6 sentences. The same term always keeps the same meaning.

    tests/readme_simplified_english_test.rs measures those rules. That test fails the build if this page breaks them. The same test holds the translated page to the structure of this one.

    The official STE dictionary of approved words is a licensed document, and this project does not hold a copy. Thus this page claims the writing rules only. It does not claim approved-word compliance. The technical names and technical verbs of this domain stay in use. Examples are ontology, triple, reason and certify. STE permits such terms for a technical domain.

    License

    MIT. Fabio Rovai maintains this project at Tesseract Semantics. If this project is useful to you, you can support it through GitHub Sponsors.