diff --git a/CHANGELOG.md b/CHANGELOG.md index 021a6d80..6a1e037f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Detection QA now applies the persisted tile coverage through the existing GiST-indexed PostGIS geometry column before loading reference rows, while retaining the complete reference population in audit counts. - The unchanged exact IoU matcher now uses a Shapely spatial index to avoid testing geometries whose envelopes cannot intersect. - Clarified the primary map source and legend whenever an AI result is active so detections are never presented as the underlying official GRB source. +- Made the fixed workbench context bar follow the active AI layer and exposed the IoU match threshold beside every detection-QA score. ## Sprint 194 Regional official time-series synchronization (2026-07-14) diff --git a/backend/tests/test_sprint169_long_context_name_readability.py b/backend/tests/test_sprint169_long_context_name_readability.py index ddab3eed..87d7cf64 100644 --- a/backend/tests/test_sprint169_long_context_name_readability.py +++ b/backend/tests/test_sprint169_long_context_name_readability.py @@ -15,7 +15,9 @@ def test_long_context_names_remain_compact_and_inspectable() -> None: assert "selectedProject?.name === REGIONAL_WORKSPACE_PROJECT_NAME" in app assert "? REGIONAL_WORKSPACE_LABEL" in app - assert "const datasetContextLabel = selectedDataset ? getDatasetDisplayName(selectedDataset)" in app + assert "const datasetContextLabel = analysisMapLayerActive && mapFeatureCollection" in app + assert "? getDatasetDisplayName(selectedDataset)" in app + assert "`${mapLayerLabel} · controle vereist`" in app assert "{projectContextLabel}" in app assert "{datasetContextLabel}" in app assert "{item.value}" in status diff --git a/backend/tests/test_sprint195_guided_detection_workflow.py b/backend/tests/test_sprint195_guided_detection_workflow.py index 25325c7b..b5dce40f 100644 --- a/backend/tests/test_sprint195_guided_detection_workflow.py +++ b/backend/tests/test_sprint195_guided_detection_workflow.py @@ -61,3 +61,12 @@ def test_detection_qa_remains_persisted_and_primary_not_parallel() -> None: assert "als kwaliteitscontrole in de database bewaard" in lab assert "detectionApi.compareWithReference" in hook assert "await loadQualityChecks(selectedProjectId)" in hook + assert "Minimale IoU voor een match" in lab + assert "detectionQaResult.iou_threshold.toFixed(2)" in lab + + +def test_active_analysis_is_not_presented_as_the_underlying_source_dataset() -> None: + app = read("frontend/src/App.tsx") + + assert "analysisMapLayerActive && mapFeatureCollection" in app + assert "`${mapLayerLabel} · controle vereist`" in app diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 3a46a2f7..457bccfc 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -8066,5 +8066,13 @@ Validation before final deployment: - Focused detection, coverage, QA and guided-workflow tests passed. - Frontend TypeScript typecheck passed after the source/legend correction. +Live operational proof: +- The final repository readiness gate passed 578 backend tests, API/document audits, frontend typecheck/build, one Alembic head and all shell smoke checks. +- Deployed commit `0cad8fd` to the Tower all-in-one runtime with AI extras enabled. Health, PostGIS 3.6, the single migration head, required schema/indexes and the port-1202 browser proxy all passed. +- The bounded QA request completed in 1.82 seconds. It retained a raw GRB population of 466,078, materialized/evaluated 1,826 coverage features and excluded 464,252 outside the nine persisted tiles. +- At match IoU 0.25, persisted quality check `341b0076-663a-4427-8a36-d5d9247a730e` measured 1,186 matches, precision 0.6073, recall 0.6495, F1 0.6277 and mean IoU 0.4565. No metric was fabricated. +- A separate UI run at its default stricter match IoU 0.50 also completed and persisted quality check `7a4464cd-152d-424f-a2b9-ed321b91524c`; the lower F1 is now explained by displaying the threshold beside the score. +- In-app browser inspection confirmed 1,953 persisted rows, map rendering over OpenStreetMap and explicit `AI-detecties`, `Detectierun`, `Gevonden gebouwen` and `controle vereist` labels. + Next: -- Deploy the bounded QA correction, rerun the live persisted detection-versus-GRB comparison, verify persisted metrics and inspect the result in MapLibre before declaring the guided operational flow complete. +- Add bounded operator-triggered orthophoto acquisition from a drawn map rectangle, then hand that raster to this proven guided pipeline. Keep external acquisition out of browser/startup paths and retain explicit source licensing/provenance. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 45a85d2a..518e39c9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -685,7 +685,13 @@ function App(): JSX.Element { ? REGIONAL_WORKSPACE_LABEL : selectedProject?.name ?? 'Geen werkruimte' const areaContextLabel = selectedArea?.name ?? (areas.length > 0 ? 'Kies een gebied' : 'Geen gebied') - const datasetContextLabel = selectedDataset ? getDatasetDisplayName(selectedDataset) : datasets.length > 0 ? 'Kies een bron' : 'Geen bron' + const datasetContextLabel = analysisMapLayerActive && mapFeatureCollection + ? `${mapLayerLabel} · controle vereist` + : selectedDataset + ? getDatasetDisplayName(selectedDataset) + : datasets.length > 0 + ? 'Kies een bron' + : 'Geen bron' const layerContextLabel = mapFeatureCollection ? `${mapFeatureCount.toLocaleString('nl-BE')} objecten` : viewportVectorLayerActive diff --git a/frontend/src/components/detection/DetectionLab.tsx b/frontend/src/components/detection/DetectionLab.tsx index 32b3007e..e37d0cdf 100644 --- a/frontend/src/components/detection/DetectionLab.tsx +++ b/frontend/src/components/detection/DetectionLab.tsx @@ -1080,6 +1080,7 @@ export function DetectionLab({

Recall: {detectionQaResult.recall?.toFixed(3) ?? 'n/a'}

F1: {detectionQaResult.f1_score?.toFixed(3) ?? 'n/a'}

Gemiddelde overlap: {detectionQaResult.mean_iou?.toFixed(3) ?? 'n.v.t.'}

+

Minimale IoU voor een match: {detectionQaResult.iou_threshold.toFixed(2)}

Fout positief: {detectionQaResult.false_positives}

Fout negatief: {detectionQaResult.false_negatives}

{detectionQaResult.coverage ? (