Link calibration rows to QA evidence map
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-08 13:23:42 +02:00
parent c0bebd609b
commit 0c826ef736
7 changed files with 78 additions and 0 deletions
+7
View File
@@ -7,6 +7,13 @@
# Changelog
## Sprint 135 Calibration evidence handoff (2026-07-08)
- Added a guided-calibration table action that opens the persisted QA/QC evidence map for successful threshold rows.
- Reused the existing quality-check evidence API and Map workspace overlay flow; no backend route, migration, model, provider or inference behavior changed.
- Kept unsuccessful/queued calibration rows read-only by disabling evidence actions until a persisted `quality_check_id` exists.
- Added regression coverage for the Detection Lab wiring and TODO tracking.
## Sprint 134 External remote-sensing YOLO candidate benchmark (2026-07-07)
- Evaluated the Hugging Face `agademer/yolo-remote-sensing-photovoltaic` YOLOv8l detection checkpoint as an explicit operator-provided runtime model asset.
@@ -0,0 +1,24 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def test_guided_calibration_rows_link_to_existing_qa_evidence_map() -> None:
lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx"
app = ROOT / "frontend" / "src" / "App.tsx"
todo = ROOT / "docs" / "TODO.md"
lab_source = lab.read_text(encoding="utf-8")
app_source = app.read_text(encoding="utf-8")
todo_source = todo.read_text(encoding="utf-8")
assert "onOpenCalibrationEvidence" in lab_source
assert "Open evidence map" in lab_source
assert "disabled={!row.quality_check_id || row.status !== 'success'}" in lab_source
assert "onOpenCalibrationEvidence(row.quality_check_id)" in lab_source
assert "Evidence" in lab_source
assert "quality_check_id" in lab_source
assert "onOpenCalibrationEvidence={openQualityEvidenceOnMap}" in app_source
assert "[x] Link guided calibration rows to the QA evidence map" in todo_source
+25
View File
@@ -1,3 +1,28 @@
## Sprint 135 Calibration evidence handoff (2026-07-08)
Changed:
- Added an `Open evidence map` action to successful guided detection calibration rows.
- Wired the Detection Lab action to the existing `openQualityEvidenceOnMap` flow, which loads persisted QA/QC evidence GeoJSON and opens the Map workspace overlay.
- Added compact table action styling and regression coverage in `backend/tests/test_sprint135_calibration_evidence_handoff.py`.
- Updated `CHANGELOG.md` and `docs/TODO.md`.
Tested:
- Red step: `python -m pytest backend\tests\test_sprint135_calibration_evidence_handoff.py -q` failed while the Detection Lab evidence handoff prop was absent.
- `python -m pytest backend\tests\test_sprint135_calibration_evidence_handoff.py backend\tests\test_sprint134_guided_detection_calibration_runner.py backend\tests\test_sprint133_detection_threshold_calibration_ux.py backend\tests\test_sprint112_qa_evidence_overlay.py -q` (`7 passed`)
- `python -m compileall backend/app`
- `cd frontend && npm run typecheck`
- `cd frontend && npm run build`
- `bash scripts/run_readiness_check.sh` (`414 passed`; frontend typecheck/build passed; Alembic head `202606120900`; live smoke syntax passed)
Open:
- Live Tower deploy validation still needs to run for this pass.
Limitations:
- This pass adds review handoff only. It does not create new QA metrics, promote thresholds, mutate model configuration, download models, add provider fetching or change API/database contracts.
Next recommended pass:
- Add an operator-facing calibration evidence summary/export shortcut once the map handoff has been used on real AOI runs.
## Sprint 134 External remote-sensing YOLO candidate benchmark (2026-07-07)
Changed:
+1
View File
@@ -421,5 +421,6 @@ This file now starts with the current implementation status. Older preparation/b
- [x] Add structured raster tile manifest handoff into Detection Lab with linked preflight visibility.
- [x] Add full threshold calibration comparison UX so detection runs can compare candidate thresholds before promotion.
- [x] Add guided in-app detection calibration runner for explicit threshold sweeps.
- [x] Link guided calibration rows to the QA evidence map.
- [ ] Add more AOIs after the tile-level baseline so the next local model attempt is not limited to Geel/Mol/Turnhout.
- [ ] Add negative/background AOIs so the next tile dataset is not all positive tiles.
+1
View File
@@ -993,6 +993,7 @@ function App(): JSX.Element {
onRunQa={runDetectionQa}
onSetCalibrationThresholdText={setCalibrationThresholdText}
onRunCalibration={runDetectionCalibration}
onOpenCalibrationEvidence={openQualityEvidenceOnMap}
/>
<SegmentationLab
@@ -79,6 +79,7 @@ interface DetectionLabProps {
onRunQa: () => void
onSetCalibrationThresholdText: (value: string) => void
onRunCalibration: () => void
onOpenCalibrationEvidence: (qualityCheckId: string) => void
}
export function DetectionLab({
@@ -133,6 +134,7 @@ export function DetectionLab({
onRunQa,
onSetCalibrationThresholdText,
onRunCalibration,
onOpenCalibrationEvidence,
}: DetectionLabProps): JSX.Element {
const selectedDetectionModel = detectionModels.find((model) => model.model_id === selectedDetectionModelId) ?? null
const selectedModelAsset = modelAssets.find((asset) => asset.model_asset_id === selectedModelAssetId) ?? null
@@ -583,6 +585,7 @@ export function DetectionLab({
<th>F1</th>
<th>False positives</th>
<th>False negatives</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
@@ -596,6 +599,17 @@ export function DetectionLab({
<td>{formatNullableNumber(row.f1_score ?? null, 3)}</td>
<td>{row.false_positives ?? 'n/a'}</td>
<td>{row.false_negatives ?? 'n/a'}</td>
<td>
<button
className="secondary-action table-action"
type="button"
onClick={() => row.quality_check_id ? onOpenCalibrationEvidence(row.quality_check_id) : undefined}
disabled={!row.quality_check_id || row.status !== 'success'}
aria-label={`Open evidence map for threshold ${row.threshold.toFixed(2)}`}
>
Open evidence map
</button>
</td>
</tr>
))}
</tbody>
+6
View File
@@ -3309,6 +3309,12 @@ button.entity-card {
background: #ffffff;
}
.table-action {
min-height: 2rem;
padding: 0.35rem 0.6rem;
white-space: nowrap;
}
.calibration-summary-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));