Fix latest snapshot map ranking
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
path, and retained every older snapshot.
|
||||
- Added compact Status UI, deterministic guardrail tests and readiness syntax
|
||||
coverage without changing migrations or enabling automatic refresh.
|
||||
- Fixed map theme ranking so a newer official observation always wins over an
|
||||
older snapshot with a marginally larger feature count.
|
||||
|
||||
## Sprint 222 Official source edition probes (2026-07-16)
|
||||
|
||||
|
||||
@@ -248,3 +248,13 @@ def test_refresh_api_and_frontend_remain_explicit_only() -> None:
|
||||
assert "void probeCatalogs(" not in hook
|
||||
assert 'choices=("plan", "stage", "apply")' in operator
|
||||
assert "--confirm-plan-sha256" in operator
|
||||
|
||||
|
||||
def test_map_theme_ranking_prefers_newer_observation_over_feature_count() -> None:
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
workspace = (root / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx").read_text(encoding="utf-8")
|
||||
observed_sort = workspace.index("const observedAtDifference")
|
||||
feature_tiebreaker = workspace.index("right.feature_count", observed_sort)
|
||||
assert observed_sort < feature_tiebreaker
|
||||
assert "new Date(right.observed_at ?? 0).getTime()" in workspace
|
||||
assert "if (observedAtDifference !== 0) return observedAtDifference" in workspace
|
||||
|
||||
@@ -9365,9 +9365,20 @@ Boundaries:
|
||||
Validation so far:
|
||||
- Backend compile and frontend typecheck passed.
|
||||
- Source-catalog plus governed-refresh focused suite passed: 20 tests.
|
||||
- Full `scripts/run_readiness_check.sh` passed: 779 backend tests, 110
|
||||
- Full `scripts/run_readiness_check.sh` passed: 780 backend tests, 110
|
||||
documented route contracts, one Alembic head, frontend typecheck/build and
|
||||
all packaged smoke checks.
|
||||
- Live Tower staging completed all 112 municipality/theme partitions for
|
||||
official edition `2026-07-15`: 1,054,223 features, 1,250,873,313 artifact
|
||||
bytes and staged plan SHA-256
|
||||
`7a772b70771c223b14d16c097c917fb160883349df61e24a2730e8c9591d56fd`.
|
||||
- Checksum-confirmed apply created four new Datasets with exact PostGIS counts:
|
||||
466,092 buildings, 84,513 roads, 88,330 water features and 415,288 parcels.
|
||||
The four `2026-07-14` snapshots remain present; total project datasets moved
|
||||
from 632 to 636 and source integrity remains zero-error.
|
||||
- Live browser validation exposed and fixed additive theme ranking where two
|
||||
extra old water features could outweigh a newer observation date. Ranking is
|
||||
now priority, observation date, import date, then feature-count tie-breaker.
|
||||
|
||||
Next:
|
||||
- Run the full release gate, deploy to Tower, execute a live read-only plan and
|
||||
|
||||
@@ -279,7 +279,7 @@ function pickThemeDataset(
|
||||
&& datasetCoversSelectedArea(dataset, selectedAreaId, regionalScope),
|
||||
)
|
||||
candidates.sort((left, right) => {
|
||||
const score = (dataset: DatasetCreateResponse) =>
|
||||
const priorityScore = (dataset: DatasetCreateResponse) =>
|
||||
(dataset.area_id && dataset.area_id === selectedAreaId ? 10_000_000 : 0) +
|
||||
(dataset.reference_layer_name && theme.tokens.includes(dataset.reference_layer_name.toLowerCase()) ? 1_000_000 : 0) +
|
||||
(dataset.source_name === 'grb' ? 100_000 : 0) +
|
||||
@@ -292,10 +292,18 @@ function pickThemeDataset(
|
||||
(dataset.source_name === 'vmm_flood_hazard' ? 5_000_000 : 0) +
|
||||
(dataset.source_metadata?.['product_key'] === 'dtm_1m' ? 1_000_000 : 0) +
|
||||
(dataset.source_metadata?.['product_key'] === 'pluviaal_current_t100' ? 1_000_000 : 0) +
|
||||
(dataset.dataset_role === 'reference' ? 10_000 : 0) +
|
||||
(dataset.observed_at ? new Date(dataset.observed_at).getTime() / 100_000_000 : 0) +
|
||||
(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0)
|
||||
return score(right) - score(left)
|
||||
(dataset.dataset_role === 'reference' ? 10_000 : 0)
|
||||
const priorityDifference = priorityScore(right) - priorityScore(left)
|
||||
if (priorityDifference !== 0) return priorityDifference
|
||||
|
||||
const observedAtDifference = new Date(right.observed_at ?? 0).getTime() - new Date(left.observed_at ?? 0).getTime()
|
||||
if (observedAtDifference !== 0) return observedAtDifference
|
||||
|
||||
const importedAtDifference = new Date(right.imported_at ?? 0).getTime() - new Date(left.imported_at ?? 0).getTime()
|
||||
if (importedAtDifference !== 0) return importedAtDifference
|
||||
|
||||
return (right.feature_count ?? right.vector_summary?.feature_count ?? 0)
|
||||
- (left.feature_count ?? left.vector_summary?.feature_count ?? 0)
|
||||
})
|
||||
return candidates[0] ?? null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user