▲ 5 r/semanticweb+1 crossposts

Computation-Ready Aerial Photography: an Open Digitisation Standard with STAC, GeoSPARQL and RiC-O

TL;DR: Most digitised heritage is scanned and catalogued but you still cannot query it. I built a small open standard that fixes this for aerial photography!

For twenty years "digitised" has meant scanned and put on a map. But a photo on a map is legible to a human, not a machine. You cannot pull "every aerial frame over this city between 1943 and 1946", run image similarity, or cross-reference a sortie to another archive without clicking through by hand. Digitised but not computable.

So I stopped guessing and measured. I took multiple real records from a national aerial-photography collection's public catalogue (metadata only, read-only, rate-limited) and checked what was already there:

- 100% already had a footprint polygon (in EPSG:3857, not lat/lon)

- 100% had an ISO-8601 date, with a day/year precision flag

- 100% had a stable identifier

- 0% had machine-readable rights (the one real gap)

The substrate is already in the data. Getting to a computation-ready baseline is a reprojection, a URI mint, and a rights mapping. All automatable. I ran all three on 292 frames in one script and validated against the standard at zero errors. The frames span 1924 to 1956, from a 1924 Royal Navy sortie over Hong Kong to the Caribbean.

The standard is pure synthesis, not invention: GeoSPARQL, PROV-O, Dublin Core, IIIF, and Records in Contexts, across three tiers you adopt incrementally. It also publishes a crosswalk I could not find anywhere else: binding the archival stack (RiC-O, PROV-O) to the geospatial stack (STAC, GeoSPARQL). Nobody had bridged both for historic aerial photography, so a recon frame is either a well-described archival object you cannot query spatially, or a searchable image with no provenance.

All open source, MIT and CC BY: ontology, SHACL shapes, harvester, STAC and GeoJSON exports, and an interactive map.

Repo: https://github.com/fabio-rovai/open-ontologies/tree/main/case-studies/heritage-aerial

Full writeup with the charts: https://gov.tesseract.academy/research/computation-ready-aerial-heritage

Happy to be told I reinvented something or missed a standard. What would you want out of a collection like this that this does not yet do?

reddit.com
u/Successful-Farm5339 — 3 days ago

I published the first open crosswalk between IES and HQDM (two UK government 4D upper ontologies), including the divergences that trip up a naive mapping

I kept running into the fact that the UK has two open 4D upper ontologies in active government use, from the same BORO / ISO 15926 lineage, with no published mapping between them:

  • IES (Information Exchange Standard): the RDF ontology used for UK national-security and defence data exchange. Open Government Licence, now stewarded by a cross-government working group.
  • HQDM: Matthew West's 4D model (the one behind the National Digital Twin's Foundation Data Model). Apache-2.0, published by GCHQ.

So I built an open crosswalk and released it. What might interest this sub is less the backbone matches and more where the two disagree, because that is where anyone reasoning across both silently gets it wrong:

  • ies:Event is not hqdm:event. In IES an Event is a happening with participants, so its real counterpart is hqdm:activityhqdm:event is an instantaneous boundary point. A label-matcher aligns them and maps a durative occurrence onto a zero-duration point.
  • Temporal boundaries are a State in IES (ies:BoundingState) but a point event in HQDM (hqdm:event via beginning/ending). Same job, different category.
  • ies:State sits as a top-level root; hqdm:state is under spatio_temporal_extent. Reasoning that relies on state ⊑ spatio_temporal_extent breaks on the IES side.
  • Participation is the clean convergence: both model it as a state (ies:EventParticipant ⊑ Statehqdm:participant as a state_of), inherited from the shared BORO commitment.

The correspondences are in SSSOM and RDF with PROV-O provenance, validated with SHACL (the pipeline uses embedding candidate generation then fuzzy-logic adjudication, in the LLMs4OM / FLORA line). Every IRI resolves against the live published ontologies. There is also a worked example grounding an autonomous sensor node (SAPIENT / BSI Flex 335) in an IES-typed world model, which is the practical reason I care: you cannot assure an agent against a world model you have not agreed on.

Repo: https://github.com/fabio-rovai/ies-hqdm-crosswalk

It is v0.1. The most useful thing anyone here could do is tell me a correspondence I got wrong, or a divergence I missed. Disclosure: this is my own work (Tesseract Academy), released open under CC-BY.

Has anyone tried aligning two 4D / perdurantist upper ontologies before? Curious whether the Event/activity trap shows up between other BORO-derived models.

