Skip to main content

The Running Example and the Proof Harness

📍 Where we are: Part I · Specification — the second move. (This book is organized as an ontology-building lifecycle: a named sequence of phases — Specification, Reuse, Conceptualization, and so on — that each chapter walks in order. Specification is the first phase: pinning down what the model must do before building it.) The requirements are written. Now meet the one campaign the whole book models, the files that hold it, and the harness that proves the model answers its 23 competency questions.

The previous chapter wrote down what the ontology — the shared, machine-checkable vocabulary that lets separate systems name the same thing — must answer. This one introduces what it answers about — a single monoclonal-antibody manufacturing campaign, the same batch the rest of the series follows — and the runnable proof harness that keeps the ORSD (Ontology Requirements Specification Document — the brief of competency questions, the plain-English questions the model must be able to answer) honest. Every Turtle (the text format the model is written in), SPARQL (the query language that asks the competency questions), and SHACL (the rule language the gates are written in) snippet in this book is a true excerpt of the files introduced here, and every competency question in the catalog is a test those files pass.

The simple version

Instead of a dozen toy examples, this book follows one medicine all the way through, like a single patient's chart that every specialist annotates. One vial of frozen cells becomes a batch, becomes a purified substance, becomes filled vials — and at each step the chart gains a few facts. The "proof harness" is just a program that re-reads the whole chart and checks that all 23 questions in the brief still have answers. If you change one fact, the program tells you which questions you broke.

A four-stage pipeline showing a competency question becoming an executable test: a natural-language competency-question box (CQ-04, impact), an arrow to a SPARQL query box labelled queries/CQ-04.rq, an arrow to a validate.py box that reads cq-catalog.json and runs every competency question, and an arrow to a green CQ-04 PASS box where the result is checked against the expected answer; a green return loop runs from the PASS box back to the question, labelled that requirements are tests re-run on every change and that all 23 must stay green to pass the build; a footer notes that cq-catalog.json binds all 23 competency questions, each to a SPARQL query, a SHACL gate, or a reasoner check. Requirements as tests: each competency question is bound in cq-catalog.json to the artifact that answers it, and validate.py runs all 23 as pass/fail acceptance tests. Original diagram by the authors, created with AI assistance.

The figure walks a single competency question, CQ-04, from end to end — chosen as the tour because it is the most investigator-facing of the 23 (when a lot fails, what else shares its lineage?) and because it exercises the full transitive derivedFrom walk the whole graph is built around (transitive = the relation chains, so following it reaches not just the parent but every ancestor; the genealogy below makes this concrete). The other 22 ride the identical loop, differing only in which artifact sits in the middle box — a SPARQL query (asks the graph a question), a SHACL gate (a rule the data must satisfy), or a reasoner check (a fact the model derives). Its two middle boxes are the CQ-04 entry from the previous chapter's cq-catalog.json made to run: its query: CQ-04.rq and check: equals [DP-001, DP-002] are exactly the CQ-04 … affected = [DP-001, DP-002] PASS line in the harness output below.

One campaign, end to end

Most ontology tutorials scatter a dozen disconnected toy examples; this book makes the opposite bet — one campaign, modeled exhaustively, so every class earns its place against the same concrete graph and the reader never has to re-learn the domain from chapter to chapter. The running example is one CHO-cell monoclonal antibody — the platform process most approved biologics are made by, chosen so the example transfers rather than being idiosyncratic — carried from the discovery target to the patient's cold-chain vial. (If the manufacturing terms below are new — CHO-cell, monoclonal antibody, cell bank, seed train, Protein A capture, viral clearance, drug substance vs drug product — Book 1 walks the whole physical cell-to-vial chain in plain language: see what a biologic is and the end-to-end bioprocessing overview. Here we need only their order and their lineage edges.) Its genealogy is the spine the whole graph hangs from:

a research cell bank RCB-CHO-001 is qualified up to a master cell bank MCB-CHO-001 and then a working cell bank WCB-CHO-001; a vial of that working bank is expanded through a shake flask SEEDFLASK-001 and a seed bioreactor SEED-001, which inoculates the production bioreactor batch BATCH-2026-001, whose harvest is clarified (CLAR-001) and captured on Protein A (PApool-001), cleared of virus (VIpool-001, VFpool-001), polished (POLpool-001), and concentrated into a drug-substance lot DS-001, filled into drug-product lots DP-001 and DP-002.

That full chain — RCB → MCB → WCB → SEEDFLASK → SEED → BATCH → CLAR → PApool → VIpool → VFpool → POLpool, eleven materials above DS-001 — is exactly what CQ-01 returns when it walks (bp:derivedFrom)+ upward from the substance lot. (The trailing + means "follow the derivedFrom edge one or more steps," so one query reaches every ancestor, not just the immediate parent.)

