diff --git a/CHANGELOG.md b/CHANGELOG.md index f7a740da..e3a8f3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ - Live-smoked a Mol rectangle through NGI, Statbel, GRB, Flemish thematic rasters, DHMV, VMM flood hazard, BWK, DOV and VHA, including persisted Dataset output and semantic vector/raster metrics. +- Classified both `Gemeente ...` and release-golden `... municipality` Areas + as local scope so a full municipality analysis cannot accidentally invoke + regional raster partition assembly. - Rebuilt the complete frontend presentation as the Stitch-guided GeoIntel Atlas Workbench. The new shell uses one compact icon navigation rail, one context bar and task-specific work surfaces across Map, Sources, AI diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index a91ce007..c7310a78 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -10924,7 +10924,10 @@ Implemented: states and counts results per theme rather than per contributing layer; - registered VMM VHA historical profile points as an operational bounded Flanders bathymetry source and connected its existing acquire/select routes - to the Map product catalogue. + to the Map product catalogue; +- treated both Dutch municipality names and release-golden + `... municipality` Areas as local scope after live verification exposed a + false regional flood-raster partition path. Live evidence: @@ -10939,7 +10942,7 @@ Live evidence: Validation: -- the complete readiness gate passed: 1,053 backend tests, 24 frontend tests, +- the complete readiness gate passed: 1,053 backend tests, 25 frontend tests, backend compile, frontend TypeScript/typecheck, production build, Alembic head `202607160001` and script smoke checks; - a live API smoke over `5.10,51.17,5.11,51.18` proved all 17 applicable Mol diff --git a/frontend/src/components/map/MapWorkspace.tsx b/frontend/src/components/map/MapWorkspace.tsx index 2672fab0..572bf9d1 100644 --- a/frontend/src/components/map/MapWorkspace.tsx +++ b/frontend/src/components/map/MapWorkspace.tsx @@ -29,6 +29,7 @@ import { getFeatureBBox, getFeatureCollectionBBox, getFeatureGeometrySummary, + isMunicipalityAreaName, isSelectionBoundedDataset, normalizeBboxFromCorners, operationalScopeProjectLabel, @@ -394,10 +395,6 @@ function datasetMatchesTheme(dataset: DatasetCreateResponse, theme: DataTheme): return theme.tokens.some((token) => searchText.includes(token)) } -function isMunicipalityAreaName(name: string | null | undefined): boolean { - return /^Gemeente\s/i.test(name ?? '') -} - function isPartitionedRaster(dataset: DatasetCreateResponse | null | undefined): boolean { return Boolean( dataset?.dataset_type === 'raster' diff --git a/frontend/src/components/map/mapWorkspaceUtils.test.ts b/frontend/src/components/map/mapWorkspaceUtils.test.ts index e010acad..207496a7 100644 --- a/frontend/src/components/map/mapWorkspaceUtils.test.ts +++ b/frontend/src/components/map/mapWorkspaceUtils.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest' import { bboxesEqual, + isMunicipalityAreaName, isSelectionBoundedDataset, normalizeBboxFromCorners, parseBboxInput, @@ -65,6 +66,13 @@ describe('map workspace selection guards', () => { expect(productCoversZones(['brussels'], ['wallonia'])).toBe(false) }) + it('recognizes Dutch and release-golden municipality areas as local scope', () => { + expect(isMunicipalityAreaName('Gemeente Mol')).toBe(true) + expect(isMunicipalityAreaName('RC Golden - Mol municipality')).toBe(true) + expect(isMunicipalityAreaName('Flanders')).toBe(false) + expect(isMunicipalityAreaName('RC Golden - Kempen region')).toBe(false) + }) + it('distinguishes selection-bounded acquisitions from reusable regional datasets', () => { expect(isSelectionBoundedDataset({ geometry_clipped_to_selection: true, diff --git a/frontend/src/components/map/mapWorkspaceUtils.ts b/frontend/src/components/map/mapWorkspaceUtils.ts index def2a56e..fb4214ea 100644 --- a/frontend/src/components/map/mapWorkspaceUtils.ts +++ b/frontend/src/components/map/mapWorkspaceUtils.ts @@ -31,6 +31,11 @@ export function selectedAreaCoverageZones(areaName: string | null | undefined): return null } +export function isMunicipalityAreaName(areaName: string | null | undefined): boolean { + const normalized = String(areaName ?? '').trim() + return /^Gemeente\s/i.test(normalized) || /\bmunicipality$/i.test(normalized) +} + export function productCoversZones(productZones: string[], selectedZones: string[] | null): boolean { return selectedZones === null || selectedZones.some((zone) => productZones.includes(zone)) }