Compact detection source tile rows
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-13 13:38:18 +02:00
parent 4455e242c6
commit d188014be2
6 changed files with 22 additions and 2 deletions
+1
View File
@@ -10,6 +10,7 @@
## Sprint 175 Detection result scale and false-positive evidence review (2026-07-13)
- Bounded Detection Lab table rendering with client-side 25/50/100-row pagination while preserving the complete persisted detection set for MapLibre and QA/QC.
- Compacted source-tile cells to filenames while preserving full persisted paths in tooltips.
- Added a strict read-only false-positive evidence audit with role-count drift checks, polygon validation, WGS84 geodesic areas, size buckets, AOI/class/tile summaries and combined review GeoJSON.
- Audited the active seven-AOI portfolio: 5,568 false positives among 13,613 candidates, median geometry area 184.5 m2, and 25.8% below 100 m2; Turnhout, Herentals and Geel carry the largest review volumes.
- Recorded that existing QA evidence has no per-detection confidence values; the audit reports zero confidence coverage and does not infer scores from the run threshold.
@@ -102,7 +102,10 @@ def test_detection_results_table_uses_bounded_local_pagination() -> None:
assert "Detection result pagination" in lab
assert "Previous detection results page" in lab
assert "Next detection results page" in lab
assert "formatSourceTilePath(detection.source_tile_path)" in lab
assert 'title={detection.source_tile_path ?? undefined}' in lab
assert "pagination-toolbar" in styles
assert ".source-tile-cell" in styles
assert "detectionItems.map((detection)" not in lab
+2 -1
View File
@@ -7145,6 +7145,7 @@ Open:
- Confirmed that Detection Lab rendered every persisted detection row at once; Westerlo alone produced 1,172 body rows in the browser.
- Added local 25/50/100-row pagination with a default of 50 rows, bounded page controls and automatic page-one reset after run/filter/result changes.
- Live visual inspection exposed tall rows caused by full container paths; source-tile cells now show the filename and retain the full persisted path as a tooltip.
- Kept the full persisted collection unchanged for the existing MapLibre GeoJSON overlay and detection QA/QC. No endpoint, response envelope or persistence contract changed.
## Persisted false-positive evidence
@@ -7167,7 +7168,7 @@ Open:
- `python -m pytest`: 475 passed.
- `python -m ruff check` for the new audit/test modules: passed.
- `npm run typecheck`: passed.
- `npm run build`: passed; app bundle `216.83 kB`, MapLibre bundle `801.82 kB` before gzip.
- `npm run build`: passed; app bundle `217.00 kB`, MapLibre bundle `801.82 kB` before gzip.
- `bash scripts/run_readiness_check.sh`: passed with 475 tests and all release-critical syntax gates.
- `python -m alembic heads`: one head, `202606120900`.
- `python -m alembic upgrade head --sql`: complete migration chain rendered successfully.
+1
View File
@@ -160,6 +160,7 @@ AI Lab run controls explicitly explain when no raster dataset is available, inst
- Detection Lab keeps the complete persisted detection collection available to the existing MapLibre overlay and QA/QC flows.
- The results table renders 50 rows by default and provides 25/50/100 row sizes plus previous/next controls. This bounds DOM work for dense AOIs without discarding or resampling detections.
- Selecting another run, changing a class/confidence filter or loading a new result collection resets the visible table to page one.
- Source tiles display their filename for compact scanning while retaining the complete persisted path in a hover tooltip.
- Pagination is intentionally client-side over the canonical persisted response; detection API contracts and GeoJSON output are unchanged.
## Sprint 15 additions
@@ -820,7 +820,9 @@ export function DetectionLab({
<td>{detection.class_name}</td>
<td>{detection.confidence.toFixed(2)}</td>
<td>{detection.model_name}</td>
<td>{detection.source_tile_path || 'n/a'}</td>
<td className="source-tile-cell" title={detection.source_tile_path ?? undefined}>
{formatSourceTilePath(detection.source_tile_path)}
</td>
</tr>
))}
</tbody>
@@ -1110,3 +1112,11 @@ function downloadJsonFile(filename: string, payload: unknown): void {
function formatNullableNumber(value: number | null, digits: number): string {
return typeof value === 'number' && Number.isFinite(value) ? value.toFixed(digits) : 'n/a'
}
function formatSourceTilePath(path: string | null | undefined): string {
if (!path) {
return 'n/a'
}
const parts = path.replace(/\\/g, '/').split('/').filter(Boolean)
return parts[parts.length - 1] ?? path
}
+4
View File
@@ -1043,6 +1043,10 @@ section th {
line-height: 1;
}
.source-tile-cell {
white-space: nowrap;
}
.workbench-inspector .job-result,
.workbench-inspector pre {
max-height: 16rem;