Each step on this spine is a real unit operation Book 1 walks through in full — the cell banks and seed train, the production bioreactor, then harvest and clarification, Protein A capture, viral clearance, polishing, and concentration into a drug substance that is filled into drug-product vials; here we only need their order and their lineage edges.

Each arrow becomes one bp:derivedFrom edge. Because that relation is transitive — if A derives from B and B from C, then A derives from C — DS-001 still traces back to WCB-CHO-001 in a single walk even though every intermediate sits between them, which is what makes CQ-01 and CQ-02 answerable. The campaign also carries a deliberately out-of-spec sibling (a tested result that falls outside its approved release limit — the trigger for a formal investigation), a parallel campaign run off the same working cell bank but down a separate seed train: WCB-CHO-001 seeds SEED-004, which inoculates BATCH-2026-004, captured into PApool-004, concentrated into substance lot DS-004 and filled into drug-product lot DP-004. Its real failure mode is specific: SEC monomer is in spec (98.687 %), but HMW aggregate is out — 2.41 % against the at most 2.0 % release limit (the pre-approved criterion a lot must meet to be shipped) — so it fails on one attribute, one path, with everything else green. That OOS lot is what lets the model answer the question an investigator actually asks — what else shares this lot's lineage? (CQ-04, which walks up to the shared WCB-CHO-001 and back down to the in-spec siblings DP-001/DP-002) — and what lets the release gate demonstrate the failure is isolated to exactly one path (CQ-11, OOS [DP-004, DS-004] on [hmwPct]). The sibling is failed on purpose. A campaign in which everything passed would never exercise the impact-tracing (CQ-04) or release-gate (CQ-11) questions at all — the model could claim to answer them without ever being forced to. A single, surgically isolated failure — one attribute, one path, everything else green — is the smallest case that proves the machinery rather than just the happy path.

(The genealogy above is a deliberate simplification: this headline spine names the load-bearing lineage, while later chapters elaborate the steps it foreshortens — the clarification stage CLAR-001, the orthogonal viral-clearance pools VIpool-001/VFpool-001, and the polishing pool POLpool-001 each get their own worked example.)

A word on what those lots are for. The numbers threaded through the campaign are the drug substance's critical quality attributes (CQAs) — the measured properties that matter to safety or efficacy — each with a real release meaning: SEC monomer / HMW aggregate (aggregation is a recognised immunogenicity risk — clumped antibody can trigger an immune reaction in patients — so HMW is capped at at most 2.0 %, the limit DP-004 breaches), CEX main peak (the charge-variant fingerprint that tracks deamidation and C-terminal lysine, bounded 60–80 %, here 70.686 %), and the process-related impurities host-cell protein (at most 100 ppm — parts per million — here 12 ppm) and residual DNA (a patient-safety limit, not cosmetic). The deep chemistry of these assays is Book 1's analytical chapter; here they are simply the attributes the gate checks. They are driven by critical process parameters (CPPs) — the settings you control on the line, here culture temperature (setpoint 36.5 °C) and feed rate (setpoint 0.40 vessel-volumes/day) — each declared bp:affectsQuality bp:MonomerPct-CQA (i.e. this parameter affects the monomer-percentage quality attribute) and carrying a normal operating range and a proven acceptable range, so the link from a parameter you set to an attribute you measure is itself walkable (CQ-06, CQ-07). That — the parameters you set, the attributes you measure, and the limits that tie them together — is the campaign's control strategy in miniature.

