bound the QA evidence overlay and fetch only what it draws

evidence_geojson emitted one feature per false positive, one per false negative
and two per match, with no limit. A regional check of 40k detections against 45k
reference footprints produced well over a hundred thousand features in a single
response, plus one warning string per unresolvable identifier. The endpoint the
entire review workflow depends on therefore failed exactly where review matters
most.

What to draw is now decided before any geometry is fetched, so the query work is
proportional to the result rather than to the size of the check — previously
130k geometries were resolved through an IN clause holding every identifier in
the check, to then discard most of them.

The budget is split between misses and false positives in proportion to their
populations with at least one of each, rather than by strict priority, which
would mean a check with 50.000 misses and three false positives never showed
one. Confirmations fill what remains, and a match is kept or dropped as a pair
because half a match is not reviewable evidence.

limit_evidence and evidence_role_counts are removed: plan_evidence supersedes
them, and helpers kept alive only by their own tests read like a contract.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Jens
2026-08-22 15:14:26 +02:00
co-authored by Claude Opus 5
parent 52c2bfd120
commit 5278fcd361
7 changed files with 412 additions and 64 deletions
+24
View File
@@ -1081,6 +1081,30 @@ Return vector stats (feature counts and geometry summary).
Return vector bounds and feature count.
### GET `/api/v1/projects/{project_id}/quality-checks/{id}/evidence/geojson`
Returns the reviewable geometry behind one quality check: the objects the model
missed, the ones it found without a reference, and the confirmed matches.
The overlay is capped by `limit` (default 5.000, `0` returns everything). A
regional check emitted one feature per false positive, one per false negative
and *two* per match with no bound at all, so a run of 40k detections against
45k footprints produced well over a hundred thousand features in one response —
the endpoint the whole review workflow depends on stopped working exactly where
review matters most.
What to draw is decided before any geometry is fetched, so the database work is
proportional to what is returned rather than to the size of the check. The
budget is split between misses and false positives in proportion to their
populations, with at least one of each: strict priority would mean a check with
50.000 misses and three false positives never showed one. Confirmations fill
what is left, and a match is kept or dropped as a candidate/reference pair
because half a match is not reviewable evidence.
`total_feature_count` and `role_counts` describe the complete population,
`truncated` says whether the cap applied, and unresolvable identifiers are
summarised in one warning rather than one per identifier.
### Export provenance
Every exported GeoJSON carries a `geointel_provenance` foreign member on the