Skip to learning content
← All articles
RAG free

Build a working ontology from defence logistics data

Build an ontology from an empty Python file, inspect actual graph records and their sources, and extend a maintenance example to multiple required parts. Six chapters combine plain-language explanations with a downloadable, locally tested implementation.

The question: How do we actually create, validate and use an ontology from operational source records?

You’ll learn: Construct an ontology step by step, trace RDF facts to CSV records, validate and query them, and migrate the model to support several required parts per order.

For: Domain experts, analysts and engineers; concepts are explained before the runnable commands.

Executed teaching prototype · AI-assisted source check . This is not a human expert endorsement.

Chapter 5: Orchestrate the calculation and preserve a reviewable result

5. Orchestrate the calculation and preserve a reviewable result#

The query is one stage of the application. A reproducible run records which inputs were transformed, whether validation succeeded, what was requested, and where processing stopped. Here, orchestration is a fixed sequence of commands and artifacts. The sequence has no uncertain planning step that needs an autonomous agent.

Step 1: Run dependent stages with failure handling#

Run these commands from the extracted lab directory using the environment created in Chapter 2. PowerShell must inspect each external program's exit code so a failed stage prevents the next one from running:

powershell
.\.venv\Scripts\python.exe ontology_lab.py build
if ($LASTEXITCODE -ne 0) { throw "Build failed; stop here." }

.\.venv\Scripts\python.exe ontology_lab.py validate
if ($LASTEXITCODE -ne 0) { throw "Validation failed; inspect the report." }

.\.venv\Scripts\python.exe ontology_lab.py query --org ORG-TRAIN --order WO-204
if ($LASTEXITCODE -ne 0) { throw "Query failed; inspect the reported condition." }

A successful process exit and sufficient stock are different outcomes. The command can successfully explain a shortage. An invalid graph follows the failure path. A nonempty JSON file may contain a diagnostic from a rejected stage, so inspect its status.

build performs the initial SHACL check. validate reopens and checks the generated artifacts. Before a query, load_verified() compares source, importer, query, and generated-artifact hashes with results/manifest.json. Changed inputs require an explicit rebuild.

A repeatable run stops at a reviewable proposal

Original process diagram for the reference implementation. Running a command again should reproduce the graph from its inputs; an external approval-and-write service is a separate extension.

Select a box to inspect its role. On a small screen, scroll the diagram sideways.
loadtestusecomputerecord
Read the source set

Identify the exact files, schema and mapping used for this run. Mixing snapshots can produce an answer that never corresponded to any real stock state.

Read the complete diagram as text
  • Read the source set: Identify the exact files, schema and mapping used for this run. Mixing snapshots can produce an answer that never corresponded to any real stock state.
  • Build the graph: Create canonical objects, links and provenance. Stop on source or identity errors rather than guessing a successful result.
  • Validate the graph: Inspect SHACL and integrity results. A failed validation must prevent the normal proposal path from using the failed build.
  • Run the scoped query: Select the requested organization and work order, then check part, stock, allocation and inspection evidence. This is deterministic data processing.
  • Expose the blockers: Six on hand minus two quarantined and three reserved leaves one. Requiring two therefore produces a shortage of one.
  • Emit a review request: The artifact records the facts and blockers for a reviewer. It grants no permission and performs no live inventory change.
  • Read the source set → load → Build the graph
  • Build the graph → test → Validate the graph
  • Validate the graph → use → Run the scoped query
  • Run the scoped query → compute → Expose the blockers
  • Expose the blockers → record → Emit a review request

The dependencies are concrete: declared source rows produce the graph; validation applies to that graph; a scoped query produces the explanation and local review draft. Keep these artifacts together so another engineer can reproduce the result.

Step 2: Read the implemented boundary in one place#

CapabilityImplemented and exercised hereRequired for a real service
Data ingestionFixed CSV contracts, explicit aliases, typed RDF mappingsApproved connectors, feed completeness, failure ownership, and refresh policy
ValidationSHACL and explicit identity, unit, allocation, and freshness checksDomain-specific acceptance coverage and trusted source verification
ScopeA CLI selector used by fixed, scoped queriesVerified identity, authorization, and protected data access
Integrity and lineageLocal hashes, source locators, and PROV recordsProtected audit records and appropriately trusted ingestion
ReviewAn unsubmitted JSON draft bound to its input revisionAuthenticated reviewer, approval expiry, and current-state rechecks
External actionsNo stock reservation, purchase, or equipment releaseAuthorized command handling, concurrency control, receipts, and reconciliation
AI extractionNo model call or neural extraction stageCandidate extraction evaluation and a review process before facts are accepted

The local --org flag is not an access-control boundary: anyone with the downloaded files can inspect all their contents. A deployed service must derive scope from verified identity and policy. ABAC is one policy model using requester, resource, operation, and environment attributes.502 A hidden record or property must not silently become a negative business fact.

Step 3: Explain the quantity and the proposal#

The baseline's physical unit sets are disjoint: two quarantined units and three other reserved units within six on hand. The calculation therefore yields:

