Skip to content

osm: migrate the cockpit key V1→V3, verified in a browser against the real slab - #109

Merged
AdaWorldAPI merged 4 commits into
mainfrom
claude/q2-osm-map-reencoding-56p5e2
Aug 10, 2026
Merged

osm: migrate the cockpit key V1→V3, verified in a browser against the real slab#109
AdaWorldAPI merged 4 commits into
mainfrom
claude/q2-osm-map-reencoding-56p5e2

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Follow-on to #108 (merged). That PR wired the endpoint and overlay and scoped the V1→V3 key gap; this one closes it and clears the gate #108 was explicitly draft on — the browser load against a real slab.

1. The V3 migration, as a real red-then-green

#108 said the falsifier was written but deliberately not committed, because this box could not link cockpit-server and shipping an unverifiable coordinate-key migration was the wrong trade. That constraint turned out to be debuginfo=2, not disk volume — building with CARGO_PROFILE_DEV_DEBUG=0 links a 150 MB binary instead of 2.2 GB, and the test binary runs.

So the loop ran honestly:

RED    hhtl_agrees_with_the_v3_substrate_oracle
       Berlin: HEEL must equal the oracle — left: 25163, right: 51425
GREEN  14 passed; 0 failed

25163/51425 are 0x624b/0xc8e1 — the values the earlier out-of-crate probe predicted, now observed inside q2.

The implementation is mostly deletion: the local Mercator formula, the 24-bit Morton pair and the depth constant become delegations to osm_soa_bake::tms. Two implementations of one projection is how the display address and the row key drifted apart; the duplicate is gone rather than widened.

Two subtleties kept in comments because they are easy to get wrong:

  • The TMS flip must happen at the tile's own zoom, then left-align. xyz_to_tms_y is 2^z-1-y, so flipping at z and shifting by 32-z yields the minimum TMS row of the tile's z=32 range — the common Morton prefix. Shifting first and flipping at 32 picks the opposite corner and breaks the prefix property.
  • Reading the bytes LEAF occupies as a tier, rather than as the head of the old family:u24, is the V3 content-blind reinterpretation.

Test changes are re-pins, not silent widenings — two pre-existing tests encoded the V1 depth. hhtl_roundtrips_to_the_tile now un-flips before comparing and asserts the row is genuinely flipped (so it fails if the flip is ever dropped); over_depth_zoom_folds_to_its_native_ancestor moves to z=33 and additionally asserts z=25 is not folded; coarse_zoom_lives_in_heel_not_twig gained LEAF.

2. The browser load — #108's gate, passed

bake berlin-latest.osm.pbf berlin.soa      # 2,525,052 rows, 41.5s
OSM_SLAB_PATH=…/berlin.soa PORT=8099 ./target/debug/q2-cockpit
# headless chromium → /osm, click #feat, click the map

Hermetic — every non-localhost request aborted, which also proves the overlay renders independently of the external basemap.

measurement value proves
markers / fetches before toggle 0 / 0 opt-in gate holds
markers after toggle 177,963 real rows render
distinct marker positions 73,130 placed, not stacked
panel HEEL 0xc8e1 the V3 value, live in a browser
page errors [] clean

3. A defect the browser found that the tests could not

Markers clump into a corner of each dense tile. Placement is faithful — the cap is spatially biased:

capped  14/8802/5373 (5,000 of 15,016) → 99.9% of width, 50.0% of height
control 15/17604/10746 (4,717, under cap) → 100% width, 100% height

take(5000) over a Morton-ordered range returns a spatially contiguous prefix (a sub-quadrant), not a sample. The control tile is what isolates the cause to truncation rather than coordinate math. total/returned were honest; the shape of the result was not, and a count cannot convey that.

Filed with its fix and falsifier, deliberately not applied here — it changes a shipped endpoint's behaviour and deserves its own red-then-green, which the measurement above now makes automatable.

4. Route choices documented, nothing removed

