fix: separate historical source methodologies
This commit is contained in:
@@ -30,6 +30,9 @@
|
||||
- Added deterministic estimate disclosure for population answers and instructed
|
||||
the local model to copy governed values literally instead of inventing
|
||||
averages, rates or derived trends.
|
||||
- Clarified the source inventory so current GRB layers are shown as a different
|
||||
methodology beside, rather than as part of, the comparable 2013-2025 land-use
|
||||
time series.
|
||||
|
||||
## Sprint 201 Semantic area-selection metrics (2026-07-15)
|
||||
|
||||
|
||||
@@ -328,3 +328,5 @@ def test_frontend_exposes_source_inventory_timeline_and_ai_window() -> None:
|
||||
assert "nextAssistantMessageId" in assistant_hook
|
||||
assert "crypto.randomUUID" not in assistant_hook
|
||||
assert "Officiële bronnen die hierna kunnen worden ingeladen" in catalog
|
||||
assert "vergelijkbare meetmomenten" in catalog
|
||||
assert "andere bronmethode" in catalog
|
||||
|
||||
@@ -8422,6 +8422,10 @@ Validation evidence:
|
||||
limitation whenever an answer discusses estimated population data, while the
|
||||
model prompt forbids independent averages, rates and derived trends. Focused
|
||||
tests and full readiness passed with 619 backend tests.
|
||||
- Browser review identified that the source summary visually combined current
|
||||
GRB geometry with historical 10 m land-use observations. The UI now reports
|
||||
comparable observations per temporal-series key and labels singleton/current
|
||||
datasets as a separate source method. Full readiness remained green.
|
||||
|
||||
Known limitations:
|
||||
- Water volume remains unavailable until a governed depth/bathymetry source is
|
||||
|
||||
@@ -66,12 +66,42 @@ function datasetTheme(dataset: DatasetCreateResponse): string | null {
|
||||
return null
|
||||
}
|
||||
|
||||
function timelineSummary(
|
||||
temporalCount: number,
|
||||
temporalSeriesCount: number,
|
||||
otherMethodCount: number,
|
||||
firstYear: number | null,
|
||||
lastYear: number | null,
|
||||
): string {
|
||||
if (temporalCount < 2 || !firstYear || !lastYear) {
|
||||
return 'Alleen de huidige toestand is vergelijkbaar beschikbaar.'
|
||||
}
|
||||
const seriesNote = temporalSeriesCount > 1
|
||||
? ` in ${temporalSeriesCount} afzonderlijke reeksen`
|
||||
: ''
|
||||
const methodNote = otherMethodCount > 0
|
||||
? `plus ${otherMethodCount} andere bronmethode${otherMethodCount === 1 ? '' : 'n'}`
|
||||
: null
|
||||
return [
|
||||
`${temporalCount} vergelijkbare meetmomenten${seriesNote}`,
|
||||
`${firstYear}-${lastYear}`,
|
||||
methodNote,
|
||||
].filter(Boolean).join(' · ')
|
||||
}
|
||||
|
||||
export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.Element {
|
||||
const ready = datasets.filter((dataset) => dataset.status === 'ready')
|
||||
const themes = Object.keys(THEME_LABELS).map((theme) => {
|
||||
const matches = ready.filter((dataset) => datasetTheme(dataset) === theme)
|
||||
const temporal = matches.filter((dataset) => dataset.temporal_series_key && dataset.observed_at)
|
||||
const years = temporal.map((dataset) => new Date(dataset.observed_at as string).getUTCFullYear())
|
||||
const seriesGroups = new Map<string, DatasetCreateResponse[]>()
|
||||
temporal.forEach((dataset) => {
|
||||
const seriesKey = dataset.temporal_series_key as string
|
||||
seriesGroups.set(seriesKey, [...(seriesGroups.get(seriesKey) ?? []), dataset])
|
||||
})
|
||||
const comparableSeries = [...seriesGroups.values()].filter((series) => series.length >= 2)
|
||||
const comparableObservations = comparableSeries.flat()
|
||||
const years = comparableObservations.map((dataset) => new Date(dataset.observed_at as string).getUTCFullYear())
|
||||
const latest = [...matches].sort(
|
||||
(left, right) => new Date(right.observed_at ?? right.imported_at ?? 0).getTime() - new Date(left.observed_at ?? left.imported_at ?? 0).getTime(),
|
||||
)[0]
|
||||
@@ -79,7 +109,9 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
|
||||
theme,
|
||||
label: THEME_LABELS[theme],
|
||||
datasetCount: matches.length,
|
||||
temporalCount: temporal.length,
|
||||
temporalCount: comparableObservations.length,
|
||||
temporalSeriesCount: comparableSeries.length,
|
||||
otherMethodCount: matches.length - comparableObservations.length,
|
||||
firstYear: years.length ? Math.min(...years) : null,
|
||||
lastYear: years.length ? Math.max(...years) : null,
|
||||
source: latest?.source_name ?? latest?.source ?? null,
|
||||
@@ -105,11 +137,13 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
|
||||
<span>{theme.source ? theme.source.replaceAll('_', ' ') : 'Nog niet ingeladen'}</span>
|
||||
</div>
|
||||
<b>{theme.datasetCount > 0 ? 'Beschikbaar' : 'Ontbreekt'}</b>
|
||||
<p>
|
||||
{theme.temporalCount >= 2 && theme.firstYear && theme.lastYear
|
||||
? `${theme.temporalCount} officiële meetmomenten · ${theme.firstYear}-${theme.lastYear}`
|
||||
: 'Alleen de huidige toestand is vergelijkbaar beschikbaar.'}
|
||||
</p>
|
||||
<p>{timelineSummary(
|
||||
theme.temporalCount,
|
||||
theme.temporalSeriesCount,
|
||||
theme.otherMethodCount,
|
||||
theme.firstYear,
|
||||
theme.lastYear,
|
||||
)}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user