formula
Available = 6 − 2 − 3 = 1
Shortage = max(0, 2 − 1) = 1

The max means extra usable stock produces zero shortage. It does not justify hiding impossible negative availability. If allocations exceed stock, or the same unit appears in both excluded sets, the inputs require correction.

The query writes results/explanation.json and results/human-review-request.json. These selected review fields come from the baseline run:

json
{
  "type": "human-review-request",
  "orderId": "WO-204",
  "org": "ORG-TRAIN",
  "status": "UNSUBMITTED_LOCAL_DRAFT",
  "shortage": 1,
  "basisSchemaVersion": "1.0.0",
  "basisSnapshotRevision": 1,
  "requiresFreshnessAndAuthorizationRecheck": true,
  "approvalImplemented": false,
  "businessWritesExecuted": false
}

The complete draft also includes basisInputFingerprint. It has not been delivered to a reviewer. A coordinator can inspect what was requested, which evidence revision supported it, and why another filter is needed. That is the completed output of the baseline workflow.

Step 4: Test freshness separately from structure#

A well-typed integer may still be too old to use. fixtures/scenario.json sets a fixed demonstration clock of 14 September 2026, 08:00 UTC, and a 7,200-second freshness allowance. The baseline's stock, two allocations, and inspection were observed at 07:30, giving four fresh records out of four required.

To test the boundary without editing the fixtures, run:

powershell
.\.venv\Scripts\python.exe ontology_lab.py query --org ORG-TRAIN --order WO-204 --as-of 2026-09-15T08:00:00Z

Inspect results/explanation.json: status becomes insufficient_evidence, while available and shortage become null. Rerun the original query to restore the baseline output. The command accepts an explicit clock for repeatable tests; it does not fetch current depot records.

A connector must distinguish observation time from ingestion time. Downloading an old spreadsheet today does not create a new stock observation. SHACL checks graph conditions; the freshness policy and physical meaning of an observation are separate responsibilities.501

Step 5: Explore changed quantities locally#

Inspect the stock calculation and proposal gates

Change the fictional PF-9 quantities and inspect why the proposal passes or stops. These controls calculate an example in your browser; they do not change an inventory system.

Proposal blocked

Available = 6 − 2 − 3 = 1. Shortage = 1.

The request is short by 1. Reviewer approval cannot remove a stock shortage.

  • Quarantined: 2
  • Reserved: 3
  • Available: 1

The calculation assumes quarantined and reserved quantities are disjoint subsets of the on-hand count, and every quantity uses the same part, depot, unit and source snapshot. The downloadable lab also validates those source relationships.

With seven units on hand and the same two quarantined and three reserved, two remain available. That removes the quantity shortage. The exercise lets you change quantity, freshness, scope, and a simulated approval state to see which condition controls the outcome.

The controls are teaching inputs. They do not authenticate a supervisor or change inventory. The equation can be satisfied while a real maintenance process still requires other evidence or authorization.

Step 6: Define an action contract before connecting a system#

If a later pilot reserves stock, name a separate operation, for example RequestStockReservation. Agree on the following proposed contract before writing its adapter. This contract is an implementation specification, not an additional command in the download.

Contract elementConcrete requirement
Request identityUnique operation ID and authenticated requester; derive permitted organization server-side
Intended changeExact work order, requirement line, part, unit, quantity, depot, and selected snapshot
Decision basisInput fingerprint, model version, source revision, approval identity, and expiry
Submission checksCurrent authorization, fresh evidence, approved requirement, and sufficient stock
Concurrent changeCompare the expected revision with current state; reject and re-evaluate on conflict
Result and retryDurable operation receipt; reuse the operation ID; reconcile ambiguous downstream outcomes

Submission conditions need both business criteria and permissions.503 Passing a quantity check alone is insufficient. If another job reserves the last unit after review, the stale proposal must not proceed with its earlier arithmetic.

An external system can succeed while a later local update fails; documented writeback behavior illustrates why these effects cannot simply be assumed to form one transaction.504 After a timeout, inspect the operation's recorded outcome before retrying. The adapter and downstream service must agree on operation identity and recovery behavior.

Checkpoint: what your workflow guarantees#

You have an ordered build, validation, and query sequence; a result tied to source revisions; and a local review draft. You can demonstrate that stale evidence withholds the calculation. You also have a concrete specification for a future action service. Chapter 6 now changes the ontology itself and proves the new requirement-line model with data, queries, and failure tests.

Source 501 ↗

W3C, Shapes Constraint Language — validation against graph conditions; checked 14 September 2026. Freshness and inventory policies are explicit lab choices.

Source 502 ↗

NIST, SP 800-162: Attribute Based Access Control — attributes and policy decision model; checked 14 September 2026.

Source 503 ↗

Action submission criteria — configured submission conditions; checked 14 September 2026. The proposed reservation contract is this guide's design.

Source 504 ↗

External writeback and webhook behavior — external success with later ontology failure remains possible; checked 14 September 2026. No webhook was configured or invoked.