Skip to content

chore(map-layers): match OGC collections exactly and drop unpublished layers (BDMS-977/978/979) - #355

Open
jirhiker wants to merge 2 commits into
stagingfrom
chore/bdms-977-978-979-trim-public-ogcapi-catalog
Open

chore(map-layers): match OGC collections exactly and drop unpublished layers (BDMS-977/978/979)#355
jirhiker wants to merge 2 commits into
stagingfrom
chore/bdms-977-978-979-trim-public-ogcapi-catalog

Conversation

@jirhiker

Copy link
Copy Markdown
Member

UI counterpart to the pygeoapi catalog trim in BDMS-977, BDMS-978, and BDMS-979.

⚠️ Merge order

Do not merge before the pygeoapi change deploys. Four of the layers removed here are live and working today. If this reaches staging first, they disappear from the map with no catalog change behind them.

The bug this fixes

resolveCollection scored partial matches — exact 100, prefix 60, suffix 50, substring 20 — with no minimum score and exists: Boolean(bestMatch). Any substring hit bound a layer.

Once BDMS-978 unpublishes locations, the candidate locations no longer matches anything real, but it does match rock_sample_locations — normalized, that string ends with locations, scoring 50 + 5. The Locations layer would have silently rebound to the rock-sample collection:

  • on the map, that collection renders twice under two different toggles
  • on the collections page, ogc-locations is defined first, so it claims rock_sample_locations in the seenCollectionIds dedupe and the real rock-sample entry is skipped entirely

No crash, no error — just the wrong data under the right label.

What changed

Resolution is now exact: id/collection_id first, then name/title, candidates tried in order. Separators and case are still normalized, so one candidate covers both water_elevation_contours and Water Elevation Contours. A layer either names a published collection or it does not exist. The regex token scorer backstopping the water-elevation layers is gone too.

Layers removed, with what they actually bound to:

Layer Collection Ticket
ogc-locations locations BDMS-978
ogc-latest-depth-to-water latest_depth_to_water_wells BDMS-977
ogc-average-tds avg_tds_wells BDMS-977
ogc-other-thing-types other_things BDMS-979

All four bound by title, not id — Latest Depth to Water (Water Wells), Average TDS (Water Wells), Other Thing Types — which is why candidate lists that never mention avg_tds_wells still resolved to it.

ogc-water-elevation-contours is removed as well: the catalog publishes no contour collection and never has, so the entry was already dead. Its derived counterpart — contours computed from water_elevation_wells via turf — was gated on !waterElevationContours.exists, which was always true, so the gate is dropped and the derived layer is now unconditional. Same runtime behavior.

Downstream config removed along with the layers: popup labels and row builders, preferred selection columns, feature-detail configs.

Two judgment calls worth a look

  • DEFAULT_VISIBLE_LAYERS was ['ogc-latest-depth-to-water'] — the map's opening layer. Left as-is the map would open empty, so it now opens on ogc-water-well-summary, which BDMS-977 names as the layer making latest-depth-to-water redundant.
  • DEPTH_LEGEND, latestDepthToWaterColorFromFeature, averageTdsColorFromFeature had no other consumers and are deleted.

Verification

Replayed both registries — the map hook and the collections page — against the deployed catalog with the trim applied: 18/18 surviving layers resolve exactly, no orphans, no mis-binds.

  • npm run typecheck — clean
  • npm run test:run with the Prism mock up — 357 passed. The 16 failures in integration/api/*.contract.test.ts are byte-identical to the pre-change baseline (mock-vs-interface drift on IWellScreen/ISpring/ISample/IWell), untouched by this work
  • New src/test/utils/ogcLayerUtils.test.ts pins the failure modes: locations must not bind to rock_sample_locations, a candidate must not bind to a collection it is merely a prefix of
  • npm run lint cannot run tree-wide in a checkout with worktrees under .claude/ (Biome aborts on nested root configs, pre-existing). Per-file: same 10 format errors as HEAD, none new; lint warnings in useThingLayers.tsx drop 28 → 22

Follow-up, not in this PR

Eight published collections have no registered layer: waterlevels, water_chemistry, and six geothermal ones. The collections page already has a Geothermal group described as reserved "when they are published" — they are published. Separate branch.

The second commit adds CLAUDE.md, unrelated to the tickets — AGENTS.md already documented the branch-off-staging rule but no CLAUDE.md existed for Claude Code to load. Easy to drop if you would rather it went on its own.

🤖 Generated with Claude Code

jirhiker and others added 2 commits August 22, 2026 07:55
…hed layers

Layer resolution scored partial matches: exact 100, prefix 60, suffix 50,
substring 20, with no minimum score and `exists: Boolean(bestMatch)`. Any
substring hit bound a layer. With `locations` removed from the catalog per
BDMS-978, the Locations layer would have silently rebound to
`rock_sample_locations` (normalized, it ends with "locations"), rendering
that collection twice on the map and displacing the real rock-sample entry
on the collections page through its `seenCollectionIds` dedupe.

Resolution is now exact against `id`/`collection_id`, then `name`/`title`,
candidates tried in order. Separators and case are still normalized so one
candidate covers both `water_elevation_contours` and its display title.
A layer either names a published collection or does not exist. The regex
token scorer that backstopped the water-elevation layers is gone too.

Verified every registered layer against the deployed catalog: all 18 that
survive the BDMS-977/978/979 trim resolve exactly, in both the map hook and
the collections page.

Removes the layers whose collections those tickets unpublish:

  ogc-locations               locations                    BDMS-978
  ogc-latest-depth-to-water   latest_depth_to_water_wells  BDMS-977
  ogc-average-tds             avg_tds_wells                BDMS-977
  ogc-other-thing-types       other_things                 BDMS-979

All three bound by title, not id, which is why the shorter candidate lists
still matched them today.

Also removes ogc-water-elevation-contours: the catalog publishes no contour
collection and never did, so the entry was dead before this change. Its
derived counterpart, computed from water_elevation_wells via turf, was gated
on `!waterElevationContours.exists` -- always true -- so that gate is now
dropped and the derived layer is unconditional. Same runtime behavior.

DEFAULT_VISIBLE_LAYERS pointed at ogc-latest-depth-to-water, so the map would
have opened with nothing. It now opens on ogc-water-well-summary, the layer
BDMS-977 names as making latest-depth-to-water redundant.

DEPTH_LEGEND, latestDepthToWaterColorFromFeature, and
averageTdsColorFromFeature had no remaining consumers and are removed.

Merge order matters: this must not reach staging before the pygeoapi catalog
change deploys, or four working layers disappear with nothing behind it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AGENTS.md already documents that feature, fix, chore, docs, and CI branches
all base off staging, but there was no CLAUDE.md on any branch, so Claude
Code never loaded it. Cutting a branch from the default branch, production,
produces a PR into staging that drags every commit staging is missing.

Imports AGENTS.md and restates the branching rule up front. Carries the
model-attribution frontmatter the repo's documentation rule requires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

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.

1 participant