Case Study

GBlocks

A real UK Property Digital Twin -- ~150,000 real properties across 24 open-government sources, built to prove the Source-to-Scene method with real data instead of a synthetic sample.

Personal research project, evolved into Trusted Data Framework validation evidenceWorking case

Evidence & trust

Current evidence status

Validatedsupporting authority

The case combines reproducible implementation evidence with explicit interpretation. It is supporting evidence for the method, not a delivered client engagement.

Assessment
28/32
Eight-dimension assessment run against live database evidence on 8 July 2026
Data scope
24 sources
Approximately 150,000 properties in the bounded UK study area
Quality control
Fail-closed
Native checks plus a second observability engine share governed results
Latest review
16 July 2026
Municipal and temporal PoCs were independently reviewed and corrected
Decision use

Use the case to decide whether a bounded Reality Mapping or semantic-readiness follow-up is justified.

Known limits
  • This is a personal research demonstrator, not evidence from a paying client engagement.
  • Source-to-Scene still needs a second independent domain before it can claim broad generalisation.
  • Satellite observations, official models and administrative records represent different phenomena and must not be treated as interchangeable ground truth.

Context

GBlocks (github.com/steven4320555/GBlocks) is a UK geospatial data platform linking every address and postcode to its full administrative and statistical hierarchy, inspired by Steven's PhD research on a modular, hierarchical, spatial-temporal data framework for GB homes. It was built independently of the Trusted Data Framework -- to explore the thesis's data spine concept -- and only afterwards recognised as the real-data version of the framework's own UK Property Digital Twin reference scenario.

The reference scenario document explicitly states the first demonstration should be synthetic, "should not rely on restricted datasets," and lists specific data issues a synthetic scenario should simulate: mismatched address strings, missing UPRNs, EPC-vs-property address-format mismatches, postcode-vs-Census granularity mismatch, spatial-vs-key matching, and snapshot-vs-live data. GBlocks solved every one of these for real, using real UK government open data (NSPL, ONS boundaries, OS Open UPRN, NSUL, HM Land Registry Price Paid Data, MHCLG EPC, police.uk crime, Ofsted, Companies House, Environment Agency flood zones, ONS Census 2021, OS greenspace/roads, and -- added in a second expansion round -- Historic England Listed Buildings and their curtilage outlines, HM Land Registry Title Boundaries, and DfE Educational Establishments, all via the MHCLG Planning Data Platform), not synthetic samples. 24 sources are declared and governed today, up from the 12+ this case was first written against.

Framework Lens

The case is especially relevant to Reality, Information (Raw/Curated Data), Identity, and the Semantic Layer. It also produced the first real evidence for the Source-to-Scene Pipeline native method.

How the Core Concepts Apply, With Real Examples

Reality Mapping

GBlocks' reality landscape names 12 real-world concepts before any table is designed: Property, Address, Postcode, the OA/LSOA/MSOA/LAD nesting hierarchy, Transaction, Energy Assessment, Crime Incident, School, Company, Flood Zone, Physical Feature, and Population Context. Two concrete examples of Reality Mapping doing real work, not just naming things:

  • Three partial representations of one reality. EPC, Price Paid, and OpenStreetMap each describe "a property" differently -- EPC assesses it, Price Paid records a transaction on it, OSM attempts to represent its address. None is complete on its own (EPC only covers properties assessed since ~2008; Price Paid is transactional, not a live register; OSM is crowd-sourced and covers ~20% of the authoritative property count in the study area). Reality Mapping is what makes it possible to say precisely which partial view each source offers, rather than silently treating them as interchangeable.
  • A live Reality Mapping failure, caught, not hidden. Mid-build, a layer fetched from the OS Features API (greenspace, roads) returned 100% valid-looking GeoJSON that nonetheless represented every point at the wrong coordinates -- the API returns EPSG:4326 in a different axis order depending on request method (GET vs POST). A geometrically "valid" representation was silently misrepresenting reality. It was caught only because a data quality check asserted "this table should have thousands of rows intersecting the study area" and got zero -- proof that Reality Mapping needs continuous verification, not a one-time exercise.
  • "Zero results" investigated as a fact about reality, not assumed to be a bug. Adding a fifth planning.data.gov.uk dataset (planning-application) returned 0 rows for the study area. Rather than debugging the query further on the assumption something was broken, the investigation traced the actual cause: querying the dataset's own organisation-entity values showed only 4 councils nationally currently publish to this feed, none in Hertfordshire. The reality being mapped genuinely has no data there yet -- a materially different finding from "the pipeline is broken," and one that would have been missed by treating an empty result as self-evidently a defect.