Every alternative arm is recorded with which is wired, why, and what switching would cause: the three /api/osm/* routes; direct tile_range vs the capability arm; hand-decode vs project_fields; local slab vs S3 hydrate; the two basemap skins. Two worth a reviewer's eye:

  • project_fields is a real gap. The declared capability is surface ∩ role, fail-closed. The current arm means the endpoint is effectively unauthenticated — fine locally, not fine deployed. It needs a role source first, so the honest posture is to say so rather than imply a mask exists.
  • q2 must never declare its own HOT_PLUG. GEO_EXPECTED_EXECUTORS = ["osm-soa-bake"], so a plug from cockpit-server earns UnexpectedConsumer by design. q2 calls an already-activated device; it is not a second device.

Verification status — honest

  • 14/14 osm tests green; 79/80 crate-wide.
  • The single failure (osint_gotham::dual_use_facets_pack_into_the_value_tenant) was confirmed pre-existing by stashing this change and re-running against main's state — it fails identically there and references nothing in this diff. Worth attention independently.
  • Full cargo xtask verify --skip-hub-build still not run — the workspace-wide build remains beyond this box.

Draft per convention; the gate #108 was waiting on is now closed, so this can go ready as-is.


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • OSM map tiles now use a four-tier address display, including the LEAF tier.
    • Tile overlays and slab rows share consistent addressing, improving feature alignment.
    • Locate results now show the returned leaf-level value.
  • Bug Fixes

    • Improved handling of deep-zoom tiles by resolving them to supported ancestors.
    • Corrected map coordinate orientation and addressing to match the underlying tile system.

claude added 4 commits August 10, 2026 22:13
The OSM substrate is already plugged into OGAR USB-style: socket in
lance_graph_contract::hotplug, authority in ogar_vocab::geo_actions,
bridge via ogar_osm::plug_in, and the device is osm-soa-bake::capability
with a real dispatch arm per capability. Six capabilities are declared on
osm_node/osm_way, and two of them are things this endpoint already
touches: locate_tile IS slab.tile_range, and project_fields is the
masked projection.

Three consequences, recorded so a future session does not re-derive them:

q2 must not declare its own HOT_PLUG. GEO_EXPECTED_EXECUTORS is
["osm-soa-bake"] and resolve_hotplug checks the consumer name, so a plug
from cockpit-server earns UnexpectedConsumer by design. q2 calls an
already-activated device; it is not a second device.

Phase 1 needs no rework. Calling slab.tile_range directly is explicitly
sanctioned by capability.rs's own module doc -- the arms exist to make the
registration falsifiable, not to be a mandatory call path.

project_fields is a real gap, and it is the authorization one. The
endpoint returns decoded values with no mask; the declared capability is
surface-intersect-role and fail-closed, meaning an unauthorised position
is absent from the response rather than hidden by the caller. Moot for a
local cockpit, not moot for a deployment. Filed as a Phase 4 addendum
with the honest caveat that it needs a role source first -- until then
the endpoint should be described as unauthenticated rather than implying
a mask exists.
…strate

The cockpit's displayed address and the key RowSlab sorts rows by are now
the same key. They were not before: osm_tiles carried its own 3-tier,
z=24, un-flipped Morton key while the slab is keyed 4-tier, z=32,
Cesium-TMS-flipped. Every tier differed at every point tested -- Berlin
HEEL 0x624b vs 0xc8e1 -- so this was a different key, not a coarser one.

Done as a real TDD loop, since the environment can now link the test
binary (dropping debuginfo was what unblocked it):

  RED   hhtl_agrees_with_the_v3_substrate_oracle failed 25163 vs 51425
  GREEN 14/14 osm tests after the migration

The test asserts equality against osm_soa_bake::tms::point_to_tiers -- the
implementation the slab is actually keyed on -- rather than asserting the
key "has four tiers", which would pass against a wrong key.

Implementation is mostly deletion. The local Mercator formula, the 24-bit
Morton interleave/deinterleave and the depth constant are now delegations
to osm_soa_bake::tms. Two implementations of one projection is precisely
how the display address and the row key drifted apart, so the duplicate is
gone rather than widened.

Two subtleties worth keeping:
- The TMS flip must happen at the tile's own zoom and THEN be left-aligned.
  xyz_to_tms_y is 2^z-1-y, so flipping at z and shifting by 32-z yields the
  minimum TMS row of the tile's z=32 range, which is the common Morton
  prefix. Shifting first and flipping at 32 picks the opposite corner and
  breaks the prefix property.
- Reading the bytes LEAF occupies as a tier, rather than as the head of the
  old family:u24, IS the V3 content-blind reinterpretation.

TEST CHANGES -- two pre-existing tests encoded the V1 depth and were
re-pinned, not silently widened:
- hhtl_roundtrips_to_the_tile: z=24/3-tier/48-bit -> z=32/4-tier/64-bit,
  and it now un-flips the recovered row before comparing. It also asserts
  the stored row is genuinely flipped, so the test fails if tile_to_hhtl
  ever stops applying the flip.
- over_depth_zoom_folds_to_its_native_ancestor: over-depth begins at 33,
  not 25. It now also asserts z=25 is NOT folded, which the V1 form did.
- coarse_zoom_lives_in_heel_not_twig: strengthened to cover LEAF.

Panel gains a fourth tier cell; the overlay JS was re-checked with
node --check. The key-space warning in osm_features.rs was rewritten
rather than deleted -- it records why the two keys once differed, which is
the reason the equality test exists.

Verification: 14/14 osm tests green; 79/80 for the whole crate. The single
failure, osint_gotham::dual_use_facets_pack_into_the_value_tenant, was
confirmed pre-existing by stashing this change and re-running it on main's
state -- it fails identically there and touches nothing in this diff.
…e route choices

The POC gate is passed. q2-cockpit was run against the real 2.5M-row Berlin
slab and /osm loaded in headless chromium: 0 markers and 0 fetches before
the toggle, 177,963 markers across 73,130 distinct positions after, no JS
errors, and the panel reporting HEEL 0xc8e1 -- the V3 oracle value the
Phase-3 falsifier asserts, now observed in a browser rather than a test.
The run is hermetic (every non-localhost request aborted), so it also
proves the overlay renders independently of the external basemap.

The run found a real defect that tests had not: the row cap is spatially
biased. MAX_FEATURES_PER_TILE is applied as take(5000) over a
Morton-ordered range, so a truncated tile returns a spatially contiguous
prefix -- a sub-quadrant -- rather than a sample. Measured: a capped tile
covers 99.9% of its width but only 50.0% of its height, while a control
tile under the cap covers 100%/100%. The counts were honest; the shape of
what came back was not, and a count cannot convey that. Filed with the fix
(stride-sample) and its falsifier, deliberately not applied here since it
changes a shipped endpoint's behaviour and deserves its own test.

Also documents every route alternative that is deliberately kept rather
than removed, with which arm is wired and what switching would cause:
the three /api/osm/* routes (locate is wired, tile is kept for non-map
callers), direct tile_range vs the capability arm (direct is sanctioned by
the capability module's own doc; q2 must not plug in or it earns
UnexpectedConsumer), hand decode vs project_fields (the one with a real
consequence -- the endpoint is currently unauthenticated), local slab vs
S3 hydrate, and the two basemap skins (whose toggle also carries
attribution, which is a licensing requirement).
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5912b9b0-f152-4059-876d-4349bb9274d9

📥 Commits

Reviewing files that changed from the base of the PR and between 25ba3af and 5d5d625.

📒 Files selected for processing (4)
  • claude-notes/plans/2026-08-08-osm-soa-cockpit-wiring.md
  • crates/cockpit-server/src/osm.rs
  • crates/cockpit-server/src/osm_features.rs
  • crates/cockpit-server/src/osm_tiles.rs

📝 Walkthrough

Walkthrough

The OSM cockpit now uses substrate-backed four-tier HHTL addressing at native depth 32. The UI displays the new LEAF tier, and documentation records shared V3 keys, browser verification, oracle testing, and OGAR integration details.

Changes

OSM V3 migration

Layer / File(s) Summary
Substrate-backed four-tier addressing
crates/cockpit-server/src/osm_tiles.rs
Tile projection and Morton operations now use osm_soa_bake::tms. Hhtl now contains HEEL, HIP, TWIG, and LEAF tiers. Over-depth tiles resolve to z=32 ancestors.
Addressing validation
crates/cockpit-server/src/osm_tiles.rs
Tests cover four-tier round trips, TMS Y-flipping, ancestor folding, native-depth behavior, and substrate oracle agreement.
Cockpit display and integration records
crates/cockpit-server/src/osm.rs, crates/cockpit-server/src/osm_features.rs, claude-notes/plans/2026-08-08-osm-soa-cockpit-wiring.md
The cockpit renders LEAF values and documents the shared V3 key space. The plan records browser verification, oracle results, Morton-order sampling bias, and OGAR integration gaps.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: claude

Poem

A rabbit hops through tiles of light,
Four HHTL tiers align just right.
HEEL and HIP, then TWIG in flight,
LEAF now marks the finest height.
TMS turns the map just so—
The cockpit blooms in rows below.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Aug 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_482b5f03-3f5c-4f5a-b5a3-f887adff6a89)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 10, 2026 23:20
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@AdaWorldAPI
AdaWorldAPI merged commit d022a9e into main Aug 10, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants