From 06c15dbcb9e8f26a4234b828211913be9cbaab49 Mon Sep 17 00:00:00 2001 From: "Claude (OGAR session)" Date: Fri, 5 Jun 2026 12:22:33 +0000 Subject: [PATCH 1/2] fix(domain-instances): OSM IDs are flat per-type spaces; adapter constructs prefix from coordinates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes Codex P2 on PR #41 (now merged). # The error §2.6 said: > "OSM IDs are *already* prefix-structured > (`country/region/city/street/house`), so the adapter is doing > identity-*extraction*, not identity-construction" That's wrong on two axes: 1. OSM IDs are NOT hierarchical. Per the OSM data model (https://wiki.openstreetmap.org/wiki/Data_model), Node, Way, and Relation each have their own per-element-type flat numeric ID space. `Node 100`, `Way 100`, and `Relation 100` are unrelated; IDs carry no spatial information. 2. The "country/region/city/street/house" hierarchy I cited is what Nominatim CONSTRUCTS from geocoding queries — it's an *output* of geocoding, not a property of OSM IDs. Relying on identity-extraction from raw OSM IDs would produce non-local or colliding NiblePath keys (the Codex P2's specific concern). # The fix Rewrite the §2.6 lead paragraph to correctly describe: - OSM elements use per-element-type flat numeric ID spaces (with Wikipedia-link to the OSM data model spec for citation). - The adapter does identity *construction*, not extraction: * Computes the Cesium TMS quadkey FROM the element's coordinates (for Node/Way with geometry). * For Relations without coordinates, derives from the centroid of members OR from an admin_level boundary walk. * Prepends the quadkey to the per-type OSM ID, yielding `osm///` as the NiblePath form. - Pins the architectural distinction: "The quadkey IS the spatial frame; the per-type ID is the leaf inside it." # Internal consistency - The "Spatial prefix-locality" bullet's example `osm//way/123` matches the corrected lead's form `osm///`. Unchanged. - The verbatim §6 callout ("Marienplatz is_in Munich in sub- microsecond") still holds: Marienplatz IS routed via `osm//way/`, and `is_in Munich` IS a quadkey-prefix-containment check. The mechanism is unchanged; only the lead's origin-story was wrong. - The §3 capability matrix row "Spatial prefix routing (Cesium TMS quadkey via NiblePath)" already correctly named quadkey (not OSM ID) as the prefix source. Unchanged. - The Q2 coordination outcome (Cesium TMS quadkey as NiblePath) is unchanged — this fix tightens the prose that explains WHY the outcome was correct. # Verification cargo check --workspace --all-targets -> clean (docs-only) PII abort-guard (word-boundary) -> CLEAN # Note The error was framing-grade, not architecture-grade. The runtime session's lance-graph PR #473 §2 already correctly specified "Cesium TMS quadkey as NiblePath prefix" (Q2 outcome) — the mistake was in my §2.6 lead claiming the prefix came from the OSM ID structure rather than from the coordinate-derived quadkey. The corrected text now matches the Q2 outcome's design intent exactly. https://claude.ai/code/session_01PBTGaPCSnnt6u3pjXpbLwY --- docs/DOMAIN-INSTANCES.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/DOMAIN-INSTANCES.md b/docs/DOMAIN-INSTANCES.md index 3434426..44e3e4d 100644 --- a/docs/DOMAIN-INSTANCES.md +++ b/docs/DOMAIN-INSTANCES.md @@ -125,13 +125,22 @@ inner auth AND durable outer audit, and ships exactly that separation. ### 2.6 Geospatial / OSM — geographic calibration -**What OSM proves: geography doesn't break the IR.** OSM IDs are -*already* prefix-structured (`country/region/city/street/house`), so -the adapter is doing identity-*extraction*, not identity-construction -— a much smaller surface than typical. Three OSM Classes (`Node`, -`Way`, `Relation`) lift via the queued `ogar-from-osm-pbf` adapter +**What OSM proves: geography doesn't break the IR.** OSM elements use +**per-element-type flat numeric ID spaces** ([OSM data model][osm-dm] +— `Node 100`, `Way 100`, and `Relation 100` are unrelated; IDs are +not hierarchical and carry no spatial information on their own). The +adapter therefore does identity *construction*, not extraction: it +computes the Cesium TMS quadkey **from the element's coordinates** +(or, for `Relation`s without coordinates, from the centroid of its +members or from an `admin_level`-boundary walk) and prepends it to +the per-type OSM ID, yielding the `NiblePath` form +`osm///`. The quadkey IS the spatial frame; the +per-type ID is the leaf inside it. Three OSM Classes (`Node`, `Way`, +`Relation`) lift via the queued `ogar-from-osm-pbf` adapter (`docs/RDF-OWL-ALIGNMENT.md §10` Phase 2c). Exercises: +[osm-dm]: https://wiki.openstreetmap.org/wiki/Data_model + - **Spatial prefix-locality** — Cesium TMS quadkey as `NiblePath` prefix, per Q2 coordination outcome locked in `lance-graph` PR #473 §2. HHTL trie routes `osm//way/123` byte-identically to From 5b1fd22e3749ce2cbe42dd6d6bf389c2b89fbf24 Mon Sep 17 00:00:00 2001 From: "Claude (OGAR session)" Date: Fri, 5 Jun 2026 12:26:23 +0000 Subject: [PATCH 2/2] fix(domain-instances): resolve Way / Relation geometry before deriving quadkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex P2 follow-up on PR #42 — caught a second over-simplification in the §2.6 lead paragraph. # The remaining error The previous fix said: > "computes the Cesium TMS quadkey from the element's coordinates > (or, for Relations without coordinates, from the centroid of > its members…)" That's still wrong because **only Nodes carry coordinates in OSM**. Ways are ordered Node-references; Relations are member lists. Neither has a coordinate of its own — both must be resolved through their members first. Per the linked OSM data model: https://wiki.openstreetmap.org/wiki/Data_model # The fix Restructure the lead paragraph's quadkey-derivation step as an explicit per-type bullet list: - Node → directly from its own lat/lon (the ONLY element type that carries coordinates) - Way → resolve the ordered Node-references first to get the underlying lat/lon list, then centroid / covering tile - Relation → resolve member references recursively (members are Node/Way/Relation refs with roles), then centroid / covering tile, or admin_level-boundary walk when the Relation IS an administrative polygon The corrected text now matches the OSM data model exactly and removes the implementer footgun Codex flagged (where "follow this literally leaves ways without a coordinate source or pushes implementers toward using the way id"). # Internal consistency preserved The `osm///` NiblePath form is unchanged; "the quadkey IS the spatial frame; the per-type ID is the leaf" claim is unchanged; the §2.6 bullets that follow ("Spatial prefix- locality", "Tag-as-Class", "Palette256 codec adoption", "D-OSM-3 crossing deliverable") all stand. Only the geometry-resolution sub-step in the lead is clarified. # Verification PII abort-guard (word-boundary): CLEAN # Same branch, not new PR Pushed onto claude/fix-osm-id-hierarchy-claim (PR #42, still open) rather than opening a fresh PR — the user's "fresh PR for visibility" pattern was for merged PRs only; for an open PR, amend in place per standard review-loop discipline. https://claude.ai/code/session_01PBTGaPCSnnt6u3pjXpbLwY --- docs/DOMAIN-INSTANCES.md | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/DOMAIN-INSTANCES.md b/docs/DOMAIN-INSTANCES.md index 44e3e4d..639fee7 100644 --- a/docs/DOMAIN-INSTANCES.md +++ b/docs/DOMAIN-INSTANCES.md @@ -130,14 +130,28 @@ inner auth AND durable outer audit, and ships exactly that separation. — `Node 100`, `Way 100`, and `Relation 100` are unrelated; IDs are not hierarchical and carry no spatial information on their own). The adapter therefore does identity *construction*, not extraction: it -computes the Cesium TMS quadkey **from the element's coordinates** -(or, for `Relation`s without coordinates, from the centroid of its -members or from an `admin_level`-boundary walk) and prepends it to -the per-type OSM ID, yielding the `NiblePath` form -`osm///`. The quadkey IS the spatial frame; the -per-type ID is the leaf inside it. Three OSM Classes (`Node`, `Way`, -`Relation`) lift via the queued `ogar-from-osm-pbf` adapter -(`docs/RDF-OWL-ALIGNMENT.md §10` Phase 2c). Exercises: +computes the Cesium TMS quadkey from the element's **resolved** +geometry — only `Node`s carry coordinates directly; `Way`s and +`Relation`s reference other elements and must be resolved through +their members first: + +- **`Node`** — quadkey from its own `lat`/`lon` (the only element + type that carries coordinates). +- **`Way`** — resolve the ordered `Node`-references first to get the + underlying lat/lon list, then take the centroid (or the smallest + covering tile at the target zoom — whichever fits the consumer's + query pattern). +- **`Relation`** — resolve member references recursively (members + are `Node`/`Way`/`Relation` refs with roles), then centroid / + covering tile, or an `admin_level`-boundary walk when the + Relation IS an administrative polygon. + +The resolved quadkey gets prepended to the per-type OSM ID, yielding +the `NiblePath` form `osm///`. The quadkey IS the +spatial frame; the per-type ID is the leaf inside it. Three OSM +Classes (`Node`, `Way`, `Relation`) lift via the queued +`ogar-from-osm-pbf` adapter (`docs/RDF-OWL-ALIGNMENT.md §10` Phase +2c). Exercises: [osm-dm]: https://wiki.openstreetmap.org/wiki/Data_model