Ontology

semantic/ontology.yaml in the GBlocks repo is a working, if deliberately lightweight, ontology: 19 concepts (grown from an initial 15 as new sources were added), each with a formal definition, a mapping to the physical table/fields that implement it, and typed relationships to other concepts, using a small closed vocabulary (originally 10 types -- located_in, part_of, represents, refers_to, assesses, occurred_near, serves, registered_at, constrains, describes -- extended to 12 when two new relationship shapes appeared for real: same_as, for two sources confirmed or suspected to describe the same real-world instance, and co_locates, for a spatial correspondence that hasn't been materialised as a join yet). Three things worth noting:

  • Confidence is part of the ontology, not bolted on afterward. The Transaction refers_to Property relationship is marked confidence: medium, with an explicit note that only 7.0% resolve to an exact matched UPRN (a conservative fuzzy match) while 92.9% fall back to the coarser postcode-level relationship. A knowledge consumer -- human or AI -- reading the ontology knows how much to trust that relationship before using it, not just that it exists.
  • Governance facts live inside the model. The PhysicalFeature concept's definition states outright that two of its three source tables (greenspace, roads) are billed OS Premium products, not free OS OpenData, discovered only after the fact via a usage-dashboard check. An ontology that only encoded "what this means" and not "what it costs to keep this true" would miss a real operational constraint.
  • Duplicate representations were caught before they entered the model, not cleaned up afterward. While adding four new datasets from the MHCLG Planning Data Platform, a fifth candidate (flood-risk-zone) was investigated via schema inspection and recognised as a republication of the EA Flood Zones 2 & 3 data already loaded directly from the Environment Agency. It was never ingested. Ontology discipline here isn't just modelling what's already in the database -- it's recognising, before ingestion, when two differently-labelled sources describe the same real-world concept.

Semantic Layer

GET /semantic-model serves the ontology above as live JSON, not a static document -- the semantic layer is queryable infrastructure a downstream AI agent or application could consume directly, the same pattern the framework's own Semantic Readiness Accelerator looks for. This is deliberately a Reality Semantic Layer, not a Business Semantic Layer: it extends meaning across physical objects (Property, Boundary, Flood Zone), identity, and spatial relationships, rather than BI metrics or KPI definitions. Self-assessed at Maturity Level 3 ("priority concepts, terms, mappings defined for selected use cases") per the framework's own semantic layer maturity scale -- explicitly not yet Level 4, since there is no versioning or change-control process governing edits to ontology.yaml beyond git history.

The model has now been extended once under real pressure (four new concepts, two new relationship types) without needing to restructure any of the original 15 concepts -- a small but genuine data point that the Level 3 scope was drawn in the right place the first time, rather than an accident of a small initial dataset. A changelog field was added directly inside ontology.yaml to record what changed and why -- itself a lightweight, honest step toward the missing Level 4 governance, short of a full versioning process.

Knowledge Graph

GBlocks deliberately does not build a knowledge graph, matching this framework's own guidance (ADR004) not to make the graph the centre of the architecture prematurely. But the relationships a graph would formalise already exist as queryable, materialised traversal views -- geo.epc_hierarchy, geo.price_paid_hierarchy, geo.crime_hierarchy, and so on each answer a one-hop question (everything connected to this property) without graph infrastructure. GET /scene/uprn/{uprn} goes further: given one UPRN, it assembles identity, every source's representation, the full boundary hierarchy, a chronological event timeline (sales, assessments), current state, and per-link confidence in a single call -- exactly the question a property-centred knowledge graph node would answer, answered today with a relational/spatial store and no graph database.

This is itself a useful, evidenced answer to the Knowledge Graph Readiness Accelerator's central question -- "should we build a graph, where, and why?" For GBlocks: not yet. The operational questions asked so far are one-hop ("what does this property look like") and a relational store with good spatial joins answers them well. A graph would earn its complexity the moment questions become genuinely multi-hop -- e.g. "find every property within 500m of an Outstanding- rated school, built before 1950, outside any mapped flood zone, sold in the last two years" -- a query that's awkward as chained SQL joins but natural as graph traversal. GBlocks doesn't need that query yet; a future case that does would be the right trigger to build one.

A concrete example of the gap a graph's entity-resolution layer exists to close showed up while adding the DfE's Educational Establishment dataset: it describes the same real-world entity type -- a school -- as the Ofsted schools dataset already in the spine, using a different identifier scheme (DfE establishment number vs Ofsted URN), with no link between them. Today that's honestly recorded as an open gap in semantic/ontology.yaml (a same_as relationship with confidence: none) rather than silently presented as two unrelated tables. A knowledge graph's entity-resolution step is exactly the mechanism that would close a gap like this at scale -- but naming the gap explicitly, without graph infrastructure, is itself most of the value a Knowledge Graph Readiness Accelerator engagement would otherwise have to surface from scratch.

What It Teaches

Evidence added after the original assessment

  • Quality gates now fail closed. Data-quality findings no longer remain warnings that a build can silently ignore. A second observability engine runs alongside the native rules rather than replacing them.

  • Cross-source checks need semantic qualification. A 2.4% overlap between Environment Agency flood zones and routine surface-water observations was expected once the represented phenomena were distinguished. The result is not evidence that either source is wrong.

  • Observation coverage is not unconditional ground truth. The green-space check reports both scene coverage and valid-observation coverage; 94.8% refers to valid observed area, not every square metre at every time.

  • Time has its own trust boundary. Recent Land Registry periods are marked provisional inside a 90-day registration-lag window instead of being presented as a real fall in activity.

  • A useful PoC records rejected scope. Solid was not recommended as the bulk analytical backing store; the narrower user-owned Watchlist slice remained a future evaluation route.

  • A method built for a synthetic reference scenario can turn out to already match a system built for entirely unrelated reasons -- worth actively looking for this kind of accidental validation rather than only building demonstrations to order.

  • Identity resolution at scale is genuinely messy: two independently- sourced authoritative UPRN registers agreeing 99.9% is strong evidence, but the remaining sources (crowd-sourced addresses, event-based transactions with no native identifier) need honestly-stated, not hidden, confidence levels.

  • A data quality/observability layer (a rule-based DQ engine plus pipeline-run logging) turns "trust" from a claim into something machine-checked and re-verified on every rebuild.

  • A semantic layer doesn't need to start as RDF/OWL to be real -- a small, versioned, field-mapped concept model with typed relationships is enough to move from Maturity Level 2 (implicit) to Level 3 (explicit, per-use-case) and be genuinely useful to a consuming API.

  • A reusable access-method pattern can emerge mid-project, not just at design time: streaming a remote bulk file with a server-side filter (DuckDB's httpfs extension) turned out to be dramatically more reliable than a source's own live query API for large datasets -- confirmed directly across four datasets, not assumed from one.

  • Growing a system honestly means it will surface its own new gaps, not just new capability -- adding one more source revealed an existing, unaddressed entity-resolution problem between two already-loaded sources. Treating that discovery as a finding to record, not a defect to quietly patch over, is what keeps a semantic model trustworthy as it scales.

Consulting Use

Use this case as the primary evidence base for the Trusted Data Discovery Accelerator and as the first real validation of the Source-to-Scene Pipeline native method (see lib/athena-registry.ts, source-to-scene-pipeline: promoted from Hypothesis to Pattern, confidence 40 -> 62, on the strength of this case). A full Capability 1 assessment report, a modelled semantic layer, and formal identity/ coverage registers exist in the GBlocks repo itself (notes/CAPABILITY_1_ASSESSMENT_GBLOCKS.md, semantic/ontology.yaml, notes/IDENTITY_LINKAGE_REGISTER.md, notes/COVERAGE_GRANULARITY_MATRIX.md) and can be walked through live (GET /semantic-model, GET /scene/uprn/{uprn}, GET /reports/reality-mapping).

Next Research Questions

  • Does the Source-to-Scene method generalise to a second, independent reference scenario (different domain or region), or is its current fit specific to spatial/property data?
  • What would a formal ownership and change-control process for semantic/ontology.yaml look like in practice, once more than one person maintains it?
  • Can the Coverage and Granularity Matrix pattern be reused as-is for a non-spatial domain, or does it need generalising beyond the spatial framing in its current template?
  • Is the school/educational_establishment entity-resolution gap worth fixing now (a conservative fuzzy name+postcode match, the same pattern already proven for Price Paid), or is naming it and leaving it open a legitimate governance choice until a real use case needs the merged view? Answering this for one small case may be a useful input to a more general Entity Resolution pattern this framework doesn't yet have.