This is also where the book's central problem first bites: no single system holds all of those facts in one place, and each system records them in its own format. The culture temperature and feed rate live in the historian / OPC UA layer (the time-series database and the industrial sensor protocol that feeds it) as tags (BR101.Temp.PV, BR101.Feed.PV) carrying UCUM unit strings (a standard code for units like Cel or 1/d); the batch genealogy and the assertion that BATCH-2026-001 is a batch come from the MES / electronic batch record (the Manufacturing Execution System that records each batch as it runs — the bp:BatchRegister); the CQA results and the working bank's passage count come from the LIMS / ELN (the lab's result and notebook systems — bp:ELN). These systems and the protocols between them are the subject of the open-source companion book; here it is enough that each speaks its own private dialect, and the ontology's job is to make them name the same thing.

Throughout, the bp: prefix you have already seen (bp:derivedFrom, bp:BatchRegister) is a namespace — a shorthand for the address that uniquely names our terms, here the illustrative https://example.org/bioproc#. It is the same one the open-source companion book uses, so a class (a category of thing, like "Batch" or "Bioreactor") here is the same class there.

The dataset: six files that load as one

The campaign lives in examples/platform/ontology/ as a small set of files that parse into a single RDF graph. (RDF — the Resource Description Framework — models every fact as a subject–predicate–object triple, so the whole dataset is literally a web of linked nodes; this is the data model the rest of the book is built on, and the unit the harness counts below.)

filewhat it holds
bioproc.ttlthe local bp: vocabulary — classes and relations across the BFO spine (Material / Equipment / Quality / RealizableEntity / InformationArtifact / Process) with their load-bearing OWL axioms
align.ttlthe alignment up to public ontologies — BFO, IOF Core and biopharma, OBO biology, Allotrope, QUDT, PROV, SOSA (the subject of Part II) — and to the manufacturing data-model standards the companion data book grounds: ISA-95's equipment hierarchy and B2MML's batch vocabulary, so a bp:BatchRegister node carries the same role an ISA-95/B2MML record would
instances.ttlthe running example as individuals — every node in the genealogy above, plus the design space, analytics, release panel, serialization, distribution, and provenance
shapes.ttlthe SHACL gates — the release specification, the finish gate, the cell-bank gate, and the disjointness guards
cq-catalog.jsonthe executable ORSD — the 23 competency questions, each bound to the artifact that answers it
queries/CQ-*.rqone SPARQL file per query-backed competency question

The Turtle, SPARQL, and JSON are language-neutral, so the Korean edition quotes the very same files — there is no translated copy of the model, only of the prose around it.

The harness: validate.py

Prose requirements rot: a brief written in one file and a model built in another drift apart silently, and no one notices until a reviewer hits the gap. That is why the 23 competency questions are not left as prose but compiled into a program — a requirement you cannot run is a requirement you cannot trust. validate.py is that program, the inspector from the previous chapter's analogy. It does three things, in order:

  1. Parse the three Turtle files into one graph.
  2. Reason over it with an OWL-RL closure [1], which derives the entailed facts — new facts that logically follow from the ones written down. For example, because derivedFrom is transitive, the reasoner spells out every ancestor pair (not just the immediate parent), and because equipment is declared a kind of material entity, it tags each piece of equipment as one. Making all of these implied facts explicit is why the triple count grows so much (from 2120 to 7137 below); it is what lets the long-range lineage and structural questions (CQ-22) be answered by a plain query.
  3. Run the competency questions from cq-catalog.json — each query-backed one as a SPARQL evaluation [2], each gate one as a SHACL validation [3], each structural one as a reasoner check — and print a pass/fail line per question.

It exits zero only if all 23 pass. To reproduce this yourself, the README.md in examples/platform/ontology/ lists the three open-source Python dependencies (rdflib, pyshacl, owlrl) and the single command that produces the output below. Nothing in the stack is proprietary or licensed: rdflib parses and queries the graph, owlrl runs the reasoner, and pyshacl validates the gates — all pip-installable, all permissively licensed, so the exit code is reproducible on any machine with a Python interpreter and pinned dependency versions, with no triplestore server, no vendor key, and no cloud account. That the same authoring loop is just as well served by the open-source desktop editor Protégé and a local triplestore as by any commercial platform is the open-source companion book's whole argument; this harness is its smallest runnable proof. Here is that real output — the green baseline this entire book is engineered to keep:

[1] parsed 2120 triples (bioproc + align + instances)
[2] reasoned: 2120 -> 7137 triples after OWL-RL closure
[3] competency questions (ORSD v1.0.0 acceptance tests):

CQ GROUP RESULT DETAIL
CQ-01 lineage PASS 11 row(s)
CQ-02 impact PASS descendant superset of {DP-001, DP-002, DP-004, DS-001} (26 total)
CQ-03 lineage PASS row {batch: BATCH-2026-001, monomer: 98.611} present
CQ-04 impact PASS affected = [DP-001, DP-002]
CQ-05 trajectory PASS material superset of {PApool-001, POLpool-001} (2 total)
CQ-06 qbd PASS parameter superset of {FeedRate, Temperature} (2 total)
CQ-07 qbd PASS row {parameter: FeedRate, lot: DS-001} present
CQ-08 release PASS DS-001 release panel complete and in spec
CQ-09 release PASS ASK = True
CQ-10 release PASS DP-001/DP-002 pass release + finish gates
CQ-11 release PASS OOS [DP-004, DS-004] on path [hmwPct]
CQ-12 viral PASS sum(lrv) = 8.7 over 2 step(s)
CQ-13 packaging PASS package = [CARTON-001, CASE-001, PALLET-001]
CQ-14 packaging PASS ASK = False
CQ-15 provenance PASS claim = [claim-batch-001, claim-vessel-001]
CQ-16 provenance PASS ASK = True
CQ-17 characterization PASS WCB-CHO-001 conforms to the cell-bank gate
CQ-18 characterization PASS ASK = True
CQ-19 units PASS 0 row(s)
CQ-20 units PASS row {host: CHO-host, taxon: NCBITaxon_10029} present
CQ-21 structural PASS row {run: CCP-001, vessel: BR-101, vesselType: ProductionBioreactor} present
CQ-22 structural PASS transitive lineage + equipment-is-material inferred
CQ-23 structural PASS Batch-as-process and Batch-as-bioreactor both caught

23/23 competency questions PASS

ALL CHECKS PASSED

Read a few lines and the design becomes concrete. CQ-01 walks 11 ancestors from DS-001. CQ-04 returns exactly the two siblings that share the cell bank with the failed lot. CQ-11 shows the release gate failing on only hmwPct for only the two -004 lots — every other panel value in spec — which is what a realistic out-of-spec event looks like. CQ-12's 8.7 is not a free addition: it is the orthogonal viral-clearance claim in the ICH Q5A sense (the regulatory guideline on viral safety, which lets two independent clearance steps be summed). The two steps clear by independent mechanisms — a low-pH hold (pH 3.6, 60 min) that inactivates enveloped virus (4.5 LRV) and a virus-retentive nanofilter that removes small non-enveloped virus by size (4.2 LRV) — so their log-reduction values (LRV — each unit is a tenfold reduction in virus) may be summed into 4.5 + 4.2 = 8.7 total clearance. The validated capability (LogReductionValue, established once in a spiking study) is modelled separately from the per-batch conditions (holdPH 3.6, holdTimeMin 60, recorded every batch) — the same distinction a reviewer enforces. CQ-14 is an ASK (a SPARQL query that returns a yes/no answer rather than a table of rows) that is correctly False: nothing a vial is packed inside is also something it was made from, so containment and genealogy stay separate. The DETAIL column is the evidence; the RESULT column is the contract.

Truth as a build rule

The non-functional requirement that "every snippet is a true excerpt" is not a stylistic promise — it is enforced. Because the snippets are excerpts of bioproc.ttl, instances.ttl, and shapes.ttl, and because validate.py runs the same files, a snippet that drifts from the dataset either breaks a competency question (and fails the build) or is caught by review against the live output. The numbers in this book — 98.611 % monomer, an 8.7 total LRV, 11 ancestors, 2120 triples closing to 7137 — are not illustrative round numbers; they are what the harness prints. When a later chapter shows you a Turtle block, you are reading the model, not a sketch of it.

The unsolved part: green is necessary, not sufficient

A passing harness proves the model is consistent and complete against its own questions. It does not prove the model is true. validate.py confirms WCB-CHO-001 is fully characterized and within its passage limit (CQ-17, CQ-18); it cannot confirm the vial in the freezer is actually WCB-CHO-001 and not a mislabeled neighbor. It confirms every quantity carries a unit (CQ-19); it cannot confirm the analyst entered the right number. The harness closes the loop between requirements and model; the loop between model and reality is closed by wet-lab characterization, data integrity, and human judgment — the limits the verdict returns to. Keep the distinction in view as the green table reappears, chapter after chapter: it certifies that the model does what it promised, which is a smaller and more honest claim than that the model is right.

The harness as ground truth for a model

The same gap the last section named — the model is consistent, but is it true? — is, almost word for word, the question a machine-learning model raises in reverse, and it is where this deterministic harness quietly earns a second job. A reasoned, gated graph is exactly the ground truth (the verified, curated facts a learning system is anchored to) that the companion ML book argues a fluent model cannot supply for itself. Three of its lessons map directly onto the artifacts on this page.

First, the gates that refuse a bad release also refuse bad training data. The shapes.ttl SHACL gate was built to reject a non-conformant release; pointed at a subgraph about to be handed to a model — as a feature set, or as the retrieval context for a retrieval-augmented LLM (one that answers only from facts pulled from a trusted store, not from training memory) — the identical shapes reject a non-conformant load. A graph that passes its shapes is one where every lot has its bp:derivedFrom parent and every CQA its unit-bearing value; a graph that fails them is the hollow, mislabeled input a model would cheerfully complete with a confident invention. SHACL is how you catch that before the model does, in front of a reviewer.

Second, the typed lineage is the answer key, not a feature to be learned. When an LLM is asked what was DP-004 derived from?, the honest design does not let the model guess: it runs the very (bp:derivedFrom)+ walk CQ-04 already runs — GraphRAG, where the trusted store is this graph and retrieval follows the typed edges (bp:derivedFrom, bp:affectsQuality) rather than loose text — and the model only narrates the bound rows. So validate.py, the suite that keeps CQ-04 green, is also the regression test for that retrieval path; a green harness is a graph good enough to ground an answer. The frontier chapter develops this turn in full.

Third — and most pointedly for the ML reader — a model and a reasoned graph fail in opposite directions, and that is exactly why you keep both. This harness is deterministic: it asserts a fact only when the data and the OWL/SHACL rules entail it, and it abstains otherwise. A trained model is the inverse — it always emits an answer, fluent and unmarked, true or not. Validating a non-deterministic model therefore cannot mean re-running 23 pass/fail checks; it means held-out metrics under an honest split, the credibility and CSA discipline of the models chapter. And on graph-derived data the split that keeps those metrics honest is structural: rows that share a BATCH-2026-001 lineage must not straddle the train/test line, or a model scores high by memorizing a batch it will never see in production — data leakage. The ontology makes that grouping legible, because bp:derivedFrom already says which rows belong to one batch; you group the cross-validation by batch (leave-one-batch-out) using the lineage the graph asserts. The verified graph constrains and audits the learner it cannot replace; the learner predicts where the graph only records — the division of labor the book's hybrid-model and digital-twin chapter is built on.

Why it matters

A running example plus an executable harness is what makes the rest of this book trustworthy rather than merely plausible. Every modeling decision ahead can be checked the same way: change the model, run the harness, read 23 lines. If a class earns its place, a competency question depends on it and stays green; if it does not, nothing breaks when you remove it — which is the cleanest possible test of whether a class belongs. The medicine gives the book its concreteness; the harness gives it its rigor.

In the real world

A single, fully worked example backed by a runnable validator is how serious ontologies are actually shipped and regression-tested — the pattern SAMOD formalizes and the one large vocabulary projects use to keep a model from rotting as it grows [2][3]. On real platforms the same derivedFrom walk is a Palantir Foundry object link or a Neo4j Cypher traversal, and the same SHACL gate runs in a triplestore's validation step; the dataset here is small enough to read in an afternoon and complete enough to exercise every question a production graph must answer, which is exactly what a teaching artifact should be.

Key terms

  • Running example — the one CHO mAb campaign (WCB-CHO-001 → … → DP-001, with OOS sibling DP-004) modeled end to end, so every chapter builds on the same concrete graph.
  • Proof harness (validate.py) — the program that parses, reasons over, and runs the 23 competency questions against the dataset, printing a pass/fail table and gating on it.
  • RDF — the graph data model the whole dataset is expressed in: every fact is a subject–predicate–object link, so the dataset is a web of connected nodes.
  • Triple — one such subject–predicate–object fact; the atomic unit the harness counts (2120 → 7137).
  • Turtle (.ttl) — the human-readable text syntax for writing that RDF graph.
  • SPARQL (.rq) — the query language that walks the graph to answer a competency question.
  • SHACL (shapes.ttl) — the rule language that defines the release / finish / cell-bank gates the data must pass.
  • OWL-RL closure — the reasoning step that spells out the facts already implied by the written-down ones (e.g. every transitive ancestor, every equipment item tagged as a material entity) before the queries run; this is why the triple count grows.
  • True excerpt — a code snippet that is a verbatim part of the loadable dataset, not a simplified illustration; the book's standing rule.
  • Green baseline — the all-pass state of the harness (23/23) that every later chapter must preserve.
  • Ground truth — the verified, curated facts a learning or retrieval system is anchored to; here, the reasoned and SHACL-gated graph, which supplies the substance a fluent model cannot supply for itself.
  • GraphRAG — retrieval-augmented generation whose trusted store is a knowledge graph, so the model answers by walking typed edges (bp:derivedFrom) rather than guessing — the same (bp:derivedFrom)+ walk CQ-04 runs.
  • Data leakage — the validation error of letting rows from one batch fall on both sides of the train/test split, which flatters a model's score; the lineage graph makes the leave-one-batch-out grouping that prevents it explicit.

Where this leads

The requirements are written and the example loads green. Now the lifecycle proper begins — and its first rule is do not build what you can borrow. The next chapter, The Upper Spine: Continuants, Occurrents, and Why Everyone Builds on BFO, opens Part II (Reuse) at the very top of the model: the small, domain-neutral set of categories every later class hangs from, and the first and most consequential reuse decision an ontology makes.