fix(catalog): read per-asset table:columns in extractColumns (#311) - #312
Conversation
extractColumns (the client-side map's schema channel — tooltips, legends, layer columns, isParentContainer detection) read only the collection-level table:columns. The catalog/publisher standard is moving to per-asset table:columns, so once publishers drop the collection-level block this returned [] and the map UI lost all column info. Repoint it at the per-asset table:columns on the queryable parquet assets, unioning across them and preferring the H3 hex asset (the primary query target) so its H3-aware column defs win on collisions; the flat GeoParquet fills any gaps. Geometry columns are dropped. This is the same canonical location the MCP get_stac_details renderer (the LLM's schema channel) reads. Falls back to the legacy collection-level block when no per-asset schema is present, so catalogs mid-migration keep working.
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||
…olumn loss Ground-truth check against the live STAC (all 6 golden-bench apps, 133 dataset instances) showed the per-asset-only reading regressed the map UI on not-yet-backfilled collections: wwf-ecoregions/overture-* carry no per-asset table:columns on the flat parquet asset and only join keys on the hex asset, so their display columns still live only in the collection-level block (20-26 cols -> 3). Union the per-asset blocks (canonical, hex-preferred) with the collection- level block as a lower-priority trailer — mirroring the MCP get_stac_details renderer (per-asset + collection-level trailer). Result vs main across the 6 apps: 0 datasets lose a column, 108 are FIXED (main returned [] because the collection is already per-asset-only, e.g. wdpa), 0 isParentContainer flips (so the headless system prompt is byte-identical -> no LLM behavior change).
Regression check (requested: headless / gold-question performance, dse-nimbus
|
| metric | result |
|---|---|
datasets that lost any column vs main |
0 |
datasets fixed (main returned [] → now populated) |
108 |
isParentContainer flips |
0 |
| assembled prompt-catalog text (content, order-normalized) | byte-identical on all 6 apps |
Gold-question / qwen verdict: the system prompt qwen receives is content-identical, so no gold-question regression is possible from this change — a live qwen matrix run can only reconfirm this while adding sampling noise. Happy to run the k8s matrix bench if you want the empirical datapoint anyway.
What the check surfaced (and why the PR changed)
The 108 fixed datasets are the important number: most collections have already migrated to per-asset-only table:columns (e.g. wdpa has no collection-level block at all), so main's extractColumns was already returning [] for them — the map UI already had no column info. That's #311's predicted breakage, already live.
The first commit (per-asset only, per the issue's literal "hex + flat GeoParquet") introduced its own regression: wwf-ecoregions-2017 and overture-divisions-* carry no per-asset block on the flat parquet asset and only join keys (_cng_fid, h8, h0) on the hex asset — their display columns still live only in the collection-level block (20–26 → 3). The catalog is mid-migration (data-workflows #404/#369 backfill incomplete).
Fix: union the per-asset blocks (canonical, hex-preferred) with the collection-level block as a lower-priority trailer — which is what the MCP get_stac_details renderer already does ("per-asset + collection-level trailer"). This fixes the already-migrated datasets and keeps the not-yet-backfilled ones whole, and when the collection block is finally retired the per-asset union already carries everything (no consumer left behind — the issue's stated goal).
Closes #311.
Problem
extractColumns(app/dataset-catalog.js) — the client-side map's schema channel feeding tooltips, legends, layercolumns, andisParentContainerdetection — read only the collection-levelcollection['table:columns']. Meanwhile the LLM's schema channel (get_schema→ MCPget_stac_details) already reads per-assettable:columns.The catalog/publisher standard is moving to per-asset
table:columns(data-workflowsverify-stac.pyhard-fails collection-level). Once publishers drop the collection-level block,extractColumnswould return[]→ map tooltips/legends lose column info, andisParentContainer(keyed onds.columns.length === 0) would misfire on real leaf datasets.Change
Repoint
extractColumnsat the per-assettable:columnson the queryable parquet assets:geom/geometry) columns; dedup by name.table:columnsblock, so catalogs mid-migration keep working.The map UI now reads the same canonical location as the LLM renderer, and the collection-level block can be retired catalog-wide once mcp-data-server#303 lands (render-time dedup) with no consumer left behind.
Notes (out of scope, from the issue)
TOOL_RESULT_CAPtruncation of large multi-assetget_schemaresults is addressed by mcp-data-server#303's dedup; no change here.h0/h8/h9/h10) are retained.Testing
npm test— 492 passing. Added 4extractColumnscases: per-asset union with hex precedence, pmtiles ignored when parquet exists, and legacy collection-level fallback.