u/Successful-Farm5339 — 4 days ago

Governing a Stardog knowledge graph from an MCP-native engine

#

Stardog spent the last two years teaching its database to talk. Voicebox turns a question in English into a SPARQL query, runs it, and narrates the answer. It is a competent retrieval layer, and it is the wrong shape for what agents actually need to do to a knowledge graph.

Asking a graph a question is not the same as governing it. An agent that operates a production ontology has to validate generated triples, classify them under a reasoner, check design-pattern compliance, plan the blast radius of a change, verify that a proposed action has an identifiable effect, and leave an audit trail. Voicebox does none of that. It reads. The database stays a database, and the language model stays a guest at the front door, allowed to ask but not to operate.

Open Ontologies inverts the arrangement. The engine is a set of validation and scaffolding primitives exposed over the Model Context Protocol, and the agent drives them. The intelligence lives in the conversation. The guarantees live in the engine. That is the opposite of bolting a chat box onto a query endpoint, and it is the design argument of the accompanying paper (arXiv:2605.09184).

Here is the part that matters for anyone who already runs Stardog: you do not have to move your data to try it. Stardog speaks the SPARQL 1.1 Protocol, and so does Open Ontologies. Point one at the other.

# Connecting

Stardog exposes a query endpoint at `/{db}/query` and an update endpoint at `/{db}/update`, both behind HTTP Basic auth. Pull a graph in:

// onto_pull
{
"url": "http://localhost:5820/myDb/query",
"sparql": true,
"query": "CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }",
"username": "admin",
"password": "admin"
}

The triples land in the local store. Now the agent does the things Voicebox cannot:

  1. `onto_shacl` validates the data against your shapes (cardinality, datatypes, class membership), and reports every violation with its focus node.
  2. `onto_reason` materialises the entailments (transitive subclass chains, domain and range propagation, `equivalentClass` expansion).
  3. `onto_enforce` checks design-pattern compliance against a rule pack (generic, BORO, value-partition, hierarchy, or the IES 4D pack), so the graph is not just valid RDF but well-formed against a modelling discipline.
  4. `onto_align` proposes equivalences against a second ontology using weighted structural and embedding signals, surfaces the borderline pairs for the agent to judge, and learns from each verdict.
  5. `onto_plan` shows the added and removed classes, the dependents at risk, and a risk score before anything is written.

Then push the governed result back, into a named graph, with the same credentials:

// onto_push
{
"endpoint": "http://localhost:5820/myDb/update",
"graph": "http://example.org/governed",
"username": "admin",
"password": "admin"
}

The same flow works unchanged against Ontotext GraphDB (Basic auth), Apache Jena Fuseki and Eclipse RDF4J (no auth), and any other SPARQL 1.1 endpoint. Amazon Neptune with IAM auth needs SigV4 request signing, which this path does not do yet: front it with a signing proxy or use an IAM-disabled endpoint.

# Why the shape is the whole point

Voicebox is an answer engine welded to a store. Every capability it has is a way of reading what is already there. That is genuinely useful and genuinely limited, because the hard problems in a live knowledge graph are not retrieval problems. They are change-management problems: will this edit break a downstream query, is this inferred equivalence sound, does this action have an effect I can actually identify, can I roll it back, can I prove what happened.

An MCP-native engine treats every one of those as a primitive the agent can call and a verdict the engine can certify. The causal layer is the sharpest example. Before a state-changing action is applied, it can be mapped to a structural causal query and checked for identifiability, returning an auditable verdict rather than a confident sentence. A narration layer cannot do this, because narration is not verification. The full argument and the benchmark are in arXiv:2605.09168.

Stardog built a good database and gave it a voice. The more interesting move is to stop treating the language model as a visitor and start treating it as the operator, with the engine holding the guarantees. You can run that today, against the Stardog you already have. Keep your store. Change who is driving.

