osm cockpit: click a dot, get the real OSM element and its tags - #114
Conversation
Closes the last functional gap in the POC — the overlay drew dots with no
identity. A map of dots is a POC; knowing what the dots ARE is a map.
NO UPSTREAM CHANGE WAS NEEDED. Everything already existed in osm-soa-bake and
only had to be composed: cluster::facets(row), Facet::Tag{member,key,value},
codebook::read_books -> Books{identities,tag_keys,tag_values}, and
IdentityCodebook::key(ordinal). The .books sidecar was ALREADY hydrating
alongside the slab (Phase 6 carries both artifacts), so the data was on disk
and merely unread.
WHY A SECOND ENDPOINT, NOT INLINE TAGS. A city tile returns 15,016 features and
each row carries up to TAGS_PER_ROW tags, so inline tags would multiply an
already-large response by the tag fan-out — for data a viewer wants about ONE
dot at a time. FeatureOut gains a 4-byte `idx` (its slab row index) and
GET /api/osm/feature/:idx answers on demand. The detail is a click, not a
download.
TAGS BIND BY ORDINAL, NOT ADJACENCY. query_feature keeps only tag facets whose
`member` equals the row's own identity ordinal — cluster's own documented
property, the one that lets a continuation row be read alone. Filtering on it is
what stops a continuation row's tags being attributed to the wrong element.
MEASURED on the real Berlin bake:
GET /api/osm/feature/1740603
{ "osm_key": "0f02:1433098796",
"tags": { "access":"private", "emergency":"designated", "highway":"service",
"service":"driveway", "tunnel":"building_passage" } }
An emergency-access driveway passing under a building in central Berlin.
Sampled for variety: a 10-tag parking amenity with a conditional-fee
expression, a street lamp, a lift gate, a give-way sign. osm_key is the real
OSM element id via Books::identities ("{kind:04x}:{osm_id}").
THE UI. `.pt` markers carried `pointer-events:none` — they were not clickable at
all. Removing that is the whole interaction; panning still works because
mousedown bubbles from the dot to #map and the existing `moved` guard already
suppresses the click that ends a drag.
Two-sided, both measured in a hermetic browser run:
click a marker panel shows osm key 0f01:9710028117,
highway=street_lamp, layer=1; .pt.sel applied;
0 page errors
drag FROM a marker transform -562793,-343436 -> -563033,-343526,
markers repaint 64,707 -> 59,845, panel UNCHANGED
The second is the one that matters: enabling pointer events could have made
every pan open a random feature, and it does not.
90 passed, 0 failed, 3 ignored.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw
|
Warning Review limit reached
Next review available in: 35 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
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. Comment |
Bugbot couldn't run - usage limit reachedBugbot 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_3277af56-dff0-4ffb-9db9-5bf045e71532) |
Closes the last functional gap in the POC. The overlay drew dots with no identity — a map of dots is a POC; knowing what the dots are is a map.
No upstream change was needed
Everything already existed in
osm-soa-bakeand only had to be composed:cluster::facets(row)→Vec<(slot, Facet)>Facet::Tag { member, key, value }(ordinals)codebook::read_books→Books { identities, tag_keys, tag_values }IdentityCodebook::key(ordinal) -> Option<&str>lance-graph-contractThe
.bookssidecar was already hydrating alongside the slab (#112 carries both artifacts), so the data was on disk and merely unread.Why a second endpoint, not inline tags
A city tile returns 15,016 features and each row carries up to
TAGS_PER_ROWtags — inline tags would multiply an already-large response by the tag fan-out, for data a viewer wants about one dot at a time.FeatureOutgains a 4-byteidx(its slab row index) andGET /api/osm/feature/:idxanswers on demand. The detail is a click, not a download.Tags bind by ORDINAL, not adjacency
query_featurekeeps only the tag facets whosememberequals the row's own identity ordinal —cluster's own documented property, the one that lets a continuation row be read alone. Filtering on it is what stops a continuation row's tags being attributed to the wrong element.Measured, on the real Berlin bake
An emergency-access driveway passing under a building in central Berlin. Sampled for variety: a 10-tag parking amenity with a conditional-fee expression, a street lamp, a lift gate, a give-way sign;
0f01= node,0f02= way.osm_keyis the real OSM element id, resolved throughBooks::identities("{kind:04x}:{osm_id}").The UI, browser-verified
.ptmarkers carriedpointer-events:none— they were not clickable at all. Removing that is the whole interaction; panning still works because mousedown bubbles from the dot to#map, and the existingmovedguard already suppresses the click that ends a drag.Two-sided, both measured in a hermetic run:
osm key 0f01:9710028117,highway=street_lamp,layer=1;.pt.selhighlight applied; 0 page errors-562793,-343436→-563033,-343526, markers repaint 64,707 → 59,845, panel unchanged — the drag did not open a detailThe second row is the one that matters: enabling pointer events could have made every pan open a random feature, and it does not.
Two verification-method notes, each cost a run:
.ctlbutton stack (left:12, top:12, ~170 px tall) rather than a marker. Marker selection now requiresx > 320, y > 220..ptin DOM order as "outside of the viewport" — markers live inside the translated#tileslayer, so DOM order says nothing about visibility. The probe picks by measuredgetBoundingClientRect.Verification
cargo test --bin q2-cockpit— 90 passed, 0 failed, 3 ignored.🤖 Generated with Claude Code
https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw
Generated by Claude Code