Open Ontologies is MIT-licensed and ships as a single Rust binary, no JVM. Repository: [https://github.com/fabio-rovai/open-ontologies\](https://github.com/fabio-rovai/open-ontologies)

* Open Ontologies: Tool-Augmented Ontology Engineering with Stable Matching Alignment. arXiv:2605.09184
* CIVeX: Causal Intervention Verification for Language Agents. arXiv:2605.09168

reddit.com
u/Successful-Farm5339 — 21 days ago

Governing a Stardog knowledge graph from an MCP-native engine

Stardog spent the last two years teaching its database to talk. Voicebox turns a question in English into a SPARQL query, runs it, and narrates the answer. It is a competent retrieval layer, and it is the wrong shape for what agents actually need to do to a knowledge graph.

Asking a graph a question is not the same as governing it. An agent that operates a production ontology has to validate generated triples, classify them under a reasoner, check design-pattern compliance, plan the blast radius of a change, verify that a proposed action has an identifiable effect, and leave an audit trail. Voicebox does none of that. It reads. The database stays a database, and the language model stays a guest at the front door, allowed to ask but not to operate.

Open Ontologies inverts the arrangement. The engine is a set of validation and scaffolding primitives exposed over the Model Context Protocol, and the agent drives them. The intelligence lives in the conversation. The guarantees live in the engine. That is the opposite of bolting a chat box onto a query endpoint, and it is the design argument of the accompanying paper (arXiv:2605.09184).

Here is the part that matters for anyone who already runs Stardog: you do not have to move your data to try it. Stardog speaks the SPARQL 1.1 Protocol, and so does Open Ontologies. Point one at the other.

Connecting

Stardog exposes a query endpoint at /{db}/query and an update endpoint at /{db}/update, both behind HTTP Basic auth. Pull a graph in:

// onto_pull
{
  "url": "http://localhost:5820/myDb/query",
  "sparql": true,
  "query": "CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }",
  "username": "admin",
  "password": "admin"
}

The triples land in the local store. Now the agent does the things Voicebox cannot:

  1. onto_shacl validates the data against your shapes (cardinality, datatypes, class membership), and reports every violation with its focus node.
  2. onto_reason materialises the entailments (transitive subclass chains, domain and range propagation, equivalentClass expansion).
  3. onto_enforce checks design-pattern compliance against a rule pack (generic, BORO, value-partition, hierarchy, or the IES 4D pack), so the graph is not just valid RDF but well-formed against a modelling discipline.
  4. onto_align proposes equivalences against a second ontology using weighted structural and embedding signals, surfaces the borderline pairs for the agent to judge, and learns from each verdict.
  5. onto_plan shows the added and removed classes, the dependents at risk, and a risk score before anything is written.

Then push the governed result back, into a named graph, with the same credentials:

// onto_push
{
  "endpoint": "http://localhost:5820/myDb/update",
  "graph": "http://example.org/governed",
  "username": "admin",
  "password": "admin"
}

The same flow works unchanged against Ontotext GraphDB (Basic auth), Apache Jena Fuseki and Eclipse RDF4J (no auth), and any other SPARQL 1.1 endpoint. Amazon Neptune with IAM auth needs SigV4 request signing, which this path does not do yet: front it with a signing proxy or use an IAM-disabled endpoint.

Why the shape is the whole point

Voicebox is an answer engine welded to a store. Every capability it has is a way of reading what is already there. That is genuinely useful and genuinely limited, because the hard problems in a live knowledge graph are not retrieval problems. They are change-management problems: will this edit break a downstream query, is this inferred equivalence sound, does this action have an effect I can actually identify, can I roll it back, can I prove what happened.

An MCP-native engine treats every one of those as a primitive the agent can call and a verdict the engine can certify. The causal layer is the sharpest example. Before a state-changing action is applied, it can be mapped to a structural causal query and checked for identifiability, returning an auditable verdict rather than a confident sentence. A narration layer cannot do this, because narration is not verification. The full argument and the benchmark are in arXiv:2605.09168.

Stardog built a good database and gave it a voice. The more interesting move is to stop treating the language model as a visitor and start treating it as the operator, with the engine holding the guarantees. You can run that today, against the Stardog you already have. Keep your store. Change who is driving.

Open Ontologies is MIT-licensed and ships as a single Rust binary, no JVM. Repository: https://github.com/fabio-rovai/open-ontologies

  • Open Ontologies: Tool-Augmented Ontology Engineering with Stable Matching Alignment. arXiv:2605.09184
  • CIVeX: Causal Intervention Verification for Language Agents. arXiv:2605.09168
reddit.com
u/Successful-Farm5339 — 22 days ago

If you've fought with ICD-10 vs. SNOMED vs. MeSH vs. RxNorm because every downstream system wants a different code, this might look familiar.

Two paired files showing the lift. Before: ICD-10 only, free-text medications. After: `skos:exactMatch` links to SNOMED CT, MeSH, RxNorm, UNII, plus provenance and validation status. Generated by an open-source Rust ontology engine I've been building. The clinical crosswalk is built from public terminology sources.

Files: https://github.com/fabio-rovai/open-ontologies/tree/main/examples

How do people doing this in real production deal with the asymmetries? Specifically: MeSH "Hypertension" covers more ground than ICD-10 I10. Worth flagging as `skos:closeMatch`, or do you treat it as `exactMatch` and rely on downstream filtering?

reddit.com
u/Successful-Farm5339 — 2 months ago

Sharing a paired before/after JSON-LD example of clinical-record enrichment. Two diagnosis records (essential hypertension, T2DM with comorbidity link) start as single-system ICD-10 entries with free-text medications. After running through an ontology engine I built, they have `skos:exactMatch` crosswalks to SNOMED CT, MeSH, RxNorm and UNII, plus PROV-O lineage and a QA record.

Point of the artefact: make the cost of cross-terminology mapping visible. Pay it once at ingest, then queries can ignore which coding system the source used.

Files: https://github.com/fabio-rovai/open-ontologies/tree/main/examples

Two questions for people working in clinical informatics:

  1. The I10 to MeSH D006973 mapping is broader on the MeSH side (covers secondary hypertension). `skos:exactMatch` or `skos:closeMatch` in your production work?

  2. If you've ingested data from systems coded in different terminologies, did the multi-binding approach win you anything that just pinning to one canonical didn't?

reddit.com
u/Successful-Farm5339 — 2 months ago

Two paired JSON-LD files. The "before" has single-system ICD-10 diagnosis records with free-text medication strings. The "after" has the same records enriched with skos:exactMatch links to SNOMED CT, MeSH, RxNorm and UNII, plus PROV-O lineage and a QA record.

Generated by an open-source Rust ontology engine I've been building (open-ontologies). Three tools do the work: `onto_crosswalk` for the ICD/SNOMED/MeSH lookup, `onto_enrich` to insert the skos:exactMatch triples, `onto_validate_clinical` for the label check.

Files: https://github.com/fabio-rovai/open-ontologies/tree/main/examples

Two questions I'd actually like answered:

  1. The ICD-10 I10 to MeSH D006973 mapping is `skos:exactMatch` in the example, but MeSH "Hypertension" covers secondary hypertension which I10 explicitly excludes. Should this be `skos:closeMatch`? How do people handle this drift in production crosswalks?

  2. Is wrapping in a custom `clinical:` namespace better than going straight to FHIR shapes, for a non-FHIR semantic-web pipeline?

reddit.com
u/Successful-Farm5339 — 2 months ago

Background

UK and European heritage archives hold roughly 50 million aerial photographs — RAF wartime reconnaissance, post-war urban surveys, US-transferred imagery, satellite holdings. They're digitised (scanned, on the web, browsable as thumbnails). They're not computable: free-text dates in eight different formats, free-text rights statements, point coordinates instead of footprint geometries, ISAD-G metadata that doesn't survive a SPARQL query.

I've been building a focused, vertical digitisation standard that closes that specific gap. Sharing it now because the design is stable enough that pushback is more useful than more polish.

What's in it

  • Ontology — 30 classes, 29 properties, reusing PROV-O / GeoSPARQL / SKOS / Dublin Core / FOAF / DCAT (synthesis, not invention)
  • SHACL shapes for three tiers (Baseline / Enhanced / Aspirational), incrementally adoptable
  • End-to-end CSV → Turtle ingest pipeline (~200 LOC, runs)
  • IIIF Presentation 3.0 bridge so any IIIF viewer can consume it
  • Footprint derivation from flight metadata (altitude + focal length → vertical FOV polygon)
  • Stereo pair detection from overlap geometry
  • Sub-profiles for reconnaissance, satellite, UAV, photogrammetric, and aerial archaeology imagery
  • Governance proposal, partner clinic playbook, 9 ADRs, 40+ SPARQL queries, investment case

Aligned with Towards a National Collection (AHRC/UKRI) and the N-RICH Prototype. Licensed CC BY 4.0 / CC0 / MIT.

Where I'd appreciate feedback

  • Three tiers (Baseline/Enhanced/Aspirational) — right call, or would two tiers be cleaner?
  • I attach naph:capturedOn directly to the photograph rather than via a prov:Activity. Pragmatic shortcut or anti-pattern given that the rest of the model is PROV-aligned?
  • Footprint geometry in WGS84 only — should I model multi-CRS natively?
  • IIIF Presentation 3.0 mapping — anything important I'm missing?

https://github.com/fabio-rovai/open-ontologies/tree/main/case-studies/heritage-aerial

reddit.com
u/Successful-Farm5339 — 2 months ago

Background

UK and European heritage archives hold roughly 50 million aerial photographs: RAF wartime reconnaissance, post-war urban surveys, US-transferred imagery, satellite holdings. They're digitised (scanned, on the web, browsable as thumbnails). They're not computable: free-text dates in eight different formats, free-text rights statements, point coordinates instead of footprint geometries, ISAD-G metadata that doesn't survive a SPARQL query.

I've been building a focused, vertical digitisation standard that closes that specific gap. Sharing it now because the design is stable enough that pushback is more useful than more polish.

What's in it

  • Ontology — 30 classes, 29 properties, reusing PROV-O / GeoSPARQL / SKOS / Dublin Core / FOAF / DCAT (synthesis, not invention)
  • SHACL shapes for three tiers (Baseline / Enhanced / Aspirational), incrementally adoptable
  • End-to-end CSV → Turtle ingest pipeline (~200 LOC, runs)
  • IIIF Presentation 3.0 bridge so any IIIF viewer can consume it
  • Footprint derivation from flight metadata (altitude + focal length → vertical FOV polygon)
  • Stereo pair detection from overlap geometry
  • Sub-profiles for reconnaissance, satellite, UAV, photogrammetric, and aerial archaeology imagery
  • Governance proposal, partner clinic playbook, 9 ADRs, 40+ SPARQL queries, investment case

Aligned with Towards a National Collection (AHRC/UKRI) and the N-RICH Prototype. Licensed CC BY 4.0 / CC0 / MIT.

Where I'd appreciate feedback

  • Three tiers (Baseline/Enhanced/Aspirational) — right call, or would two tiers be cleaner?
  • I attach naph:capturedOn directly to the photograph rather than via a prov:Activity. Pragmatic shortcut or anti-pattern given that the rest of the model is PROV-aligned?
  • Footprint geometry in WGS84 only — should I model multi-CRS natively?
  • IIIF Presentation 3.0 mapping — anything important I'm missing?

https://github.com/fabio-rovai/open-ontologies/tree/main/case-studies/heritage-aerial

reddit.com
u/Successful-Farm5339 — 2 months ago
▲ 1 r/VibeCodeDevs+1 crossposts

I’ve been working on this and finally applied to YC with it. Is heavily based on my Open Sourced https://github.com/fabio-rovai/open-ontologies. Would really appreciate honest / harsh feedback:

https://github.com/fabio-rovai/mcp-former

Core idea

LLMs shouldn’t directly call tools. They should go through a verification layer grounded in the system’s actual domain model.

Right now, if you let an LLM operate a CLI or API:

  • it hallucinates valid commands
  • it executes destructive operations based on pattern matching
  • there’s no concept of “this action is unsafe in this specific system state

What I built (mcp-former)

A wrapper around existing software (CLIs / APIs) that forces every action through a gate:

>LLM → tool call → claimontology check → execute / reject

Example (git)

  • git branch -D mainREJECTED (main = protected branch)
  • git branch -D feature-xALLOWED

Mental model

Terraform, but for operational safety of AI agents interacting with real systems.

  • mcpf plan → introspects a system and builds an ontology
  • adapters (mcpf-git, etc.) → enforce rules at runtime
  • verification engine (separate project) → decides allow / reject

Why this might matter

  • “tool use” is the weak point of LLM systems today
  • prompting alone doesn’t solve safety or correctness
  • real deployments involve messy legacy systems (CLIs, APIs, enterprise tools)
  • organizations don’t want agents that can accidentally destroy production state

What I’m unsure about (would love critique)

  • Is this a real problem or just edge-case paranoia?
  • Is ontology the right abstraction, or overengineering?
  • Does “Terraform for agents” actually hold, or is it forced framing?
  • Would better prompting / evals solve this more simply?
  • Does this only work for structured CLIs like git and break elsewhere?

Current state (very early)

  • 1 working adapter (git)
  • heuristic introspection via --help parsing
  • separate verification engine (tardygrada)
  • end-to-end loop exists, but still v0 prototype

Closing

If this is a bad direction, I’d rather find out early.
If it’s directionally interesting but wrong in execution, that’s even better.

Would really appreciate people tearing this apart.

u/Successful-Farm5339 — 2 months ago