Prepare GeoIntel for public release
Managed validation / Managed repository validation (pull_request) Successful in 1m46s
GeoIntel release gates / Compile, test, contracts and builds (pull_request) Successful in 1m51s
GeoIntel release gates / Python and npm vulnerability policy (pull_request) Successful in 20s
GeoIntel release gates / Production AI image, SBOM and container scan (pull_request) Successful in 15m3s
GeoIntel release gates / Deploy exact gated revision to Unraid (pull_request) Skipped
Managed validation / Managed repository validation (pull_request) Successful in 1m46s
GeoIntel release gates / Compile, test, contracts and builds (pull_request) Successful in 1m51s
GeoIntel release gates / Python and npm vulnerability policy (pull_request) Successful in 20s
GeoIntel release gates / Production AI image, SBOM and container scan (pull_request) Successful in 15m3s
GeoIntel release gates / Deploy exact gated revision to Unraid (pull_request) Skipped
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Accuracy, modelgrenzen en bewijs
|
||||
|
||||
GeoIntel behandelt AI-resultaten als voorstellen die aan brondata,
|
||||
modelidentiteit, ruimtelijke context en kwaliteitsmetingen gekoppeld blijven.
|
||||
Een model wordt niet automatisch gedownload of geactiveerd.
|
||||
|
||||
## Wat gebruikers mogen verwachten
|
||||
|
||||
- GIS-bewerkingen en AI-inferentie bewaren hun invoer- en uitvoerprovenance.
|
||||
- Referentie- en kandidaatdata blijven afzonderlijk herkenbaar.
|
||||
- Precision, recall, F1, IoU, false positives en false negatives zijn
|
||||
inspecteerbaar waar een geschikte referentieset beschikbaar is.
|
||||
- Een groen technisch proces is geen garantie dat een model voor elk gebied,
|
||||
seizoen, sensortype of objecttype betrouwbaar is.
|
||||
- Modeloutput vraagt menselijke of taakgerichte kwaliteitscontrole vóór gebruik
|
||||
in beslissingen met operationele, juridische of veiligheidsimpact.
|
||||
|
||||
## Releasegrens
|
||||
|
||||
Modelpromotie vereist een reproduceerbaar benchmarkmanifest, een exacte
|
||||
model-SHA-256, gescheiden ontwikkel- en evaluatiesets, leakagecontroles en de
|
||||
toepasselijke releasegates. Ontbrekend bewijs faalt gesloten.
|
||||
|
||||
## Publieke versus lokale evidence
|
||||
|
||||
De repository bevat alleen broncode, methodedocumentatie en expliciet publieke
|
||||
fixtures. Runtime-databases, exacte operationele locaties, modelgewichten,
|
||||
contact sheets, trainingsdata en gegenereerde evaluatierapporten worden lokaal
|
||||
of in gecontroleerde artefactopslag bewaard. De scripts onder `scripts/` kunnen
|
||||
deze evidence opnieuw genereren zonder ze aan Git toe te voegen.
|
||||
|
||||
Zie ook [SECURITY.md](../SECURITY.md),
|
||||
[docs/KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md) en
|
||||
[docs/DEFINITION_OF_DONE.md](DEFINITION_OF_DONE.md).
|
||||
@@ -215,7 +215,7 @@ fail-closed validation as the false-positive workflow. It requires an exact
|
||||
one-to-one set of reviewed reference ids and emits only explicit
|
||||
`confirmed_model_false_negative` geometries. `--require-complete` rejects any
|
||||
remaining `unreviewed` row. The July 2026 96-card review is recorded in
|
||||
`docs/reviews/2026-07-15-small-building-model-review.md`; it yielded no novel,
|
||||
the controlled model-review evidence outside Git; it yielded no novel,
|
||||
leakage-free labels and therefore did not trigger model training.
|
||||
|
||||
### Local model asset catalog
|
||||
|
||||
+42
-13052
File diff suppressed because it is too large
Load Diff
+24
-1280
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
||||
# Phase 1 execution contract
|
||||
|
||||
- Status: **executed**
|
||||
- Audit date: 2026-08-01
|
||||
- Audit branch: `codex/geointel-accuracy-program`
|
||||
- Audited baseline commit: `0c019bb22f816db1e4b7a68379bcad08924d9a21`
|
||||
- Product scope: Belgium and the Belgian North Sea
|
||||
- Release conclusion: **blocked**
|
||||
- Phase 2 conclusion: **safe to start as controlled remediation, not as training or promotion**
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This contract turns the accuracy program into an evidence-bearing engineering
|
||||
program. Phase 1 establishes what exists, what actually runs, where data and
|
||||
model results originate, which claims are supportable, and which defects must
|
||||
be corrected before any new training or release promotion.
|
||||
|
||||
Phase 1 is complete when the required inventory, lineage, baseline, risk,
|
||||
metric, roadmap, machine-readable status and retained evidence exist and can be
|
||||
reproduced. Completion of Phase 1 does **not** mean that GeoIntel is accurate,
|
||||
nationally validated, release-ready, or fully trained.
|
||||
|
||||
## 2. Non-negotiable rules
|
||||
|
||||
1. No quality, coverage, authority, calibration or national-readiness claim may
|
||||
be stronger than the retained evidence.
|
||||
2. A green unit test that uses a fixture, mock, placeholder or source-text
|
||||
assertion is not evidence of live geospatial or model quality.
|
||||
3. Protected test data is never used for training, calibration, failure-driven
|
||||
sampling, threshold selection or stopping decisions.
|
||||
4. Dataset, label, tile, checkpoint, runtime and evaluation identities are
|
||||
immutable hashes, not filenames or mutable display names.
|
||||
5. Geometry entering persistence is validated, assigned an explicit source CRS,
|
||||
transformed to the canonical CRS and checked for valid domain and units.
|
||||
6. Official or authoritative status is server-attested; caller-controlled source
|
||||
names can never establish authority.
|
||||
7. Failed, unavailable and `not_configured` states remain explicit. A fallback
|
||||
cannot silently be reported as a successful primary result.
|
||||
8. Human review is only complete when reviewer identity, decision, timestamp,
|
||||
sampled object/AOI identity and reviewed artifact hash are persisted.
|
||||
9. Phase 1 does not delete, rewrite or promote datasets, checkpoints, caches,
|
||||
outputs, migrations or server state. The GPU smoke is read-only and persists
|
||||
no detections.
|
||||
10. User-owned untracked files, including `.codex-artifacts/`, server
|
||||
`.env.bak.*`, `.forgeflow/`, `storage/evaluation/` and
|
||||
`storage/source-cache/`, remain untouched.
|
||||
|
||||
## 3. Evidence vocabulary
|
||||
|
||||
Every statement in this program uses one of these classes:
|
||||
|
||||
| Class | Meaning |
|
||||
|---|---|
|
||||
| observed | Directly read from the repository, database, storage, runtime or retained artifact |
|
||||
| reproduced | Deterministic read-only reproducer demonstrated the behavior |
|
||||
| tested | An executable test or build gate ran and its result is retained or recorded |
|
||||
| inferred | A conclusion drawn from observed evidence; it must be labelled as an inference |
|
||||
| planned | Not implemented or not yet evidenced |
|
||||
| unavailable | The required system or artifact could not be inspected; reason is stated |
|
||||
| blocked | A required gate cannot pass without remediation |
|
||||
|
||||
The words “implemented”, “configured”, “available”, “validated” and “promoted”
|
||||
are not synonyms:
|
||||
|
||||
- **implemented** means code exists;
|
||||
- **configured** means a runtime selects it;
|
||||
- **available** means dependencies/assets can be loaded;
|
||||
- **validated** requires a registered evaluation and acceptance decision;
|
||||
- **promoted** requires every release gate and an auditable activation record.
|
||||
|
||||
## 4. Authorized Phase 1 mutations
|
||||
|
||||
The only authorized repository mutations are:
|
||||
|
||||
- audit collectors and deterministic reproducer scripts;
|
||||
- focused tests for those collectors;
|
||||
- `docs/accuracy-program/`;
|
||||
- retained evidence under `artifacts/evidence/accuracy/P1/`;
|
||||
- required execution-log and TODO updates;
|
||||
- a selective `.gitignore` exception that tracks only the Phase 1 evidence
|
||||
tree while keeping other generated `artifacts/` ignored.
|
||||
|
||||
No product behavior, model checkpoint, dataset, label or production database row
|
||||
is changed in Phase 1.
|
||||
|
||||
## 5. Executed investigation surface
|
||||
|
||||
The audit covered:
|
||||
|
||||
- root and nested tracked source trees, Git state and ignored/untracked state;
|
||||
- backend API routes, schemas, services, ORM entities and Alembic chain;
|
||||
- frontend TypeScript, tests, typecheck and production build;
|
||||
- CI/readiness scripts, container definitions and Tower deployment identity;
|
||||
- Postgres/PostGIS table counts, statuses, lineage gaps and geometry integrity;
|
||||
- mounted storage paths referenced by the database;
|
||||
- active NVIDIA/PyTorch/Ultralytics runtime and active model hash;
|
||||
- one existing Geel raster tile through the production YOLO adapter on
|
||||
`cuda:0`;
|
||||
- available Belgian building corpus, split, label, tiling, calibration,
|
||||
checkpoint and human-review evidence;
|
||||
- mocks, fixtures, fallbacks, placeholders and documentation drift.
|
||||
|
||||
Detailed outcomes live in documents 01 through 06 and in the P1 evidence tree.
|
||||
|
||||
## 6. Reproducibility entry points
|
||||
|
||||
Run from the repository root:
|
||||
|
||||
```powershell
|
||||
python scripts/run_accuracy_phase1_baseline.py --output-dir artifacts/evidence/accuracy/P1
|
||||
python scripts/reproduce_accuracy_phase1_findings.py
|
||||
python -m pytest tests/test_accuracy_phase1_baseline.py -q -p no:cacheprovider
|
||||
```
|
||||
|
||||
The runtime/database collector is intentionally executed inside the deployed
|
||||
application container and uses read-only SQL with a statement timeout:
|
||||
|
||||
```text
|
||||
scripts/collect_accuracy_phase1_runtime.py
|
||||
```
|
||||
|
||||
The GPU collector is streamed into the deployed container and uses the
|
||||
production adapter with an existing checksummed model, manifest and tile:
|
||||
|
||||
```text
|
||||
scripts/collect_accuracy_phase1_inference_smoke.py
|
||||
```
|
||||
|
||||
Its retained JSON includes the model, manifest and tile SHA-256 values, package
|
||||
versions, CUDA device, seed, configuration, raster CRS and raw output summary.
|
||||
It explicitly forbids deriving an accuracy or release claim from one smoke.
|
||||
|
||||
## 7. Proven release blockers
|
||||
|
||||
Phase 1 reproduced or observed all of the following:
|
||||
|
||||
- cross-theme coverage contamination can incorrectly return
|
||||
`operational`;
|
||||
- a nominal metre buffer is applied as degrees;
|
||||
- Lambert coordinates can be persisted unchanged under SRID 4326;
|
||||
- caller-controlled source identity can be elevated to authoritative coverage;
|
||||
- YOLO validation scope is bypassable through a mutable Area-name substring;
|
||||
- legal coverage identity changes when an Area display name changes;
|
||||
- Area PATCH silently ignores a documented geometry field;
|
||||
- four persisted Geel detections contain Lambert-domain coordinates while their
|
||||
geometry column is labelled SRID 4326;
|
||||
- the training loop contains a future protected-test feedback path;
|
||||
- V56 has zero accepted human AOI reviews out of 180;
|
||||
- split independence, pure-background coverage, temporal label alignment and
|
||||
unique-object evaluation are insufficient;
|
||||
- no candidate has protected-test, background-test and promotion evidence;
|
||||
- the real CI pytest work directory fails during collection, the full root suite
|
||||
has 17 stale assertion failures, Ruff has 112 findings and frontend lint is
|
||||
not configured;
|
||||
- the production AI image is not built or exercised by CI;
|
||||
- a tracked nested source mirror contains 1,153 files, 68 of which differ from
|
||||
root, creating source-of-truth ambiguity.
|
||||
|
||||
## 8. Decision gates
|
||||
|
||||
| Gate | Phase 1 decision |
|
||||
|---|---|
|
||||
| Runtime CUDA and active model load | pass |
|
||||
| One production-adapter GPU inference | pass, runtime-only evidence |
|
||||
| Database/storage reachability | pass for inspected references |
|
||||
| Geometry/CRS integrity | fail |
|
||||
| Authoritative-source integrity | fail |
|
||||
| Coverage correctness | fail |
|
||||
| Strict protected-test isolation | fail in code design |
|
||||
| Human label acceptance | fail |
|
||||
| Split independence and negatives | fail |
|
||||
| Reproducible national metric baseline | absent |
|
||||
| Backend release gate | fail |
|
||||
| Lint and frontend lint | fail / absent |
|
||||
| National model promotion | blocked |
|
||||
| Start test-first Phase 2 remediation | allowed |
|
||||
|
||||
## 9. Stop and escalation conditions
|
||||
|
||||
Training and model promotion remain prohibited until Phase 2 has closed the
|
||||
CRS, authority, coverage and protected-test isolation blockers and a frozen,
|
||||
human-approved corpus exists. If a required source snapshot, reviewer decision,
|
||||
immutable hash or independent holdout cannot be produced, the corresponding
|
||||
claim remains blocked; it is never replaced by synthetic success.
|
||||
|
||||
The protected test may be opened exactly once for a pre-registered candidate
|
||||
after all calibration gates pass. A failure after that opening creates a new
|
||||
model-development cycle and requires a newly governed protected set; its errors
|
||||
must not feed back into the same training lineage.
|
||||
@@ -1,158 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — 01 Systeeminventaris
|
||||
|
||||
## 1. Doel, peildatum en claimgrens
|
||||
|
||||
Dit document beschrijft de aantoonbaar aanwezige GeoIntel-componenten op 1 augustus 2026. Het is een forensische inventaris, geen kwaliteitscertificaat. `implemented` betekent dat code en een contractpad bestaan; `configured` betekent dat de betreffende runtimeconfiguratie daadwerkelijk is waargenomen; `fixture/mock` betekent dat het pad alleen test- of demobewijs levert; `planned/unproven` betekent dat geen uitvoerbaar productiebewijs is gevonden.
|
||||
|
||||
De inventaris is opgebouwd uit:
|
||||
|
||||
- checkout `C:\Projects\geointel` op branch `codex/geointel-accuracy-program`, basis-HEAD `0c019bb22f816db1e4b7a68379bcad08924d9a21`;
|
||||
- Tower-checkout `/mnt/user/appdata/geointel` op branch `main`, dezelfde HEAD;
|
||||
- draaiende container `/geointel`, image `geointel-all-in-one:0c019bb22f81-wipfdc62947dfb2-ai`, status `running`, health `healthy`;
|
||||
- read-only runtime-/databasecollectie in `C:\Projects\geointel\artifacts\evidence\accuracy\P1\tower-runtime-database-snapshot-detailed.json`;
|
||||
- read-only GPU-smoke in `C:\Projects\geointel\artifacts\evidence\accuracy\P1\tower-gpu-inference-smoke.json`;
|
||||
- retained model-, checkpoint-, corpus- en splitinventaris in `C:\Projects\geointel\artifacts\evidence\accuracy\P1\tower-ml-data-lineage-snapshot.json`;
|
||||
- lokale repository- en artifactinventaris in dezelfde evidence-map.
|
||||
|
||||
Geen bevinding in dit document bewijst nationale modelkwaliteit, menselijk gevalideerde labels, calibratie, geografische generalisatie of releasegeschiktheid.
|
||||
|
||||
## 2. Uitvoerbare productarchitectuur
|
||||
|
||||
| Onderdeel | Concrete code-/configpaden | Status | Bewezen runtime-/teststatus | Accuracy-grens |
|
||||
|---|---|---|---|---|
|
||||
| React/TypeScript workbench | `frontend/src/App.tsx`, `frontend/src/components`, `frontend/src/hooks`, `frontend/src/services` | implemented | 16 frontend-testbestanden; Vitest 51/51, typecheck en productiebuild slaagden in de Phase-1-baseline | UI-werking bewijst geen inhoudelijke GIS- of modeljuistheid |
|
||||
| Mapweergave en gebiedsselectie | `frontend/src/components/map/MapWorkspace.tsx`, MapLibre dependency in `frontend/package.json` | implemented | compileert en is unit-getest; geen volledige browser-E2E-uitvoering in de releasegate | selectie-UX is geen bewijs dat server-side scope/CRS correct is |
|
||||
| FastAPI HTTP-laag | `backend/app/main.py`, `backend/app/api/routes/*.py` | implemented | 148 route-decorators statisch gevonden; OpenAPI-audit zag 147 routes, waarvan 10 contractueel toegestane niet-envelope routes | route-aanwezigheid bewijst geen correcte gegevensinhoud |
|
||||
| Projecten en AOI's | `project_service.py`, `area_service.py`, routes `projects.py` en `areas.py` | implemented, persisted | 1.097 projecten en 387 gebieden in Tower; alle 387 gevulde gebiedsgeometrieën geldig, SRID 4326 en binnen het 4326-domein | Area PATCH en naamgebaseerde wettelijke scope hebben bewezen contract-/integriteitsgaten |
|
||||
| Datasetinname en versies | `dataset_service.py`, `storage_service.py`, `datasets.py` | implemented, persisted | 3.377 datasets, alle status `ready`; 1.671 datasetversies; 5.816 directe storage-referenties gecontroleerd, 0 ontbrekend | `ready` is een verwerkingsstatus, geen bronautoriteit of inhoudelijke kwaliteitsclaim |
|
||||
| Rasterverwerking | `raster_service.py`, `raster_operations_service.py`, acquisitieservices voor orthofoto/DHMV/WALOUS/SPW | implemented | raster- en GIS-gerichte tests slaagden; bestaande Tower-tiles konden read-only worden geopend | geen volledige corpusbrede rasteralignment-/nodata-/resolutieaudit afgerond |
|
||||
| Vectorverwerking | `vector_feature_service.py`, `vector_operations_service.py`, officiële-vectoracquisitie | implemented, persisted | 6.689.447 `vector_features`; alle gevulde geometrieën geldig, SRID 4326 en binnen domein in de gebonden DB-query | buffer, import-CRS en afgeleide-featurepersistentie hebben kritieke gereproduceerde fouten |
|
||||
| Bron- en dekkingsresolutie | `providers/*`, `coverage_registry_service.py`, `source_catalog_probe_service.py` | implemented | 28 waargenomen `source_name`-waarden in de DB; officiële en fixtureproviders zijn afzonderlijk gemodelleerd | bronautoriteit kan via uploadmetadata worden gespooft; dekking kan door een andere themalaag worden overschat |
|
||||
| Achtergrondjobs/AOI-operations | `job_service.py`, `aoi_operation_service.py`, `aoi_operation_worker.py`, `backend/app/workers` | implemented, configured | 4.460 jobs: 4.325 success, 135 failed; 4 AOI-operations en 61 partitions; geen lopende job/run tijdens snapshot | status `success` is geen accuracy-gate; foutpercentages zijn niet per workflow genormaliseerd |
|
||||
| Objectdetectieadapter | `detection_service.py`, `detection_georeferencing.py`, `yolo_adapter.py`, `yolo_preflight_service.py` | implemented, configured op Tower | 1.146 detectieruns: 1.144 success, 2 failed; 299.233 detecties; één read-only productieadapter-smoke op GPU slaagde | actieve modelscope wordt op een muteerbare gebiedsnaam afgedwongen; modelversie is leeg; smoke bewijst geen accuracy |
|
||||
| Modelregister | `model_registry_service.py`, runtimeinstellingen in `backend/app/core/config.py` | mixed | actief YOLO-pad bestaat; register toont daarnaast expliciet `yolo-placeholder` en `manual-fixture-detector` | placeholder/fixture mogen niet als productie-inference of kwaliteitsbewijs worden geteld |
|
||||
| Segmentatie | `segmentation_service.py`, `segmentation_adapter.py`, routes `segmentation.py` | abstraction implemented; production unproven | modelregister bevat `segmentation-placeholder` en `fixture-segmenter`; Tower bevat 0 segmentaties | geen bewijs van geconfigureerde productie-segmentatie of modelkwaliteit |
|
||||
| QA/QC en metrics | `qa_service.py`, `quality_service.py`, `detection_qa_service.py`, routes `qa.py` en `quality_checks.py` | implemented, persisted | 697 quality checks en 4.182 metricrijen; 4-scenario golden fixturebenchmark slaagde | metricnulls en ongedefinieerde no-overlap-F1 vereisen een expliciet contract; fixturebenchmark is geen veldbenchmark |
|
||||
| Exports | `export_service.py`, route `exports.py` | implemented, persisted | 768 exportrecords; directe storage-referenties zaten in de 5.816 gecontroleerde records | een export kan een foutief upstreamresultaat correct serialiseren |
|
||||
| Demo/fixtures | `demo_workflow_service.py`, `providers/fixture.py`, `fixtures/*` | fixture/demo only | expliciet gemarkeerde fixtureprovider en handmatige fixturemodellen | nooit meenemen in productie- of nationale accuracyclaims |
|
||||
| Training- en audittooling | `scripts/run_belgium_building_training_loop.py`, `scripts/evaluate_belgium_building_candidate.py`, corpus-/label-/qualityscripts | implemented tooling; release linkage incomplete | omvangrijke Tower-runs en checkpoints aanwezig; v56 automated audits en v62 previewcalibratie aantoonbaar | protected-testfeedback lekt terug naar volgende sampling; 0/180 v56-corpussamples menselijk gereviewd; geen geldige nationale promotieclaim |
|
||||
| Deployment | `deploy/unraid/Dockerfile.all-in-one`, `docker-compose.unraid.yml`, `deploy/unraid/*` | implemented, configured op Tower | all-in-one-container gezond; NVIDIA GPU doorgegeven | compose-default `cu130` en feitelijke image/runtime `cu128` zijn supply-chain/builddrift; CI bouwt standaard zonder AI |
|
||||
| Documentatie/contracts | `docs/API_CONTRACTS.md`, `docs/DATABASE_IMPLEMENTATION_PLAN.md`, scope freezes en DoD | implemented but drifted | contracttests bestaan | meerdere documenten beschrijven historische of geplande toestand die niet met de runtime overeenstemt |
|
||||
|
||||
## 3. Repositoryomvang en bronstaat
|
||||
|
||||
De machineleesbare inventaris staat in `artifacts/evidence/accuracy/P1/repository-inventory.json`.
|
||||
|
||||
| Groep | Bestanden | Regels |
|
||||
|---|---:|---:|
|
||||
| backend applicatie | 129 | 32.583 |
|
||||
| backend tests | 235 | 36.067 |
|
||||
| frontend broncode | 112 | 23.534 |
|
||||
| frontend E2E-scripts | 2 | 734 |
|
||||
| migraties | 11 | 610 |
|
||||
| root tests | 7 | 261 |
|
||||
| scripts | 158 | 43.180 |
|
||||
|
||||
Aanvullend zijn 1.182 `test_*`-functies, 16 frontend-testbestanden en 148 API-route-decorators statisch geteld. Dit zijn omvangmetingen, geen bewijs dat iedere test of route correct is.
|
||||
|
||||
De checkout bevat 2.495 tracked files. Daarvan zijn 1.153 bestanden een tweede, tracked repositorykopie onder `geointel/`: 1.085 gepaarde bestanden zijn byte-identiek en 68 verschillen van hun roottegenhanger. Docker sluit `/geointel` expliciet uit, maar lokale imports, zoekresultaten en scripts kunnen toch de verkeerde kopie raken. Verder zijn onder meer 109 tracked bestanden onder `.codex-input`, 27 onder `data`, één onder `output` en vier onder `test-results` aangetroffen. Phase 1 verwijdert of overschrijft deze user-/historieartefacten niet.
|
||||
|
||||
## 4. Runtime en persistence op Tower
|
||||
|
||||
### 4.1 Platform
|
||||
|
||||
| Eigenschap | Waargenomen waarde |
|
||||
|---|---|
|
||||
| Host/containerplatform | Linux 6.12.54 Unraid, x86_64 |
|
||||
| Python | 3.11.2 |
|
||||
| PostgreSQL | 16.14 |
|
||||
| PostGIS | extension 3.6.4; core procedures melden nog 3.4.3 en `need upgrade` |
|
||||
| Alembic-head | `202607260001` (één lineaire statische en runtime-head) |
|
||||
| PyTorch | `2.11.0+cu128` |
|
||||
| torchvision | `0.26.0+cu128` |
|
||||
| Ultralytics | `8.4.99` |
|
||||
| CUDA-runtime | 12.8 |
|
||||
| GPU | één NVIDIA GeForce RTX 4080 SUPER; CUDA beschikbaar |
|
||||
| GIS-libraries | GeoPandas 1.1.4, Rasterio 1.4.4, Shapely 2.1.2, pyproj 3.7.2, GeoAlchemy2 0.20.0 |
|
||||
|
||||
### 4.2 Persistente aantallen
|
||||
|
||||
| Tabel | Rijen | Tabel | Rijen |
|
||||
|---|---:|---|---:|
|
||||
| `projects` | 1.097 | `areas` | 387 |
|
||||
| `datasets` | 3.377 | `dataset_versions` | 1.671 |
|
||||
| `vector_features` | 6.689.447 | `analysis_runs` | 1.146 |
|
||||
| `detections` | 299.233 | `segmentations` | 0 |
|
||||
| `detection_reviews` | 0 | `quality_checks` | 697 |
|
||||
| `metrics` | 4.182 | `jobs` | 4.460 |
|
||||
| `exports` | 768 | `aoi_operations` | 4 |
|
||||
| `aoi_operation_partitions` | 61 | | |
|
||||
|
||||
De snapshot gebruikte `statement_timeout=30000` ms en read-only queries. De volledige recursieve storageaudit eindigde in een time-out en is dus geen pass; de aparte controle van alle 5.816 directe `storage_path`-referenties voltooide wel en vond 0 ontbrekende bestanden. Niet-gerefereerde, geneste of semantisch verkeerde artefacten vallen buiten dat resultaat.
|
||||
|
||||
## 5. Modellen en trainingsartefacten
|
||||
|
||||
### 5.1 Actief productiepad
|
||||
|
||||
| Veld | Waarde |
|
||||
|---|---|
|
||||
| Containerpad | `/app/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt` |
|
||||
| Hostpad | `/mnt/user/appdata/geointel/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt` |
|
||||
| SHA-256 | `a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1` |
|
||||
| Grootte | 22.516.074 bytes |
|
||||
| Geconfigureerde klasse | `building` |
|
||||
| Device | `cuda:0`, CUDA verplicht |
|
||||
| Geconfigureerde validatienamen | `Mol,Kempen` |
|
||||
| Modelversie | leeg |
|
||||
|
||||
De hash identificeert het actieve bestand. Er is geen aangetoonde release-/dataset-/commitketen die deze hash koppelt aan een menselijk gereviewd, beschermd testresultaat. De scopecheck gebruikt bovendien een substring in `Area.name`, niet een onveranderlijke geografische scope.
|
||||
|
||||
De GPU-smoke gebruikte één bestaande 512×512 RGB GeoTIFF in EPSG:31370 en de productieadapter met seed `20260801`, deterministische algoritmen, `imgsz=640`, confidence `0.5` en `max_det=1000`. Het model produceerde 17 `building`-boxes in 0,884 s inference; dat bewijst alleen dat één adapter-call op de NVIDIA-GPU uitvoer gaf.
|
||||
|
||||
### 5.2 Niet-actieve recente checkpoints
|
||||
|
||||
De retained Tower-inventaris telt 26 modelassets in `/app/models`, 229 trainingscheckpoints met samen 28.512.052.142 bytes, 424 JSON-trainingsrapporten en 36 operator-manifests. Dit zijn aanwezigheidsaantallen; de collector claimt uitdrukkelijk geen human label acceptance, strikte splitonafhankelijkheid, protected-testprestatie, nationale geldigheid of release readiness.
|
||||
|
||||
Onder de niet-actieve checkpoints bestaan onder meer:
|
||||
|
||||
- `/mnt/user/appdata/geointel/storage/training/building-be-v62-v58-flanders-balanced-transfer-r1/runs/flanders/weights/best.pt`, 456.136.473 bytes, SHA-256 `889ee5b3bfe722803542d15a53a51a716872cf0e8516da5e8291e0a2605adbdb`;
|
||||
- `/mnt/user/appdata/geointel/storage/training/building-be-v62-v58-flanders-balanced-transfer-r1/runs/flanders/weights/last.pt`, 456.136.985 bytes, SHA-256 `08d12061f017c45c123c824ffa043bc07794beef251c903299eb1e0954636c8b`.
|
||||
|
||||
Aanwezigheid is geen activatie of promotie. Het v62-pad heeft in de geïnspecteerde run alleen preview-calibratiebewijs op 144 tiles; geen protected-test-, achtergrondtest- of releasebundel werd daar aangetroffen. De meest recente geïnspecteerde v66-manifestversie bevat slechts drie Vlaamse `train`-samples, nul background-test-samples en geen andere regio/split; ze is een gerichte proef, geen opvolgende nationale corpusrelease.
|
||||
|
||||
### 5.3 Lokale checkout
|
||||
|
||||
De lokale artifactscanner inventariseerde 193 bestanden (84.874.287 bytes) onder `models`, `datasets`, `data`, `storage`, `artifacts` en `output`: 114 rasters, 32 overige bestanden, 21 runtime-databasebestanden, 13 visuele-reviewbestanden, 6 evaluatie/auditbestanden, 5 manifests en 2 vectors. Er staat lokaal geen modelcheckpoint. Grote bestanden zijn bewust niet allemaal gehasht; aanwezigheid van contact sheets telt niet als menselijke review.
|
||||
|
||||
## 6. Build-, CI- en configuratiedrift
|
||||
|
||||
- De lokale audit draaide met Python 3.13.2, Node 24.18.1 en npm 11.16.0; CI is ingericht op Python 3.11 en Node 20. Een lokaal groen resultaat is daarom niet automatisch een CI-runtimebewijs.
|
||||
- `docker-compose.unraid.yml` bouwt standaard met `GEOINTEL_INSTALL_AI=false` en noemt als Torch-index `cu130`; de actieve Tower-runtime is een AI-image met Torch/CUDA `cu128`. `deploy/unraid/Dockerfile.all-in-one` en deployscripts vormen dus een tweede, afwijkend buildpad.
|
||||
- GitHub- en Gitea-workflows voeren `scripts/run_readiness_check.sh` uit. Die gate compileert code, draait backendtests, Alembic heads, frontend unit/typecheck/build, maar controleert de E2E- en veel live-workflows alleen met `node --check` of `bash -n`.
|
||||
- `frontend/package.json` heeft geen `lint`-script en geen ESLint-configuratie, hoewel linting in de teststrategie wordt verwacht. `python -m ruff check backend scripts tests` meldde 112 bevindingen (E402 13, E701 2, E702 69, F401 23, F403 1, F811 2, F841 2) en zit niet in de huidige readinessgate.
|
||||
- De CI bouwt niet aantoonbaar de AI/CUDA-image en controleert geen hash-lock voor de PyTorch/Ultralytics-artifactketen.
|
||||
|
||||
## 7. Reproduceerbare inventariscommando's
|
||||
|
||||
Vanaf `C:\Projects\geointel`:
|
||||
|
||||
```powershell
|
||||
python scripts\run_accuracy_phase1_baseline.py --output-dir artifacts\evidence\accuracy\P1
|
||||
python scripts\collect_accuracy_phase1_runtime.py --help
|
||||
python scripts\collect_accuracy_phase1_inference_smoke.py --help
|
||||
git rev-parse HEAD
|
||||
git status --short
|
||||
```
|
||||
|
||||
De laatste twee collectors zijn ontworpen om in de Tower-container tegen `/app/storage` en `/app/models` te draaien; de bewaarde outputs zijn de JSON-bestanden in `artifacts/evidence/accuracy/P1`. Voor serveridentiteit is read-only geverifieerd:
|
||||
|
||||
```bash
|
||||
cd /mnt/user/appdata/geointel
|
||||
git rev-parse HEAD
|
||||
git branch --show-current
|
||||
docker inspect geointel --format '{{.Config.Image}} {{.State.Status}} {{.State.Health.Status}}'
|
||||
```
|
||||
|
||||
## 8. Inventarisconclusie
|
||||
|
||||
GeoIntel is geen mockplatform: de workbench, API, PostGIS-persistentie, provider- en analysekaders, jobs, exports, QA/QC en een echte CUDA-YOLO-adapter zijn aantoonbaar geïmplementeerd en draaien. Even aantoonbaar is dat meerdere kritieke correctheidsgrenzen ontbreken of omzeild kunnen worden. Segmentatie is niet als productiemodel bewezen, fixturepaden blijven aanwezig, recente training is niet naar een geldige releaseketen gepromoveerd en geen enkel Phase-1-resultaat ondersteunt “100% getraind” of nationale nauwkeurigheid.
|
||||
@@ -1,250 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — 02 Data-lineage
|
||||
|
||||
## 1. Scope en bewijsregel
|
||||
|
||||
Deze lineage-audit volgt een resultaat terug naar project/AOI, bronbestand, datasetversie, tile of vectorfeature, model of algoritme, runparameters, QA/QC en export. Een veld dat in het schema bestaat maar leeg is, geldt niet als lineagebewijs. Een door de gebruiker aangeleverde string geldt evenmin als bewijs van officiële bronautoriteit.
|
||||
|
||||
De runtimecijfers komen uit de gebonden read-only snapshot van 1 augustus 2026 in:
|
||||
|
||||
- `C:\Projects\geointel\artifacts\evidence\accuracy\P1\tower-runtime-database-snapshot-detailed.json`;
|
||||
- `C:\Projects\geointel\artifacts\evidence\accuracy\P1\tower-gpu-inference-smoke.json`;
|
||||
- `C:\Projects\geointel\artifacts\evidence\accuracy\P1\tower-ml-data-lineage-snapshot.json`.
|
||||
|
||||
Containerpaden beginnen met `/app`; dezelfde persistente volumes staan op de host onder `/mnt/user/appdata/geointel`.
|
||||
|
||||
## 2. Canonieke resultaatketen
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
S["Externe bron of upload"] --> F["Bestand / API-respons"]
|
||||
F --> D["Dataset + DatasetVersion"]
|
||||
D --> V["VectorFeature(s)"]
|
||||
D --> T["Rastertiles + manifest"]
|
||||
V --> A["AnalysisRun / geoprocessing"]
|
||||
T --> M["Modelbestand + adapter"]
|
||||
M --> R["Detection / Segmentation"]
|
||||
A --> Q["QualityCheck + Metric"]
|
||||
R --> Q
|
||||
A --> E["Export"]
|
||||
R --> E
|
||||
Q --> E
|
||||
```
|
||||
|
||||
De feitelijke persistencevelden staan in `backend/app/models/entities.py`:
|
||||
|
||||
- `Dataset`: `project_id`, `area_id`, `storage_path`, `checksum_sha256`, `derived_from_dataset_id`, CRS/bounds/resolutie/banden, `dataset_role`, `source_name`, `reference_layer_name`, source- en provenance-metadata, tijdvelden, `source_version` en status;
|
||||
- `DatasetVersion`: versie, storagepad, checksum, bronversie, observatietijd, validiteitsvenster en source/provenance-metadata;
|
||||
- `VectorFeature`: `dataset_id`, bronfeature-id, klasse, properties en PostGIS-geometrie met SRID 4326;
|
||||
- `AnalysisRun`: project/AOI/dataset/job, analysetype, status, modelnaam/-versie, parameters, resultaat en tijden;
|
||||
- `Detection`/`Segmentation`: dataset/run/job, modelnaam/-versie, klasse, confidence, EPSG:4326-geometrie, pixelbbox, bron-tile en properties/provenance;
|
||||
- `QualityCheck` en `Metric`: kandidaat-, referentie- en runkoppelingen, parameters, bevindingen en losse metricwaarden;
|
||||
- `Export`: project, optionele run, type, storagepad en metadata.
|
||||
|
||||
Dat is een bruikbaar schema, maar de audit toont breuken tussen schema, invoercontrole en opgeslagen werkelijkheid.
|
||||
|
||||
## 3. Brondatasets en versies
|
||||
|
||||
### 3.1 Volledigheid van kernvelden
|
||||
|
||||
| Controle | Datasetresultaat | DatasetVersion-resultaat | Interpretatie |
|
||||
|---|---:|---:|---|
|
||||
| totaal | 3.377 | 1.671 | alle 3.377 datasets hebben status `ready` |
|
||||
| checksum ontbreekt | 0 | 0 | bestandsidentiteit is op rijniveau aanwezig |
|
||||
| CRS ontbreekt | 0 | n.v.t. | aanwezigheid bewijst nog niet dat coördinaten correct getransformeerd zijn |
|
||||
| `imported_at` ontbreekt | 0 | n.v.t. | importtijd is gevuld |
|
||||
| source metadata ontbreekt | 0 | 0 | metadataobject aanwezig; semantische authenticiteit niet bewezen |
|
||||
| provenance metadata ontbreekt | 0 | 0 | provenanceobject aanwezig; inhoud kan caller-controlled zijn |
|
||||
| storagepad ontbreekt | n.v.t. in deze query | 0 | 5.816 directe storagepaden apart fysiek gecontroleerd |
|
||||
| `observed_at` ontbreekt | 2.377 | niet in deze gapquery | bronfamiliebeleid nodig: sommige vaste/scenariobronnen kunnen legitiem geen observatietijd hebben |
|
||||
| `source_version` ontbreekt | 1.761 | niet in deze gapquery | geen betrouwbare freshness/reproduceerbaarheid zonder bronfamilieclassificatie |
|
||||
|
||||
“Metadata aanwezig” mag niet worden omgezet in “officiële lineage geldig”. `POST /datasets/upload` in `backend/app/api/routes/datasets.py:142-163` laat de caller `source_name`, `reference_layer_name`, source-/provenance-metadata en `source_version` invullen. De dekkingsresolver vertrouwt die waarden later als materialisatiebewijs. Een in-memory reproductie met een user-upload die zich als `grb`/`buildings` presenteerde, werd als operationele, gezaghebbende GRB-dekking teruggegeven. Er is dus een cryptografische bestandsketen, maar geen afgedwongen bronautoriteitsketen.
|
||||
|
||||
### 3.2 Waargenomen bronnen
|
||||
|
||||
De volgende rijen zijn feitelijk in de Tower-database waargenomen. `reference` is alleen de opgeslagen datasetrol/-metadata, geen onafhankelijke bevestiging door de genoemde instantie.
|
||||
|
||||
| `source_name` | datasets | reference |
|
||||
|---|---:|---:|
|
||||
| `manual` | 1.751 | 660 |
|
||||
| `vmm_flood_hazard` | 339 | 0 |
|
||||
| `vmm_vha_bathymetry_profiles` | 273 | 273 |
|
||||
| `department_omgeving_thematic_raster` | 210 | 0 |
|
||||
| `grb` | 179 | 179 |
|
||||
| `digitaal_vlaanderen_orthophoto` | 168 | 0 |
|
||||
| `spw_orthophoto` | 107 | 0 |
|
||||
| `spw_picc` | 68 | 68 |
|
||||
| `digitaal_vlaanderen_dhmv` | 60 | 0 |
|
||||
| `urbis` | 36 | 36 |
|
||||
| `urbis_orthophoto` | 26 | 0 |
|
||||
| `waterinfo` | 26 | 26 |
|
||||
| `department_omgeving_land_use` | 25 | 25 |
|
||||
| `historical_landuse` | 21 | 21 |
|
||||
| `agentschap_landbouw_zeevisserij_agricultural_parcels` | 18 | 18 |
|
||||
| `statbel` | 15 | 15 |
|
||||
| `dov_soil_map` | 13 | 13 |
|
||||
| `inbo_bwk_natura2000` | 12 | 12 |
|
||||
| `spw_walous_land_cover` | 7 | 0 |
|
||||
| `vrbg` | 6 | 0 |
|
||||
| `fixture` | 5 | 1 |
|
||||
| `ngi_adminvector` | 4 | 4 |
|
||||
| `map_selection` | 3 | 0 |
|
||||
| `digitaal_vlaanderen_buildings_addresses_register` | 1 | 1 |
|
||||
| `rbins_marine_reporting_units` | 1 | 1 |
|
||||
| `rbins_msp_2026` | 1 | 1 |
|
||||
| `spw_bathymetry` | 1 | 0 |
|
||||
| `spw_terrain` | 1 | 0 |
|
||||
|
||||
Deze telling bewijst historische materialisatie, niet dat iedere externe endpoint op de peildatum bereikbaar of actueel was.
|
||||
|
||||
## 4. Vectorlineage
|
||||
|
||||
### 4.1 Bedoelde keten
|
||||
|
||||
`bron/upload -> Dataset + checksum/CRS/provenance -> VectorFeature rows -> spatial operation/AnalysisRun -> derived Dataset -> QA/export`.
|
||||
|
||||
De database bevat 6.689.447 vectorfeatures. De gebonden PostGIS-query vond 0 lege, 0 ongeldige, 0 niet-4326 en 0 buiten-4326-domeingeometrieën in de huidige tabel. Dat sluit drie concrete codeproblemen niet uit:
|
||||
|
||||
1. `backend/app/services/geojson_service.py:70-94` leest CRS-metadata, maar `vector_feature_service.py:271-299` krijgt die CRS niet mee en schrijft iedere feature met `srid=4326`. Een EPSG:31370-geometrie rond `(150000, 210000)` kon daardoor ongetransformeerd als 4326 worden opgebouwd. De huidige tabelquery bewijst alleen dat zo'n waarde nu niet in `vector_features` staat; het importpad blijft foutgevoelig.
|
||||
2. `vector_operations_service.py:179-190` voert `geometry.buffer(distance_m)` uit op de geladen geometrie zonder metrische reprojection. De retained reproductie van een 100-meterbuffer leverde 200 graden span en bounds `[-95, -49, 105, 151]`.
|
||||
3. `_persist_derived_dataset` heeft in `vector_operations_service.py:414-427` standaard `persist_vector_features=False`. Clip, buffer en intersect kunnen daardoor een `ready` GeoJSON-artifact en dataset opleveren zonder querybare `vector_features`, zonder AnalysisRun-koppeling en met een niet-atomische persistenceketen.
|
||||
|
||||
Lineageconclusie: validiteit van de huidige PostGIS-rijen is bewezen; een algemeen correct vectorimport-/operatiecontract is dat niet.
|
||||
|
||||
## 5. Raster- en tilelineage
|
||||
|
||||
Een rasterdataset bewaart bestandspad, checksum, CRS, bounds, resolutie en bandmetadata. Inference gebruikt een tegelmap onder `/app/storage/tiles/<project>/<dataset>/<run>/` met `manifest.json` en GeoTIFF-tiles.
|
||||
|
||||
De representatieve read-only smoke gebruikte:
|
||||
|
||||
| Artifact | Pad | SHA-256 |
|
||||
|---|---|---|
|
||||
| manifest | `/app/storage/tiles/cb80638d-dbef-48ac-b19c-cec7c3efc96e/ae0ff76d-70c0-404f-b777-54d14517179a/b191c968-7d56-4e0d-afbb-8b5baaa62470/manifest.json` | `6ab8a96bf2a1405e224932afb90255311a09bbeaed4e9a2fdcdf8b1bc2230abd` |
|
||||
| tile | dezelfde map, `tile_0000.tif` | `134a9e86850c92c577c73bc6ee57a9df7d4c1c513ae6450263e800b6dd47b6ee` |
|
||||
| actief model | `/app/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt` | `a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1` |
|
||||
|
||||
De tile is 669.227 bytes, 512×512, 3×`uint8`, CRS EPSG:31370, resolutie 0,9765625 meter/pixel en bounds `[193277.53584918313, 205708.27443503588, 193777.53584918313, 206208.27443503588]`. Dit is voldoende om deze ene inference-input exact te identificeren. Er is nog geen corpusbrede toets op duplicate/near-duplicate imagery, nodata, source-date/label-date, WMS-resampling, grenspadding of resolutieconsistentie.
|
||||
|
||||
## 6. Detectielineage
|
||||
|
||||
### 6.1 Persistente productieketen
|
||||
|
||||
`Dataset -> tile manifest -> AnalysisRun(parameters/model_name/model_version) -> Detection(source_tile_path/pixelbbox/confidence/EPSG:4326 geometry) -> QualityCheck/Metrics -> Export`.
|
||||
|
||||
Tower bevat 1.146 `analysis_runs`, alle type `detection` met modelnaam `yolo-configured`: 1.144 success en 2 failed. Daaruit zijn 299.233 detecties aanwezig. Geen confidence lag buiten `[0,1]`. De modelversie is bij alle 1.146 runs leeg. 1.143 runs bewaren wel een modelassethash; drie niet. Alle runs bewaren een tile-manifestpad, maar geen tile-manifest-SHA, runtime-/hardware-identiteit of seed. De drie hashloze runs zijn niet sluitend aan een checkpoint te koppelen; ook de overige missen het volledige reproduceerbare inferencecontract.
|
||||
|
||||
De read-only smoke riep de productieadapter rechtstreeks aan met seed `20260801`, deterministische algoritmen, confidence 0,5, `imgsz=640`, `max_det=1000` en `cuda:0`. Resultaat: 17 `building`-boxes, confidence 0,500877–0,814435, gemiddelde 0,559481. De smoke schreef geen DB-records en testte dus niet de volledige georeference-/persistence-/QA-keten.
|
||||
|
||||
### 6.2 Bewezen historische lineagebreuk
|
||||
|
||||
Vier detecties in run `7ba34274-411d-45e3-8f54-c37baec598b1` hebben een PostGIS-geometrie met SRID 4326 maar numerieke Lambertwaarden rond X 193.278–193.774 en Y 205.708–206.054. Alle vier verwijzen naar:
|
||||
|
||||
- project `GeoIntel Real Data Validation 20260706T235847Z`;
|
||||
- dataset `ae0ff76d-70c0-404f-b777-54d14517179a`, `geel_orthophoto_wms_512.tif`, bron `manual`;
|
||||
- tile `/app/storage/tiles/cb80638d-dbef-48ac-b19c-cec7c3efc96e/ae0ff76d-70c0-404f-b777-54d14517179a/b191c968-7d56-4e0d-afbb-8b5baaa62470/tile_0000.tif`;
|
||||
- creatietijd 6 juli 2026 en class `building`.
|
||||
|
||||
Dit zijn aantoonbaar buiten-domeindetecties; de collector markeerde de sectie desondanks generiek als `status: ok`, zodat consumenten de detailtellingen moeten gebruiken. De huidige `detection_georeferencing.py` bevat wel een pyproj-transformatie naar EPSG:4326; op basis van deze audit kan niet worden bewezen via welke historische codeversie de vier rijen ontstonden. Ze mogen niet in QA, kaarten of exports blijven zonder quarantaine/herberekening.
|
||||
|
||||
### 6.3 Scopebinding
|
||||
|
||||
`detection_service.py:223-232` laat configured YOLO alleen toe wanneer één van `Mol,Kempen` als substring in de muteerbare `Area.name` voorkomt. Een area met naam `Mol validation bypass` en een geometrie buiten de gevalideerde zone werd in de reproductie geaccepteerd. De model-toepassingsscope heeft daardoor geen onveranderlijke geometrische lineage.
|
||||
|
||||
## 7. QA/QC-, review- en exportlineage
|
||||
|
||||
Tower bevat 697 quality checks en 4.182 metrics. De metricgapquery toont:
|
||||
|
||||
| Metric | total checks | null |
|
||||
|---|---:|---:|
|
||||
| precision | 697 | 58 |
|
||||
| recall | 697 | 1 |
|
||||
| F1 | 697 | 58 |
|
||||
| mean IoU | 697 | 90 |
|
||||
| false positives | 697 | 0 |
|
||||
| false negatives | 697 | 0 |
|
||||
|
||||
De golden fixturebenchmark koppelt kandidaat/referentie, QualityCheck en zes metrics correct in-memory. Bij het no-overlapscenario zijn precision en recall `0`, maar F1 en mean IoU `null`. Zolang het API-/metriccontract niet expliciet vastlegt of F1 daar `0` of “undefined” hoort te zijn, kunnen aggregaties dezelfde run verschillend behandelen.
|
||||
|
||||
Er staan 0 `detection_reviews` in de productiedatabase. De aanwezigheid van review-UI, contact sheets of reviewtabellen bewijst dus geen uitgevoerde menselijke productiereview. De 768 exportrecords verwijzen naar concrete storagepaden; dat bewijst artifactpersistentie, niet dat upstream geometrie/model/QA correct was.
|
||||
|
||||
## 8. Trainings- en corpuslineage
|
||||
|
||||
### 8.1 Bewezen v56-keten
|
||||
|
||||
De retained snapshot telt in totaal 26 modelassets, 229 trainingscheckpoints (28.512.052.142 bytes), 424 JSON-trainingsrapporten en 36 operator-manifests. Die inventarisclaim zegt niets over menselijke acceptatie of releasekwaliteit.
|
||||
|
||||
Het canonieke v56-manifest is `/app/storage/operator-data/building-be-v56-hard-negative-instance-roofs-r1/operator_samples_manifest.json`, 212.185 bytes, SHA-256 `27a9b09f184bb9a0cc4897f1cfab7f1e953af5715c1b97a5ec1a7b80a2d270f1`. De corpusaudit `/app/storage/training/building-be-v56-corpus-audit-r1/belgium-building-corpus-audit.json` (SHA-256 `cbb9802aec1b780b306318fc172e470d29166574e9bf13d28e3107ae42f4d63c`) rapporteert:
|
||||
|
||||
- datasetversie `building-be-v56-hard-negative-instance-roofs-r1`, immutable manifest;
|
||||
- 180 AOI-samples: Vlaanderen 89 train/2 val/3 calibration/3 test/2 background-test; Wallonië 43/2/3/3/2; Brussel 18/2/3/3/2;
|
||||
- 132 positieve samples en 48 `background_candidate`-samples;
|
||||
- 31.452 inputfeatures, 30.662 geaccepteerd, 326 onder resolveerbare pixelgrootte en 464 na de beeldperiode;
|
||||
- automated `spatial_leakage_status=ok` en 0 temporal-unknown samples;
|
||||
- `status=needs_human_review`, `reviewed_sample_count=0`, `review_complete=false`, alle 180 in de reviewqueue.
|
||||
|
||||
Van de zes `background-test`-AOI's zijn er slechts drie aantoonbaar puur leeg: twee in Vlaanderen, één in Wallonië en nul in Brussel. De andere drie bevatten respectievelijk 2, 107 en 141 referentiefeatures en zijn moeilijke negatieven, geen pure backgrounds. Dit is te weinig om een regionale pure-background false-positiveclaim te dragen.
|
||||
|
||||
De bounded duplicaatscreen vond 0 exacte cross-split rasterhashduplicates en 0 hergebruikte raster-dataset-id's. Voor 4.833 cross-split dHash-paren was de minimum-Hammingafstand 17 en waren er geen paren op of onder 4. Dat sluit semantische, instance-level of flight-stripduplicatie niet uit. De AOI-bboxscreen vond een minimale cross-splitafstand van 95,7203 meter tussen `anderlecht-industry-train` en `jette-test`, 24 paren onder 2 km en 0 onder 64 meter. De auditstatus `ok` is daarom niet voldoende voor de strengere onafhankelijkheidseis; nabijheid is een risico dat instance-/imagerylineage vereist, geen bewijs op zichzelf van leakage.
|
||||
|
||||
De tile-qualityaudit `/app/storage/training/building-be-v56-rotated-quality-audit-r1/operator_yolo_dataset_quality_audit.json` (SHA-256 `da0d4648ee2365ab949f1b00518ddba0a17cb722a41cb228525b4d2e7657ce36`) rapporteert geautomatiseerd `status=ok`, 2.496 tiles, 60.229 labels, 0 ongeldige/missende labelfiles, 2.072 positieve en 424 negatieve tiles, waarvan 411 negatieve trainingtiles. Dat syntactische bewijs vervangt de ontbrekende menselijke semantische review niet.
|
||||
|
||||
De v58/v62-calibratierapporten verwijzen naar een afgeleide root `/app/storage/operator-data/building-be-v56-hard-negative-rotated-holdouts-r1`. Een releasebundel moet de transformatie van het canonieke instance-roofs-manifest naar deze rotated-holdouts-dataset expliciet, gehasht en reproduceerbaar vastleggen.
|
||||
|
||||
### 8.2 Bewezen v58/v62-preview, niet gepromoveerd
|
||||
|
||||
V58 `/app/storage/training/building-be-v58-v56-clean-pretrained-r1/preview-epoch-015/calibration.json` (SHA-256 `60538573a734d91107e25fb2a8a640ce45d90c482acfb65ed7110ff884f2f4c7`) en v62 `/app/storage/training/building-be-v62-v58-flanders-balanced-transfer-r1/preview-epoch-006/calibration-routed.json` (SHA-256 `05d8c8f0ade55907e37668758ac225aeff60cbb45604de662944fa447f6d590f`) zijn beide 144-tile, `split=val`, IoU-0,5 calibratiepreviews met 13 thresholds. Ze zijn geen protected-test-, unieke-gebouwen- of nationale releaseresultaten.
|
||||
|
||||
Bij threshold 0,15 rapporteren beide artifacts aggregate F1 0,512905, precision 0,545647 en recall 0,483871, maar Vlaanderen heeft true positives 0, recall 0 en F1 0. Bij threshold 0,02 heeft v58 aggregate F1 0,240667 en Vlaanderen F1 0,080402/recall 0,103380; v62 heeft aggregate F1 0,208283 en Vlaanderen F1 0,067111/recall 0,275348. Geen van deze observaties voldoet aan een geloofwaardige drie-regio-gate.
|
||||
|
||||
De v62-checkpointhash `889ee5…` verschilt van de actieve productiemodelhash `a9088b…`; de v62-run is dus niet het actieve model.
|
||||
|
||||
### 8.3 V66 is een gerichte trial
|
||||
|
||||
Het immutable manifest `/app/storage/operator-data/building-be-v66-lowrise-temporal-r1/operator_samples_manifest.json` (SHA-256 `d861da48aca40121e158e6ab243a6ccbe53e14d500a186af64b620f612935b07`) bevat drie positieve Vlaamse trainingssamples, nul andere splits/regio's en nul background-test-samples. Het kan v56 niet als nationale corpusbaseline vervangen.
|
||||
|
||||
### 8.4 Protected-testleakage in de loop
|
||||
|
||||
`scripts/run_belgium_building_training_loop.py:417-449` opent test en background nadat calibration slaagt. Wanneer de volledige assessment niet `training_complete` is, wordt die assessment op regels 477-498 als input gebruikt voor de volgende failure-driven trainingsset. `scripts/build_failure_driven_yolo_sampling.py:98-120` kiest expliciet `assessment.get("test") or assessment.get("calibration")` en gebruikt ook background-failures; regels 130-201 sturen vervolgens regionale/contextuele repeats van trainingtiles.
|
||||
|
||||
De sampler neemt geen protected tiles zelf op, maar de protected-testuitkomsten beïnvloeden wél de volgende trainingsverdeling. Daarmee is de testset een tuningbron geworden en kan zij niet langer als onafhankelijke, eenmalige protected test voor de uiteindelijke kandidaat gelden.
|
||||
|
||||
## 9. Lineagebreuken die Phase 2 moeten blokkeren
|
||||
|
||||
| ID | Breuk | Bewijs | Gevolg |
|
||||
|---|---|---|---|
|
||||
| LIN-01 | caller-controlled bronautoriteit | uploadvelden + coverage-reproductie | “officieel/operationeel” kan vals zijn |
|
||||
| LIN-02 | cross-theme coverage-union | `coverage_registry_service.py:481-504` | kleine juiste laag kan volledige dekking erven van verkeerde laag |
|
||||
| LIN-03 | niet-4326 import als SRID 4326 | `geojson_service.py` versus `_feature_row` | geometrie kan valide lijken maar ruimtelijk betekenisloos zijn |
|
||||
| LIN-04 | meters als graden bij buffer | 100 m-reproductie | extreme, foutieve derived geometrieën |
|
||||
| LIN-05 | derived artifact zonder querybare features/run | `persist_vector_features=False` | UI/artifact en PostGIS geven verschillende waarheid |
|
||||
| LIN-06 | modelscope via naamsubstring | area-name-reproductie | inference buiten gevalideerde scope mogelijk |
|
||||
| LIN-07 | lege modelversie bij 1.146 runs; 3 zonder modelhash; 1.146 zonder tile-manifest-SHA/runtime/seed | Tower-runtime-snapshot | historische run niet volledig reproduceerbaar; drie runs niet sluitend aan checkpoint te koppelen |
|
||||
| LIN-08 | vier Lambert-detecties als SRID 4326 | gedetailleerde DB-snapshot | kaart, QA en export kunnen corrupte geometrie consumeren |
|
||||
| LIN-09 | 0 menselijke productiereviews | `detection_reviews=0` | geen bewijs van representatieve operatoracceptatie |
|
||||
| LIN-10 | v56 human review 0/180 | corpusaudit | label-/tijd-/contextkwaliteit niet semantisch vrijgegeven |
|
||||
| LIN-11 | slechts 3 pure-empty backgrounds; 24 cross-split AOI-paren onder 2 km | retained v56-manifestanalyse | regionale background- en onafhankelijkheidsclaims zijn niet vrijgegeven |
|
||||
| LIN-12 | v66 bevat alleen 3 Vlaamse training-AOI's | retained v66-manifest | gerichte trial mag niet als nationale opvolger worden behandeld |
|
||||
| LIN-13 | protected test stuurt retraining | trainingloop + sampler | evaluatieleakage; releaseclaim ongeldig |
|
||||
|
||||
## 10. Reproduceerbare controles
|
||||
|
||||
Lokale evidence opnieuw opbouwen:
|
||||
|
||||
```powershell
|
||||
cd C:\Projects\geointel
|
||||
python scripts\run_accuracy_phase1_baseline.py --output-dir artifacts\evidence\accuracy\P1
|
||||
$env:PYTHONPATH = "$(Resolve-Path backend);$(Resolve-Path .)"
|
||||
python scripts\run_golden_qa_benchmark.py --json
|
||||
```
|
||||
|
||||
Tower-artifactidentiteit read-only controleren:
|
||||
|
||||
```bash
|
||||
sha256sum \
|
||||
/mnt/user/appdata/geointel/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt \
|
||||
/mnt/user/appdata/geointel/storage/operator-data/building-be-v56-hard-negative-instance-roofs-r1/operator_samples_manifest.json \
|
||||
/mnt/user/appdata/geointel/storage/training/building-be-v56-corpus-audit-r1/belgium-building-corpus-audit.json \
|
||||
/mnt/user/appdata/geointel/storage/training/building-be-v62-v58-flanders-balanced-transfer-r1/preview-epoch-006/calibration-routed.json
|
||||
```
|
||||
|
||||
De runtimecollector is read-only en gebruikt een SQL-statementtimeout van 30 seconden. Een toekomstige releasegate moet dezelfde queries uitvoeren én detailtellingen laten falen; een generiek `status=ok` mag vier buiten-domeinrecords niet maskeren.
|
||||
@@ -1,229 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — 03 Baseline en gaps
|
||||
|
||||
## 1. Phase-1-oordeel
|
||||
|
||||
De technische foundation draait: frontend, API, PostGIS, jobs, datasetopslag, een echte Ultralytics/PyTorch-adapter en NVIDIA CUDA-inference zijn aantoonbaar operationeel. De accuracy-/releasebaseline is echter rood. Er is geen bewijs voor nationale gebouwdetectiekwaliteit, geen complete menselijke corpusreview, geen onafhankelijke protected-testcyclus en geen sluitende modelhash-per-run-lineage. Zeven kritieke/hoge correctheidsproblemen zijn deterministisch gereproduceerd en de canonieke backend-releasegate is niet groen.
|
||||
|
||||
Daarom gelden op 1 augustus 2026 de volgende harde uitspraken:
|
||||
|
||||
- “GeoIntel kan één bestaande tile met het actieve model op de RTX 4080 SUPER verwerken” is bewezen.
|
||||
- “GeoIntel is 100% getraind”, “nationaal gevalideerd”, “productie-accurate” of “release ready” is niet bewezen en mag niet worden geclaimd.
|
||||
- De bestaande v56/v58/v62/v66-artefacten zijn diagnostische/trainingsevidence; geen daarvan vormt een geldige nationale promotiebundel.
|
||||
- Phase 2 mag remediëren en nieuwe evidence opbouwen, maar mag de protected test pas opnieuw bevriezen nadat de leakage-, corpus- en lineageproblemen zijn opgelost.
|
||||
|
||||
## 2. Reproduceerbare softwarebaseline
|
||||
|
||||
Alle hieronder genoemde logs zijn retained onder `C:\Projects\geointel\artifacts\evidence\accuracy\P1`.
|
||||
|
||||
| Check | Exact commando | Uitkomst | Evidence |
|
||||
|---|---|---|---|
|
||||
| volledige backendtestset vanuit repo-root | `python -m pytest backend/tests -q -p no:cacheprovider -W error::DeprecationWarning --junitxml=artifacts/evidence/accuracy/P1/backend-full-suite.junit.xml` | **fail**: 1.180 passed, 17 failed, 70,63 s | `backend-full-suite.txt`, `backend-full-suite.junit.xml` |
|
||||
| canonieke CI/backend-entrypoint | vanuit `backend`: `python -m pytest -W error::DeprecationWarning` | **collection fail**: 1.194 items verzameld plus importerror `scripts.render_operator_polygon_label_qa` | `backend-ci-entrypoint.txt` |
|
||||
| Phase-1 collectortests | `python -m pytest tests/test_accuracy_phase1_baseline.py -q -p no:cacheprovider` | **pass**: 4/4 | `phase1-tooling-tests.txt` |
|
||||
| frontend unit | vanuit `frontend`: `npm run test:unit` | **pass**: 16 files, 51 tests | `frontend-vitest-unit.txt` |
|
||||
| generiek frontendtestcommando | `npm test -- --run` | **fail**: script `test` ontbreekt | `frontend-vitest.txt` |
|
||||
| frontend typecheck | `npm run typecheck` | **pass** | `frontend-typecheck.txt` |
|
||||
| frontend build | `npm run build` | **pass**: 1.896 modules; Vite-build voltooid | `frontend-build.txt` |
|
||||
| frontend lint | `npm run lint` | **fail**: script `lint` ontbreekt | `frontend-lint.txt` |
|
||||
| Python lintbaseline | `python -m ruff check backend scripts tests --output-format json` | **fail**: 112 findings | `repository-ruff-baseline.json`, `.txt` |
|
||||
| Alembic head | vanuit `backend`: `python -m alembic heads` | **pass**: één head `202607260001` | `alembic-heads.txt` |
|
||||
| volledige offline migratieketen | `python -m alembic upgrade head --sql` | **pass**: alle 11 migraties renderen tot commit | `alembic-offline-upgrade.sql` |
|
||||
| API-contractaudit | `python scripts/audit_api_contracts.py` | **pass**: 147 routes; 10 expliciete non-envelope endpoints | `openapi-contract-audit.txt` |
|
||||
|
||||
De 112 Ruff-bevindingen zijn: E402 13, E701 2, E702 69, F401 23, F403 1, F811 2 en F841 2. De nieuw toegevoegde Phase-1-audittools waren in de afzonderlijke check Ruff-clean; de telling is repositorybreed.
|
||||
|
||||
De 17 backendtestfailures zijn bron-/contractasserties tegen frontend-, README- en deployteksten/implementatiedetails. Dat maakt ze niet automatisch onbelangrijk of “alleen stale”: de verwachte automatische model/theme-selectie is bijvoorbeeld doelbewust gewijzigd naar gebruikersselectie, terwijl tests nog het oude contract eisen. Test en actueel productcontract moeten expliciet worden gereconcilieerd. Tot dat gebeurt is de releasegate rood.
|
||||
|
||||
De CI-entrypointfout heeft een afzonderlijke oorzaak: vanuit `backend` resolveert `scripts` naar `backend/scripts`, waardoor de rootmodule `scripts/render_operator_polygon_label_qa.py` niet importeerbaar is. Een root-run met expliciet importpad kan de tests wel verzamelen, maar repareert de feitelijke CI-opdracht niet.
|
||||
|
||||
## 3. Wat de huidige readinessgate niet uitvoert
|
||||
|
||||
`scripts/run_readiness_check.sh` compileert veel Python en draait backendtests, Alembic head, frontend unit/typecheck/build. De volgende checks zijn daar slechts syntaxcontroles:
|
||||
|
||||
- `node --check` voor de twee frontend-E2E-scripts;
|
||||
- `bash -n` voor live migration, deploy, upgrade/fresh-install, browserruntime, demo, real-data detection/QA, calibratie, training en cleanupflows.
|
||||
|
||||
De gate voert dus geen volledige browserjourney, live PostGIS-migratie, externe provideracquisitie, echte CUDA-modelinference, protected-test-evaluatie of AI-imagebuild uit. De GitHub-/Gitea-build installeert standaard geen AI-dependencies. Een groene toekomstige unit/readinessgate blijft daarom onvoldoende zonder afzonderlijke live-, data- en modelgates.
|
||||
|
||||
## 4. Golden QA/QC-baseline
|
||||
|
||||
`python scripts/run_golden_qa_benchmark.py --json` slaagde twee keer semantisch met vier fixture-scenario's:
|
||||
|
||||
| Scenario | Precision | Recall | F1 | Mean IoU | FP | FN |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| partial match | 0,5 | 0,5 | 0,5 | 0,833976834 | 1 | 1 |
|
||||
| perfect match | 1 | 1 | 1 | 1 | 0 | 0 |
|
||||
| no overlap | 0 | 0 | `null` | `null` | 1 | 1 |
|
||||
| exact MultiPolygon | 1 | 1 | 1 | 1 | 0 | 0 |
|
||||
|
||||
De twee retained JSON-runs zijn niet byte-identiek: SHA-256 `ec96862b…` tegenover `4f900711…`. De semantische resultaten zijn gelijk; UUID4-gegenereerde project/dataset/quality-check-id's maken de output nondeterministisch. Voor een reproduceerbare benchmarkbundel moeten ids deterministisch zijn of vóór hashing worden genormaliseerd.
|
||||
|
||||
Het no-overlapscenario legt daarnaast een metriccontractgap bloot: precision en recall zijn 0, maar F1 is `null`. Dit kan wiskundig als undefined worden verdedigd, maar aggregators en releasegates moeten één expliciete semantiek hanteren. De Tower-database bevestigt bredere nullvariatie: 58/697 F1, 58/697 precision, 1/697 recall en 90/697 mean IoU zijn null.
|
||||
|
||||
De golden benchmark gebruikt kleine checked-in fixtures. Hij bewijst rekenkundige regressiestabiliteit, niet de nauwkeurigheid van het actieve model op Belgische luchtbeelden.
|
||||
|
||||
## 5. Runtime-, database- en GPU-baseline
|
||||
|
||||
### 5.1 GPU-smoke
|
||||
|
||||
De retained smoke gebruikte het actieve model:
|
||||
|
||||
- model `/app/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt`;
|
||||
- SHA-256 `a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1`;
|
||||
- één 512×512 RGB-tile in EPSG:31370, tile-SHA `134a9e86850c92c577c73bc6ee57a9df7d4c1c513ae6450263e800b6dd47b6ee`;
|
||||
- manifest-SHA `6ab8a96bf2a1405e224932afb90255311a09bbeaed4e9a2fdcdf8b1bc2230abd`;
|
||||
- PyTorch `2.11.0+cu128`, Ultralytics `8.4.99`, NVIDIA GeForce RTX 4080 SUPER;
|
||||
- seed `20260801`, deterministische algoritmen, `imgsz=640`, confidence 0,5, `max_det=1000`;
|
||||
- 17 raw `building`-detecties; inference 0,8837 s, totale model-load plus inference 1,3689 s.
|
||||
|
||||
Deze smoke is read-only en passeert. Hij toetst één tile en schrijft geen AnalysisRun/Detection/QA/Export. Hij levert daarom geen accuracy-, calibratie-, georeference-persistence-, schaal- of generalisatieclaim.
|
||||
|
||||
### 5.2 Databaseintegriteit
|
||||
|
||||
Positieve baseline:
|
||||
|
||||
- runtime Alembic-head `202607260001`;
|
||||
- 3.377 datasets en 1.671 versies hebben checksums en source/provenance-metadata;
|
||||
- 5.816 directe dataset/version/export-storagepaden gecontroleerd, 0 ontbrekend;
|
||||
- 387 area- en 6.689.447 vectorfeaturegeometrieën: 0 leeg, 0 ongeldig, 0 wrong-SRID, 0 buiten EPSG:4326-domein in de gebonden query;
|
||||
- 299.233 detection-confidences: 0 buiten `[0,1]`.
|
||||
|
||||
Negatieve baseline:
|
||||
|
||||
- 2.377/3.377 datasets zonder `observed_at` en 1.761/3.377 zonder `source_version`; eerst per bronfamilie classificeren, niet blind invullen;
|
||||
- vier detectiegeometrieën hebben SRID 4326 maar numerieke Lambertcoördinaten rond X 193k/Y 206k;
|
||||
- alle 1.146 modelruns hebben een lege modelversie; 1.143 bewaren een modelassethash, drie niet; alle 1.146 missen tile-manifest-SHA, runtime/hardware en seed;
|
||||
- 0 segmentaties en 0 detection reviews;
|
||||
- 135/4.460 jobs en 2/1.146 analysis runs hebben status failed;
|
||||
- PostGIS 3.6.4 meldt dat core/topology procedures uit 3.4.3 een upgrade nodig hebben.
|
||||
|
||||
De storagecheck dekt alleen directe DB-referenties. De volledige recursieve storageaudit eindigde in een time-out en is geen pass; daarmee is niet bewezen dat alle niet-gerefereerde caches, trainingoutputs of orphan artifacts bekend zijn.
|
||||
|
||||
## 6. Deterministisch gereproduceerde productfouten
|
||||
|
||||
`forensic-reproductions.json` bevat zeven read-only, deterministische reproducties; alle zeven zijn opnieuw waargenomen.
|
||||
|
||||
| ID | Ernst | Geobserveerd | Waarom blokkerend |
|
||||
|---|---|---|---|
|
||||
| P1-COV-001 | critical | een kleine buildings-partitie wordt `fully_covered=true` doordat een roads-bbox in dezelfde bounded union zit | coverage- en beschikbaarheidsclaims kunnen inhoudelijk fout zijn |
|
||||
| P1-CRS-001 | critical | 100 “meter” buffer levert bounds `[-95,-49,105,151]`, 200 graden lengtespan | units/CRS worden verwisseld; derived geometrie is onbruikbaar |
|
||||
| P1-CRS-002 | critical | EPSG:31370-coördinaten `(150000,210000)` worden ongewijzigd met SRID 4326 opgebouwd | valide SRID-label maskeert verkeerde werkelijkheid |
|
||||
| P1-AUTH-001 | critical | caller-controlled upload `source_name=grb` wordt `operational`/`authoritative` | gebruikersmetadata kan officiële bronautoriteit spoofen |
|
||||
| P1-AI-001 | critical | area `Mol validation bypass` met geometrie in Noord-Amerika passeert modelscope | model draait buiten de gevalideerde geografie |
|
||||
| P1-COV-002 | high | dezelfde Vlaamse geometrie werkt als naam `Flanders`, maar wordt `outside=true` na rename naar `Vlaanderen` | wettelijke scope hangt van een muteerbare displaynaam af |
|
||||
| P1-API-001 | high | Area PATCH accepteert payload met geometry maar negeert die stil | contract en opgeslagen AOI lopen uiteen |
|
||||
|
||||
Aanvullende statisch bewezen risico's staan nog buiten deze zeven reproductions:
|
||||
|
||||
- clip/buffer/intersect roepen `_persist_derived_dataset` standaard aan met `persist_vector_features=False`; een `ready` derived artifact hoeft dus niet PostGIS-querybaar te zijn;
|
||||
- meerdere services slikken secundaire fouten of vallen stil terug, onder meer projectdetailbootstrap en cached rasterpreview; fallback moet expliciete status/provenance krijgen;
|
||||
- het tracked mirror `geointel/` bevat 1.153 bestanden, waarvan 68 van de rootversie verschillen; Docker sluit de mirror uit, lokale tools niet noodzakelijk.
|
||||
|
||||
## 7. Corpus-, split- en trainingbaseline
|
||||
|
||||
### 7.1 Inventaris is geen kwaliteit
|
||||
|
||||
Tower bevat 26 modelassets, 229 trainingscheckpoints (28.512.052.142 bytes), 424 JSON-trainingsrapporten en 36 operator-manifests. De aantallen tonen veel experimenten, niet dat de beste kandidaat is gevonden of geldig vrijgegeven.
|
||||
|
||||
### 7.2 V56 is de breedste aangetroffen corpusbasis, maar niet vrijgegeven
|
||||
|
||||
De retained v56-evidence toont:
|
||||
|
||||
- 180 AOI's over Vlaanderen, Wallonië en Brussel;
|
||||
- immutable manifest, 0 exacte cross-split rasterhashduplicates en 0 cross-split raster-dataset-id-duplicates;
|
||||
- dHash-screen over 4.833 cross-split paren: minimumafstand 17, geen paren op/onder 4;
|
||||
- bbox-afstandscreen: minimum 95,7203 m en 24 cross-split paren onder 2 km;
|
||||
- 31.452 inputfeatures; 30.662 geaccepteerd, 326 onder pixel-resolutie, 464 na de imageryperiode;
|
||||
- automated corpusstatus `needs_human_review`; 0/180 gereviewd, alle 180 pending;
|
||||
- 48 background candidates, maar slechts drie pure-empty background-test-AOI's: Vlaanderen 2, Wallonië 1, Brussel 0;
|
||||
- de drie overige background-test-AOI's bevatten 2, 107 en 141 referentiefeatures en zijn moeilijke negatieven.
|
||||
|
||||
De exact-hash- en dHashscreen zijn positief maar begrensd. Ze bewijzen geen gebouw-instance-, gemeente-, vluchtstrook-, seizoen- of bronopname-onafhankelijkheid. De 95,7-meter train/testnabijheid en 24 paren onder 2 km vereisen expliciete imagery-/instance-audits voordat een protected split wordt geaccepteerd.
|
||||
|
||||
De automated tile-qualityaudit meldt 2.496 tiles, 60.229 geldige labels, 0 invalid/missing labels, 2.072 positieve en 424 negatieve tiles. Dat valideert syntax en enkele pixelregels, niet of daken correct, volledig, tijdsconform of contextueel representatief zijn. Contact sheets bestaan, maar menselijke acceptatiebeslissingen ontbreken.
|
||||
|
||||
### 7.3 V58/V62 halen geen regionale gate
|
||||
|
||||
V58 en v62 hebben alleen 144-tile `val`/calibratiebewijs met IoU 0,5 en 13 confidence-sweeps. Bij threshold 0,15 rapporteren beide aggregate F1 0,512905, precision 0,545647 en recall 0,483871, terwijl Vlaanderen 0 true positives, recall 0 en F1 0 heeft. Bij threshold 0,02 blijft Vlaanderen zwak: v58 F1 0,080402/recall 0,103380; v62 F1 0,067111/recall 0,275348. Dit is geen protected test en geen nationale releaseprestatie.
|
||||
|
||||
V62 `best.pt` bestaat, maar de hash `889ee5…` is niet de actieve productiemodelhash `a9088b…`. Er is geen geldige promotie aangetoond.
|
||||
|
||||
### 7.4 V66 is geen nationale opvolger
|
||||
|
||||
Het v66-manifest heeft slechts drie positieve Vlaamse `train`-AOI's in twee low-rise-contexten, zonder val/calibration/test/background en zonder Wallonië/Brussel. Het is een gerichte trial.
|
||||
|
||||
### 7.5 Protected-testleakage
|
||||
|
||||
De trainingloop opent na een geslaagde calibration zowel test als background. Als de kandidaat vervolgens faalt, geeft de loop de volledige assessment aan de failure-driven sampler. Die kiest `assessment.get("test") or assessment.get("calibration")`, gebruikt regionale testmetrics en background-failures en verandert daarmee repeats van trainingtiles voor de volgende iteratie. Protected tiles worden niet letterlijk opgenomen, maar hun uitkomsten sturen training. De huidige testset is dus voor die loop niet langer onafhankelijk en moet na de correctie worden vervangen of aantoonbaar nooit eerder ingezien zijn.
|
||||
|
||||
## 8. Claim-matrix
|
||||
|
||||
| Claim | Status | Maximaal verdedigbare formulering |
|
||||
|---|---|---|
|
||||
| platform draait technisch | ondersteund | gezonde Tower-container, echte PostGIS-data en uitvoerbare frontend/API |
|
||||
| NVIDIA/PyTorch wordt gebruikt | ondersteund | één actieve YOLO-adaptercall draaide op RTX 4080 SUPER/CUDA 12.8 |
|
||||
| volledige inferenceketen is correct | niet ondersteund | smoke sloeg persistence/georeference/QA/export over; vier historische geometrieën zijn corrupt |
|
||||
| actief model is reproduceerbaar | gedeeltelijk | actief bestand heeft SHA; historische runs missen volledige manifest/runtime-lineage en drie runs missen ook de modelassethash |
|
||||
| labels zijn correct | niet ondersteund | automated syntax ok, maar v56 menselijke review 0/180 |
|
||||
| splits zijn onafhankelijk | niet ondersteund | exact/dHashscreen positief, maar nabijheid onbeslist en testuitkomsten sturen retraining |
|
||||
| building accuracy voor Mol/Kempen | niet vastgesteld in Phase 1 | er is geen retained protected Mol/Kempen-releasebenchmark voor actieve hash |
|
||||
| building accuracy voor heel België | weerlegd als actuele releaseclaim | v58/v62 calibration heeft bij bruikbare aggregate threshold Vlaanderen recall/F1 0 |
|
||||
| pure-backgroundrobustheid per regio | niet ondersteund | slechts 3 pure-empty AOI's, geen in Brussel |
|
||||
| productie-segmentatie | niet ondersteund | abstraction/fixture aanwezig, 0 runtime segmentaties |
|
||||
| officiële bronnen zijn authentiek | niet ondersteund | source identity kan via uploadmetadata worden gespooft |
|
||||
| databasegeometrieën zijn integraal | gedeeltelijk | areas/vectorfeatures schoon in gebonden query; 4 detecties buiten domein |
|
||||
| release ready | nee | backend/CI/lint rood plus kritieke data-/GIS-/ML-blockers |
|
||||
|
||||
## 9. Geprioriteerde gaps
|
||||
|
||||
### P0 — vóór nieuwe modeltraining of productclaim
|
||||
|
||||
1. Fix en regressietest de zeven gereproduceerde contract-/CRS-/scope-/authorityfouten; maak coverage unions themaspecifiek, source authority server-attested en modelscope geometrisch/checksumgebonden.
|
||||
2. Quarantaineer de vier buiten-domeindetecties, identificeer hun producerende code/image/model, herbereken of verwijder ze via een gecontroleerde migratie en laat detailtellingen de gate falen.
|
||||
3. Maak vector- en detectie-CRS-transformaties expliciet; verbied SRID relabeling; voer metric buffers in een geschikte lokale CRS uit; persisteer derived features en runlineage atomisch.
|
||||
4. Verwijder test/background uit failure-driven sampling en checkpointpromotie. Bevries daarna een nieuwe, ongeziene protected test met hashes en éénmalige-openingspolicy.
|
||||
5. Voer menselijke review uit op alle 180 v56-AOI's met beslissingen, reviewer, timestamp, label-/beeldversie en reden; herbouw contact sheets wanneer bron of label verandert.
|
||||
6. Voeg onafhankelijke AOI's en pure-empty backgrounds toe per regio/context, in het bijzonder Brussel; audit de 24 cross-split paren onder 2 km op imagery-, vluchtstrook- en instance-overlap.
|
||||
7. Herzie image/label time deltas, vooral de 464 uitgesloten features en dichte PICC/UrbIS-zones; definieer regels voor onzekere/occluded/nieuwe/verdwenen gebouwen.
|
||||
8. Koppel iedere training, inference-run, detection, QA en export aan model-SHA, datasetmanifest-SHA, codecommit, containerdigest, seed, parameters en dependency lock.
|
||||
|
||||
### P1 — vóór releasecandidate
|
||||
|
||||
1. Maak de canonieke backend-CI-entrypoint verzamelbaar en reconcilieer de 17 contracttests met de actuele, handmatige modelselectie-UX.
|
||||
2. Voeg Ruff en frontend lint toe aan de readinessgate; werk de 112 bestaande bevindingen gecontroleerd weg.
|
||||
3. Bouw en test de echte AI/CUDA-image in CI; pin PyTorch/torchvision/Ultralytics en leg image digest/SBOM vast; hef cu128/cu130-drift op.
|
||||
4. Draai echte browser-E2E, live PostGIS upgrade/fresh-install, externe-provider- en full inference/persistence/QA/exportjourneys.
|
||||
5. Definieer null-/zero-/undefinedsemantiek voor precision, recall, F1 en IoU; maak golden outputs byte-reproduceerbaar of canonicaliseer ids.
|
||||
6. Classificeer de 2.377 missende observatietijden en 1.761 missende bronversies per broncontract en maak onverklaarde gevallen fail-closed.
|
||||
7. Verwijder bronambiguïteit door de tracked `geointel/`-mirror gecontroleerd te migreren; niet in Phase 1 destructief opruimen.
|
||||
|
||||
## 10. Wanneer Phase 2 veilig kan trainen
|
||||
|
||||
Nieuwe GPU-training is pas zinvol nadat de P0-datacontracten, human review en splitpolicy zijn opgelost. Anders optimaliseert een nieuwe run opnieuw tegen mogelijk foutieve labels, onvoldoende negatives en een gecontamineerde testlus. De veilige volgorde is:
|
||||
|
||||
`fix contracten -> nieuwe regressietests -> corpusbeslissingen -> onafhankelijke splits -> frozen manifests/hashes -> train/val/calibration -> kandidaatselectie -> éénmalige protected test -> onafhankelijke menselijke foutreview -> promotiebundel -> shadow deploy`.
|
||||
|
||||
Een trainingsloop mag itereren op train/validation/calibration. Hij mag de protected test niet opnieuw in de loop voeren. “100%” wordt niet als numerieke gate gebruikt; release vereist vooraf vastgelegde, context- en regiogebonden thresholds met confidence intervals, failure budgets en expliciete abstention/unsupported-statussen.
|
||||
|
||||
## 11. Evidence-integriteit
|
||||
|
||||
| Retained bestand | Bytes | SHA-256 |
|
||||
|---|---:|---|
|
||||
| `backend-full-suite.txt` | 23.972 | `8521ed48b17b382752418750b3ea374831958fb063e83ef87048212e0fd5ea69` |
|
||||
| `backend-ci-entrypoint.txt` | 1.601 | `0ac774ec19b4ff0a15142aab5f1db68c2592a230401d794ae7d040320e3ac0c0` |
|
||||
| `frontend-vitest-unit.txt` | 2.774 | `6341bfa51ca3f4fe5ec7d4af7239c3c5e1a29e6bfe8bdfae85e824a2a6482ad0` |
|
||||
| `frontend-typecheck.txt` | 163 | `3891c85c77b5ff50a1eb6d27a2a65d40c2c05423768734efd9d980f3784d68fa` |
|
||||
| `frontend-build.txt` | 2.356 | `c3b8e10ef177ac1c2dc045bd710df1caeb46f8922a721291be431b304abbc079` |
|
||||
| `frontend-lint.txt` | 418 | `1115b013515c753e2dfb73abdad9024aec7b4c2337d117c7e1181341fef15c7f` |
|
||||
| `repository-ruff-baseline.json` | 59.359 | `de6617f030e49550e714c49b6e14bf291bf85016fd58086e9ca38b33a52252e9` |
|
||||
| `alembic-heads.txt` | 116 | `da4521233c6718fc7a5865c53904e73685fbdce65a1449b19cd0dc2e40d037ed` |
|
||||
| `alembic-offline-upgrade.sql` | 20.199 | `e8905b881890cf95885a7515e3d9dcf2a7a0a24c4edbc57e98a363edcb22dd0e` |
|
||||
| `openapi-contract-audit.txt` | 212 | `5af3d8f00be3f57fc309bc198fa3995d1eae7270a5f210b3e94d1aeeb653119d` |
|
||||
| `forensic-reproductions.json` | 3.533 | `f6349199a15ae789092d3d65c17a39a9b32ea3ed557571c0c228c4be3cf7235e` |
|
||||
| `golden-qa-reproducibility.json` | 505 | `576e5667a989c34086db3a2bc57003115a8a61b14e9f49f5407ee380baf0829d` |
|
||||
| `phase1-tooling-tests.txt` | 250 | `a9bf261e1a811ad3e8bfa8edc439a11f00b46bc157f9ab6fc970033a87f45748` |
|
||||
| `tower-gpu-inference-smoke.json` | 5.675 | `692a9fa193d589123b042110d7e80755f0c6634854f3134c291fc6083adb7b77` |
|
||||
| `tower-runtime-database-snapshot-detailed.json` | 14.946 | `744389b6c384a9fb3a9e16e56f1477f3b752e11a5b98e1fad7df47b4703a9ca1` |
|
||||
| `tower-ml-data-lineage-snapshot.json` | 71.659 | `d80275e8198ce63366d2a2d44eb8fba1f27c29d85aaaaedb94991d8c56febfb6` |
|
||||
|
||||
Deze hashes zijn van de retained Phase-1-bestanden op het moment van documentgeneratie. Als evidence opnieuw wordt gegenereerd, moet een nieuwe evidence-manifestversie de nieuwe hash, producerende commandoregel, timestamp en reden bewaren; oude evidence wordt niet overschreven of als identiek voorgesteld.
|
||||
@@ -1,89 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — risicoregister
|
||||
|
||||
- Status: **release blocked**
|
||||
- Auditmoment: 2026-08-01
|
||||
- Scope: Belgium land en Belgische Noordzee, met de actieve building-detector beperkt tot zijn bewezen Mol/Kempen-scope
|
||||
|
||||
## Beslissing en claimgrens
|
||||
|
||||
GeoIntel mag op basis van de huidige evidence niet als nationaal gevalideerd AI-systeem worden vrijgegeven en de scope van de actieve detector mag niet worden verruimd. De productie-adapter heeft op de Tower één echte tile op `cuda:0` verwerkt, maar die smoke bewijst uitsluitend dat het model technisch kan laden en infereren. Hij bewijst geen nauwkeurigheid, calibratie of geografische generalisatie.
|
||||
|
||||
De volgende regels gelden totdat alle bijbehorende exit-evidence is vastgelegd:
|
||||
|
||||
- geen nationale kwaliteitsclaim voor building detection;
|
||||
- geen promotie van v56, v58, v62, v66 of een afgeleid checkpoint;
|
||||
- geen wijziging van de actieve modelscope op basis van bestandsaanwezigheid of aggregate metrics;
|
||||
- geen productieclaim voor segmentatie of zonnepaneeldetectie;
|
||||
- geen verwijdering of overschrijving van bestaande datasets, checkpoints, evaluaties of auditbewijzen;
|
||||
- elke herstelling begint met een regressietest die het bewezen defect op de oude implementatie reproduceert.
|
||||
|
||||
Ernstclassificatie:
|
||||
|
||||
- **Critical**: kan een plausibel maar ruimtelijk/inhoudelijk fout resultaat, een onterechte autoriteitsclaim of een besmet promotiebesluit veroorzaken;
|
||||
- **High**: blokkeert de nationale claim, reproduceerbaarheid of een betrouwbare releasebeslissing;
|
||||
- **Medium**: verzwakt assurance, onderhoudbaarheid of deploymentcontrole, maar is op zichzelf geen bewezen fout resultaat.
|
||||
|
||||
Alle risico's hieronder zijn open. Een controle telt pas als uitgevoerd wanneer de genoemde exit-evidence bestaat en door QA opnieuw is geverifieerd.
|
||||
|
||||
## A. Ruimtelijke juistheid en bronautoriteit
|
||||
|
||||
| ID | Ernst | Bewezen evidence | Impact | Owner | Vereiste controle | Exit-evidence |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| ACC-R01 | Critical | `geojson_service.py` behoudt bron-CRS-informatie, terwijl `vector_feature_service.py` geometrieën zonder transformatie als SRID 4326 schrijft. De runtime-snapshot vindt 4 detections met Belgische Lambert-coördinaten rond x=193k/y=205k maar SRID 4326; zie `artifacts/evidence/accuracy/P1/tower-runtime-database-snapshot-detailed.json`. | Verkeerde kaartpositie, ruimtelijke predicates, clipping, export en coverage; resultaten kunnen geldig ogen maar buiten het EPSG:4326-domein liggen. | GIS + Architecture | Eén expliciet CRS-ingestcontract; gekende CRS transformeren naar canoniek 4326, onbekende CRS fail-closed weigeren; bestaande vier records quarantainen of herleiden vanuit tile-transform en bron-CRS. | Unit- en PostGIS-integratietests voor EPSG:31370, EPSG:3812 en EPSG:4326; round-trip/extent-asserties; migratierapport met voor/na-ID's en zero `outside_epsg4326_domain`; geen stille datawijziging. |
|
||||
| ACC-R02 | Critical | `VectorOperationsService.buffer` voert `geometry.buffer(distance_m)` uit op ongetransformeerde GeoJSON. Een 100 m-reproductie nabij Mol levert een span van circa 200 graden. | Een meterparameter wordt als graden geïnterpreteerd; analysegebied en downstream-resultaten zijn materieel fout. | GIS | Bufferen in een geschikte metrische projectie/geography; bron- en doel-CRS en eenheden verplicht valideren; ongeschikte/ontbrekende CRS weigeren. | Regressietest met een gekend punt/polygoon in Mol en geodetische toleranties; API-test voor onbekende CRS; PostGIS/Shapely-pariteit; bewijs dat 100 m geen graadbuffer meer oplevert. |
|
||||
| ACC-R03 | Critical | `CoverageRegistryService._matching_datasets` voegt bbox-scopes toe vóór `layer_matches` en `zone_matches`. Een kleine buildingscope plus een volledige roadscope resulteert voor buildings ten onrechte in `fully_covered=true`. | Verkeerde bron/thema-combinaties kunnen als operationeel en volledig gedekt verschijnen. | Architecture + GIS | Alleen scopes van datasets die bron, thema, layer en zone volledig matchen in de union opnemen; coverage per bronversie en thema isoleren. | Regressietest voor mixed-theme/mixed-zone datasets; property-based tests voor monotoniciteit en bronisolatie; API-evidence dat de buildingscope in de reproductie `fully_covered=false` blijft. |
|
||||
| ACC-R04 | Critical | De uploadroute accepteert caller-controlled `source_name`, `reference_layer_name`, `source_metadata` en `provenance_metadata`; coverage vertrouwt deze velden. Een upload kan zich als GRB/authoritative voordoen. | Een handmatige upload kan de attributie, autoriteit en operationele dekking van een officiële bron erven. | Architecture + Data Governance | Server-owned source registry en trust class; user uploads altijd `manual/untrusted`; officiële identiteit uitsluitend via een governed acquisition adapter met immutable provider evidence; bestaande records classificeren. | Security/regressietest die een forged GRB-upload uitvoert en `manual/untrusted` verwacht; migratie-audit van bestaande bronnen; API-response toont bronvertrouwen en kan geen officiële attribution injecteren. |
|
||||
| ACC-R05 | High | Juridische coveragezones worden via mutable displaynamen (`SCOPE_AREA_NAMES`) bepaald. Dezelfde geometrie met `Flanders` versus `Vlaanderen` verandert de zonematch. | Een hernoeming kan scope/coverage juridisch en operationeel veranderen zonder geometrische wijziging. | Architecture + GIS | Immutable area/zone code en geometry-backed containment gebruiken; displaynaam uitsluitend presentatie; grensgevallen expliciet modelleren. | Rename-regressietest met identieke geometrie; zone-ID-migratie; grens- en Noordzee-tests; coverage-uitkomst blijft naam-onafhankelijk. |
|
||||
| ACC-R06 | Critical | De YOLO-validatiescope wordt afgedwongen via substringmatching op de mutable `Area.name`. Een gebied buiten Mol met naam `Mol validation bypass` wordt aanvaard. | Inferentie kan buiten de bewezen modelscope worden uitgevoerd en als ondersteund worden gepresenteerd. | AI + GIS + Architecture | Scope koppelen aan immutable geometry/zone-ID en model-card scope polygon; volledige containment/intersection-policy vastleggen; lege geometrie en naammatch nooit voldoende. | Negatieve API/service-tests voor spoofnaam, lege geometry en deels overlappende AOI; positieve Mol/Kempen-tests; scope-evidence bevat modelhash, scope-ID en spatial predicate. |
|
||||
| ACC-R07 | High | `Area` PATCH documenteert geometry-wijziging, maar het schema verwerkt enkel naam/CRS en negeert extra geometry; CRS kan los van de geometry worden herschreven. | API kan 200 retourneren zonder gevraagde geometry-update of coördinaten fout labelen. | Architecture + GIS | Extra velden verbieden; contract en implementatie gelijkmaken; CRS alleen wijzigen via gevalideerde transformatie, niet via relabeling. | Contracttest met geometry PATCH; unknown-field 422-test; CRS-transformtest; OpenAPI-contract en implementatie tonen hetzelfde gedrag. |
|
||||
| ACC-R08 | High | Clip/buffer/intersect roepen `_persist_derived_dataset` aan met `persist_vector_features=false`; een dataset kan `ready` zijn zonder querybare PostGIS-features, volledige provenance of atomaire AnalysisRun-koppeling. | Downstreamanalyse ziet een gereed artefact dat niet betrouwbaar querybaar/reproduceerbaar is; partial commits zijn mogelijk. | Architecture + GIS | Eén transactie voor AnalysisRun, DatasetVersion, vector_features en lineage; `processing` tot artifact én PostGIS-persist voltooid zijn; failure rollback/fail-closed. | Integratietests per operatie, inclusief geïnjecteerde write failure; zero ready-derived datasets zonder features; lineage-query van inputhash tot output; transactie-evidence. |
|
||||
|
||||
## B. Dataset-, split- en labelintegriteit
|
||||
|
||||
| ID | Ernst | Bewezen evidence | Impact | Owner | Vereiste controle | Exit-evidence |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| ACC-R09 | Critical | De training-orchestrator evalueert iedere iteratie op calibration, test en background. `build_failure_driven_yolo_sampling.py` gebruikt vervolgens `assessment.get("test")` bij het wegen van de volgende training en registreert test als failure source. | De protected test stuurt training; daardoor is hij geen onafhankelijke eenmalige release-evaluatie meer. | AI + QA | Orchestrator in twee fysiek/logisch gescheiden paden splitsen: iteratie mag alleen train/val/calibration lezen; test/background-test blijven verzegeld tot kandidaat, threshold en gates zijn bevroren. Sampler moet ieder testartefact of protected sample weigeren. | Canary-tests met protected IDs; file-access/auditlog bewijst nul testreads vóór freeze; sampler-test faalt op test-input; één gesigneerd test-open event voor exact één modelhash/config; geen verdere training in die candidate family na opening. |
|
||||
| ACC-R10 | High | V56 rapporteert een minimale cross-split AOI-afstand van 95,72 m en 24 cross-splitparen onder 2 km. Dat bewijst geen overlap, maar wel dat de vereiste buffer groter dan maximale tile-context nog niet is aangetoond. | Nabije context, dezelfde bebouwing of providerseams kunnen validatie/calibratie/test correleren met training. | GIS + AI + QA | Splittoewijzing op gebufferde AOI's vóór tiling; buffer afleiden uit tilecontext/resolutie; instance-, bronbeeld- en perceptuele near-duplicatecontrole. | Immutable split-audit met minimumafstand ≥ bevroren contextbuffer, zero intersecties, zero gedeelde feature-ID's/checksums/near-dupes en kaartbewijs per dichtste paar. |
|
||||
| ACC-R11 | High | Het v56 operator-manifest heeft 180 AOI's maar `reviewed=0/180`; de productie-DB telt 0 `detection_reviews`. | Labelkwaliteit en representatieve fouten zijn niet door menselijke beoordeling afgesloten; automatische audits kunnen semantische mislabels niet bewijzen. | QA + Data Governance | Gestratificeerde menselijke review van label-contact-sheets door regio, context, provider, objectgrootte, dichte en moeilijke gevallen; beslissingen als immutable records met reviewer, tijd en reden. | 100% van de vooraf geselecteerde reviewqueue beslist; zero unresolved critical/high label findings; manifest met review-ID's en hashes; inter-reviewer steekproef en getekende QA-beslissing. |
|
||||
| ACC-R12 | High | V56 bevat slechts 3 pure-empty background-test-AOI's (Flanders 2, Wallonia 1, Brussels 0). V66 bevat slechts 3 Vlaamse train-AOI's. | De achtergrond- en nationale claim is niet representatief voor alle regio's en contexten. | AI + GIS + QA | Nieuwe ruimtelijk onafhankelijke AOI's per regio/context; pure-empty én moeilijke negatieve voorbeelden voor alle regio's, waaronder Brussels; protected portfolios nooit naar training kopiëren. | Corpus-compositiematrix voldoet aan het vooraf bevroren contract uit `PYTORCH_TRAINING_ROADMAP_BELGIUM.md`; elk vereist stratum heeft positieve/negatieve coverage; zero protected-to-train overlap; kaart/contact-sheet evidence. |
|
||||
| ACC-R13 | High | V56: 31.452 inputfeatures, 30.662 geaccepteerd, 326 onder minimumresolutie en 464 post-imagery; 521 kleine labels en maximale aspectratio 103,67. V66 gebruikt imagery/labels met circa 575 dagen verschil. | Onzichtbare, verouderde, te kleine of extreem gevormde labels veroorzaken fout-negatieven/positieven en onbetrouwbare boxtraining, met extra risico in dichte PICC/UrbIS-gebieden. | GIS + AI + QA | Per-provider tijdsrelatie en resolvability vastleggen; post-imagery/subpixel uitsluiten met reason code; extreme aspect/dense-cluster review; dak/footprint-displacement en PICC/UrbIS-regels bevriezen. | Label-audit met accepted/rejected reason per feature; temporal matrix per AOI; zero unknown silent inclusion; alle extreme/dense reviewqueues gesloten; opnieuw gerenderde contact sheets en corpus-SHA. |
|
||||
| ACC-R14 | High | V56-tiling telt 2.496 tiles en 60.229 labels, maar dataset-YAML/class/tile/stride-velden zijn afwezig of null in de auditketen. | Het trainingsinputcontract kan niet exact worden gereconstrueerd of vergeleken; een checkpoint kan aan ambiguë preprocessing worden gekoppeld. | AI + Data Engineering | Eén verplicht manifest-schema met dataset-YAML SHA, class mapping, tile size, stride/overlap, nodata, normalization, augmentations, software/runtime en seed; schema fail-closed. | JSON-schema-tests; volledige immutable manifest; alle artifacts hash-bound; clean-room export produceert identieke samplelijst/labels en gedocumenteerde byteverschillen waar bestandmetadata varieert. |
|
||||
| ACC-R15 | High | Van 3.377 datasets missen 2.377 `observed_at` en 1.761 `source_version`; checksums, CRS, imported_at en provenancevelden zijn wel volledig. | Tijd- en bronversievergelijkingen kunnen niet voor elke bronfamilie worden gereproduceerd; sommige misses kunnen legitiem zijn maar zijn nog niet geclassificeerd. | Data Governance + Architecture | Veldbeleid per bronfamilie: `required`, `not_applicable` of `unknown_with_reason`; backfill uitsluitend uit authoritative evidence; nooit downloadtijd als observatietijd invullen. | Audit per source family met zero ongeclassificeerde ontbrekende waarden; migratie/backfillrapport; API toont unknown/not-applicable expliciet; checksums blijven ongewijzigd. |
|
||||
|
||||
## C. Modelvalidatie, metrics en runtime-lineage
|
||||
|
||||
| ID | Ernst | Bewezen evidence | Impact | Owner | Vereiste controle | Exit-evidence |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| ACC-R16 | Critical | V58-calibratie bij confidence 0,15 geeft aggregate F1 0,5129, Brussels 0,6944, Wallonia 0,4674 en Flanders 0; er is geen protected-test-, background-test- of promotion-evidence. De actieve modelkaart blijft `nationally_validated=false` en Mol/Kempen-scoped. | Aggregate score maskeert een volledige regionale failure; geen nationale kwaliteitsclaim of promotie is verdedigbaar. | AI + QA | Region/context macro- en worst-stratum gates vóór aggregate score; threshold alleen op calibration; actieve scope fail-closed behouden; geen status op basis van checkpointnaam. | Bevroren gateconfig vóór test; calibrationrapport per regio/context/objectgrootte; alle gates pass; daarna pas eenmalige protected-test en promotion report voor exact model-SHA. |
|
||||
| ACC-R17 | Critical | 1.146 persisted detection runs en 299.233 detections hebben een lege `model_version`; 3 runs missen modelhash; alle missen tile-manifest-SHA, runtime/hardware en seed. | Resultaten kunnen niet eenduidig aan model, preprocessing en execution environment worden herleid; incidentanalyse en reproduceerbaarheid falen. | Architecture + AI | Verplicht immutable RunManifest vóór inference: model-ID/version/SHA, adapter/config, tile-manifest/SHA, dataset/version, CRS/transform, threshold/NMS/max_det, seed, runtime/container/GPU. Run weigeren als verplichte velden ontbreken. | DB-migratie en schema constraints; contracttests; nieuwe run round-trip; reproduction op dezelfde tile/model/config; legacy records expliciet `lineage_incomplete`, nooit stil aangevuld. |
|
||||
| ACC-R18 | High | Van 697 QA-samenvattingen zijn F1 en precision 58 keer null, mean IoU 90 keer null en recall 1 keer null. De no-overlap golden case geeft precision/recall 0 maar F1 null. | Undefined, zero en not-computable worden door elkaar gebruikt; dashboards/gates kunnen failures overslaan. | QA + Architecture | Metricsemantiek per empty/empty, prediction-only, truth-only en no-match case bevriezen; status/reason naast waarde; gate-aggregator mag null niet negeren. | Truth-table unit tests; migratie/classificatie van historische nulls; golden benchmark per case; promotion fails bij onverwachte null of ontbrekend stratum. |
|
||||
| ACC-R19 | High | De GPU-smoke op één bestaande EPSG:31370-tile slaagt met active model SHA `a9088…59c1`, 17 detections en RTX 4080 SUPER, maar heeft geen ground truth en verklaart zelf geen accuracy/generalization claim. | Technische beschikbaarheid kan onterecht als modelkwaliteit worden geïnterpreteerd. | AI + QA | Smoke strikt scheiden van evaluatie; UI/docs/status benoemen `runtime_ready` apart van `validated_scope`; geen promotie op smoke-resultaat. | Contracttests voor statussen; model card toont afzonderlijk runtime-, calibration-, test- en scopebewijs; promotion code vereist alle hashes en gates. |
|
||||
| ACC-R20 | High | De runtime heeft 0 segmentations en het gevalideerde segmentatiemodel ontbreekt; aanwezige assets zijn geen configuratie- of kwaliteitsbewijs. | UI/API kan door bestandsaanwezigheid een niet-bewezen capability suggereren. | AI + Frontend + QA | Segmentatie en zonnepaneelmodellen blijven `not_configured` totdat hun eigen corpus, metrics, model card en releasepad slagen. | End-to-end `not_configured`-tests; capability registry is evidence-driven; geen persisted outputs vóór aparte validatie/promotion. |
|
||||
|
||||
## D. Verificatie, foutafhandeling en deployment
|
||||
|
||||
| ID | Ernst | Bewezen evidence | Impact | Owner | Vereiste controle | Exit-evidence |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| ACC-R21 | High | Met root/backend `PYTHONPATH` worden 1.197 tests verzameld: 1.180 pass en 17 falen. De gedocumenteerde backend-CI-aanroep faalt al bij collection doordat `backend/scripts` het rootpakket `scripts` overschaduwt. | Een groene deelset kan een kapotte canonical testentrypoint of regressies verbergen. | QA + Architecture | Eén canonical testcommand vanuit repo-root; package shadowing verwijderen; stale source-text assertions vervangen door behavior tests; geen baseline-updating zonder contractreview. | Volledige suite pass op CI-runtime én Tower-compatible image; exact command/exitcode/log vastgelegd; 17 regressies inhoudelijk geclassificeerd en opgelost. |
|
||||
| ACC-R22 | Medium | Ruff rapporteert 112 issues (69 E702, 23 F401, 13 E402, 2 E701, 2 F811, 2 F841 en 1 F403). Frontend heeft geen `lint` script ondanks de teststrategie; typecheck, 51 Vitest-tests en build slagen wel. | Dead imports/compact statements en ontbrekende frontendlint verhogen defectrisico; het formele QA-contract is niet uitvoerbaar zoals beschreven. | QA + Frontend + Architecture | Ruff-baseline gecontroleerd afbouwen; echte frontendlintconfig/script toevoegen; lint in CI; generated/legacy uitzonderingen expliciet en smal. | `ruff check` en `npm run lint` pass; CI voert beide uit; bestaande typecheck/Vitest/build blijven groen. |
|
||||
| ACC-R23 | High | Frontend detail/bootstrapfouten worden stil omgezet naar fallback/null; raster cache-open kan ondanks fout `ready` opleveren; secundaire detection/segmentation DB-markering kan worden ingeslikt. | Gebruiker ziet oude, onvolledige of schijnbaar succesvolle output zonder zichtbare lineagebreuk. | Frontend + Architecture + QA | Error states expliciet en typed; stale/cache-status tonen; persistence-failure maakt run/dataset failed of incomplete; geen broad catch zonder telemetry en user-visible status. | Fault-injectiontests per fallback; API/UI tonen correlation/run ID en retry; zero `ready/success` na verplichte persistence failure; structured logs/evidence. |
|
||||
| ACC-R24 | High | Golden benchmark gebruikt UUID4 en meerdere trainingsscripts hebben onvolledig bevroren seed/runtimegedrag. | Baselines en manifests zijn byte-onstabiel; reruns kunnen niet betrouwbaar worden vergeleken. | QA + AI | Deterministische IDs uit inhoud/hash, seed alle RNG's, deterministische algoritmen waar ondersteund, expliciete nondeterministische kernelregistratie en tolerantiebeleid. | Twee clean-room reruns met identieke manifest/sample/split hashes; metrische verschillen binnen vooraf bevroren tolerantie; runtime/seed in RunManifest. |
|
||||
| ACC-R25 | High | Lokale audit draait op Python 3.13/Node 24, CI op Python 3.11/Node 20. Compose default verwijst naar cu130, deployment naar cu128; CI bouwt alleen AI-disabled en valideert CUDA/AI-dependencies niet. Tower gebruikt PyTorch 2.11.0+cu128 en Ultralytics 8.4.99. | Een image kan lokaal/CPU slagen en op de GPU-runtime falen of een andere dependencyset gebruiken. | DevOps + AI + QA | Eén pinned AI build path en lock/SBOM; CI bouwt CPU-contract én GPU-image; Tower preflight valideert exacte torch/CUDA/Ultralytics/modelhash; geen CPU-fallback voor training. | Image digest + SBOM; build/test logs voor AI-enabled image; `cuda:0` preflight en bounded inference op RTX 4080; runtimeversies exact in release manifest. |
|
||||
| ACC-R26 | Medium | De repo bevat een tracked geneste `geointel/`-kopie met 1.153 files en 68 afwijkende root/mirror-paren, plus grote tracked audit/inputartefacten. `.dockerignore` sluit de geneste mirror wel uit. | Lokale tooling/imports kunnen de verkeerde kopie analyseren; review en branchgrootte worden onnodig ambigu. | Architecture + DevOps | Canonieke root expliciet afdwingen; mirror in P2 via afzonderlijke, reviewbare migratie inventariseren en pas na bewijs archiveren/verwijderen; artifact-retentiebeleid. | CI-test faalt bij nieuwe root/mirrorduplicatie; nul ambigue importpaden; migratiemanifest met hashes en herstelpad; runtime image blijft rootcode gebruiken. |
|
||||
| ACC-R27 | High | Tower checkout staat op `main`, loopt 67 commits vóór de stale `origin/main` en bevat untracked runtime-evidence/cache. | Deploybron en remote history zijn niet eenduidig; rollback/restore kan een andere codebasis opleveren. | DevOps + Architecture | Deployment uitsluitend vanaf gepushte immutable commit/tag en image digest; servercheckout niet als bron van waarheid; untracked runtime data buiten source tree of expliciet gemount. | Push/commit ancestrybewijs; deployment manifest met commit+digest+config; clean source checkout; rollbacktest naar vorige digest zonder dataverlies. |
|
||||
| ACC-R28 | Medium | PostGIS meldt versie 3.6.4, maar core/topology procedures uit 3.4.3 “need upgrade”. | Ruimtelijke functiegedrag/migraties kunnen per omgeving afwijken en upgrades kunnen onverwacht falen. | Architecture + GIS + DevOps | Extension-upgradepad in restorebare stagingdatabase; functieversie/preflight in deployment; geen in-place productie-upgrade zonder backup en dry-run. | Restoretest, `ALTER EXTENSION`-dry-run/resultaat, PostGIS regression suite en versie-evidence vóór/na; rollbackprocedure getest. |
|
||||
| ACC-R29 | Medium | API-contract, implementation gap docs, preflightvoorbeelden en actieve runtimeversies spreken elkaar op meerdere plaatsen tegen. | Operators en agents kunnen verouderde instructies volgen of capabilities overclaimen. | Architecture + QA | Docs genereren/valideren tegen OpenAPI, migrations, capability registry en runtime manifest; stale claims verwijderen met behoud van historisch bewijs. | Doc-contracttests; alle versies/scopes uit één bron; accuracy-program en operator README verwijzen naar actuele model card en release status. |
|
||||
|
||||
## Positieve controles die behouden moeten blijven
|
||||
|
||||
Deze bevindingen verlagen de bovenstaande risico's niet, maar zijn bewezen onderdelen waarop Phase 2 kan voortbouwen:
|
||||
|
||||
- Tower ziet een NVIDIA GeForce RTX 4080 SUPER; PyTorch CUDA is beschikbaar en de productie-adapter heeft één bounded, read-only inference uitgevoerd.
|
||||
- Alle 3.377 datasets hebben checksum, CRS, imported-at en source/provenance metadata; alle 1.671 DatasetVersions hebben checksum, storage path en metadata.
|
||||
- De database-audit vond geen ontbrekende directe storage references in de gecontroleerde set.
|
||||
- Areas en vector_features hebben in de runtime-snapshot geen invalid, empty of wrong-SRID geometrieën; de vier detection-afwijkingen blijven afzonderlijk releaseblokkerend.
|
||||
- API/OpenAPI-, GIS-, AI-contract-, migratie-, frontend typecheck/Vitest/build- en gerichte testgroepen slaagden; de volledige canonical gate blijft desondanks rood door ACC-R21/22.
|
||||
|
||||
## Risicoacceptatie
|
||||
|
||||
Geen Critical-risico is accepteerbaar voor promotie of scopeverruiming. Een High-risico kan alleen door een expliciete, tijdgebonden operatorbeslissing worden geaccepteerd wanneer het geen accuracy-, bronautoriteits-, split- of lineagegate omzeilt. Zo'n uitzondering moet het risico-ID, bereik, eigenaar, rollback en bewijs bevatten. Ontbrekende evidence telt als een gefaalde gate, niet als “niet van toepassing”.
|
||||
@@ -1,631 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — metric framework
|
||||
|
||||
- Status: Phase 1 measurement contract
|
||||
- Scope: Belgium and the Belgian North Sea, with task-specific claims only
|
||||
- Evidence root: `artifacts/evidence/accuracy/P1/`
|
||||
- Last updated: 2026-08-01
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document defines how GeoIntel must measure, compare and communicate
|
||||
accuracy. It is a measurement contract, not an assertion that any current model
|
||||
meets a release threshold.
|
||||
|
||||
The framework has five non-negotiable goals:
|
||||
|
||||
1. every reported number is reproducible from checksum-bound inputs;
|
||||
2. model-selection data stays separate from protected release evidence;
|
||||
3. aggregate scores cannot hide a failing region or context;
|
||||
4. missing, undefined or insufficient evidence fails closed;
|
||||
5. claims never exceed the evaluated task, class, geography, source edition or
|
||||
operating configuration.
|
||||
|
||||
This framework applies to learned detection and segmentation outputs and to
|
||||
deterministic spatial QA where a candidate layer is compared with a reference.
|
||||
It does not turn authoritative GIS functions into machine-learning tasks.
|
||||
|
||||
## 2. Current baseline versus future acceptance thresholds
|
||||
|
||||
### 2.1 Baselines that exist now
|
||||
|
||||
GeoIntel currently has a deterministic QA/QC code-regression baseline in
|
||||
`fixtures/golden/golden_qa_benchmarks.json`. At IoU `0.5`, its frozen scenarios
|
||||
include:
|
||||
|
||||
| Scenario | Precision | Recall | F1 | Mean matched IoU |
|
||||
|---|---:|---:|---:|---:|
|
||||
| partial match | 0.5 | 0.5 | 0.5 | 0.8339768339761133 |
|
||||
| perfect match | 1.0 | 1.0 | 1.0 | 1.0 |
|
||||
| no overlap | 0.0 | 0.0 | undefined (`null`) | undefined (`null`) |
|
||||
| multipolygon match | 1.0 | 1.0 | 1.0 | 1.0 |
|
||||
|
||||
These values prove regression stability of the fixture matcher. They do **not**
|
||||
measure production-model accuracy, Belgium-wide generalisation, source quality
|
||||
or human acceptability.
|
||||
|
||||
The runtime GPU/model smoke evidence proves only that a particular asset can be
|
||||
loaded and invoked under the recorded configuration. It is not an accuracy
|
||||
benchmark. Historical calibration reports and persisted `Metric` rows are
|
||||
evidence candidates only when their complete lineage, split role, evaluator
|
||||
version and inputs can be reproduced.
|
||||
|
||||
Several scripts contain historical or provisional numeric defaults, including
|
||||
the gate defaults in `scripts/assess_belgium_building_training_iteration.py`.
|
||||
Those implementation defaults are not automatically approved Accuracy Program
|
||||
release thresholds. Reports using them must label the gate source and version
|
||||
as `legacy` or `provisional`; they cannot be relabelled as a Phase 1 contract.
|
||||
|
||||
At the Phase 1 evidence cut, a canonical release-grade national model-quality
|
||||
baseline is therefore `not_established`. No existing number may be presented as
|
||||
a Belgium-wide acceptance result until the data, split, evaluator and review
|
||||
requirements below are satisfied.
|
||||
|
||||
### 2.2 Thresholds that must be frozen later
|
||||
|
||||
All new promotion floors, ceilings, non-inferiority margins, sample minima,
|
||||
confidence levels and latency budgets are `TBD`. They must be proposed from a
|
||||
reviewed incumbent baseline and operational requirements, approved and
|
||||
versioned **before** the protected test set is opened.
|
||||
|
||||
The freeze record must identify:
|
||||
|
||||
- task, class ontology and claim scope;
|
||||
- dataset and split-manifest hashes;
|
||||
- incumbent and candidate model hashes;
|
||||
- exact preprocessing, tile, overlap, confidence and NMS configuration;
|
||||
- evaluator version and object-matching policy;
|
||||
- metric, aggregation level, direction and threshold;
|
||||
- required strata and minimum evaluable support;
|
||||
- confidence-interval or paired-comparison rule;
|
||||
- runtime hardware and latency measurement protocol;
|
||||
- approver, timestamp and immutable gate-definition hash.
|
||||
|
||||
Seeing test results can never justify relaxing a threshold. A changed threshold
|
||||
creates a new, independently approved evaluation protocol and requires evidence
|
||||
that remains independent of the change.
|
||||
|
||||
## 3. Evaluation unit and identity contract
|
||||
|
||||
Every metric record must be traceable to the following identity tuple:
|
||||
|
||||
```text
|
||||
task + class_ontology_version + model_sha256 + dataset_manifest_sha256
|
||||
+ split_manifest_sha256 + evaluator_version + inference_config_sha256
|
||||
+ reference_source_version + imagery_source_version + run_id
|
||||
```
|
||||
|
||||
The evidence record must also contain the Git commit, container image digest,
|
||||
Python/PyTorch/CUDA/driver versions, random seed, deterministic-mode flags,
|
||||
hardware, timestamps and command arguments. A metric without this tuple is
|
||||
`unverifiable`, not an approximate success.
|
||||
|
||||
All geometries must be validated and transformed to a declared common CRS
|
||||
before matching. Distance, area and boundary metrics require a documented
|
||||
metric/equal-area CRS appropriate to the AOI. CRS assumptions, geometry repair,
|
||||
clipping and ignored boundary zones must be counted and reported.
|
||||
|
||||
## 4. Error taxonomy
|
||||
|
||||
Each reviewed error receives one primary code and any applicable secondary
|
||||
codes. Counts must be available by sample, AOI, region and context. Free text
|
||||
may explain an error but cannot replace a code.
|
||||
|
||||
### 4.1 Data and lineage errors (`D-*`)
|
||||
|
||||
- `D-MISSING-PROVENANCE`: missing source, edition, acquisition time, licence,
|
||||
checksum or transformation lineage.
|
||||
- `D-STALE-SOURCE`: imagery or reference is outside its declared validity
|
||||
period.
|
||||
- `D-TEMPORAL-MISMATCH`: the labelled object and image do not represent the
|
||||
same observable time.
|
||||
- `D-CRS-MISSING` / `D-CRS-WRONG`: CRS is absent, misdeclared or transformed
|
||||
incorrectly.
|
||||
- `D-ALIGNMENT`: systematic or local image/reference displacement.
|
||||
- `D-INVALID-GEOMETRY`: empty, corrupt, self-intersecting or otherwise invalid
|
||||
geometry, including an unrecorded repair.
|
||||
- `D-RESOLUTION`: object is below the declared resolvable pixel/ground size or
|
||||
input resolution differs from the model contract.
|
||||
- `D-LICENCE-SCOPE`: source use or redistribution cannot be proven.
|
||||
- `D-CACHE-STALE`: cached content does not match the requested source/version.
|
||||
|
||||
### 4.2 Label and ontology errors (`L-*`)
|
||||
|
||||
- `L-MISSING`: visible in-scope object has no label.
|
||||
- `L-SPURIOUS`: label has no visible in-scope object.
|
||||
- `L-CLASS`: wrong canonical class or source-to-canonical mapping.
|
||||
- `L-EXTENT`: polygon/box extent is materially wrong.
|
||||
- `L-INSTANCE-SPLIT`: one real instance is labelled as multiple instances.
|
||||
- `L-INSTANCE-MERGE`: distinct instances are merged.
|
||||
- `L-AMBIGUOUS`: imagery/reference cannot support a defensible decision.
|
||||
- `L-EXCLUSION`: excluded ontology item was included, or a valid item was
|
||||
excluded.
|
||||
- `L-REVIEW-MISSING`: required human review or adjudication is absent.
|
||||
|
||||
### 4.3 Split and duplication errors (`S-*`)
|
||||
|
||||
- `S-EXACT-DUPLICATE`: byte/content-equivalent image, label or derived tile
|
||||
crosses split boundaries.
|
||||
- `S-NEAR-DUPLICATE`: materially identical view or transformed derivative
|
||||
crosses split boundaries.
|
||||
- `S-SPATIAL-OVERLAP`: AOIs, tile context or instances overlap across protected
|
||||
split groups.
|
||||
- `S-TEMPORAL-FAMILY`: repeated acquisitions of the same site leak site identity
|
||||
or labels across splits without an approved temporal generalisation design.
|
||||
- `S-SOURCE-FAMILY`: provider mosaics or parent rasters are divided in a way
|
||||
that leaks shared context.
|
||||
- `S-PROTECTED-USE`: calibration, test or background-test evidence influenced
|
||||
fitting, sampling, augmentation, architecture, threshold or NMS selection.
|
||||
- `S-MANIFEST-MUTATION`: an evaluated split or its role changed after freeze.
|
||||
|
||||
Any `S-*` error invalidates the affected comparative evaluation until a new
|
||||
independent split is frozen.
|
||||
|
||||
### 4.4 Model-output errors (`M-*`)
|
||||
|
||||
- `M-FP-BACKGROUND`: detection on a pure-background sample.
|
||||
- `M-FP-CONFUSER`: detection on a named hard-negative/confuser.
|
||||
- `M-FP-DUPLICATE`: multiple retained predictions for one reference instance.
|
||||
- `M-FP-LOCALISATION`: predicted instance overlaps a reference but misses the
|
||||
frozen match criterion.
|
||||
- `M-FN-MISSED`: resolvable in-scope reference instance is absent.
|
||||
- `M-FN-SUPPRESSED`: valid instance is removed by confidence, NMS, containment
|
||||
or post-processing.
|
||||
- `M-CLASS`: prediction is assigned to the wrong class.
|
||||
- `M-BOUNDARY`: segmentation boundary is materially displaced despite object
|
||||
detection.
|
||||
- `M-AREA-BIAS`: predicted geometry has systematic area over- or
|
||||
under-estimation.
|
||||
- `M-MISCALIBRATED`: confidence does not correspond to empirical correctness.
|
||||
- `M-OOD`: sample is outside the declared training/evaluation domain.
|
||||
|
||||
False positives and false negatives must retain evidence links to prediction
|
||||
and reference IDs, source tiles and review decisions.
|
||||
|
||||
### 4.5 Pipeline and claim errors (`P-*`, `C-*`)
|
||||
|
||||
- `P-FALLBACK`: mock, heuristic, alternate source or stale cache replaced the
|
||||
declared path.
|
||||
- `P-NONDETERMINISTIC`: rerun differences exceed the frozen reproducibility
|
||||
policy without explanation.
|
||||
- `P-PARTIAL`: missing tile/chunk/output was silently omitted.
|
||||
- `P-UNIT`: metres, degrees, pixels, CRS units or resolution were confused.
|
||||
- `P-RUNTIME`: OOM, timeout, truncation or worker failure changed the evaluated
|
||||
output.
|
||||
- `C-OVERCLAIM`: wording exceeds evaluated task/scope/data.
|
||||
- `C-MISSING-DENOMINATOR`: a rate is published without counts/support.
|
||||
- `C-UNSUPPORTED-AGGREGATE`: an aggregate hides missing or failed strata.
|
||||
- `C-UNTRACEABLE`: result cannot be tied to the identity tuple in section 3.
|
||||
|
||||
## 5. Object-level metrics
|
||||
|
||||
### 5.1 Matching contract
|
||||
|
||||
Metrics are meaningless without a matching policy. Every report must specify:
|
||||
|
||||
- supported geometry types and class matching;
|
||||
- IoU thresholds;
|
||||
- confidence ordering;
|
||||
- one-to-one matching algorithm and tie-breaking;
|
||||
- boundary clipping/ignore policy;
|
||||
- treatment of difficult, ambiguous and below-resolution labels;
|
||||
- duplicate-suppression configuration.
|
||||
|
||||
The current `QaService` performs one-to-one greedy polygon matching at a
|
||||
configurable IoU threshold (default `0.5`) and conditions mean IoU on matched
|
||||
objects. This is a deterministic spatial QA baseline when input order and
|
||||
evaluator version are fixed, but it is not automatically COCO AP.
|
||||
|
||||
For detector PR/AP evaluation, predictions must be sorted by confidence and
|
||||
matched one-to-one at each IoU threshold using a frozen COCO-compatible policy.
|
||||
For fixed-threshold spatial comparison, a separately named matcher may use a
|
||||
deterministic maximum-weight one-to-one assignment. Results from different
|
||||
matchers must never be combined under the same metric key.
|
||||
|
||||
### 5.2 Counts and rates
|
||||
|
||||
For an evaluable class and stratum:
|
||||
|
||||
```text
|
||||
precision = TP / (TP + FP)
|
||||
recall = TP / (TP + FN)
|
||||
F1 = 2 * precision * recall / (precision + recall)
|
||||
IoU = intersection_area / union_area
|
||||
```
|
||||
|
||||
Always publish `TP`, `FP`, `FN`, prediction count and reference count beside the
|
||||
rates. Undefined denominators produce `null`, never zero and never pass. In
|
||||
particular:
|
||||
|
||||
- no predictions makes precision undefined;
|
||||
- no references makes recall undefined;
|
||||
- zero precision plus zero recall keeps F1 undefined under the current QA
|
||||
service semantics;
|
||||
- pure-background performance is evaluated with explicit FP/background metrics,
|
||||
not fabricated precision or recall;
|
||||
- mean matched IoU is conditional on matches and must not be used alone because
|
||||
it excludes FP and FN.
|
||||
|
||||
### 5.3 Precision-recall and average precision
|
||||
|
||||
Report the full precision-recall curve and its confidence thresholds. Required
|
||||
detector summaries are:
|
||||
|
||||
- `AP50`: area under the interpolated PR curve at IoU 0.50;
|
||||
- `AP50-95`: mean AP across IoU 0.50 through 0.95 in steps of 0.05;
|
||||
- per-class AP and macro AP for multi-class tasks;
|
||||
- recall at the frozen operating point;
|
||||
- precision at the frozen operating point.
|
||||
|
||||
AP must be calculated before choosing a production confidence threshold. A
|
||||
single-threshold F1 value cannot be called AP. AP values from a training
|
||||
framework are accepted only when evaluator version, input set, class mapping
|
||||
and settings are recorded and independently reproducible.
|
||||
|
||||
### 5.4 Localisation and geometry
|
||||
|
||||
Report the distribution, not only the mean, of matched IoU: count, median,
|
||||
quartiles and lower-tail quantiles. Segmentation candidates additionally need
|
||||
pixel/geometry IoU, Dice, boundary distance/score, area bias and topology-error
|
||||
counts under a frozen geometry protocol. Metric thresholds for those measures
|
||||
remain `TBD` until the segmentation label contract exists.
|
||||
|
||||
Object results must be stratified by predeclared size bands derived from ground
|
||||
area and/or source-image pixels. Band boundaries are `TBD` and must be frozen
|
||||
from resolution and ontology rules before candidate results are inspected.
|
||||
|
||||
## 6. Tile-level metrics
|
||||
|
||||
Tile metrics expose operational failure modes that object-level micro-averages
|
||||
can hide:
|
||||
|
||||
- tile count, evaluable tile count and excluded-tile reasons;
|
||||
- positive/empty tile counts;
|
||||
- fraction of pure-empty tiles with one or more predictions;
|
||||
- FP count per pure-empty tile and per square kilometre;
|
||||
- fraction of positive tiles with at least one FN;
|
||||
- per-tile precision, recall and F1 where defined;
|
||||
- detection/reference count error per tile;
|
||||
- duplicate predictions created at tile overlaps;
|
||||
- tile processing latency, throughput and peak memory;
|
||||
- tile-level error/uncertainty score for review routing.
|
||||
|
||||
Report macro distributions across tiles as diagnostics. Do not average undefined
|
||||
tile rates into zero, and do not let a large number of easy empty tiles dominate
|
||||
the primary object metric.
|
||||
|
||||
## 7. AOI-level metrics
|
||||
|
||||
The AOI is the primary unit for paired operational comparison. For each AOI,
|
||||
publish:
|
||||
|
||||
- TP, FP, FN, precision, recall, F1 and matched-IoU distribution;
|
||||
- reference and predicted object counts and signed/absolute count error;
|
||||
- reference and predicted geometry area and signed/absolute area bias when
|
||||
geometry outputs support it;
|
||||
- pure-background/context-negative errors;
|
||||
- excluded area/objects and reasons;
|
||||
- end-to-end runtime, failed/retried tiles and completeness;
|
||||
- taxonomy counts and links to visual evidence.
|
||||
|
||||
Candidate-versus-incumbent deltas must be paired on the exact same AOIs,
|
||||
references and inference contract. Macro AOI results give each AOI equal weight;
|
||||
micro results pool TP/FP/FN. Both are reported and explicitly named. The primary
|
||||
aggregation and any non-inferiority margin remain `TBD` until frozen in the
|
||||
gate definition.
|
||||
|
||||
## 8. Region-, context- and portfolio-level metrics
|
||||
|
||||
At minimum, building-model evidence must report Flanders, Wallonia and Brussels
|
||||
separately. The Belgian North Sea is not an implicit building-detector claim;
|
||||
offshore tasks need their own ontology and evidence.
|
||||
|
||||
Required stratification dimensions, where applicable, are:
|
||||
|
||||
- region and provider/source edition;
|
||||
- urban, suburban, ribbon development, rural/village, farm, industrial and
|
||||
other frozen context families;
|
||||
- dense/occluded/touching-object contexts;
|
||||
- pure background and named hard-negative families;
|
||||
- object-size band and input ground resolution;
|
||||
- imagery period/season and reference-to-imagery time difference;
|
||||
- AOI boundary/interior and tile-edge/interior;
|
||||
- native class/source subtype and label-review state;
|
||||
- normal domain versus declared OOD challenge set.
|
||||
|
||||
For every required stratum report support, micro metrics, macro AOI metrics and
|
||||
uncertainty intervals. Also report the worst evaluable required stratum. A
|
||||
portfolio aggregate is valid only if every mandatory stratum has sufficient
|
||||
predeclared support; otherwise its state is `not_evaluable`.
|
||||
|
||||
Intersectional slices should be added where error evidence warrants them, but
|
||||
post-hoc slices are diagnostic and cannot replace the frozen primary analysis.
|
||||
Small groups stay visible with an `insufficient_support` label; they are not
|
||||
silently pooled into a better-performing group.
|
||||
|
||||
## 9. Confidence calibration
|
||||
|
||||
Model confidence is not accuracy and is not a complete uncertainty estimate.
|
||||
Calibration is evaluated on the frozen calibration split after one-to-one
|
||||
matching and before protected-test access.
|
||||
|
||||
### 9.1 Expected calibration error
|
||||
|
||||
For prediction bins `B_m` frozen before evaluation:
|
||||
|
||||
```text
|
||||
ECE = sum_m (|B_m| / n) * |accuracy(B_m) - confidence(B_m)|
|
||||
```
|
||||
|
||||
The binning method, boundaries, empty-bin handling and minimum observations must
|
||||
be recorded. Report a reliability diagram and per-bin counts. A predefined
|
||||
fixed-bin ECE is the comparable metric; adaptive-bin ECE may be reported only as
|
||||
a labelled diagnostic. ECE is paired with recall because missed references have
|
||||
no prediction confidence and are invisible to prediction-only ECE.
|
||||
|
||||
### 9.2 Brier score
|
||||
|
||||
For each scored prediction, define `y=1` only when it is the retained match under
|
||||
the frozen policy, otherwise `y=0`:
|
||||
|
||||
```text
|
||||
Brier = mean((confidence - y)^2)
|
||||
```
|
||||
|
||||
Report Brier overall and by required stratum. The exact construction of the
|
||||
prediction set must be frozen; Brier does not replace FN/recall reporting.
|
||||
|
||||
Calibration fitting may use only calibration data. If temperature scaling,
|
||||
isotonic regression or another mapping is used, its fitted parameters and code
|
||||
version become part of the immutable inference configuration. Test data may
|
||||
evaluate that mapping but may not refit it.
|
||||
|
||||
## 10. Latency, capacity and reliability
|
||||
|
||||
Accuracy promotion also requires a reproducible operational profile on the
|
||||
declared server GPU. Record separately:
|
||||
|
||||
- cold-start/model-load time;
|
||||
- warm model-only inference time per tile;
|
||||
- preprocessing, inference, post-processing and persistence time;
|
||||
- end-to-end AOI latency excluding and including queue wait;
|
||||
- median, p95, p99 and maximum latency with sample counts;
|
||||
- tiles/second and square kilometres/minute at the recorded resolution;
|
||||
- peak allocated/reserved VRAM and host RAM;
|
||||
- batch size, tile size, overlap, worker concurrency and retry count;
|
||||
- OOM, timeout, truncation, partial-output and failed-job rates.
|
||||
|
||||
Warm-up count, timing clock, synchronisation method, hardware, driver and
|
||||
background load must be fixed. A local CPU run and an RTX 4080 SUPER CUDA run
|
||||
are different baselines. Latency budgets are `TBD`; current smoke timings may be
|
||||
reported as observations only.
|
||||
|
||||
## 11. Uncertainty and selective review
|
||||
|
||||
Uncertainty evidence may include confidence, entropy/margin where meaningful,
|
||||
test-time-augmentation disagreement, ensemble variance, spatial disagreement
|
||||
and OOD scores. Every method must state what variation it measures; confidence
|
||||
alone may not be labelled epistemic uncertainty.
|
||||
|
||||
For any abstain/review policy, report:
|
||||
|
||||
- retained coverage versus error/risk curve;
|
||||
- error rate in auto-accepted, human-review and rejected bands;
|
||||
- review volume per AOI/region/context;
|
||||
- area under the risk-coverage curve as a diagnostic;
|
||||
- failure cases where high-confidence predictions are wrong;
|
||||
- threshold source and calibration-only selection evidence.
|
||||
|
||||
Uncertainty thresholds are `TBD`. Uncertainty may route work to a human; it must
|
||||
not create self-training labels or silently suppress output.
|
||||
|
||||
## 12. Strict split and deduplication rules
|
||||
|
||||
### 12.1 Split roles
|
||||
|
||||
- `train`: fitting and training-time augmentation only;
|
||||
- `val`: epoch/checkpoint/architecture selection only;
|
||||
- `calibration`: confidence, tiling, overlap, NMS and calibration mapping only;
|
||||
- `test`: sealed, one-time promotion evidence for a frozen candidate family;
|
||||
- `background-test`: sealed, difficult and pure-background release evidence.
|
||||
|
||||
No test or background-test result may influence fitting, sampling weights,
|
||||
label policy, architecture, hyperparameters, post-processing or gate values. If
|
||||
it does, that split is retired from independent testing, the candidate becomes
|
||||
a new family and a new untouched protected split is required.
|
||||
|
||||
### 12.2 Grouping before splitting
|
||||
|
||||
Deduplication and grouping happen before split assignment. The atomic group must
|
||||
keep together:
|
||||
|
||||
- a parent AOI plus every derived/overlapping tile;
|
||||
- all tiles sharing an object instance;
|
||||
- exact image/label hashes and transformed copies;
|
||||
- perceptual near-duplicate families;
|
||||
- repeated views whose shared spatial context exceeds the declared independence
|
||||
buffer;
|
||||
- source-raster/mosaic or temporal families when they would leak scene identity.
|
||||
|
||||
Train, val, calibration, test and background-test AOIs must be spatially
|
||||
disjoint, including a buffer larger than the maximum tile context used by any
|
||||
candidate. The buffer value and near-duplicate thresholds are `TBD` but must be
|
||||
frozen before corpus generation, not chosen after metric inspection.
|
||||
|
||||
### 12.3 Required leakage audits
|
||||
|
||||
The frozen split evidence must contain:
|
||||
|
||||
- exact SHA-256 duplicate matrix for raw image, processed image and label;
|
||||
- perceptual-image and label-geometry near-duplicate audit;
|
||||
- buffered AOI/tile intersection audit in a metric CRS;
|
||||
- shared native feature/source identifier audit;
|
||||
- parent raster, acquisition and temporal-family audit;
|
||||
- tile-versus-manifest role consistency audit;
|
||||
- counts and explicit disposition for every collision.
|
||||
|
||||
All cross-split collisions must be zero unless a written experimental design
|
||||
defines a non-independence group and assigns that whole group to one split. A
|
||||
leakage audit that did not run, timed out or lacks inputs is a failed gate.
|
||||
|
||||
## 13. Human-review metrics
|
||||
|
||||
Automated geometry checks do not replace representative human review. Corpus
|
||||
labels and model outputs need separate review records.
|
||||
|
||||
### 13.1 Label-corpus review
|
||||
|
||||
Report:
|
||||
|
||||
- planned, rendered, reviewed and adjudicated sample/object counts;
|
||||
- completion rate by region, context, provider, size band, split and label
|
||||
source;
|
||||
- contact-sheet/render failures and unreadable samples;
|
||||
- prevalence of every `D-*` and `L-*` finding;
|
||||
- accepted, corrected, excluded and ambiguous counts;
|
||||
- single-review and independent double-review counts;
|
||||
- raw reviewer agreement, class-wise agreement and an approved chance-corrected
|
||||
agreement statistic such as Cohen's kappa or Krippendorff's alpha;
|
||||
- disagreement/adjudication rate and unresolved critical findings.
|
||||
|
||||
Sampling quotas, double-review fraction, agreement statistic and acceptance
|
||||
thresholds are `TBD` and must be frozen before reviewers see model results.
|
||||
Protected test labels should be reviewed independently of candidate predictions.
|
||||
|
||||
### 13.2 Output-error review
|
||||
|
||||
For each candidate, use a frozen stratified sample that includes TP, FP, FN,
|
||||
low-confidence, high-confidence, tile-edge, dense, temporal-mismatch and OOD
|
||||
cases. Reviewers record taxonomy codes and severity, not only approve/reject.
|
||||
Report reviewer agreement, adjudication, severe-error prevalence and error
|
||||
distribution by stratum.
|
||||
|
||||
Review UI/version, imagery/reference layers, zoom/scale and reviewer identity or
|
||||
pseudonymous ID must be retained. A generated contact sheet with zero completed
|
||||
review decisions is `unreviewed`, not passed.
|
||||
|
||||
## 14. Statistical reporting
|
||||
|
||||
All rates include numerator, denominator and support. Confidence intervals use
|
||||
a predeclared method appropriate to the unit: object-level bootstrap must not
|
||||
pretend correlated tiles are independent. Prefer cluster bootstrap or paired
|
||||
analysis at AOI/group level for model comparisons.
|
||||
|
||||
Report:
|
||||
|
||||
- point estimate and interval;
|
||||
- number of independent AOIs/groups;
|
||||
- micro and macro aggregation;
|
||||
- paired candidate-minus-incumbent delta by AOI;
|
||||
- worst required stratum and its support;
|
||||
- missing/excluded evidence and reason;
|
||||
- multiplicity policy for any formal multi-stratum hypothesis claims.
|
||||
|
||||
The confidence level, bootstrap seed/replicates and non-inferiority margins are
|
||||
`TBD` until the gate specification is frozen. Descriptive diagnostics must not
|
||||
be presented as confirmatory release evidence.
|
||||
|
||||
## 15. Acceptance-gate semantics
|
||||
|
||||
Every gate returns exactly one state:
|
||||
|
||||
- `pass`: complete evidence meets the frozen rule;
|
||||
- `fail`: complete evidence violates the frozen rule;
|
||||
- `not_evaluable`: evidence is missing, invalid, leaked or below frozen support.
|
||||
|
||||
`not_evaluable` blocks promotion exactly like `fail`; it is never coerced to
|
||||
zero, ignored or averaged away.
|
||||
|
||||
A promotion decision is a logical AND across all mandatory gate families:
|
||||
|
||||
1. identity, provenance, licence and immutable manifest;
|
||||
2. zero unresolved split leakage and duplicate-family violations;
|
||||
3. automated data/label/geometry integrity;
|
||||
4. completed representative human review and adjudication;
|
||||
5. frozen object/AOI/region/context accuracy gates;
|
||||
6. pure-background and hard-negative gates;
|
||||
7. calibration and uncertainty/review-policy gates;
|
||||
8. paired incumbent comparison and reproducibility rerun;
|
||||
9. GPU latency, capacity and failure-rate gates;
|
||||
10. model card, scope limitation, rollback and live shadow evidence.
|
||||
|
||||
No weighted composite score may compensate for a failed mandatory gate. The
|
||||
aggregate and every mandatory region/context gate must pass independently.
|
||||
Candidate selection and operating-point selection use calibration evidence
|
||||
only. The protected test is evaluated once with the frozen configuration. A
|
||||
rerun is allowed only to reproduce the same immutable computation or to resolve
|
||||
a proven execution failure without inspecting/using partial results.
|
||||
|
||||
Gate output must include machine-readable rule IDs, observed values, expected
|
||||
direction/range, support, evidence paths and hashes. Manual override cannot
|
||||
change a metric result; an exceptional operational decision must remain a
|
||||
separate signed record and cannot widen the accuracy claim.
|
||||
|
||||
## 16. No-claim rules
|
||||
|
||||
GeoIntel must not claim that a model is “fully trained”, “validated”,
|
||||
“production accurate”, “Belgium-wide” or equivalent when any of the following
|
||||
is true:
|
||||
|
||||
- only model-file presence, load success, a GPU smoke or output existence was
|
||||
proven;
|
||||
- results come from train/val data, an unfrozen calibration set or leaked test
|
||||
evidence;
|
||||
- the dataset, model, evaluator or inference configuration lacks hashes;
|
||||
- required region/context support or representative human review is missing;
|
||||
- a metric is undefined/null, a job is partial or a fallback/mock/heuristic was
|
||||
used;
|
||||
- only aggregate performance is shown while a required stratum is absent or
|
||||
failing;
|
||||
- precision/recall/AP is reported without match policy and TP/FP/FN/support;
|
||||
- confidence is presented as probability of correctness without calibration
|
||||
evidence;
|
||||
- a deterministic fixture benchmark is presented as production-model quality;
|
||||
- the claim is extrapolated to another class, source, imagery period,
|
||||
resolution, region, segmentation task or deterministic GIS function;
|
||||
- test results were used to choose the next training data or configuration.
|
||||
|
||||
Permitted wording must be evidence-bounded, for example: “candidate X achieved
|
||||
the recorded metrics on frozen portfolio Y under configuration Z.” It must name
|
||||
limitations and may not imply untested generalisation.
|
||||
|
||||
## 17. Required machine-readable outputs
|
||||
|
||||
Each future baseline or candidate evaluation must retain, without overwriting
|
||||
earlier evidence:
|
||||
|
||||
```text
|
||||
evaluation-contract.json
|
||||
input-manifest.json
|
||||
split-and-leakage-audit.json
|
||||
object-metrics.json
|
||||
tile-metrics.json
|
||||
aoi-metrics.json
|
||||
stratified-metrics.json
|
||||
calibration-metrics.json
|
||||
latency-and-reliability.json
|
||||
human-review-summary.json
|
||||
error-taxonomy.json
|
||||
candidate-vs-incumbent.json
|
||||
acceptance-gates.json
|
||||
evidence-manifest.json
|
||||
```
|
||||
|
||||
`evidence-manifest.json` must SHA-256 hash every retained input and output. Any
|
||||
amendment is additive, versioned and linked to its predecessor. Raw records
|
||||
must remain available so every aggregate can be recomputed.
|
||||
|
||||
## 18. Phase 2 metric implementation sequence
|
||||
|
||||
1. freeze evaluator schemas, taxonomy codes and undefined-value semantics;
|
||||
2. implement strict group split and exact/near-duplicate audits;
|
||||
3. validate CRS/alignment/label lineage and complete human corpus review;
|
||||
4. freeze an incumbent portfolio and run a reproducible baseline twice;
|
||||
5. derive and approve numeric thresholds from reviewed baseline distributions
|
||||
and operational requirements without protected-test access;
|
||||
6. calibrate candidate operating points on calibration data only;
|
||||
7. execute the one-time protected test and background-test gates;
|
||||
8. publish scope-bounded evidence or retain `not_configured`/current limited
|
||||
scope when any gate is not evaluable.
|
||||
|
||||
Until those steps pass, this framework authorises measurement and remediation,
|
||||
not a widened accuracy claim.
|
||||
@@ -1,342 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — uitvoerbare roadmap
|
||||
|
||||
- Status: **Phase 2 mag starten; release en nationale modelclaim blijven geblokkeerd**
|
||||
- Bronnen: Phase-1 inventory, lineage, baseline/gaps, risicoregister en metric framework
|
||||
- Runtime voor training: Tower NVIDIA GeForce RTX 4080 SUPER op `cuda:0`
|
||||
|
||||
## Doel en definitie van gereed
|
||||
|
||||
Deze roadmap herstelt eerst de bewijs- en vertrouwensketen en bouwt daarna pas een nieuw Belgisch building-corpus en model. “100% getraind” betekent hier: alle vooraf bevroren corpus-, split-, runtime-, metric-, review-, test-, promotion- en deploymentgates zijn aantoonbaar geslaagd voor één expliciete modelscope. Het betekent niet 100% precision/recall en geeft geen claim buiten de geëvalueerde regio's, contexts, imagery editions en objectgroottes.
|
||||
|
||||
De volgorde is verplicht. Een work package start pas wanneer zijn dependency-gate groen is. Bij een gefaalde gate blijft productie op de huidige beperkte, expliciet gecommuniceerde Mol/Kempen-scope of schakelt de betrokken capability fail-closed naar `not_configured`. Checkpoints, datasets en bewijs worden nooit overschreven.
|
||||
|
||||
## Niet-onderhandelbare regels
|
||||
|
||||
1. **Test-first:** ieder bewezen defect uit `04-risk-register.md` krijgt eerst een regressietest die op de huidige foutieve implementatie faalt.
|
||||
2. **Protected-test isolation:** train, val en calibration mogen tijdens iteraties worden gelezen; test en background-test blijven verzegeld tot één kandidaat-SHA, preprocessingconfig, threshold en gates bevroren zijn.
|
||||
3. **Geen testgestuurde retraining:** na openen van protected test volgt voor die candidate family geen training, thresholdwijziging, sampleweging of configuratiekeuze meer.
|
||||
4. **Evidence of fail:** ontbrekend, null of niet-reproduceerbaar bewijs is een gefaalde gate.
|
||||
5. **Immutable lineage:** iedere dataset-, run-, model- en releaseversie heeft een checksum-bound manifest; legacy gaps blijven zichtbaar als `lineage_incomplete`.
|
||||
6. **GPU verplicht:** training gebruikt `cuda:0` op de Tower RTX 4080 SUPER met `TRAIN_REQUIRE_CUDA=true`; CPU-fallback is een failure.
|
||||
7. **Geen claim op file presence:** een `.pt`-bestand of succesvolle smoke maakt een model niet gevalideerd.
|
||||
8. **Menselijke review is echt menselijk:** automatische QA mag een ontbrekende review nooit als akkoord invullen. De finale productreview door de gebruiker volgt pas nadat alle objectieve gates groen zijn.
|
||||
|
||||
## Dependency-overzicht
|
||||
|
||||
| Volgorde | Work package | Depends on | Primaire output | Risico's gesloten |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| P2-00 | Promotion lock en evidence freeze | Phase 1 | immutable baseline + release lock | claimgrens voor alle risico's |
|
||||
| P2-01 | Canonical test harness | P2-00 | rode regressietests en uitvoerbare CI-matrix | ACC-R21, R22, basis voor alle fixes |
|
||||
| P2-02 | CRS, units en geometry integrity | P2-01 | veilig ingest/transform/buffer + data repair | ACC-R01, R02, R07 |
|
||||
| P2-03 | Coverage, authority en wettelijke scope | P2-02 | trusted source registry en geometry-backed scope | ACC-R03–R06 |
|
||||
| P2-04 | Transactionele lineage en foutzichtbaarheid | P2-02, P2-03 | complete Run/Dataset lineage en fail-closed persistence | ACC-R08, R15, R17, R23 |
|
||||
| P2-05 | Protected-split redesign | P2-01, P2-04 | test vault, manifest schema en sampler firewall | ACC-R09, R10, R14, R24 |
|
||||
| P2-06 | Menselijke labelreview en corpusrebuild | P2-02, P2-03, P2-05 | immutable reviewed `building-be-*` corpus | ACC-R10–R15 |
|
||||
| P2-07 | Metric framework en reproducible incumbent baseline | P2-04, P2-06 | frozen metrics/gates + paired baseline | ACC-R16, R18, R19 |
|
||||
| P2-08 | Reproducible CUDA candidate training | P2-05, P2-06, P2-07 | immutable RTX 4080 candidate portfolio | ACC-R14, R16, R17, R24, R25 |
|
||||
| P2-09 | Calibration-only improvement loop | P2-08 | fixed candidate that passes all pre-test gates | ACC-R12, R13, R16 |
|
||||
| P2-10 | Eenmalige protected test | P2-09 | signed pass/fail promotion evidence | ACC-R09, R16, R18 |
|
||||
| P2-11 | Guarded promotion, shadow en redeploy | P2-10 pass | model card, immutable image, rollback | ACC-R17, R19, R25, R27, R29 |
|
||||
| P2-12 | Monitoring en controlled next cycle | P2-11 | reviewed drift queue zonder self-training | blijvende beheersing |
|
||||
|
||||
## P2-00 — Promotion lock en evidence freeze
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Leg current commit, server commit, container digest, DB migration head, active model path/SHA, modelscope en alle P1-evidencehashes vast.
|
||||
- Zet `nationally_validated=false` en de actuele Mol/Kempen-scope expliciet in de capability/model-card response; voorkom scopeverruiming zonder promotion report.
|
||||
- Markeer v56/v58/v62/v66 en andere checkpoints als `candidate/unpromoted`; verander of verwijder geen files.
|
||||
- Maak een restorebare databaseback-up en inventory van storage references vóór migraties.
|
||||
- Bewaar de succesvolle GPU-smoke als runtimebewijs met de expliciete claimgrens “geen accuracy-evidence”.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Evidence manifest is hash-compleet en read-only gekopieerd naar de release-auditlocatie.
|
||||
- Production promotion endpoint/config weigert een kandidaat zonder signed promotion report.
|
||||
- Rollbackdoel (huidige image digest + model SHA + config) is reproduceerbaar vastgelegd.
|
||||
|
||||
## P2-01 — Canonical test harness en rode regressies
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Maak één repo-root testentrypoint voor Python; verwijder de `backend/scripts` versus root `scripts` shadowing.
|
||||
- Voeg vóór productcodewijzigingen regressies toe voor:
|
||||
- EPSG:31370/3812 als 4326 gelabeld;
|
||||
- 100 m buffer als graden;
|
||||
- cross-theme coverage union;
|
||||
- forged authoritative upload;
|
||||
- area-name/YOLO-scope bypass;
|
||||
- Area PATCH geometry/CRS;
|
||||
- ready-derived dataset zonder PostGIS-features;
|
||||
- protected test als samplerinput;
|
||||
- metric null/empty truth table;
|
||||
- persistence- en frontendfallbacks.
|
||||
- Vervang stale broncode-stringasserties door behavior/contracttests; wijzig expected output alleen met een gedocumenteerde contractbeslissing.
|
||||
- Voeg Ruff en een echte frontend `npm run lint` gate toe; behoud typecheck, Vitest en build.
|
||||
- Laat CI dezelfde Python/Node-versies en commands gebruiken als de pinned build; maak een aparte AI-enabled image gate.
|
||||
|
||||
### Verificatiecontract
|
||||
|
||||
De CI-matrix bevat minimaal: volledige backend-Pytest, Alembic offline+live PostGIS, Ruff, frontend lint/typecheck/Vitest/build, OpenAPI-contractaudit en de gerichte GIS/AI regressies. De oude implementatie moet de nieuwe regressies aantoonbaar laten falen; pas daarna worden fixes geaccepteerd.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Eén canonical commandmatrix is volledig groen in een schone checkout.
|
||||
- De 17 bestaande failures zijn per contract geclassificeerd en opgelost.
|
||||
- Geen test wordt geskipt op basis van ontbrekende lokale AI/GIS-dependency zonder expliciete, afzonderlijk rode environment gate.
|
||||
|
||||
## P2-02 — CRS-, eenheden- en geometry-integriteit
|
||||
|
||||
### Uitvoering
|
||||
|
||||
1. Definieer per API/file-ingest het bron-CRS, canonical storage-CRS en output-CRS. Ontbrekende of ambigue CRS faalt met een typed fout.
|
||||
2. Transformeer EPSG:31370 en EPSG:3812 met `pyproj`/GeoPandas/PostGIS naar EPSG:4326 vóór `from_shape(..., srid=4326)`.
|
||||
3. Implementeer buffer via een geldige metrische projectie of PostGIS geography; log units en transform.
|
||||
4. Maak Area PATCH exact conform contract: geometry wordt valide getransformeerd of extra input wordt geweigerd; CRS relabeling zonder transform is onmogelijk.
|
||||
5. Herleid de vier buiten-domein detections uit originele tile, manifest, EPSG:31370-transform en modeloutput. Bewaar oude rijen/evidence; corrigeer via een auditabele migratie of markeer ze `invalid_legacy_geometry`.
|
||||
6. Voeg DB constraints/checks toe waar die legitieme EPSG:4326-extents kunnen afdwingen zonder de Noordzee of grensgebieden fout af te wijzen.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- CRS/units regressies en live PostGIS-tests slagen.
|
||||
- Runtime-audit meldt zero ongeclassificeerde invalid/empty/wrong-SRID/out-of-domain geometry.
|
||||
- De vier legacy detection-ID's zijn traceerbaar vóór en na migratie; geen stille overschrijving.
|
||||
|
||||
## P2-03 — Coverage-, authority- en scopevertrouwen
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Herstructureer coverage zodat alleen datasets die source, theme, layer én zone matchen aan de coverage union deelnemen.
|
||||
- Introduceer immutable `source_registry_id`, trust class, provider adapter en bronversie. Caller metadata blijft descriptief en kan nooit official authority verlenen.
|
||||
- Migreer user uploads naar `manual/untrusted` tenzij hun acquisition/job lineage een governed adapter bewijst.
|
||||
- Vervang displaynaam-gebaseerde legal zones door stable codes en geometry-backed predicates.
|
||||
- Vervang YOLO-name-substringcontrole door model-card scope geometry/zone IDs met expliciete containment-policy.
|
||||
- Maak API/UI onderscheid tussen `available`, `covered`, `authoritative`, `runtime_ready` en `model_validated_for_scope`.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Forged-source-, mixed-theme-, rename- en scope-bypasstests slagen.
|
||||
- Bestaande source records hebben een auditbare trust classification.
|
||||
- Een AOI buiten Mol/Kempen kan het actieve model niet uitvoeren door naam of metadata te manipuleren.
|
||||
|
||||
## P2-04 — Transactionele lineage en zichtbare failures
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Maak een verplicht `RunManifest` met model-ID/version/SHA, dataset/version/SHA, tile-manifest/SHA, source imagery/reference versions, CRS/transform, preprocessing, threshold, NMS/max-det, seed, runtime/container/GPU en code commit.
|
||||
- Maak derived vector persistence atomair: AnalysisRun, Dataset, DatasetVersion, artifact en vector_features gaan samen van `processing` naar `ready`; elke verplichte write failure maakt de run failed.
|
||||
- Classificeer `observed_at` en `source_version` per bronfamilie als required/not-applicable/unknown-with-reason en voer een provenance-safe backfill uit.
|
||||
- Markeer historische detection runs zonder volledige lineage als `lineage_incomplete`; vul modelversies niet afgeleid of op basis van huidige config in.
|
||||
- Verwijder silent catches: UI krijgt een typed error/stale state met run ID; services mogen geen success/ready rapporteren na persistence failure.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Nieuwe analyses zijn van UI-resultaat tot tile, bron, model en container volledig traceerbaar.
|
||||
- Fault-injection geeft failed/incomplete, nooit ready/success.
|
||||
- Lineage-audit heeft zero ongeclassificeerde verplichte gaps voor nieuwe records en een expliciete legacybucket.
|
||||
|
||||
## P2-05 — Protected-split redesign en manifest firewall
|
||||
|
||||
### Uitvoering
|
||||
|
||||
1. Definieer één versioned corpusmanifest met immutable sample-ID, image/label SHA, bronfeature-ID, region/context, provider/edition, imagery/reference time, CRS/resolution, tile/stride/overlap, split en reviewstatus.
|
||||
2. Bereken splits op buffered AOI's vóór tiles worden geëxporteerd. Controleer geometry overlap, contextbuffer, feature-ID's, image/label hashes en perceptuele near-dupes.
|
||||
3. Verplaats protected test en background-test naar een afzonderlijke read-only locatie/credential die de training- en samplerprocessen niet kunnen lezen.
|
||||
4. Splits de huidige orchestrator:
|
||||
- `train/val/calibration loop`: fit, early stopping, threshold en error taxonomy;
|
||||
- `release evaluation`: alleen frozen kandidaat/config en protected credentials.
|
||||
5. Laat de failure-driven sampler uitsluitend calibration-aggregaten en train-only contextcatalogi lezen. Hij moet hard falen zodra een assessment testdata, test-ID's of een protected pad bevat.
|
||||
6. Log iedere protected access met candidate SHA, config SHA, operator/runner, timestamp en output SHA.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Canary protected sample verschijnt in geen enkel train/val/calibration manifest, log, cache of sampleroutput.
|
||||
- Minimum cross-splitafstand voldoet aan de vooraf vastgelegde contextbuffer; 24 huidige near-pairs zijn opgelost of met objectief geometrisch bewijs als onafhankelijk geclassificeerd.
|
||||
- Testcredentials zijn tijdens training technisch niet beschikbaar.
|
||||
|
||||
## P2-06 — Menselijke review en immutable corpusrebuild
|
||||
|
||||
### 1. Review de bestaande kandidaatdata
|
||||
|
||||
- Genereer contact sheets/kaartoverlays voor een vooraf geregistreerde, gestratificeerde reviewqueue: regio, provider, dense urban, suburban, rural, industrial, coast, forest/heath, rail/port/quarry, pure-empty, hard negative, kleine objecten, extreme aspectratio en providerseams.
|
||||
- Beoordeel expliciet de 521 kleine labels, extreme aspectgroepen, sub-resolution/post-imagery exclusions en zeer dichte PICC/UrbIS-labelgebieden.
|
||||
- Sla accept/reject/repair/uncertain op met reviewer, reason code, native feature-ID, image/label version en checksum. `uncertain` blijft uitgesloten of in een afzonderlijke non-training queue.
|
||||
|
||||
### 2. Provision onafhankelijke AOI's
|
||||
|
||||
- Vul iedere vereiste region/context-cel uit het bevroren corpuscontract; voeg Brussels pure-background toe en breid moeilijke negatives uit zonder protected voorbeelden te kopiëren.
|
||||
- Gebruik officiële imagery/reference adapters en leg acquisition edition/periode vast.
|
||||
- Houd train-only uitbreidingen ruimtelijk onafhankelijk van val/calibration/test/background-test en van elkaar waar het contract dat vereist.
|
||||
|
||||
### 3. Herbouw en freeze
|
||||
|
||||
- Pas temporal/resolution/providersemantics toe op GRB, PICC en UrbIS; post-imagery en niet-resolveerbare features krijgen een expliciete rejection reason.
|
||||
- Exporteer deterministisch met ingevulde dataset-YAML/class/tile/stride/overlap-velden.
|
||||
- Run geometry, label, density, class, blank/variance, duplicate/near-duplicate, split-distance, temporal en provenance audits.
|
||||
- Freeze een nieuwe corpusversie; verander v56/v66 niet.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Representatieve menselijke review is volledig; zero unresolved Critical/High findings.
|
||||
- Elke verplichte region/context/background-cel voldoet aan het vooraf bevroren contract.
|
||||
- Zero cross-split leakage/near-duplicate violations; timestamps en unknowns zijn expliciet.
|
||||
- Corpus, reviewrecords, manifests, YAML en auditrapporten zijn SHA-bound en immutable.
|
||||
|
||||
## P2-07 — Metric framework en reproduceerbare incumbent baseline
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Implementeer de truth table uit `05-metric-framework.md` voor empty/no-match/undefined cases; null kan een gate nooit stil passeren.
|
||||
- Meet detection precision, recall, F1 en AP op bevroren IoU-contracten; voeg objectgrootte, dichtheid, region, provider, context en pure-background strata toe.
|
||||
- Behandel calibration en test afzonderlijk. Selecteer threshold/NMS/tile-overlap op calibration met worst-region/worst-context vóór aggregate.
|
||||
- Evalueer het actieve model als incumbent op exact dezelfde niet-protected calibrationportfolio en bewaar paired AOI-resultaten.
|
||||
- Maak FP/FN contact sheets en error taxonomy: label/temporal mismatch, tile-edge, small object, dense cluster, roof displacement, source seam, context confusion en model miss.
|
||||
- Freeze alle numeric gates vóór protected test. Bestaande minimale gates mogen alleen vóór test en op basis van reviewed baseline distributions worden aangescherpt; nooit versoepeld na testinzage.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Twee baseline-runs met dezelfde inputs leveren dezelfde sample/split hashes en metrics binnen vooraf vastgelegde tolerantie.
|
||||
- Alle strata hebben een waarde of expliciete failstatus; zero silently ignored nulls.
|
||||
- Gateconfig, evaluator, incumbent SHA en calibrationresultaat zijn immutable.
|
||||
|
||||
## P2-08 — Reproduceerbare CUDA-training op RTX 4080 SUPER
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Bouw één pinned AI image voor PyTorch/CUDA/Ultralytics; leg image digest, SBOM, driver/runtime, GPU, peak VRAM en code commit vast.
|
||||
- Voer VRAM-preflight uit voor iedere kandidaatconfig; OOM/failure blijft als artifact en mag niet stil naar CPU vallen.
|
||||
- Train een vooraf begrensde matrix zoals vastgelegd in `PYTORCH_TRAINING_ROADMAP_BELGIUM.md`; wijzig matrix noch primary metric na resultaten te zien.
|
||||
- Seed Python/NumPy/PyTorch/Ultralytics; gebruik deterministic algorithms waar ondersteund en registreer afwijkingen.
|
||||
- Training leest uitsluitend train; val kiest epochs/checkpoint; calibration kiest threshold/NMS/tile policy. Protected testmount/credential ontbreekt.
|
||||
- Sla per run config, stdout/stderr, curves, checkpoints, optimizer state, dataset/corpus SHA, seed, runtime en peak VRAM op. Kopieer checkpoints immutably; overschrijf active model nooit.
|
||||
- Herhaal de winnende configuratie clean-room vanaf dezelfde base weights en corpus om reproduceerbaarheid te toetsen.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Alle geplande kandidaten hebben complete run manifests of expliciete failure artifacts.
|
||||
- Minstens één kandidaat en zijn clean-room rerun voldoen aan vooraf bevroren reproducibilitytoleranties.
|
||||
- GPU-evidence toont RTX 4080 SUPER/`cuda:0`; zero CPU fallback; protected-accesslog blijft leeg.
|
||||
|
||||
## P2-09 — Calibration-only verbeterloop
|
||||
|
||||
De loop mag worden herhaald, maar alleen binnen de volgende state machine:
|
||||
|
||||
```text
|
||||
reviewed immutable corpus
|
||||
-> CUDA train
|
||||
-> validation checkpoint selection
|
||||
-> calibration + error taxonomy
|
||||
-> all pre-test gates pass?
|
||||
no -> provision independent train-only AOIs / reviewed labels
|
||||
-> freeze new corpus version -> CUDA train
|
||||
yes -> freeze candidate SHA + preprocessing + threshold + gates
|
||||
-> P2-10 protected test
|
||||
```
|
||||
|
||||
### Regels
|
||||
|
||||
- Calibrationresultaten mogen aangeven welke regio/context faalt, maar nooit protected sample-ID's of testresultaten.
|
||||
- Nieuwe voorbeelden komen uit onafhankelijk geprovisioneerde train-only AOI's en doorlopen dezelfde provenance, temporal en human-reviewgates.
|
||||
- Een corpuswijziging maakt een nieuwe immutable corpusversie en een nieuwe run family; bestaande evidence blijft behouden.
|
||||
- De loop stopt niet op aggregate F1 alleen. Iedere regionale/context-, background-, lineage-, runtime- en reviewgate moet groen zijn.
|
||||
- Indien geen betrouwbare labels of onafhankelijke AOI's beschikbaar zijn, is de correcte status `blocked/not_validated`, niet een afgezwakte gate.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Eén candidate SHA passeert alle vooraf bevroren validation/calibration-, regional/context-, pure-background-calibration-, runtime-, lineage- en reviewgates.
|
||||
- Candidate, threshold, NMS, tileconfig, corpus en evaluator zijn daarna read-only bevroren.
|
||||
|
||||
## P2-10 — Eenmalige protected-testbeslissing
|
||||
|
||||
### Voorwaarden vóór openen
|
||||
|
||||
- P2-00 tot P2-09 zijn groen.
|
||||
- Candidate/model SHA, container digest, corpus SHA, preprocessing, threshold, evaluator en numeric gates zijn gesigneerd/bevroren.
|
||||
- Test/background-test manifesthashes bestaan, maar hun inhoud was niet toegankelijk voor train/calibration runners.
|
||||
- Promotion policy specificeert vooraf wat pass, fail en infrastructure-invalid betekent.
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Start één isolated release-evaluation job met read-only protected credentials op `cuda:0`.
|
||||
- Bereken alle bevroren regionale/context/object-size en background-test metrics; produceer contact sheets en machine-readable gate decision.
|
||||
- Een infrastructure-invalid run mag uitsluitend opnieuw worden uitgevoerd wanneer bewijs aantoont dat geen bruikbaar modelresultaat is vrijgegeven; de incidentbeslissing wordt gelogd.
|
||||
|
||||
### Beslissing
|
||||
|
||||
- **Pass:** ga naar P2-11; resultaten mogen niet worden gebruikt om alsnog threshold/config te wijzigen.
|
||||
- **Fail:** release blijft blocked. Train deze candidate family niet verder op basis van het testresultaat. Archiveer de beslissing; een volgende poging vereist een nieuw vooraf geregistreerd ontwikkelprogramma en een nieuwe onaangeroerde protected portfolio.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Exact één geldig access event en één immutable report voor candidate SHA.
|
||||
- Geen write naar corpus/training config na testopening.
|
||||
- Alle gates zijn groen; anders is P2-11 niet bereikbaar.
|
||||
|
||||
## P2-11 — Guarded promotion, shadow en redeploy
|
||||
|
||||
### Uitvoering
|
||||
|
||||
1. Genereer model card en promotion report met task, class, scope, imagery/reference versions, known limitations, metrics per stratum, calibration, test, runtime, lineage en rollbackmodel.
|
||||
2. Kopieer de kandidaat naar een immutable model-ID/version/SHA-pad; overschrijf het actieve `.pt`-bestand niet.
|
||||
3. Bouw/push één immutable GPU image vanaf een gepushte commit/tag; leg image digest en SBOM vast.
|
||||
4. Migreer DB/schema via backup, dry-run en restoretest; voer PostGIS extension-upgrade alleen volgens P2-evidence uit.
|
||||
5. Draai production preflight: exact modelhash, CUDA required, bounded tile inference, CRS/georeferencing, persistence en restart.
|
||||
6. Start shadowvergelijking binnen exact de gevalideerde scope; shadowoutput is niet publiek en kan de protected-testbeslissing niet aanpassen.
|
||||
7. Laat UI/API alleen de bewezen scope/classes/status zien; segmentatie en solar blijven `not_configured`.
|
||||
8. Activeer pas na shadow- en rollbackgate; monitor en behoud één-command rollback naar vorige image/model/config.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Commit/tag, image digest, model SHA, config SHA, migration head en promotion report verwijzen wederzijds naar elkaar.
|
||||
- End-to-end selectie → inference → persisted result → uitschuifbare inzichten → export is getest met correcte lineage en zichtbare error states.
|
||||
- Restart en rollback slagen zonder data- of evidenceverlies.
|
||||
- De gedeclareerde scope is exact de geslaagde testscope, nooit “heel België” door implicatie.
|
||||
|
||||
## P2-12 — Monitoring en gecontroleerde volgende cyclus
|
||||
|
||||
### Uitvoering
|
||||
|
||||
- Monitor per region/context/provider/imagery edition/object size: input drift, confidence, density, QA mismatches, latency/VRAM en persistence failures.
|
||||
- Maak een menselijke reviewqueue met FP/FN/uncertain voorbeelden; production outputs worden nooit automatisch training labels.
|
||||
- Een volgende training gebruikt alleen een reviewed, opnieuw gefreezede labelrelease en herstart bij P2-05/P2-06.
|
||||
- Bewaar oude datasets, modellen, run manifests, promotion reports en rollbackimages volgens retentiebeleid.
|
||||
- Widening van scope of class is een nieuwe releaseclaim en doorloopt opnieuw P2-06 tot P2-11 met een onaangeroerde testportfolio.
|
||||
|
||||
### Exit gate
|
||||
|
||||
- Alerts, reviewqueue, ownership en rollbackrunbook zijn operationeel getest.
|
||||
- Er bestaat geen automatische self-training of silent promotion path.
|
||||
- Periodieke audits kunnen ieder publiek resultaat terugvoeren naar bron, tile, model, config en releasebeslissing.
|
||||
|
||||
## Verplichte release-evidence
|
||||
|
||||
P2-11 blijft geblokkeerd zolang één van deze artifacts ontbreekt:
|
||||
|
||||
- canonical CI commandmatrix en logs;
|
||||
- CRS/coverage/authority/scope regressierapport;
|
||||
- DB migration, backup/restore en legacy-quarantainerapport;
|
||||
- trusted source registry en lineage completeness audit;
|
||||
- immutable corpus, split/duplicate/temporal/label audits en human-reviewmanifest;
|
||||
- pinned AI image digest/SBOM en RTX 4080 CUDA run manifests;
|
||||
- reproducible incumbent/candidate calibrationrapporten;
|
||||
- vooraf bevroren gateconfig;
|
||||
- één protected-test/background-test accesslog en report;
|
||||
- model card, signed promotion report, shadow report en rollbacktest;
|
||||
- bijgewerkte API/contracts, limitations, execution log en TODO.
|
||||
|
||||
## Stop-the-line criteria
|
||||
|
||||
Stop de betrokken pipeline en behoud `release blocked` wanneer:
|
||||
|
||||
- protected data vóór de freeze wordt gelezen of in sampler/training evidence voorkomt;
|
||||
- een geometry zonder betrouwbare CRS of een meteroperatie in graden wordt verwerkt;
|
||||
- user metadata officiële authority kan verlenen;
|
||||
- model/dataset/tile/config hashes ontbreken;
|
||||
- een verplichte metric null/ontbrekend is;
|
||||
- menselijke labelreview Critical/High findings openlaat;
|
||||
- training niet aantoonbaar op de vereiste NVIDIA GPU draait;
|
||||
- een regio/context/background-gate faalt;
|
||||
- de protected test faalt;
|
||||
- deploy commit, image, model, DB migration en promotion report niet exact aan elkaar gebonden zijn.
|
||||
|
||||
Alleen bewijs kan een gate openen. Een nieuwe training, hogere epoch count of gunstig aggregate cijfer kan een ontbrekende lineage-, split-, regionale, menselijke of deploymentgate niet compenseren.
|
||||
@@ -1,330 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — 07 Bronautoriteitsmatrix
|
||||
|
||||
- Status: Fase-2 implementatie in uitvoering; normatief beleid en gerealiseerde bronfundering
|
||||
- Scope: België en de Belgische Noordzee
|
||||
- Samenhang: 00-execution-contract, 02-data-lineage, 04-risk-register, 05-metric-framework en 08-data-contracts
|
||||
- Beslissing: een bronnaam in een upload, feature, dataset of UI-label verleent nooit zelf autoriteit.
|
||||
|
||||
## 0. Gerealiseerde Phase-2-fundering en grens
|
||||
|
||||
De repository bevat nu een server-owned registry in
|
||||
`backend/app/services/source_registry_service.py`, de persistente modellen
|
||||
`SourceRegistry` en `SourceSnapshot`, migratie `202608010001`, en expliciete
|
||||
Dataset/DatasetVersion-koppelingen. Elke nieuwe governed import schrijft een
|
||||
checksumgebonden snapshot, exacte contractversie en validatierapport. Een
|
||||
handmatige upload wordt altijd aan `manual` gebonden; een meegegeven
|
||||
`source_name=grb` blijft slechts een descriptieve claim.
|
||||
|
||||
Dit maakt geen oude Tower-datasets, bestaande modelgewichten of een
|
||||
historische bronnaam alsnog betrouwbaar. De migratie behoudt die rijen maar
|
||||
markeert ontbrekende provenance als `incomplete/not_validated`. Zij blijven
|
||||
niet inzetbaar voor training, productie-inferentie, primaire QA of
|
||||
authoritative coverage tot een nieuwe governed ingest een eigen snapshot en
|
||||
contractrapport heeft vastgelegd.
|
||||
|
||||
## 1. Doel en claimgrens
|
||||
|
||||
Dit document bepaalt welke bron beslissend, aanvullend of uitsluitend
|
||||
contextueel mag zijn voor elk GeoIntel-resultaat. Het maakt twee vragen
|
||||
expliciet verschillend:
|
||||
|
||||
1. welke organisatie of productfamilie is gezaghebbend voor een concrete
|
||||
bewering;
|
||||
2. is de concrete snapshot ook werkelijk met server-attested provenance,
|
||||
versie, licentie, CRS, dekking en integriteitscontrole beschikbaar?
|
||||
|
||||
Een officiële publicatie zonder gecontroleerde snapshot is geen geactiveerde
|
||||
autoriteit in een resultaat. Omgekeerd maakt een bestand met source_name=grb
|
||||
of een UI-label “officieel” een handmatige upload nooit gezaghebbend. Dit
|
||||
herstelt de door Phase 1 gereproduceerde ACC-R04-breuk.
|
||||
|
||||
Autoriteit is taak-, zone-, product- en tijdsgebonden. Een bron kan dus
|
||||
authoritative zijn voor één bewering en slechts corroborative of contextual
|
||||
voor een andere. De classificatie is geen kwaliteitsoordeel over de bron en
|
||||
maakt geen algemene België-claim.
|
||||
|
||||
## 2. Verplichte classificaties
|
||||
|
||||
| Klasse | Betekenis | Mag beslissend zijn? | Minimale server-attested voorwaarden |
|
||||
|---|---|---|---|
|
||||
| authoritative | Formeel bevoegde bron voor een afgebakende taak, zone en productversie. | Alleen voor de exact geregistreerde taak, dekking en tijd. | Goedgekeurde registry-entry, publisher/collection allowlist, snapshot- of editie-identiteit, checksum, licentie/attributie, CRS/eenheden, ruimtelijke en temporele dekking, succesvolle contractvalidatie. |
|
||||
| corroborative | Onafhankelijke aanvullende bron die een resultaat kan controleren, duiden of van een status voorzien. | Nee; zij kan een mismatch of onzekerheid creëren, maar overschrijft de primaire referentie niet automatisch. | Zelfde minimale provenance als voor authoritative, plus een expliciete comparison/reconciliation policy. |
|
||||
| contextual | Bron voor kaartcontext, interpretatie, kandidaatselectie of reviewhulp. | Nee. Niet gebruiken als label-, truth- of promotionbeslissing. | Duidelijke attributie/licentie en expliciete limitation; ontbreken daarvan maakt de context onbeschikbaar. |
|
||||
| derived | Door GeoIntel of een geregistreerde transformatie afgeleid artefact. | Alleen als afgeleide metriek met volledige upstream-lineage; nooit als nieuwe externe autoriteit. | Immutable inputhashes, transformatie/code/config-hash, outputchecksum, validatie en parent-lineage. |
|
||||
| experimental | Fixture, handmatige upload, proefbron, niet-gevalideerde adapter of niet-beoordeeld model-/labelartefact. | Nee voor productie, training, QA-waarheid, dekking of promotie. | Herkenbaar als experimental/manual/untrusted; expliciete operatorbeperking en quarantainestatus wanneer ongeschikt. |
|
||||
|
||||
De registry bewaart de klasse als server-owned beleid; de seeding- of
|
||||
definition-revisie staat in de registrymetadata. Een datasetrecord kopieert
|
||||
die klasse niet vrij tekstueel: het bindt een concrete registry-entry én een
|
||||
immutable source snapshot met checksum. De ingestlaag schrijft de effectieve
|
||||
trust/authority-status zelf. Er is in deze eerste P2-migratie bewust nog geen
|
||||
los mutable UI-veld dat als historische "registry-versie" kan worden
|
||||
misbruikt; een snapshot/checksum blijft de concrete evidence-identiteit.
|
||||
|
||||
## 3. Bronautoriteit voor gebouwresultaten
|
||||
|
||||
### 3.1 Beslissingsregel
|
||||
|
||||
Een gebouwgerelateerde validatie kiest eerst de zone, vervolgens de concrete
|
||||
taak en ten slotte de geregistreerde bronversie. Een referentielaag is pas
|
||||
bruikbaar als geometry-, tijd-, resolutie-, feature-identity- en
|
||||
provenancecontracten groen zijn.
|
||||
|
||||
| Zone en taak | Primaire referentie | Rol van andere bronnen | Geen-claim / fallbackregel |
|
||||
|---|---|---|---|
|
||||
| Vlaanderen: footprint- of gebouwdetectievalidatie | GRB GBG is authoritative en primaire gezagsbron, voor zover de gekozen GRB-snapshot, dekking, beeld/referentietijd en taak dat rechtvaardigen. | Gebouwenregister kan identiteit/lifecycle en GRB-reconciliation corroboreren; orthofoto is waarnemingsinput; DHMV en OSM zijn niet beslissend. | Geen governed, passend GRB-datasetversie betekent not_evaluable of partial; nooit stil OSM, een upload of een oude/onbekende snapshot als truth inzetten. |
|
||||
| Wallonië: footprint- of gebouwdetectievalidatie | Alleen een expliciet governed PICC-building-product kan authoritative zijn voor zijn eigen product/versie/zone. | GRB heeft geen Vlaamse autoriteit buiten Vlaanderen. Orthofoto, DHMV en OSM zijn slechts volgens hun eigen rol bruikbaar. | Geen semantische pariteit met GRB aannemen; cross-region aggregate blijft not_evaluable totdat een bevroren harmonisatiecontract bestaat. |
|
||||
| Brussel: footprint- of gebouwdetectievalidatie | Alleen een expliciet governed UrbIS-building-product kan authoritative zijn voor zijn eigen product/versie/zone. | Gebouwenregister en GRB zijn niet automatisch Brusselse truth. OSM/imagery blijven niet-beslissend. | Geen governed UrbIS-versie betekent not_evaluable/partial; geen regionale substitutie. |
|
||||
| Zoneoverschrijdend België-resultaat | Een per-zone, per-versie gevalideerde portfolio van de bovenstaande referenties. | Alleen vergelijkbare ontologie, tijd, resolutie, matchingpolicy en metriek mogen later geaggregeerd worden. | Een Belgisch cijfer mag geen ontbrekende of mislukte zone verbergen; zonder alle verplichte strata is de status not_evaluable. |
|
||||
| Gebouwstatus, units en adressen in Vlaanderen | Gebouwen- en Adressenregister is authoritative voor zijn geregistreerde object-/statussemantiek binnen de gedateerde snapshot. | GRB is corroborative voor geometrische reconciliatie; registerstatus is geen GRB-footprint en omgekeerd. | Units/adressen zijn geen woningen, huishoudens, bewoners, volume of modeltruth. |
|
||||
|
||||
GRB is dus de primaire geometrische validatiereferentie voor een passende
|
||||
Vlaamse building-taak, niet een automatische waarheid voor elk gebouw, iedere
|
||||
tijd of andere regio. De registerstatus of een zichtbaar dak in imagery kan
|
||||
een reviewfinding opleveren, maar vervangt een geldige referentie niet zonder
|
||||
vooraf bevroren adjudicatiebeleid.
|
||||
|
||||
### 3.2 Verboden automatische substituties
|
||||
|
||||
- OSM mag nooit automatisch als building ground truth, labelbron of
|
||||
promotie-referentie worden gebruikt.
|
||||
- Sentinel-2 mag nooit als building ground truth, footprintlabel of
|
||||
fine-grained objectvalidatie worden gebruikt.
|
||||
- DHMV DTM/DSM mag nooit een gebouwfootprint, gebouwhoogte, waterdiepte of
|
||||
gebouwtruth fabriceren.
|
||||
- Een Gebouwenregister-snapshot mag GRB niet automatisch vervangen als
|
||||
primaire footprintreferentie; zijn lifecycle-/registersemantiek blijft
|
||||
afzonderlijk.
|
||||
- Een derived GeoIntel-laag, YOLO-detectie, segmentatie of kaartselectie mag
|
||||
nooit zijn eigen referentie zijn.
|
||||
- Wanneer de primaire bron niet beschikbaar, verlopen, temporeel ongeschikt
|
||||
of contractueel ongeldig is, retourneert GeoIntel expliciet
|
||||
not_configured, partial, unavailable of not_evaluable. Geen fallback mag
|
||||
als geslaagde primaire validatie worden weergegeven.
|
||||
|
||||
Een concrete source snapshot is alleen consumeerbaar wanneer zijn
|
||||
`freshness_status` `current` of expliciet `not_applicable` is. `unknown`,
|
||||
`review_required`, `due` en `stale` worden aan elke productiegrens
|
||||
geblokkeerd, ook wanneer de registry-familie op zichzelf authoritative is.
|
||||
Een historische bron die bewust bruikbaar blijft, moet dus expliciet door
|
||||
zijn contract als `not_applicable` zijn gemotiveerd; een ontbrekende of oude
|
||||
status is geen stilzwijgende uitzondering.
|
||||
|
||||
## 4. Matrix van governable source families
|
||||
|
||||
De volgende matrix onderscheidt de beleidsrol van een bron van de actuele
|
||||
implementatiestatus. “Implemented” betekent uitsluitend dat een begrensde
|
||||
code-/operatorroute is aangetroffen; het betekent niet dat iedere opgeslagen
|
||||
dataset al aan het Fase-2 registry-contract voldoet.
|
||||
|
||||
| Registry source id | Klasse per taak | Autoriteit en toepassingsgebied | Toegelaten gebruik | Verboden/limieten | Stand op 2026-08-01 |
|
||||
|---|---|---|---|---|---|
|
||||
| grb | authoritative voor Vlaamse GRB-producten; primary voor passende building-footprintvalidatie | Digitaal Vlaanderen; Vlaanderen; GBG, Wegsegment, WTZ/WLAS/WGR en ADP volgens product allowlist | Referentievector, ruimtelijke QA, footprint-/lengte-/oppervlaktemetingen binnen productsemantiek | Geen juridische perceelgrens, vloeroppervlakte, volume, waterdiepte of tijdloze fysieke verandering claimen | Governed OGC acquisition en registry/snapshot/contractbinding zijn geïmplementeerd; een concrete snapshot blijft alleen primary-eligible wanneer taak-, zone-, tijd- en contractchecks slagen. |
|
||||
| digitaal_vlaanderen_buildings_addresses_register | authoritative voor geregistreerde gebouw-/unit-/adresstatus; corroborative voor footprintreconciliatie | Digitaal Vlaanderen; gedateerde gemeentelijke snapshot; Gebouw, Gebouweenheid en Adres | Registerstatus, stable objectidentity, aggregate unit/adrescontext, GRB-matchreview | Geen automatische vervanger voor GRB footprinttruth; geen persoonsgegevens/adreslabels als featureoutput; geen demografieclaim | Server-owned registry-entry en task policy bestaan; zonder concrete governed snapshot blijft dit een niet-geactiveerde autoriteit. |
|
||||
| spw_picc | authoritative voor de goedgekeurde PICC building-taak in Wallonië | SPW; Wallonië; exact product/edition en zone | Regionale building reference/QA binnen vastgelegde semantics | Geen GRB-semantic parity of Vlaamse/nationale extrapolatie | Governed official-vector ingest schrijft registry/snapshot/contractbinding; per-versie semantische acceptance en cross-region harmonisatie blijven afzonderlijke gates. |
|
||||
| urbis | authoritative voor de goedgekeurde UrbIS building-taak in Brussel | Paradigm/competente Brusselse instantie; Brussels Hoofdstedelijk Gewest | Regionale building reference/QA binnen vastgelegde semantics | Geen automatische parity met GRB/PICC of nationale claim | Governed official-vector ingest schrijft registry/snapshot/contractbinding; per-versie semantische acceptance en cross-region harmonisatie blijven afzonderlijke gates. |
|
||||
| digitaal_vlaanderen_orthophoto | contextual als imagery; observatie-input voor matching en review | Digitaal Vlaanderen; Vlaanderen; product-/vlucht-/editiegebonden | Inference input, visuele labelreview, temporal alignmentcontrole | Geen truth zonder onafhankelijke reference; latest is geen per-pixel observed_at | Governed acquisition en centrale contractvalidatie zijn geïmplementeerd; source version/time blijft per product/snapshot aantoonbaar. |
|
||||
| spw_orthophoto | contextual als imagery | SPW; Wallonië; product-/editiegebonden | Inference input en review | Geen building truth of semantische parity claim | Implemented governed acquisition volgens API-contract; registry/contractgate vereist |
|
||||
| urbis_orthophoto | contextual als imagery | Paradigm; Brussel; product-/editiegebonden | Inference input en review | Geen building truth of semantische parity claim | Implemented governed acquisition volgens API-contract; registry/contractgate vereist |
|
||||
| sentinel_2 | contextual, pas na eigen registered contract | Copernicus/Sentinel-2; sensor-, tile-, processing-level- en acquisitiongebonden | Coarse land-cover/vegetation/temporal context wanneer contract en resolution passend zijn | Nooit building ground truth, footprintlabel, fine building QA of stille fallback voor orthofoto | Planned/not configured: health en API markeren Sentinel als planned/disabled; geen governed ingestadapter aangetroffen |
|
||||
| digitaal_vlaanderen_dhmv | authoritative voor exact declared elevation product; corroborative voor terrain/elevation bij building reviews | Digitaal Vlaanderen; Vlaanderen; DHMV II DTM/DSM, EPSG:31370, TAW, 2013-2015 | Terrain/reliëf/slope, elevationcontext en review van plausibiliteit | Geen building footprinttruth, directe gebouwhoogte, waterdiepte of volume | Bounded WCS acquisition plus registry/snapshot/raster-contractgate zijn geïmplementeerd; verticale productsemantiek blijft source-specifiek gecontroleerd. |
|
||||
| osm | contextual; eventueel corroborative alleen onder vooraf vastgelegd onderzoek/handmatige review | OpenStreetMap contributors; vrijwillig bijgewerkte werelddekking | Kaartcontext, kandidaat-/confuserinventaris, menselijke reviewhulp | Nooit automatische ground truth, primary reference, labelbron of coverage-authority | Provider bestaat maar live Overpass/download is not_configured |
|
||||
| ngi_adminvector, statbel, rbins en andere competentiebronnen | authoritative uitsluitend voor hun eigen bestuurlijke, statistische of maritieme taak | Bevoegde federale/regionale/maritieme instantie en exacte source family | Scope, context en bron-specifieke metrics | Geen building labels tenzij expliciet geregistreerde productsemantiek dat toelaat | De geregistreerde source families hebben server-owned class/policy records; niet-gegovernde historische rows blijven expliciet onvolledig. |
|
||||
| manual | experimental/untrusted | Door gebruiker aangeleverd; autoriteit onbekend tenzij later formeel ingestbewijs is gekoppeld | Privé-projectcontext of expliciete operatorreview | Nooit officiële authoriteit, coverage, trainingtruth of promotionbasis op naam alleen | Implemented uploadflow; Phase 1 bewees spoofability van source_name en maakt migratie naar manual/untrusted verplicht |
|
||||
| fixture | experimental | Lokale test- en demofiles | Unit/integratietests en expliciete demo | Nooit productie, nationale metric, source authority of trainingclaim | Implemented and explicitly marked fixture provider |
|
||||
| derived, map_selection en training_label | derived | GeoIntel-transformatie van bekende parents | Datasets, tiles, metrics, exports met volledige parent-lineage | Geen externe source authority, geen verbergen van incomplete parent | Vector/raster-mapoperaties registreren `derived`/`map_selection`, outputchecksum, contractrapport en parent-edge; ontbrekende of ongeschikte parent leidt tot quarantine. |
|
||||
| labels en modelartefacten | derived of experimental tot volledig governed | Corpus/label-/trainingrelease | Alleen volgens 08-data-contracts en split/firewallbeleid | Geen training/promotion bij onbekende bron, review, split of hash | V56/V58/V62/V66 evidence is incomplete for release; nationale claim blocked |
|
||||
|
||||
### 4.1 Licentie- en gebruiksgrenzen per bronprofiel
|
||||
|
||||
Een registry-entry bewaart momenteel de family-level licentie of
|
||||
gebruiksvoorwaarde. Een generieke tekst als “official” is niet voldoende, en
|
||||
wordt niet automatisch een snapshot-specifieke licentie-eigenschap. De actuele
|
||||
startinventaris ondersteunt alleen de volgende begrensde uitspraken:
|
||||
|
||||
| Bronprofiel | Vastgelegde of vereiste licentie-/attributiegrens |
|
||||
|---|---|
|
||||
| GRB | De bestaande governed adapter bewaart de Digitaal Vlaanderen-attributie en verwijst naar hergebruik volgens de open-datavoorwaarden en bronvermelding. Elke snapshot bewaart de gebruikte catalogue/product identity; een onbekende licentie is niet primary-QA-eligible. |
|
||||
| Gebouwen- en Adressenregister | De operator bewaart bron-URL's, catalogue URL en Digitaal Vlaanderen-attributie, maar de nieuwe registry moet de concrete hergebruiksvoorwaarde per snapshot vastleggen. Privacy-minimalisatie is verplicht: adreslabels, straat-, huis- en busnummers komen niet in queryable vectorfeatures. |
|
||||
| DHMV | De bestaande adapter vermeldt het gebruiksrecht voor geografische webdiensten van Digitaal Vlaanderen en bronvermelding. Zij mag geen verticale datum, hoogtesemantiek of resolutie herinterpreteren. |
|
||||
| PICC en UrbIS | De API-contracten documenteren bekende SPW- respectievelijk Paradigm/FPS Finance-licentienoten. Snapshot-specifieke licentietekst/versie, attribution en redistribution-restrictie zijn nog geen getypeerde P2-velden; een adapter mag ze voorlopig alleen aanvullend in `snapshot_metadata_json` bewaren. Een productcontract dat deze evidence vereist, moet een ontbrekend veld expliciet laten falen of quarantainen. |
|
||||
| OSM | OSM is onder ODbL met verplichte attributie volgens de bestaande providercapability. Afgeleide of gecombineerde OSM-output volgt de toepasselijke ODbL-verplichtingen en blijft nooit automatic truth. |
|
||||
| Sentinel-2 | Vóór een toekomstige adapter activeert, legt de registry de exacte Copernicus/Sentinel productlicentie, verwerking, attribution en redistributionvoorwaarden vast. Zonder die snapshot is Sentinel not_configured. |
|
||||
| Manual, fixture en derived | De uploader/producer kan een licentie beschrijven maar niet authoriteit verlenen. Ontbrekende of onverenigbare gebruiksrechten blokkeren training, publicatie en herdistributie. |
|
||||
|
||||
### 4.2 Verplichte migratie van alle waargenomen source_name-waarden
|
||||
|
||||
Phase 1 zag 28 verschillende source_name-waarden in de Tower-database. De
|
||||
volgende tabel is de migratieregistratie: een klasse is pas activeerbaar na
|
||||
controle van publisher, product, licentie en snapshot. De tabel verheft geen
|
||||
historische row met die naam automatisch tot trusted data.
|
||||
|
||||
| Bestaande source_name | Initiële registry-klasse | Afbakening |
|
||||
|---|---|---|
|
||||
| grb | authoritative | Alleen GRB-product/zone/versie volgens de governed allowlist; primary building footprint reference enkel in Vlaanderen. |
|
||||
| digitaal_vlaanderen_buildings_addresses_register | authoritative + corroborative | Authoritative registersemantiek; corroborative voor footprintreconciliatie. |
|
||||
| spw_picc | authoritative | Alleen de allowlisted PICC productfamilie in Wallonië; geen GRB-pariteit. |
|
||||
| urbis | authoritative | Alleen de allowlisted UrbIS productfamilie in Brussel; geen GRB/PICC-pariteit. |
|
||||
| digitaal_vlaanderen_dhmv | authoritative + corroborative | Authoritative elevation product; corroborative in building-reviewcontext. |
|
||||
| digitaal_vlaanderen_orthophoto | contextual | Official imageryinput, nooit automatic reference truth. |
|
||||
| spw_orthophoto | contextual | Walloon imageryinput, nooit automatic reference truth. |
|
||||
| urbis_orthophoto | contextual | Brussels imageryinput, nooit automatic reference truth. |
|
||||
| vmm_flood_hazard | authoritative | Alleen voor geregistreerde scenario-/overstromingssemantiek; geen observed_at fabriceren. |
|
||||
| vmm_vha_bathymetry_profiles | authoritative | Alleen voor exact profiel, datum en verticale referentie; geen raster/depth extrapolatie. |
|
||||
| department_omgeving_thematic_raster | authoritative | Alleen voor de specifieke Vlaamse klasse/productdefinitie. |
|
||||
| department_omgeving_land_use | authoritative | Alleen voor de geregistreerde landgebruikeditie/klasse. |
|
||||
| agentschap_landbouw_zeevisserij_agricultural_parcels | authoritative | Alleen voor declared agricultural use per jaar; geen eigendom/gebouwtruth. |
|
||||
| waterinfo | authoritative | Alleen voor exact meetreeks-/station-/tijdcontract. |
|
||||
| statbel | authoritative | Alleen voor statistische publicaties en hun aggregatieniveau. |
|
||||
| ngi_adminvector | authoritative | Alleen voor governed administratieve scope. |
|
||||
| rbins_marine_reporting_units | authoritative | Alleen voor mariene rapportage-eenheden en exact legal scope. |
|
||||
| rbins_msp_2026 | authoritative | Alleen voor het vastgelegde mariene plan/edition. |
|
||||
| vrbg | authoritative | Alleen voor het wegregister en zijn eigen semantiek. |
|
||||
| dov_soil_map | authoritative | Alleen voor bodemkaart/surveyperiode; geen actuele ground truth insinueren. |
|
||||
| inbo_bwk_natura2000 | authoritative | Alleen voor de vastgelegde natuur-/habitatproductsemantiek. |
|
||||
| spw_walous_land_cover | authoritative | Alleen voor de vastgelegde Waalse landbedekkingsclassificatie. |
|
||||
| spw_bathymetry | authoritative | Alleen met CRS, verticale referentie, surveyperiode en archive identity. |
|
||||
| spw_terrain | corroborative | Alleen voor de vastgelegde terreincontext/reconciliatie; geen zelfstandige authoritative claim zonder een toekomstige productpolicy. |
|
||||
| historical_landuse | corroborative | Alleen als historische context met bron-, editie-, partition- en identity evidence; objecthistory blijft disabled wanneer identity_stable=false. |
|
||||
| manual | experimental | Manual/untrusted totdat een aparte governed re-ingest een nieuwe accepted snapshot oplevert. |
|
||||
| fixture | experimental | Alleen test/demo. |
|
||||
| map_selection | derived | Alleen een GeoIntel-selectie; nooit externe bron, reference of trainingtruth. |
|
||||
|
||||
## 5. Centrale source registry: gerealiseerd datamodel en normatieve uitbreiding
|
||||
|
||||
### 5.1 Registry-entry versus snapshot
|
||||
|
||||
De centrale registry heeft twee server-owned lagen:
|
||||
|
||||
1. SourceDefinition: het server-owned beleid voor een source family/product;
|
||||
2. SourceSnapshot: de concrete, checksummed acquisitie of
|
||||
editie die een DatasetVersion mag voeden.
|
||||
|
||||
Een SourceDefinition wordt niet door een client in een uploadformulier
|
||||
aangemaakt. Een SourceSnapshot kan alleen door een governed adapter of een
|
||||
expliciet reviewed operator-import aan een Definition worden gebonden. Een
|
||||
handmatige upload verwijst uitsluitend naar de server-owned manual Definition
|
||||
met trust_class=experimental/untrusted.
|
||||
|
||||
### 5.2 Verplichte SourceDefinition-velden
|
||||
|
||||
| Veldgroep | Verplichte inhoud |
|
||||
|---|---|
|
||||
| identity | getypeerd: immutable source_registry_id, source_key, display name, publisher/authority en registry definition revision in `registry_metadata_json`; toekomstig normatief: afzonderlijke registry-version en deprecated lifecycle |
|
||||
| authority | source class, trust class, allowed task claims, reference priority, allowed zones/legal scope IDs, forbidden claims en fallbackbeleid |
|
||||
| access/licence | governed endpoint/catalogue allowlist, attribution template, licence/use/redistribution restrictions, credentials/secret reference buiten de registry-payload |
|
||||
| spatial | native CRS, canonical storage CRS, approved metric CRS strategy, units inclusief verticale referentie indien relevant, native resolution/scale, expected geometry families/bands |
|
||||
| temporal | getypeerd: source-version policy, temporal/geografische coverage JSON en freshness policy; toekomstig normatief: afzonderlijke published/observed/valid requirementvelden per product |
|
||||
| schema | contract id/version voor raster, vector, label of model, expected collections, feature-id strategy, required/optional attributes, topology/attribute constraints |
|
||||
| operations | approved acquisition adapter, request limits, cache/idempotency policy, allowed transformations, provenance requirements en quarantine routing |
|
||||
| limitations | source-native semantic beperkingen, comparison exclusions, privacy restrictions, known gaps en operator note |
|
||||
|
||||
### 5.3 SourceSnapshot-velden: gerealiseerd versus normatief
|
||||
|
||||
De getypeerde P2-tabel bevat `source_registry_id`, `snapshot_key`,
|
||||
`source_version`, `snapshot_at`, `fetched_at`, `source_url`,
|
||||
`checksum_sha256`, `crs`, `units`, resolution-, temporal- en coverage-JSON,
|
||||
observed-schema JSON, `freshness_status`, `ingest_status`, known limitations
|
||||
en `snapshot_metadata_json`. De registry-entry bewaart de bronlicentie,
|
||||
licentie-URL en gebruiksbeperkingen. Deze velden worden samen met de
|
||||
Dataset/DatasetVersion-contractversie en validation report gebruikt voor
|
||||
consumeerbare provenance.
|
||||
|
||||
`published_at`, afzonderlijke request-/collection identity,
|
||||
snapshot-specifieke licentie/attributie, validation-report-hash en
|
||||
immutable-manifest-hash zijn in de huidige P2-opslag geen afzonderlijke
|
||||
getypeerde kolommen. Wanneer een adapter ze kent, bewaart hij ze alleen als
|
||||
aanvullende `snapshot_metadata_json`; afwezigheid mag geen primary, training-
|
||||
of productieclaim opleveren wanneer het relevante contract ze vereist. Zij
|
||||
blijven een expliciete normatieve uitbreiding, geen reeds gerealiseerde
|
||||
kolommen.
|
||||
|
||||
Fetchtime is nooit een vervanging voor observed_at. Een bron waarvoor een
|
||||
observatietijd niet bestaat, gebruikt in het datacontract een expliciete
|
||||
`not_applicable` of `unknown_with_reason`-reden; die tweede term is een
|
||||
contractbeslissing en geen waarde van `SourceSnapshot.freshness_status`.
|
||||
|
||||
## 6. Freshness, ingest en authority states
|
||||
|
||||
### 6.1 Freshness
|
||||
|
||||
De P2 registry en snapshot gebruiken exact `unknown`, `current`, `due`,
|
||||
`stale`, `not_applicable` en `review_required`. Fase 2 bindt die betekenis aan
|
||||
registry-policy en snapshot in plaats van aan vrije metadata. Toegelaten
|
||||
uitkomsten zijn:
|
||||
|
||||
| Status | Betekenis voor gebruik |
|
||||
|---|---|
|
||||
| current | Snapshot valt binnen de geregistreerde review-/geldigheidsregel. |
|
||||
| due | Snapshot moet worden vernieuwd/gecontroleerd en mag niet door een productiegrens. |
|
||||
| stale | Snapshot is verlopen en mag niet door een productiegrens. |
|
||||
| review_required | Een verplichte versie-, tijd-, checksum-, licentie- of policywaarde ontbreekt; niet gebruiken voor authoritative claim. |
|
||||
| unknown | Freshness is niet aantoonbaar; niet consumeerbaar. |
|
||||
| not_applicable | Alleen wanneer het concept inhoudelijk niet op de bron past, bijvoorbeeld observed_at voor een niet-temporele vaste bron. |
|
||||
|
||||
### 6.2 Ingest en trust
|
||||
|
||||
| Ingeststatus | Betekenis | Toegang tot training / productie-inference / QA |
|
||||
|---|---|---|
|
||||
| registered | Server-owned brondefinitie bestaat, nog geen consumeerbare snapshot. | Geen |
|
||||
| configured / not_configured / available | Adapter- of beschikbaarheidsstatus; geen ingestbewijs. | Geen |
|
||||
| ingested | Snapshot is geschreven; Dataset/DatasetVersion moet daarnaast een groen contractrapport hebben. | Alleen volgens source class en task policy |
|
||||
| failed | Ingest of validatie is mislukt. | Geen |
|
||||
| quarantined | Fout, twijfel, ontbrekende provenance of policyconflict is vastgelegd. | Geen |
|
||||
| legacy_unverified | Gemigreerd historisch record zonder complete P2-provenance. | Geen nieuwe training/promotion; UI/API toont beperking |
|
||||
|
||||
Een status ready op de huidige Dataset-tabel is hoogstens een bestaande
|
||||
processingstatus. Zij is niet gelijk aan accepted, authoritative of
|
||||
model-validatable totdat de Fase-2 contractstatus dat bewijst.
|
||||
|
||||
## 7. Huidige implementatie en aantoonbare gaten
|
||||
|
||||
| Onderwerp | Aangetroffen | Niet aangetroffen / Fase-2 verplichting |
|
||||
|---|---|---|
|
||||
| Provider capabilities | Server-owned registry definieert 40 source families, classificatie, task policy en immutable snapshot-binding. | Per product nog geen volledige typed published/request/licence-manifestvelden; zie §5.3. |
|
||||
| Dataset provenance | Dataset en DatasetVersion hebben registry/snapshot FK, versioned contract/reportvelden en lineage/quarantine records. | Historische records blijven incompleet; een daadwerkelijke nieuwe governed ingest is nodig voor gebruik. |
|
||||
| GRB | Bounded allowlisted OGC acquisition, registry/snapshotbinding, contractgate en primaire Vlaamse building-policy zijn aanwezig. | Concrete snapshot blijft zone-, tijd- en productafhankelijk; geen nationale claim. |
|
||||
| DHMV | Bounded WCS-flow, registry/snapshot/rastercontract en elevation-policy zijn aanwezig. | Geen gebouwfootprinttruth of impliciete verticale semantiek. |
|
||||
| Gebouwenregister | Registry task policy onderscheidt registersemantiek van GRB-footprintreconciliatie. | Concrete governed snapshot en productcontract blijven vereist voor activatie. |
|
||||
| Generic upload | Uploads worden server-side als manual/experimental behandeld, niet op caller source_name. | Alleen expliciete reviewed ingest kan later een andere governed route gebruiken. |
|
||||
| OSM/Sentinel | OSM blijft contextual/not_configured; Sentinel blijft planned/not_configured. | Geen live acquisition of automatic authority totdat adapter en contract bestaan. |
|
||||
| Quarantine | `SourceRegistryService.quarantine_dataset` en de database-trigger propageren quarantine naar gekoppelde Dataset/DatasetVersion/snapshot en downstream lineage-descendants; consumption gates sluiten training/inference/QA/export/coverage. | Geen in-place release: een governed re-ingest/nieuwe versie is nodig. |
|
||||
|
||||
## 8. Resultaatweergave en fallbackcontract
|
||||
|
||||
Dit is het verplichte doelcontract voor API en UI. De P2-evidence bewijst nog
|
||||
niet met een end-to-end browser/API-journey dat elk bestaand zichtbaar resultaat
|
||||
de volledige set velden al toont.
|
||||
|
||||
Ieder zichtbaar GeoIntel-resultaat met bronafhankelijkheid moet minimaal tonen:
|
||||
source display name, source_registry_id, snapshot/version, source class,
|
||||
authority scope, observed/published/fetched time, freshness, checksum,
|
||||
licence/attribution, CRS/units, resolution, coverage and limitation.
|
||||
|
||||
Een resultaat dat op een contextual, derived of experimental bron steunt, draagt
|
||||
die status in de API en UI. Een resultaatsamenvatting mag niet alleen de
|
||||
merknaam “GRB” of “officieel” tonen wanneer de concrete DatasetVersion niet
|
||||
aan de registry is gebonden.
|
||||
|
||||
Voor building QA omvat een mismatch ten minste: candidate/source tile,
|
||||
primary-reference snapshot, eventuele Gebouwenregister-reconciliatie,
|
||||
orthophoto observation time, DHMV-context indien gebruikt, en OSM uitsluitend
|
||||
als contextual review evidence. Die aanvullende bronnen veranderen de
|
||||
primary-reference match niet zonder een expliciete menselijke adjudicatie.
|
||||
|
||||
## 9. Exit-evidence voor deze matrix
|
||||
|
||||
Fase 2 kan bronautoriteit alleen als groen markeren wanneer bewijs bestaat van:
|
||||
|
||||
1. een migratie- en registry-inventory met alle bestaande source_name-waarden
|
||||
geclassificeerd of expliciet in quarantine;
|
||||
2. server-side tests waarin een forged GRB upload manual/untrusted blijft;
|
||||
3. bounded GRB, DHMV en register-snapshots met registry/snapshot/contract
|
||||
identity, immutable checksums en validatierapport;
|
||||
4. tests voor zone-/theme-/version-isolatie en geen cross-theme coverage union;
|
||||
5. bewijs dat OSM en Sentinel niet als automatic truth/fallback kunnen lopen;
|
||||
6. resultaten waarin unavailable, partial, not_configured, quarantined en
|
||||
not_evaluable zichtbaar en niet als success gepresenteerd worden.
|
||||
|
||||
Tot deze evidence bestaat, blijven de Phase-1 bronautoriteitsclaims en de
|
||||
nationale building-promotion blocked.
|
||||
@@ -1,578 +0,0 @@
|
||||
# GeoIntel Accuracy Improvement Program — 08 Versieerbare datacontracten
|
||||
|
||||
- Status: Fase-2 contractnorm met een geïmplementeerde fail-closed
|
||||
validatiebibliotheek; bestaande DatasetVersions, artefacten en
|
||||
modelbestanden worden niet stilzwijgend betrouwbaar verklaard
|
||||
- Scope: raster-, vector-, label- en modeldata, inclusief afgeleide datasets
|
||||
en uitvoerbare inference-inputs
|
||||
- Samenhang: 05-metric-framework, 07-source-authority-matrix,
|
||||
docs/API_CONTRACTS.md en docs/DATABASE_IMPLEMENTATION_PLAN.md
|
||||
|
||||
## 1. Doel en harde regel
|
||||
|
||||
Een GeoIntel-resultaat is alleen herleidbaar wanneer alle gebruikte data een
|
||||
versieerbaar contract heeft, de concrete artefacten checksummed zijn, de
|
||||
validatie-uitkomst is bewaard en ieder derived artifact zijn parents en
|
||||
transformaties kent.
|
||||
|
||||
Voor een nieuwe ingest geldt daarom, met de actuele P2-statuswoorden:
|
||||
|
||||
ontvangen -> registered/configured -> ingested + contractvalidatie -> eligible of quarantined
|
||||
|
||||
`ready` is hoogstens een bestaande processingstatus, geen trust- of
|
||||
consumptiestatus. Alleen een record met complete P2-evidence kan via de
|
||||
consumption gate operationeel worden gebruikt. Er bestaat geen consumptiepad
|
||||
van een ontvangen of legacy `ready` record naar training,
|
||||
productie-inference, primaire QA, coverage authority of normale export dat een
|
||||
gefaalde, ontbrekende of onbekende contractcontrole stilzwijgend overslaat. Een
|
||||
incomplete legacyrecord blijft zichtbaar als `lineage_incomplete` en krijgt
|
||||
geen gefingeerde metadata.
|
||||
|
||||
## 2. Huidige startsituatie versus Fase-2-doel
|
||||
|
||||
De generieke exact-versioned contracten zijn geïmplementeerd in
|
||||
`backend/app/services/data_contract_validation.py`:
|
||||
`geointel.vector.geojson@1.0.0`, `geointel.raster.geotiff@1.0.0`,
|
||||
`geointel.label.yolo@1.0.0` (historisch, geen lege labels),
|
||||
`geointel.label.yolo@1.1.0` (actueel, expliciete `pure_background`-modus) en
|
||||
`geointel.model.pytorch@1.0.0`. De ingest- en derived-paden bewaren de
|
||||
reportvelden. De validator levert een fail-closed report en
|
||||
`DataQuarantineService` bepaalt de beslissing; `SourceRegistryService` en de
|
||||
database-quarantinetrigger leggen de persistente quarantine en propagatie vast,
|
||||
terwijl `DatasetConsumptionGate` operationele consumptie blokkeert. Deze
|
||||
generieke contracten vervangen geen
|
||||
toekomstige, strengere productprofielen voor GRB, PICC, UrbIS of
|
||||
sensor-/modelversies.
|
||||
|
||||
| Onderwerp | Aangetroffen op 2026-08-01 | Fase-2 contractdoel |
|
||||
|---|---|---|
|
||||
| Datasetbasis | Dataset en DatasetVersion bevatten storage path, checksum, CRS, bounds, resolution/bands JSON, source/provenance JSON en temporele velden. De Phase-2-migratie voegt contract, registry/snapshot, validation, lineage, quarantine en idempotencyvelden toe. | Iedere nieuwe DatasetVersion krijgt contract-id/-versie, registry/source-snapshotbinding, validation report met contractfingerprint en lineage edges. |
|
||||
| Uploadvalidatie | Generic upload en server-owned vector/rasteracquisities gaan via dezelfde registry/snapshot/contractflow; een upload blijft `manual` ongeacht caller text. | Generic metadata blijft descriptief; source authority, policy en training/production eligibility komen uitsluitend uit server-owned contracts. |
|
||||
| Specialistische acquisitie | GRB, DHMV en andere adapterpaden voeren bron-specifieke checks uit en gebruiken de centrale registry/contract engine. | Elke adapter levert machineleesbare pass/fail/quarantine evidence; product-specifieke semantische profiles blijven afzonderlijke uitbreidingen. |
|
||||
| Vector-CRS | Het beoogde model bewaart EPSG:4326, maar Phase 1 reproduceerde een non-4326 relabeling en vier historische detection geometrieën buiten het 4326-domein. | Bron-CRS is verplicht; transform wordt expliciet gelogd; relabeling zonder transform is verboden; legacy is quarantined of traceerbaar gerepareerd. |
|
||||
| Versions | DatasetVersion en checksums bestaan, met unieke dataset/version. | Een inhoudelijke mutatie maakt een nieuwe snapshot/datasetversion met parent edge en reportfingerprint; de ingest-API wijzigt geen geaccepteerde evidence in place. |
|
||||
| Labels/modellen | De Phase-1-training- en auditbestanden ontbeerden governed manifest-/review-/split-/runtimecontract. P2 voegt versioned YOLO-labelcontracten, release-/asset-/label-sidecars en een PyTorch-runtime-sidecar toe; historische bestanden blijven legacy. | Labels en modellen zijn first-class contractartefacten met hashes, split/firewall, review en runtime lineage. |
|
||||
| Quarantine | `DatasetQuarantine`, een validation report en een consumption gate bestaan nu. | Quarantine heeft eigen status, reden, evidence en toegangsblokkade; gefaalde input kan nergens operationeel worden geconsumeerd. |
|
||||
|
||||
De bestaande velden zijn waardevol als legacy evidence, maar hun aanwezigheid
|
||||
bewijst geen source authority, semantic validity of release eligibility. Dit
|
||||
document voorkomt dat metadata-aanwezigheid met contractacceptatie wordt
|
||||
verward.
|
||||
|
||||
## 3. Universeel contractenvelope
|
||||
|
||||
Elke valideerbare entiteit gebruikt een versieerbaar envelope. De fysieke
|
||||
opslag kan relationeel, GeoJSON, GeoTIFF, manifest-JSON of modelbestand zijn.
|
||||
De tabel hieronder is de normatieve envelope; de huidige relationele P2-kolommen
|
||||
en `validation_report_json` realiseren de kernvelden. Nog niet getypeerde
|
||||
snapshotvelden worden niet als aanwezig of groen verondersteld (zie 07 §5.3).
|
||||
|
||||
| Veldgroep | Verplicht veld of regel |
|
||||
|---|---|
|
||||
| identity | contract_id, contract_version, entity_kind, immutable entity_id, contract/schema fingerprint en waar van toepassing manifest_sha256 |
|
||||
| source authority | source_registry_id, source_snapshot_id, authority_class, trust_status en allowed_use; de server-owned registrymetadata bevat de seeding/definition-revisie |
|
||||
| artifact identity | storage URI/path, media type, byte count, sha256, original filename/object key en retained_at |
|
||||
| time | observed_at, published_at, fetched_at/imported_at, valid_from, valid_to en precise status voor missing/not_applicable/unknown_with_reason |
|
||||
| spatial | source_crs, canonical_crs, transformation identifier, bounds in source and canonical CRS, units, spatial resolution/scale, vertical datum/unit if applicable |
|
||||
| coverage | legal/coverage zone IDs, geometry/bbox checksum, exact AOI/partition identity and coverage completeness/truncation status |
|
||||
| semantic schema | expected geometry/band/class/attribute contract, ontology version, source feature-id strategy and known limitations |
|
||||
| validation | validation_status, validator version/code commit, started/finished timestamps, checks run, issue list, warning list and report hash |
|
||||
| lineage | ordered parent identities/hashes, transformation name/version/config hash, child artifact hashes and derivation purpose |
|
||||
| lifecycle | SourceSnapshot: registered/configured/not_configured/available/ingested/failed/quarantined/legacy_unverified; Dataset contract: not_validated/passed/failed plus quarantine reason/evidence |
|
||||
|
||||
De envelope zelf is canonical JSON. De canonical bytes en ieder gerefereerd
|
||||
input-/outputartefact zijn SHA-256-bound in een evidence manifest. Filename,
|
||||
mutable display name and current configuration are never identity substitutes.
|
||||
|
||||
Voor een relationele `Dataset` of `DatasetVersion` die `passed` wordt, dwingt
|
||||
de P2-migratie bovendien een niet-leeg, bijpassend validation report af: exact
|
||||
contract en versie, registry/snapshot, report- en contractfingerprint,
|
||||
`provenance_status=complete`, geldige lineage-status,
|
||||
`quarantine_status=not_quarantined` en een canonieke SHA-256 die exact met de
|
||||
gebonden `SourceSnapshot` overeenkomt. Die evidencevelden kunnen niet worden
|
||||
vervangen terwijl het record `passed` blijft; een inhoudelijke correctie is een
|
||||
nieuwe versie of eerst een expliciete invalidatie/quarantaine. De
|
||||
databaseregel bewaakt die structurele binding en immutable evidencevelden, maar
|
||||
herberekent geen contract- of reporthash en valideert geen bronsemantiek. De
|
||||
applicatievalidator en `DatasetConsumptionGate` bewaken de inhoudelijke
|
||||
artefactcontrole en consumptie; een JSON-vorm op zichzelf is nooit een
|
||||
accuracy- of authority-claim.
|
||||
|
||||
### 3.1 Version rules
|
||||
|
||||
1. Contract major version changes only when semantics or required validation
|
||||
change incompatibly.
|
||||
2. New optional fields may use a minor version only when their absence cannot
|
||||
relax a required gate.
|
||||
3. A validation rule may become stricter only with a new contract version; old
|
||||
accepted artifacts retain their historical report and are not silently
|
||||
relabelled.
|
||||
4. A re-export, clip, reprojection, normalization, tile build, label repair,
|
||||
calibration or model conversion is a derived artifact with a new checksum
|
||||
and lineage edge.
|
||||
5. A source snapshot is immutable in its source identity/checksum semantics.
|
||||
Refresh creates a new snapshot and new DatasetVersion/derived graph; it
|
||||
never overwrites accepted evidence in place. Registry policy is
|
||||
server-owned; callers never supply an authority or policy version.
|
||||
|
||||
### 3.2 Required use policies
|
||||
|
||||
The allowed_use field is a server computed set. Its relevant values are:
|
||||
|
||||
| Use | Minimum state |
|
||||
|---|---|
|
||||
| map_context | accepted contextual/authoritative/corroborative dataset with attribution and spatial contract |
|
||||
| qa_reference | accepted authoritative source for the exact task/zone/version, or a documented corroborative comparison role |
|
||||
| training_input | accepted source/derived dataset plus label, temporal, review, split and leakage gates |
|
||||
| calibration_input | training requirements plus frozen calibration split role |
|
||||
| protected_test | sealed contract with protected access policy; inaccessible to train/val/calibration processes |
|
||||
| production_inference_input | accepted raster/tile contract and model compatibility contract |
|
||||
| export | accepted governed record with complete or explicitly not-applicable lineage; quarantined of lineage-incomplete historic records are not normally exportable |
|
||||
|
||||
No client-provided request field can add qa_reference, training_input or
|
||||
production_inference_input to this set.
|
||||
|
||||
## 4. Common validation policy
|
||||
|
||||
### 4.1 Mandatory gates
|
||||
|
||||
Every ingest validates the following where applicable:
|
||||
|
||||
| Gate | Required behaviour | Failure disposition |
|
||||
|---|---|---|
|
||||
| source attestation | Registry source and snapshot are chosen by the server-side adapter or an explicit review action. | quarantine with SOURCE_UNATTESTED or SOURCE_POLICY_MISMATCH |
|
||||
| checksum | Persisted content hash equals the observed or generated artifact hash and matches the manifest. | quarantine with CHECKSUM_MISMATCH |
|
||||
| file safety | File type, byte size, decompression/container constraints and parser safety match the contract. | reject or quarantine before product persistence |
|
||||
| CRS | Source CRS is declared and parseable; transform to canonical CRS is explicit and recorded. | quarantine with CRS_MISSING, CRS_INVALID or CRS_TRANSFORM_FAILED |
|
||||
| bounding box | Bounds are finite, nonempty, in source CRS and consistent after transform with legal/domain scope. | quarantine with BBOX_INVALID or BBOX_OUT_OF_SCOPE |
|
||||
| units/resolution | Unit, pixel/ground resolution, scale and vertical datum match source/product contract. | quarantine with UNIT_MISMATCH or RESOLUTION_MISMATCH |
|
||||
| time/freshness | Required source version, observed/valid period, fetched time and freshness policy are satisfied or explicitly classified. | quarantine with TEMPORAL_METADATA_MISSING or FRESHNESS_REVIEW_REQUIRED |
|
||||
| semantic schema | Geometry/bands/attributes/classes/ontology/feature IDs meet the contract. | quarantine with SCHEMA_MISMATCH |
|
||||
| lineage | Every parent artifact/version/transformation is resolvable and checksummed. | quarantine with LINEAGE_MISSING or PARENT_INVALID |
|
||||
| topology/integrity | Geometry/raster/label/model-specific validity is green. | quarantine with the specific integrity code |
|
||||
|
||||
At a consumption boundary a concrete snapshot must be `current` or explicitly
|
||||
`not_applicable`. `unknown`, `review_required`, `due` and `stale` are not
|
||||
eligible for production inference, primary reference validation, derived
|
||||
processing, authoritative coverage or normal export. This guard is separate
|
||||
from source-family classification: an authoritative registry entry never
|
||||
overrides an unsuitable snapshot.
|
||||
|
||||
Warnings never change a failed required gate to accepted. A warning may retain
|
||||
accepted only when the exact contract explicitly says that it is non-blocking,
|
||||
the warning is visible, and the allowed_use policy excludes inappropriate uses.
|
||||
|
||||
### 4.2 CRS, units and geometry rules
|
||||
|
||||
- Canonical persisted vector/result geometry is EPSG:4326 only after an
|
||||
explicit source-to-canonical transform. Setting SRID to 4326 on coordinates
|
||||
in EPSG:31370, EPSG:3812 or any other CRS is prohibited.
|
||||
- Every metric distance, buffer, area, length and topology tolerance uses an
|
||||
approved metric CRS or a documented geodesic operation. In the Belgian land
|
||||
scope, EPSG:31370 is the default candidate when suitable; an operation must
|
||||
record the chosen CRS and unit.
|
||||
- The Belgian North Sea keeps horizontal CRS and vertical datum separate.
|
||||
TAW, LAT, mDNG, NAP and depth/elevation semantics never convert implicitly.
|
||||
- Bbox checks validate coordinate order, finite values, positive extent,
|
||||
source CRS domain, transformed canonical domain and declared coverage zone.
|
||||
- Geometry repair is only allowed under a named repair policy. The original
|
||||
hash, repair method, before/after validity and changed feature count remain
|
||||
in provenance. A repair that changes type, dimension or exceeds the
|
||||
tolerance is quarantined for review.
|
||||
|
||||
## 5. Raster data contract
|
||||
|
||||
### 5.1 Required raster fields
|
||||
|
||||
| Group | Required contract content |
|
||||
|---|---|
|
||||
| artifact | GeoTIFF/COG or approved format, sha256, byte size, parser/driver result, compression/nodata and immutable storage path |
|
||||
| spatial | source CRS, affine transform, width/height, source and canonical bounds, pixel size x/y and unit, pixel interpretation and resampling method |
|
||||
| bands | band count/order, data type, colour interpretation or physical unit, nodata, scale/offset, valid pixel statistics and allowed ranges |
|
||||
| source/time | source registry/snapshot, product/collection/scene/tile identity, source version, acquisition/observation period and fetched/imported time |
|
||||
| coverage | requested AOI/partition hash, clipping/mosaic inputs, complete/truncated status, coverage percentage and edge/padding policy |
|
||||
| lineage | original response/archive hash, normalization/clipping/mosaic operation and configuration hash, every parent raster hash |
|
||||
| compatibility | task-specific accepted bands, resolution range, colour/channel arrangement and temporal suitability for label/model task |
|
||||
|
||||
The parser must reject a non-georeferenced analytical raster unless the
|
||||
contract explicitly marks it image-space only. Image-space-only data cannot
|
||||
produce map geometry or location claims.
|
||||
|
||||
### 5.2 Raster-specific checks
|
||||
|
||||
1. CRS, affine transform, width, height, bounds and resolution must agree
|
||||
numerically within a contract tolerance.
|
||||
2. The raster must have the exact expected band count/data type/nodata policy
|
||||
for the source product; unknown values are not silently filled.
|
||||
3. Resolution cannot be represented as finer than the source's native
|
||||
resolution. Derived resampling records source and analysis resolution
|
||||
separately.
|
||||
4. Mosaic/clip outputs declare every parent tile, overlap/nodata merge rule,
|
||||
exact AOI mask and output checksum.
|
||||
5. Acquisition time is separate from fetch time. A rolling latest orthophoto
|
||||
with unknown per-pixel observation time remains unknown_per_pixel.
|
||||
6. A raster used for labels or metrics records the reference-to-imagery time
|
||||
delta and its policy decision. This closes the temporal source of
|
||||
D-TEMPORAL-MISMATCH without inventing a date.
|
||||
|
||||
### 5.3 Source-specific requirements
|
||||
|
||||
| Product family | Additional contract rule |
|
||||
|---|---|
|
||||
| Official orthophoto | Product key, provider, native resolution, colour mode, imagery edition/flight-date precision, coverage zone and licence are mandatory. It is imagery/context, not reference truth. |
|
||||
| Sentinel-2 | Contract must declare processing level, tile/granule, acquisition time, band/resampling method, cloud/nodata mask and native ground resolution. It remains contextual and cannot satisfy a building label/reference contract. |
|
||||
| DHMV | Contract requires product key, DTM/DSM semantics, EPSG:31370, native/analysis resolution, one-band numeric units, nodata, TAW vertical reference and 2013-2015 period for the currently configured DHMV II source. It is elevation evidence, not building truth. |
|
||||
| Bathymetry | Vertical datum/reference plane, depth versus bed-elevation semantics, survey epoch and uncertainty are mandatory. No water volume is inferred. |
|
||||
|
||||
|
||||
### 5.4 Inference tile-manifest contract
|
||||
|
||||
Raster tiling emits `geointel.raster.tile-manifest@2.0.0`. The manifest binds
|
||||
the source Dataset id/checksum/size, the latest DatasetVersion identity and
|
||||
checksum, registry/snapshot identities and snapshot checksum, data-contract
|
||||
identity, source version and—when present—the Area identity and geometry hash.
|
||||
Each tile has an explicit CRS/bounds, byte size and SHA-256.
|
||||
|
||||
Configured detection and segmentation validate that exact binding against the
|
||||
requested live Dataset before model loading. They recompute every tile hash,
|
||||
normalize the tile union to EPSG:4326 and require it to remain inside the
|
||||
manifest and persisted Dataset extents and intersect the bound Area. Missing,
|
||||
legacy or changed evidence is not inferred from filenames: it fails closed with
|
||||
a typed dataset, provenance, tile-integrity or spatial-scope error.
|
||||
|
||||
## 6. Vector data contract
|
||||
|
||||
### 6.1 Required vector fields
|
||||
|
||||
| Group | Required contract content |
|
||||
|---|---|
|
||||
| artifact | GeoJSON/approved vector artifact hash, feature count, media type, source/canonical CRS, original artifact retained path |
|
||||
| geometry | allowed geometry types/dimensions, empty/valid counts, repair policy, source and canonical bbox, geometry precision/tolerance |
|
||||
| identity | source feature-id attribute/namespace, uniqueness policy, stable-identity flag and collision report |
|
||||
| attributes | contract version, required/optional fields, type/domain/null policy, canonical mapping and retained native properties policy |
|
||||
| authority/time | registry source/snapshot, product/collection, zone, source version, observation/validity/fetched time, licence/attribution |
|
||||
| topology | per-product topology rules, overlap/gap/containment/line connectivity policy and known exceptions |
|
||||
| lineage | input artifact hashes, clip/filter/transform configuration, source feature counts and derived output feature mapping |
|
||||
|
||||
### 6.2 Vector-specific checks
|
||||
|
||||
1. De parser accepteert een feature collection met een expliciete CRS of de
|
||||
RFC 7946-standaard EPSG:4326. De ingestservice transformeert een niet-4326
|
||||
bron expliciet vóór canonical persistence; `build_vector_ingest_input`
|
||||
valideert daarna de getransformeerde feature collection en haar
|
||||
transformation evidence. Coördinaten buiten het Belgische/Noordzee-domein,
|
||||
een ongeldige CRS of een Lambertlaag die als 4326 wordt aangeboden, worden
|
||||
gequarantined; veldvorm alleen is nooit voldoende om een andere CRS te
|
||||
raden.
|
||||
De normale `Dataset.storage_path` en zijn checksum verwijzen daarna naar
|
||||
exact die canonieke EPSG:4326-bytes. Originele niet-canonieke bronbytes
|
||||
blijven uitsluitend als checksummed provenance-evidence buiten het
|
||||
consumptiepad bewaard; vectorbewerkingen weigeren een CRS- of
|
||||
storage-checksum-mismatch fail-closed.
|
||||
2. Every feature has a nonempty supported geometry. Invalid features are
|
||||
quarantined individually or cause the dataset to quarantine according to
|
||||
an all-or-nothing policy recorded in the contract.
|
||||
3. Source geometry is transformed before canonical PostGIS persistence.
|
||||
Post-transform coordinates must pass canonical domain/bbox checks.
|
||||
4. Source feature IDs are unique whenever object lineage/temporal comparison
|
||||
needs them. Missing/duplicate/unexpected IDs set identity_stable=false and
|
||||
prevent object-level change claims.
|
||||
5. Required attributes are type-checked before any source-to-canonical mapping.
|
||||
Unknown native fields may be retained in properties JSON but can never
|
||||
satisfy a required canonical attribute by name coincidence.
|
||||
6. Topology rules are task-specific. A self-intersection is always invalid;
|
||||
overlapping building footprints may be a source semantic/review event
|
||||
rather than an automatic geometric repair. The contract states which.
|
||||
7. Any clipping, buffering, intersection or dissolve creates a derived
|
||||
contract with parent hashes, metric CRS, units, tolerance, analysis run and
|
||||
queryable feature-persistence count. A derived Dataset cannot be accepted
|
||||
while its artifact and vectorfeatures diverge.
|
||||
|
||||
### 6.3 Building reference profiles
|
||||
|
||||
| Profile | Required fields / checks | Authority rule |
|
||||
|---|---|---|
|
||||
| GRB GBG | approved GRB collection, official feature ID, Polygon/MultiPolygon, governed request/response/artifact hashes, exact coverage, source snapshot/version, temporal limitation and EPSG:4326 output transform | Primary authoritative footprint reference in Flanders only when 07-source-authority-matrix conditions hold |
|
||||
| Buildings Register | building object/version/status, snapshot date, bounded area, privacy-minimized output, raw-page hashes, register-to-GRB reconciliation and exact source URLs | Authoritative for its register semantics; corroborative for footprint reconciliation, never automatic GRB replacement |
|
||||
| PICC buildings | allowlisted provider product, stable product identity, authorised Walloon coverage, feature ID, native CRS transform, edition/time and geometry contract | Authoritative only for approved Walloon building task/version |
|
||||
| UrbIS buildings | allowlisted product, Brussels coverage, provider-native identity, native CRS transform, edition/time and geometry contract | Authoritative only for approved Brussels building task/version |
|
||||
| OSM buildings | OSM extract/version/timestamp/licence, geometry and tag mapping if intentionally ingested | Contextual/corroborative only; no automatic truth, labels or coverage authority |
|
||||
|
||||
## 7. Label data contract
|
||||
|
||||
Labels are not just text files. Every label has a physical image/tile,
|
||||
reference/source geometry and a training-policy decision.
|
||||
|
||||
### 7.1 Required label-manifest fields
|
||||
|
||||
| Group | Required content |
|
||||
|---|---|
|
||||
| identity | corpus_id/version, label artifact sha256, image/tile sha256, sample ID, tile-manifest sha256 and ontology/class-map version |
|
||||
| spatial/image | image CRS/affine/bounds/resolution, tile size/stride/overlap, pixel coordinate convention and image orientation |
|
||||
| reference | source registry/snapshot, native source feature IDs, geometry/reference hash, source/reference version and license eligibility |
|
||||
| time | imagery observed/acquisition time, label/reference observed time, delta calculation, temporal policy/reason code |
|
||||
| semantics | class, inclusion/exclusion rule, difficult/ambiguous/occluded flag, geometry-to-box conversion policy and minimum resolvable size |
|
||||
| review | review state, reviewer/adjudicator ID, decision/reason code, contact-sheet/overlay hash and decision timestamp |
|
||||
| split | train/val/calibration/test/background-test role, split-manifest hash, parent AOI/group ID and protected flag |
|
||||
| eligibility | accepted, excluded, quarantined or uncertain; allowed training/evaluation use and all reasons |
|
||||
|
||||
### 7.2 Label validation
|
||||
|
||||
- Every label references an image/tile that exists and has exactly the recorded
|
||||
checksum. A label cannot migrate across tiles by filename matching.
|
||||
- Coordinates are finite, in the declared pixel convention and within image
|
||||
bounds. Boxes/polygons must have positive area, supported class and
|
||||
deterministic normalization.
|
||||
- The label's native source feature ID, source snapshot, geometry transform
|
||||
and image/reference time relation are mandatory for trainable labels.
|
||||
- Below-resolution, post-imagery, dense/occluded, extreme-aspect and
|
||||
uncertain labels require an explicit disposition. Unknown is not accepted.
|
||||
- A reviewed label preserves all earlier review decisions; repair produces a
|
||||
new label release and links the superseded artifact.
|
||||
- Test- en background-testlabels zijn logisch beschermd door manifest-,
|
||||
release- en trainingsgates. Ze mogen niet aan samplers, augmentation,
|
||||
calibration, thresholdselectie of training worden aangeboden. Fysieke
|
||||
read-only opslag en afzonderlijke credentials mogen pas worden geclaimd
|
||||
wanneer daarvoor afzonderlijke P2-05-evidence bestaat.
|
||||
|
||||
`geointel.label.yolo@1.0.0` is historisch en laat geen lege labelbestanden
|
||||
toe. `geointel.label.yolo@1.1.0` onderscheidt exact twee modi: `objects` voor
|
||||
een niet-leeg YOLO-bestand en `pure_background` voor een leeg bestand. Een
|
||||
leeg bestand wordt dus nooit automatisch als negatief voorbeeld geïnterpreteerd.
|
||||
Voor `pure_background` zijn naast de normale labelchecks minstens verplicht:
|
||||
|
||||
- de exacte `sample_slug` en een toegestane `train`- of `val`-split;
|
||||
- raster- en referencedataset-ID, checksums, registry en concrete snapshot
|
||||
via de upstream lineage;
|
||||
- `review_decision=accepted`, reviewer-ID, tijdstip met tijdzone en hash van
|
||||
het menselijke reviewartefact/contact sheet.
|
||||
|
||||
Objectlabels met `pure_background` en lege labels zonder deze evidence falen
|
||||
gesloten. Test- en achtergrond-testrollen worden niet toegelaten als deze
|
||||
trainbare `pure_background`-modus.
|
||||
|
||||
Bij het maken van een trainingsrelease wordt ieder label opnieuw gevalideerd
|
||||
en gebonden in `<dataset.yaml>.geointel-training-label-contracts.json`. Die
|
||||
immutable sidecar bevat per label de checksum, sample, mode, exact
|
||||
contract/fingerprint en de tellingen voor objecten/achtergronden; de release
|
||||
en release-freeze binden vervolgens de sidecarhash. Voor het aanmaken,
|
||||
verifiëren en elke initial/retry/resume-trainingsstap wordt de bevroren corpus
|
||||
opnieuw tegen de live Dataset-status gecontroleerd. Een later gequarantined,
|
||||
ontbrekende of niet-meer-eligible raster/referencepartner herroept de release
|
||||
en blokkeert training, ook wanneer de freeze zelf ooit groen was.
|
||||
|
||||
The current V56 evidence has automated tile syntax checks but zero accepted
|
||||
human AOI reviews. It therefore remains a legacy candidate corpus, not an
|
||||
accepted label release under this contract.
|
||||
|
||||
Grayscale-transformaties, SAM-labelverfijningen, rotated holdouts en
|
||||
proposal-crops controleren hun upstream release vóór verwerking, maar erven die
|
||||
release niet als nieuwe trainability. Hun output is expliciet
|
||||
`training_eligible=false` totdat een nieuwe governed corpus-, review-,
|
||||
contract- en releasecyclus de nieuwe bytes heeft geaccepteerd. Dit voorkomt dat
|
||||
een cosmetische of modelgestuurde afleiding stilzwijgend in een bestaande
|
||||
PyTorch-trainingsrelease terechtkomt.
|
||||
|
||||
## 8. Model data contract
|
||||
|
||||
### 8.1 Required model-manifest fields
|
||||
|
||||
| Group | Required content |
|
||||
|---|---|
|
||||
| identity | model_id, model_version, weights sha256/size, format, architecture and class ontology version |
|
||||
| origin | base weights hash/source, training code commit, training image/container digest, dependency lock/SBOM and license |
|
||||
| data | corpus manifest sha256, label release sha256, split manifest sha256, training/validation/calibration roles and data access policy |
|
||||
| config | preprocessing/tile/normalization/augmentation config hash, input dimensions/bands/colour order, threshold/NMS/max detections and seed |
|
||||
| runtime | Python/PyTorch/CUDA/Ultralytics/driver versions, required device, GPU identity, deterministic flags and known nondeterminism |
|
||||
| evidence | training run manifest/checkpoints/logs/curves, evaluator version, calibration and protected-test policy, model card scope polygon/zone IDs |
|
||||
| lifecycle | candidate/unpromoted/validated/promoted/retired status, promotion report/rollback link and explicit supported/not_configured task scope |
|
||||
|
||||
### 8.2 Model validation
|
||||
|
||||
1. Weights hash, architecture and class map must load under the recorded
|
||||
runtime. Load success is runtime evidence only.
|
||||
2. Input raster/tile contract must match bands, colour order, resolution,
|
||||
preprocessing and image geometry expected by the model.
|
||||
3. Model scope is a server-owned geometry/zone policy bound to the model
|
||||
manifest, never a mutable Area display name.
|
||||
4. Training reads only its allowed split roles. A protected credential/path,
|
||||
protected sample identifier or protected assessment causes a hard failure.
|
||||
5. A detection/segmentation run persists the exact model manifest hash, model
|
||||
hash, inference config hash, tile manifest hash, dataset version,
|
||||
transform, seed, container/runtime/hardware and code commit before
|
||||
status=success can be emitted.
|
||||
6. Legacy model runs with missing values remain lineage_incomplete. Current
|
||||
active configuration must not be copied backwards as an invented version.
|
||||
|
||||
### 8.3 Runtime sidecar gate for local PyTorch weights
|
||||
|
||||
Configured local YOLO and SAM weights are **not runnable** merely because a
|
||||
`.pt` file exists or is listed as an active model asset. Before
|
||||
`load_model()` is called, GeoIntel requires a neighbouring immutable sidecar:
|
||||
|
||||
<weights-file>.geointel-model.json
|
||||
|
||||
The sidecar must validate exactly as `geointel.model.pytorch@1.0.0` and binds
|
||||
the following at minimum:
|
||||
|
||||
- a fixed sidecar schema version, configured model ID and task type;
|
||||
- the SHA-256 of the physical weights and the source-snapshot checksum of the
|
||||
same bytes;
|
||||
- `model_format`, framework, non-empty class mapping and source/model version;
|
||||
- source registry/snapshot UUIDs, a training-manifest checksum and non-empty
|
||||
upstream asset/checksum plus transformation lineage;
|
||||
- a timezone-aware import timestamp; and
|
||||
- `metadata.runtime_manifest_sha256`: a SHA-256 of canonical sidecar JSON with
|
||||
only that self-referential field omitted.
|
||||
|
||||
Missing, malformed, wrong-contract, version/task/framework-mismatched or
|
||||
tampered sidecars make the capability `contract_incomplete`; detection and
|
||||
segmentation do not load the adapter or weights. Validated sidecar evidence is
|
||||
copied into the analysis run/job and into each configured detection or
|
||||
segmentation provenance payload. This is a byte-binding and structural
|
||||
lineage gate, not a promotion or accuracy claim: a model still needs its
|
||||
separate training, calibration, protected-test and scope evidence before it
|
||||
can be called validated or nationally suitable.
|
||||
|
||||
For production inference the structural sidecar check is insufficient on its
|
||||
own. Immediately before adapter loading, GeoIntel resolves both UUIDs against
|
||||
the database and requires the `model` registry entry, a matching immutable
|
||||
snapshot, safe configured/current and ingested/current states, exact
|
||||
model/sidecar/snapshot checksum and source-version equality, and no active
|
||||
quarantine record. A missing, detached, mismatched, stale or quarantined
|
||||
database record fails before `load_model()`; catalogue and preflight discovery
|
||||
remain explicitly non-production structural checks.
|
||||
|
||||
The fixture detector/segmenter and placeholders remain explicit test-only
|
||||
paths. They require `fixture_mode=true` where execution is allowed and cannot
|
||||
be made production-ready by a sidecar or request parameter.
|
||||
|
||||
The Phase-1 active model has an asset hash and a successful GPU smoke, but its
|
||||
historical detection runs lack the complete RunManifest fields and it is not
|
||||
nationally validated. It cannot meet this model contract retroactively without
|
||||
original evidence.
|
||||
|
||||
## 9. Derived data and lineage graph
|
||||
|
||||
### 9.1 Required lineage edge
|
||||
|
||||
Each derived entity records:
|
||||
|
||||
parent entity id + parent manifest/hash + transformation id/version
|
||||
+ configuration hash + code commit + runtime/container identity
|
||||
+ output entity id + output hash + validation report hash
|
||||
|
||||
Examples include source raster to clipped raster, raster to tiles, source
|
||||
vector to normalized vector, vector to label, labels to corpus, corpus to
|
||||
checkpoint, checkpoint to inference run, detections to QA and QA to export.
|
||||
|
||||
The graph must be acyclic. A derived artifact cannot cite itself or a mutable
|
||||
“latest” path as its only parent. Parent availability, hash and contract state
|
||||
are checked recursively to the configured evidence boundary.
|
||||
|
||||
### 9.2 Idempotency and resume
|
||||
|
||||
An ingest/derivation idempotency key is the canonical combination of:
|
||||
source snapshot or parent hashes, contract version, transformation/config hash,
|
||||
requested AOI/partition hash and destination semantic role.
|
||||
|
||||
Repeated requests with the same key return the existing accepted artifact only
|
||||
after rechecking its manifest/checksum/validation state. Interrupted work
|
||||
resumes from staged checkpoint evidence or creates a new attempt record; it
|
||||
does not invent success, duplicate a visible DatasetVersion or bypass
|
||||
validation. A partial result is marked failed or quarantined and never reused
|
||||
as a complete parent.
|
||||
|
||||
An identical replay may bind a second project-scoped ingest key to the same
|
||||
immutable source snapshot. It preserves the snapshot's first recorded
|
||||
`fetched_at`; all other immutable snapshot evidence, including checksum and
|
||||
CRS, must still be equal. A changed fetch time alone therefore cannot rewrite
|
||||
provenance or cause a duplicate snapshot.
|
||||
|
||||
## 10. Safe quarantine flow
|
||||
|
||||
### 10.1 Policy
|
||||
|
||||
Quarantine is preservation, not deletion. De huidige P2-implementatie bewaart
|
||||
in een `DatasetQuarantine`-record de target-FK's, stage, één reason code,
|
||||
details JSON, optioneel artifactpad/checksum, status en resolutietimestamps.
|
||||
Het validation report blijft bij `Dataset`/`DatasetVersion`; lineage wordt via
|
||||
de lineage-edges en de snapshotbinding herleid. `SourceRegistryService` en de
|
||||
database-trigger maken het target, gedeelde snapshotpartners en downstream
|
||||
lineage non-consumable voor training, productie-inference, normale QA en
|
||||
automatische export. Een fysieke move/copy naar een afzonderlijke
|
||||
access-controlled quarantine-storage is nog geen gerealiseerd
|
||||
opslagmechanisme; die ontbrekende fysieke isolatie mag niet als bewijs worden
|
||||
geclaimd. Tot die uitbreiding houdt de logische quarantine gate de verplichte
|
||||
operationele veiligheidsgrens in stand.
|
||||
|
||||
| Event | Required action |
|
||||
|---|---|
|
||||
| parser/file failure | Retain minimal evidence and report; quarantine when artifact preservation is safe, otherwise reject with captured hash/error metadata |
|
||||
| CRS/bounds/unit failure | Quarantine dataset/feature/run with source coordinates and validator report; never relabel CRS |
|
||||
| source/trust failure | Route user/manual data to manual/untrusted or quarantine; do not materialize authoritative coverage |
|
||||
| missing version/time/license | Quarantine when policy requires the field; source freshness shows review_required, not current |
|
||||
| label-review/split failure | Quarantine label/corpus release and deny training/calibration/test use |
|
||||
| model/run lineage failure | Mark lineage_incomplete or quarantine candidate output; deny validation/promotion |
|
||||
| derived persistence mismatch | Roll back the transactional visible result when possible; retain failed attempt evidence and do not emit ready/success |
|
||||
|
||||
### 10.2 Quarantine dispositions
|
||||
|
||||
De gerealiseerde P2-statuswaarden zijn `quarantined`, `released` en
|
||||
`rejected`, met de bewaartechnische velden hierboven. Een `released` quarantine
|
||||
maakt de oorspronkelijke dataset niet opnieuw operationeel: een governed
|
||||
re-ingest of nieuwe versie blijft vereist. Een rijkere disposition-taxonomie
|
||||
met severity, secundaire reason codes, validatorversie, reviewer action,
|
||||
`pending_review`, `remediated_as_new_version` en
|
||||
`accepted_for_limited_historical_view_only` is vervolgwerk en mag nog niet als
|
||||
gerealiseerde recordstructuur worden voorgesteld. Een reviewer kan nooit een
|
||||
authoritative-, protected-split- of source-identity-gate in-place opheffen.
|
||||
|
||||
## 11. Contract test matrix
|
||||
|
||||
The implementation must retain tests for valid and deliberately invalid
|
||||
fixtures. At a minimum:
|
||||
|
||||
| Dataset kind | Green fixture | Red fixture / expected outcome |
|
||||
|---|---|---|
|
||||
| governed GRB vector | bounded GBG fixture with registry attestation, valid CRS, unique IDs and request/response hashes | user upload claiming source_name=grb; it remains manual/untrusted or quarantined |
|
||||
| vector CRS | EPSG:31370 or EPSG:3812 source transformed to EPSG:4326 with correct bounds | Lambert coordinates persisted as 4326 or source CRS absent; quarantine |
|
||||
| vector geometry/topology | valid source polygons and explicit valid repair evidence | self-intersection, empty geometry, invalid dimensionality, duplicate required source ID or unsupported attribute type |
|
||||
| raster/DHMV | one-band EPSG:31370, expected nodata/resolution/TAW metadata | wrong band count, unit, vertical reference, resolution, affine/bounds or checksum |
|
||||
| Sentinel-2 | deliberately contextual fixture with full sensor/tile/time metadata | attempt to use it as building reference/ground truth; policy failure |
|
||||
| label | bounded objectlabels of expliciet reviewed `pure_background` labels linked to image/hash/source/review/split manifest | out-of-bounds box, missing source feature, unmarked empty label, post-imagery unknown, unreviewed required sample or protected-role leakage |
|
||||
| model/run | checksummed model with complete manifest and matching tile contract | model/run missing model hash, tile-manifest hash, GPU/runtime identity or scope policy; no success/promotion |
|
||||
| lineage | one parent-to-child transformation graph with reproducible output hash | missing parent, changed parent checksum, cycle, partial operation or output count mismatch |
|
||||
| quarantine | failed record remains non-consumable and visible with reason | attempt to train, infer, QA-as-truth, cover or export a quarantined artifact; hard denial |
|
||||
|
||||
Tests include unit, service, API, migration and live PostGIS coverage where
|
||||
the contract relies on database constraints. A test that only asserts source
|
||||
text is insufficient; it must exercise the actual validation and state
|
||||
transition.
|
||||
|
||||
## 12. Fase-2 completion gates for data contracts
|
||||
|
||||
The source/provenance part of Fase 2 is green only when:
|
||||
|
||||
1. every new accessible DatasetVersion, raster, vector, label release and
|
||||
model/run type is routed through an explicit contract;
|
||||
2. every new imported dataset has a server-attested registry/snapshot binding,
|
||||
checksum, validation report and lineage identity;
|
||||
3. generic uploads cannot acquire authoritative source identity from caller
|
||||
text;
|
||||
4. invalid CRS, geometry, bbox, unit, resolution, checksum, freshness,
|
||||
attribute, topology and lineage fixtures all fail closed;
|
||||
5. quarantine is tested and has zero path into training, production inference,
|
||||
primary QA, coverage authority or normal export;
|
||||
6. migrations preserve existing records, classify legacy gaps and do not
|
||||
silently backfill uncertain facts;
|
||||
7. an evidence manifest retains test, migration and source/contract audit
|
||||
outputs under artifacts/evidence/accuracy/P2.
|
||||
|
||||
Until all gates are green, Fase 2 is in progress, Fase 3 is not ready and
|
||||
training/promotion remains blocked by the Phase-1 execution contract.
|
||||
|
||||
> **Historische handoff:** deze zin legt de P2-gate vast zoals die bij oplevering
|
||||
> van dit document gold. Fase 3 is nadien binnen de afgebakende lokale scope
|
||||
> uitgevoerd. De actuele fasebeslissing staat uitsluitend in
|
||||
> `docs/accuracy-program/status.json`.
|
||||
@@ -1,103 +0,0 @@
|
||||
# Fase 3 — Volledige datascan en quarantaine
|
||||
|
||||
## Resultaat
|
||||
|
||||
De reproduceerbare scan `scripts/run_accuracy_phase3_full_data_scan.py` is read-only uitgevoerd over de veilige lokale scope `models/`, `datasets/`, `data/`, `storage/`, `artifacts/` en `output/`. De scan schrijft uitsluitend bewijs naar `artifacts/evidence/accuracy/P3/`; bronbestanden zijn niet gewijzigd.
|
||||
|
||||
| Telling | Aantal |
|
||||
| --- | ---: |
|
||||
| Onderzochte bestanden | 1013 |
|
||||
| Overgeslagen bestanden | 0 |
|
||||
| Onbereikbare scope-items | 3 |
|
||||
| Geïnventariseerd totaal | 1016 |
|
||||
| Reconciliatie | groen (`1013 + 0 + 3 = 1016`) |
|
||||
|
||||
De drie expliciet onbereikbare items zijn grenzen van deze lokale
|
||||
Windows-scan: de niet lokaal gemounte Tower-corpora, modelvolumes en het
|
||||
productie-PostGIS/API-endpoint. Elk staat als `unreachable` in het volledige
|
||||
manifest met concrete reden; er is geen stilzwijgende skip. Dit betekent niet
|
||||
dat de server zelf onbereikbaar is. Een afzonderlijke gecontroleerde
|
||||
productiescan moet die remote scopes beoordelen voordat een nationale
|
||||
volledigheidsclaim mogelijk is.
|
||||
|
||||
De scan leverde 711 anomalieën op. Dat is geen geldigheidsclaim: 682 items
|
||||
zijn daarom in het logische quarantainemanifest opgenomen. De scanner promoot
|
||||
geen enkel foutief item tot ground truth en voert geen automatische reparatie
|
||||
uit. De huidige bevindingen zijn:
|
||||
|
||||
| Categorie | Aantal | Standaardactie |
|
||||
| --- | ---: | --- |
|
||||
| Onleesbare/corrupte GeoTIFF | 96 | unavailable or unreadable |
|
||||
| Afgeleide artefacten zonder expliciete lineage | 577 | quarantine |
|
||||
| Bronlabel zonder declared freshness | 29 | requires review |
|
||||
| Manifest met nul-bounding-box | 6 | quarantine |
|
||||
| Niet-bereikbare externe scope | 3 | unavailable or unreadable |
|
||||
|
||||
De eerdere P1-splitinventaris blijft zichtbaar in `leakage-report.json`: 24 AOI-paren lagen onder 2 km en split-onafhankelijkheid was niet bewezen. De scan rapporteert dat als `attention`; bestandsnamen alleen kunnen AOI-onafhankelijkheid niet bewijzen. Er was geen toegankelijke GRB-snapshot in de lokale scope, zodat geen afgeleid resultaat als GRB-ground-truth is gemarkeerd.
|
||||
|
||||
## Scancontract
|
||||
|
||||
Iedere inventarisregel bevat een immutable padidentiteit, bestandsgrootte en SHA-256 (waar leesbaar), typecontract, bronclassificatie, lineage, schema/CRS, resolutie/eenheden, ruimtelijke en temporele dekking, freshness, geometrie- of rasterstatus, duplicaatinformatie, anomalieën, ernst en aanbevolen actie. Ondersteunde typecontracten zijn:
|
||||
|
||||
- `geointel.vector.geojson@1.0.0` — GeoJSON-schema, geometrievaliditeit en EPSG:4326-bounds;
|
||||
- `geointel.raster.geotiff@1.0.0` — leesbaarheid, CRS, dimensies, resolutie, bounds, nodata en sample-validiteit;
|
||||
- `geointel.label.yolo@1.1.0` — genormaliseerde YOLO-labelregels en expliciete achtergrondreview;
|
||||
- `geointel.model.pytorch@1.0.0` — immutable modelartefact-identiteit;
|
||||
- `geointel.manifest.json@1.0.0` — CRS, bounds, tile-paden en bron-ID's;
|
||||
- `geointel.database.sqlite@1.0.0` en `geointel.artifact.generic@1.0.0` — veilige byte-/schema-inventaris voor runtime- en bewijsartefacten.
|
||||
|
||||
Er zijn vijf vaste ernstniveaus (`blocker`, `critical`, `major`, `minor`, `informational`) en zeven vaste acties (`accept`, `repairable automatically`, `requires review`, `quarantine`, `exclude from training`, `exclude from evaluation`, `unavailable or unreadable`). Een anomaly wordt nooit automatisch als waarheid gebruikt.
|
||||
|
||||
## Hervatbaarheid en determinisme
|
||||
|
||||
De scanner bouwt eerst een gesorteerde inventory-hash. Per batch wordt `scan-checkpoint.json` atomair bijgewerkt. Met dezelfde inventory en `--resume` worden onveranderde records hergebruikt; gewijzigde records worden opnieuw gelezen. De inhoudshash sluit alleen uitvoertimestamps uit. Twee opeenvolgende runs gaven dezelfde scan-ID en content-hash:
|
||||
|
||||
`p3-eb67185e61107cc7` / `f4ea193d2bdd96a5b391cf7d9d93685cc58e98742c40e4513bcbc434907e720a`
|
||||
|
||||
## Bewijsartefacten
|
||||
|
||||
- `artifacts/evidence/accuracy/P3/full-scan-manifest.json` — volledige machineleesbare scan;
|
||||
- `artifacts/evidence/accuracy/P3/anomaly-manifest.json` — alle afwijkingen;
|
||||
- `artifacts/evidence/accuracy/P3/quarantine-manifest.json` — veilige logische quarantine;
|
||||
- `artifacts/evidence/accuracy/P3/duplicates-report.json` — exacte en genormaliseerde near-duplicategroepen;
|
||||
- `artifacts/evidence/accuracy/P3/leakage-report.json` — checksum-/splitsignalen en P1-splitinventaris;
|
||||
- `artifacts/evidence/accuracy/P3/source-freshness-report.json` — bron/freshness-kruistabel;
|
||||
- `artifacts/evidence/accuracy/P3/dataset-summary.json` — samenvatting per contracttype;
|
||||
- `artifacts/evidence/accuracy/P3/scan-checkpoint.json` — hervatbare batchstaat.
|
||||
|
||||
## Reproduceerbare uitvoering
|
||||
|
||||
```powershell
|
||||
python scripts/run_accuracy_phase3_full_data_scan.py --batch-size 40
|
||||
python scripts/run_accuracy_phase3_full_data_scan.py --batch-size 40 --resume
|
||||
python -m pytest backend/tests/test_accuracy_phase3_full_data_scan.py -q -p no:cacheprovider
|
||||
python -m ruff check scripts/run_accuracy_phase3_full_data_scan.py backend/tests/test_accuracy_phase3_full_data_scan.py
|
||||
```
|
||||
|
||||
De fixturetest controleert geldige en foutieve GeoJSON, corrupte rasterinput, exacte duplicaten, quarantine en identieke herhaling. Productie- of brondata wordt door deze tests niet aangeraakt.
|
||||
|
||||
## Fasebeslissing
|
||||
|
||||
De lokale Fase-3-scan is volledig voor de afgebakende projectomgeving: alle
|
||||
1013 veilige lokale bestanden zijn verwerkt en de drie niet-gemounte grenzen
|
||||
zijn expliciet geregistreerd. Fase 3 blijft voor de totale operationele
|
||||
omgeving `production_inventory_pending` totdat de servervolumes en database
|
||||
in een gecontroleerde productiescan zijn gereconcilieerd. Fase 4 kan de lokale
|
||||
quarantine- en leakage-signalen al beoordelen. Dit is geen modelpromotie- of
|
||||
nationale kwaliteitsclaim; de inhoudelijke anomalieën moeten eerst worden
|
||||
hersteld of representatief menselijk beoordeeld.
|
||||
|
||||
> **Historische handoff:** `ready` beschrijft het overdrachtsmoment direct na
|
||||
> de Phase-3-scan. Het Phase-4-harnas is inmiddels geïmplementeerd, maar de
|
||||
> actuele productbenchmark is nog `not_evaluable`; de normatieve actuele
|
||||
> status staat in `docs/accuracy-program/status.json`.
|
||||
|
||||
## Accuracy-handoff na de scan
|
||||
|
||||
De onafhankelijke AI-visuele triage van 30 augustus is vastgelegd in
|
||||
`artifacts/evidence/accuracy/model-training/20260830-independent-ai-visual-review.json`.
|
||||
Daarin blijven `human_reviewer=false`, corpusacceptatie, training en promotie
|
||||
expliciet geblokkeerd. Een model kan bovendien pas worden geactiveerd wanneer
|
||||
de exacte candidate key en model-SHA-256 overeenkomen met een geslaagd governed
|
||||
Phase-4/5 release-gaterapport dat ook de benchmarkmanifest-SHA-256 bindt. De
|
||||
taakgeschikte officiële bron blijft doorslaggevend voor productresultaten.
|
||||
@@ -1,175 +0,0 @@
|
||||
# Fase 4 — Evaluatieprotocol
|
||||
|
||||
## Doel en huidige claimgrens
|
||||
|
||||
Het Phase-4-harnas maakt evaluatorgedrag, splits, ruwe voorspellingen en
|
||||
releasebeslissingen reproduceerbaar. De lokale referentiecases zijn bewust
|
||||
synthetisch en bewijzen uitsluitend dat het harnas correct en fail-closed
|
||||
werkt. Zij zijn geen meting van productie-accuracy, België-brede
|
||||
generaliseerbaarheid of menselijke aanvaardbaarheid.
|
||||
|
||||
De volledige workflow is:
|
||||
|
||||
```powershell
|
||||
python scripts/run_accuracy_phase4_benchmark.py
|
||||
```
|
||||
|
||||
De standaarduitvoering retourneert exitcode `2` zolang een productgate niet
|
||||
groen is. Voor het uitsluitend regenereren en testen van lokale evidence mag:
|
||||
|
||||
```powershell
|
||||
python scripts/run_accuracy_phase4_benchmark.py --allow-product-blocked
|
||||
```
|
||||
|
||||
worden gebruikt. Die vlag verandert geen gate, score of beslissing. Hij maakt
|
||||
alleen een succesvolle lokale harnascontrole bruikbaar in CI terwijl externe
|
||||
productinput aantoonbaar ontbreekt.
|
||||
|
||||
## Geïmplementeerde taken
|
||||
|
||||
De inventaris scheidt geleerde modellen van deterministische GIS-analyse. Een
|
||||
officiële of deterministische GIS-functie wordt niet kunstmatig als
|
||||
machine-learningmodel voorgesteld.
|
||||
|
||||
De machineleesbare inventaris omvat 15 concrete platformcapabilities, gemapt
|
||||
op zeven evaluatorfamilies. Een family-dekking geldt niet automatisch als een
|
||||
zelfstandige benchmarkclaim voor iedere onderliggende microfunctionaliteit.
|
||||
|
||||
| Taakfamilie | Werkelijke implementatie | Phase-4-metrics | Huidige productstatus |
|
||||
| --- | --- | --- | --- |
|
||||
| Objectdetectie | `backend/app/services/detection_service.py` | precision, recall, F1, AP50, AP50–95, matched IoU, ECE, Brier, coverage-risk | evaluatorcontract groen; actieve modelbenchmark lokaal niet uitvoerbaar |
|
||||
| Gebouwfootprintsegmentatie | `backend/app/services/segmentation_service.py` | object-P/R/F1, IoU, Dice, boundary F1, centroidafstand, relatieve oppervlaktefout, topologie | evaluatorcontract groen; geen representatieve beschermde productset bereikbaar |
|
||||
| Vectorvergelijking en detectie-QA | `backend/app/services/qa_service.py`, `backend/app/services/detection_qa_service.py` | object-P/R/F1, mean IoU, topologische geldigheid | referentie-implementatie via de golden QA-fixtures uitgevoerd |
|
||||
| Veranderingsdetectie | `backend/app/services/change_detection_service.py` | event-level P/R/F1, apart voor toegevoegd en verwijderd | evaluatorcontract groen; productbaseline niet vastgesteld |
|
||||
| Thematische rasterinterpretatie | `backend/app/services/thematic_raster_analysis_service.py` en rasterservices | confusion matrix, pixelaccuracy, class-P/R/F1, class-IoU, mean IoU | alleen metriekcontract voor categorische rasters; er is geen geleerd generiek rasterclassificatiemodel aangetroffen |
|
||||
| Hoogte- en terreininterpretatie | terrein-, hoogte-, bathymetrie- en overstromingsservices | MAE, RMSE, bias, coverage en foutverdeling in gedeclareerde eenheid | deterministische bronanalyse; referentiedata en eenheden blijven taakgebonden |
|
||||
| Geospatiale datavalidatie | `backend/app/services/data_contract_validation.py` en Phase-3-scanner | anomaly-P/R/F1, blocker/critical misses | contractfixture groen; echte bronscan blijft de Phase-3-evidence |
|
||||
|
||||
Vector clip/buffer/intersect, ruimtelijke aggregatie, raster inspect/reproject/
|
||||
clip/tile, NDVI/NDWI/NDBI, flood hazard, bathymetrie en AOI-partitionering
|
||||
vallen onder de overeenkomstige deterministische validatie-, vector-, raster-
|
||||
of terreinfamilie. De geo-assistent is een orkestratie-interface en krijgt geen
|
||||
misleidende zelfstandige accuracy-score; de onderliggende toolresultaten
|
||||
blijven maatgevend.
|
||||
|
||||
## Metriccontract
|
||||
|
||||
Alle objectmatches zijn one-to-one en gebruiken de vooraf vastgelegde
|
||||
taakconfiguratie. Er is geen data-afhankelijke threshold-, operating-point- of
|
||||
modelselectie op test-, background-test- of challenge-input. Vaste diagnostische
|
||||
AP- en coverage-riskcurves veranderen het vooraf geregistreerde operating point
|
||||
niet. Ongedefinieerde delingen worden `null` met expliciete support, niet
|
||||
kunstmatig `1.0`.
|
||||
|
||||
| Uitvoertype | Verplichte kernmetingen | Aanvullende controle |
|
||||
| --- | --- | --- |
|
||||
| Objecten | TP, FP, FN, precision, recall, F1 | IoU, AP, calibration en abstention |
|
||||
| Footprints | objectmetingen, mean IoU en Dice | boundary F1, centroid, area en topologie |
|
||||
| Categorische rasters | confusion matrix, per-class F1/IoU, mean IoU | pixelaccuracy en class-support |
|
||||
| Changes | event-level P/R/F1 per changeklasse | globale score mag een klasse niet maskeren |
|
||||
| Continue hoogte | MAE, RMSE, bias | coverage, eenheid en foutverdeling |
|
||||
| Validatie | anomaly-P/R/F1 | iedere gemiste blocker/critical anomaly blokkeert |
|
||||
|
||||
Voor binomiale precision en recall rapporteert het harnas 95%-Wilsonintervallen.
|
||||
Bij te weinig support blijft de subgroepgate `not_evaluable`; de supportreden
|
||||
blijft afzonderlijk zichtbaar. Een breed interval of ontbrekende metric is geen
|
||||
positief bewijs. Voor een toekomstige productbenchmark moet bij ruimtelijk
|
||||
geclusterde observaties bovendien een vooraf vastgelegde AOI- of
|
||||
clusterbootstrap worden gebruikt in plaats van pixels als onafhankelijke
|
||||
steekproeven te behandelen.
|
||||
|
||||
## Splitcontract en leakage-gates
|
||||
|
||||
`scripts/generate_accuracy_phase4_splits.py` genereert twee afzonderlijke,
|
||||
gehashte manifesten uit één versieerbare bron:
|
||||
|
||||
- development: `train`, `val` en `calibration`;
|
||||
- protected release only: immutable `test`, `background-test` en sealed
|
||||
`challenge`.
|
||||
|
||||
Iedere sample draagt minimaal taak, split, `sample_id`, ruimtelijke `group_id`,
|
||||
`source_family`, `temporal_family`, acquisition- en parent-rasteridentiteit,
|
||||
native feature- en object-ID's, bounding box, ruwe en verwerkte imagehash,
|
||||
labelhash, perceptual imagehash, labelgeometriehash en een canonieke recordhash.
|
||||
Bij automatische toewijzing worden gekoppelde records eerst als één component
|
||||
gegroepeerd. De generator faalt wanneer:
|
||||
|
||||
- een identiteit, object, bron-/tijdsfamilie, acquisition of parent-raster
|
||||
meerdere splits raakt;
|
||||
- exacte image-, label- of recordbytes meerdere splits raken;
|
||||
- perceptuele of geometrische bijna-duplicaten meerdere splits raken;
|
||||
- bounding boxes uit verschillende splits dichter liggen dan de vooraf
|
||||
gedeclareerde onafhankelijkheidsbuffer;
|
||||
- een verplichte split ontbreekt of een record niet valideerbaar is.
|
||||
|
||||
Bronvolgorde heeft geen invloed op de bron- of splitmanifesthash. De huidige
|
||||
fixture bevat 21 samples over alle zes normatieve rollen en gebruikt een buffer
|
||||
van 2.000 meter. Zij kan alleen door een expliciete codeparameter als synthetische
|
||||
fixture worden geopend en draagt altijd `production_accuracy_use_allowed=false`.
|
||||
Productiemodus vereist een strikt P3-manifest, exact provenance-record, vier
|
||||
toegankelijke assetpaden en herberekende bytes-hashes. Dit is dus geen bewijs dat
|
||||
het historische Belgische corpus onafhankelijk is. De Phase-3-bevinding van 24
|
||||
cross-splitparen onder 2 km blijft blokkerend.
|
||||
|
||||
## Bescherming van test en challenge
|
||||
|
||||
De lokale workflow bindt evaluatie aan de exacte protected-manifesthash en
|
||||
accepteert alleen de `test`- en `background-test`-ID's uit dat manifest.
|
||||
Challengecases en -labels worden door de evaluator geweigerd. Configuraties zijn
|
||||
vooraf vast. Per case bewaart `baseline-raw-predictions.json` de exacte
|
||||
referenties, pre-filter- en post-filtervoorspellingen, configuratie en lineage.
|
||||
`assert_training_inputs_safe()` en de twee echte trainingsdataset-builders
|
||||
weigeren beschermde rollen, paden, inhoudshashes en alle relevante identiteit-
|
||||
en lineagevelden. In productiemodus worden toegankelijke bronbytes en hun P3-
|
||||
en provenancebinding opnieuw gecontroleerd; een padloos of hernoemd record faalt.
|
||||
De regressietests bewijzen blokkering en een geldige development-run.
|
||||
|
||||
Dit is logische bescherming in de repository. Fysieke isolatie met een
|
||||
afzonderlijke vault, beperkte credentials en een immutable accesslog is in de
|
||||
huidige projectomgeving niet bewezen. Daarom staat
|
||||
`protected_storage_isolation` in de productgates op `not_evaluable`; de lokale
|
||||
firewall mag niet als vervanging voor die productcontrole worden beschreven.
|
||||
|
||||
## Stratificatie en failure-evidence
|
||||
|
||||
Iedere beschermde case declareert waar relevant regio/gemeente, stedelijk of
|
||||
landelijk karakter, objectgrootte, bron/sensor, resolutie, seizoen/datum,
|
||||
vegetatie/occlusie, moeilijkheid en context. Het metricrapport groepeert die velden en
|
||||
legt support expliciet vast. Kritieke subgroepen moeten vóór een echte baseline
|
||||
worden vastgesteld; ontbrekende of te kleine groepen blokkeren een release.
|
||||
|
||||
`baseline-raw-predictions.json` bewaart de ongesommeerde referenties,
|
||||
pre-/postfiltervoorspellingen, matches, configuratie en lineage.
|
||||
`failure-gallery.json` bewaart stabiele failure-ID's, taak, fouttype, strata en
|
||||
concreet machineleesbaar bewijs. Een visuele gallery van echte productbeelden
|
||||
kan pas worden gemaakt wanneer de beschermde imagery rechtmatig en gecontroleerd
|
||||
bereikbaar is.
|
||||
|
||||
## Reproduceerbaarheid
|
||||
|
||||
Het benchmarkmanifest bindt repositorycommit, evaluator- en workflowversie,
|
||||
alle drie Phase-4-scripts, de echte QA-service, bronfixtures, protected cases,
|
||||
golden QA-fixture, Phase-3-manifesten, bronmatrix, metriekcontract, runtime en
|
||||
beide splitmanifesten met SHA-256. Uit `status.json` wordt uitsluitend de
|
||||
gate-relevante `/runtime/active_model`-projectie canoniek gehasht. Administratieve
|
||||
velden zoals `generated_at`, Phase-4/5-status, documenten en evidence-run-ID's
|
||||
zijn bewust geen benchmarkinput: zo kan het schrijven van de evidenceledger niet
|
||||
zijn eigen runfingerprint veranderen. Review-, authority-, leakage-, vault- en
|
||||
subgroepgates kunnen daardoor niet uit losse statusvelden slagen; zij vereisen
|
||||
checksumgebonden product- en Phase-3-evidence. Een productbaseline wordt alleen
|
||||
geaccepteerd wanneer dezelfde evaluator alle zeven taakfamilies in-process
|
||||
herberekent en exact overeenkomt met checksumgebonden raw-, review-, authority-,
|
||||
leakage-, vault- en CUDA-evidence. Dynamische UUID's uit de QA-service worden uit
|
||||
de canonieke referentiescore verwijderd. Iedere run krijgt een content-addressed
|
||||
ID; twee gelijke uitvoeringen leveren byte-identieke inhoud op en onverwachte
|
||||
bestanden of submappen maken de immutable bundle ongeldig.
|
||||
|
||||
```powershell
|
||||
python scripts/run_accuracy_phase4_benchmark.py --allow-product-blocked
|
||||
python -m pytest backend/tests/test_accuracy_phase4_evaluation.py backend/tests/test_accuracy_phase4_evaluator_hardening.py backend/tests/test_accuracy_phase4_split_hardening.py -q -p no:cacheprovider
|
||||
python -m ruff check scripts/accuracy_phase4_evaluator.py scripts/generate_accuracy_phase4_splits.py scripts/run_accuracy_phase4_benchmark.py backend/tests/test_accuracy_phase4_evaluation.py backend/tests/test_accuracy_phase4_evaluator_hardening.py backend/tests/test_accuracy_phase4_split_hardening.py
|
||||
```
|
||||
|
||||
De machineleesbare bewijsset staat onder
|
||||
`artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b/`. De
|
||||
actuele fasebeslissing staat in `12-release-gates.md` en `status.json`.
|
||||
@@ -1,124 +0,0 @@
|
||||
# Fase 4 — Baselinebenchmark
|
||||
|
||||
## Beslissing
|
||||
|
||||
Het lokale evaluatieharnas is reproduceerbaar en groen. Een betrouwbare
|
||||
baseline van het actieve GeoIntel-productiemodel is in deze omgeving niet
|
||||
uitvoerbaar. De productbenchmark is `fail` door de bevestigde Phase-3-leakage;
|
||||
andere productgates blijven `not_evaluable` zonder governed bewijs. Er wordt
|
||||
daarom geen productie-accuracy-, België-brede of promotieclaim afgeleid.
|
||||
|
||||
| Statusveld | Waarde |
|
||||
| --- | --- |
|
||||
| Benchmark-ID | `geointel-p4-reference-harness-v2` |
|
||||
| Lokale harnasstatus | `pass` |
|
||||
| Productbenchmark | `fail` |
|
||||
| Promotie toegestaan | `false` |
|
||||
| Phase 4 done | `false` |
|
||||
| Phase 5 ready | `false` |
|
||||
|
||||
## Referentie-implementatie als nulmeting
|
||||
|
||||
De bestaande productiecode in `backend/app/services/qa_service.py` is via
|
||||
`scripts/run_golden_qa_benchmark.py` uitgevoerd op vier bevroren golden
|
||||
QA-scenario's. De dynamische service-UUID wordt niet meegenomen in de
|
||||
canonieke inhoudshash.
|
||||
|
||||
| Golden scenario | Precision | Recall | F1 | Mean matched IoU |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| Partial match | 0,50 | 0,50 | 0,50 | 0,8339768339652592 |
|
||||
| Perfect match | 1,00 | 1,00 | 1,00 | 1,00 |
|
||||
| No overlap | 0,00 | 0,00 | `null` | `null` |
|
||||
| Multipolygon match | 1,00 | 1,00 | 1,00 | 1,00 |
|
||||
|
||||
De canonieke referentiehash is
|
||||
`aeb0f6510352f4e205e4fc4e8c423110ca72c2142016c7af846d758865f258c6`.
|
||||
Dit bewijst de rekenkundige regressiestabiliteit van de QA-service, niet de
|
||||
kwaliteit van een detector of segmentatiemodel.
|
||||
|
||||
## Multi-task evaluatorbaseline
|
||||
|
||||
Negen synthetische, deterministische `test`/`background-test`-cases oefenen
|
||||
zeven evaluatorfamilies en 15 concrete capabilityrecords uit. De gecombineerde
|
||||
resultaathash is
|
||||
`55cdba9cce4dcdc88cee0829cd510d7e624a3472feb9d33f7e681621a792eba3`.
|
||||
De cases zijn bewust klein; hun scores testen formules, null-semantiek,
|
||||
raw-retentie, stratificatie en foutclassificatie, niet productkwaliteit.
|
||||
|
||||
| Familie | Voornaamste fixture-uitkomst | Claimgrens |
|
||||
| --- | --- | --- |
|
||||
| Objectdetectie | P 0,667; R 1,000; F1 0,800; AP50 1,000; AP50–95 0,901 | formule-/harnastest |
|
||||
| Footprintsegmentatie | mean IoU 0,799; Dice 0,888; boundary F1 1,000 | formule-/harnastest |
|
||||
| Categorisch raster | accuracy 0,833; macro F1 0,822; mean IoU 0,722 | metriekcontract, geen geleerd rastermodel |
|
||||
| Vectorvergelijking | P/R/F1 0,500; mean matched IoU 1,000 | formule-/harnastest |
|
||||
| Change detection | globale P/R/F1 0,500; afzonderlijke added/removed metrics | eventclassificatie zichtbaar |
|
||||
| Terrein | MAE 0,275 m TAW; RMSE 0,287 m TAW; coverage 0,800 | eenheids-/coveragecontract |
|
||||
| Datavalidatie | P/R/F1 0,667; één critical miss | fail-closed anomaliecontract |
|
||||
|
||||
Alle subgroepen hebben in deze kleine fixture onvoldoende statistische support.
|
||||
Hun `release_gate_status` is daarom `not_evaluable`, met de supportreden apart
|
||||
geregistreerd; geen gemiddelde kan dit omzetten in releasebewijs. De
|
||||
95%-Wilsonintervallen zijn overeenkomstig breed.
|
||||
|
||||
## Ruwe voorspellingen en fouten
|
||||
|
||||
De workflow bewaart exacte referenties, pre-/postfiltervoorspellingen,
|
||||
configuratie en lineage vóór iedere samenvatting. De failure gallery bevat 14
|
||||
deterministische voorbeelden, waaronder FP/FN, boundary- en area-bias,
|
||||
rastermisclassificatie, calibratie en een gemiste critical-validatieafwijking.
|
||||
De failure-ID's zijn inhoudsgebonden en kunnen in regressietests worden
|
||||
hergebruikt.
|
||||
|
||||
Relevante evidence:
|
||||
|
||||
- `baseline-raw-predictions.json` — exacte raw referenties, pre-/postfilteroutputs, config en lineage;
|
||||
- `metric-report.json` — taak- en subgroepmetingen met support en intervallen;
|
||||
- `failure-gallery.json` — machineleesbare fouttaxonomie en voorbeelden;
|
||||
- `reference-implementation-baseline.json` — werkelijke QA-service-uitvoering;
|
||||
- `benchmark-manifest.json` — alle input-, split-, code- en evaluatoridentiteiten.
|
||||
|
||||
De canonieke benchmarkmanifesthash is
|
||||
`0ea5ab07f46c509a7a24943b31d5e9bfd6368920609227bc47613e18e52c4642`;
|
||||
de exacte bestandshash is
|
||||
`868dd7eb2dfa8344e417879ed3f5dd7c7d9e5673add7e3e2294c5cbde4b75d57`.
|
||||
Evidence-run `p4-2.0.1-9677d0ef37db82bcf39b` bindt uitvoerbare codecommit
|
||||
`70fb4b94e5cb7c248beec5a936ce186f38cc183c`. De evidence-manifestbestandshash
|
||||
is `fdc15a95ee2a0754dfa169f4b41036e084b8d8909afc37fd8ea68ee6b9210f98`;
|
||||
de release-gatereportbestandshash is
|
||||
`e5f1c9c43c8da22acfa5486e641c010a278431f90634f91335b039ab7bdb50a4`.
|
||||
Deze hashes bewijzen reproduceerbaarheid en integriteit, niet productaccuracy.
|
||||
|
||||
## Waarom de productbaseline niet uitvoerbaar is
|
||||
|
||||
De productgates zijn bewijsgebonden en kunnen niet vanuit losse statusvelden
|
||||
groen worden gemaakt:
|
||||
|
||||
1. de actieve modelconfiguratie verwijst naar `/app/models/...pt`, die lokaal
|
||||
niet als bestand beschikbaar is;
|
||||
2. er is geen governed productmanifest met in-process herberekende raw evidence
|
||||
voor alle zeven taakfamilies en een actueel CUDA/GPU-receipt;
|
||||
3. een volledige GRB/PICC/UrbIS/DHMV/SPW/MDK-taak-/zoneportfolio ontbreekt;
|
||||
4. een checksumgebonden reviewledger ontbreekt; historisch staat V56 op 0/180;
|
||||
5. een productgebonden geometrische leakage-audit ontbreekt; historisch zijn er
|
||||
24 cross-splitparen onder 2 km;
|
||||
6. de Phase-3-leakagestatus is bevestigd `attention` en dus `fail`;
|
||||
7. vaultisolatie met hash-chained accesslog is niet bewezen;
|
||||
8. representatieve support over alle 13 vereiste subgroupdimensies ontbreekt.
|
||||
|
||||
Door de fail-first aggregatie maakt de bevestigde Phase-3-leakage de huidige
|
||||
productbenchmark `fail`; ontbrekende productartefacten blijven afzonderlijk
|
||||
`not_evaluable`. Geen van beide toestanden laat promotie toe.
|
||||
|
||||
Daarnaast waren Tower-corpora, gemounte modelvolumes en de productie-PostGIS/API
|
||||
in Phase 3 expliciet onbereikbaar. Het harnas verzint daarvoor geen vervangende
|
||||
ground truth en gebruikt OSM niet automatisch als gezagsbron voor gebouwen.
|
||||
|
||||
## Betekenis voor volgende training
|
||||
|
||||
Test- en challenge-data mogen niet worden geopend voor training,
|
||||
thresholdselectie, modelselectie of iteratieve foutcorrectie. Eerst moeten de
|
||||
representatieve review, nieuwe onafhankelijke splits, lokale gezagsdata,
|
||||
protected vault en een checksumbare incumbent-run beschikbaar zijn. Daarna
|
||||
worden modelkeuzes op `val` en operating points op `calibration` vooraf
|
||||
vastgelegd; pas vervolgens mag één immutable kandidaat de protected test en
|
||||
background-test doorlopen. Challenge-labels blijven sealed.
|
||||
@@ -1,109 +0,0 @@
|
||||
# Fase 4 — Releasegates
|
||||
|
||||
## Gateprincipe
|
||||
|
||||
GeoIntel gebruikt een conjunctieve, fail-closed beslissing: iedere verplichte
|
||||
gate moet groen zijn. Een hogere gemiddelde score compenseert nooit een
|
||||
ernstige regressie, ontbrekende support of een critical miss in een vereiste
|
||||
regio, bron, context of taak.
|
||||
|
||||
Er wordt in Phase 4 geen arbitrair hoog accuracydoel verzonnen. Numerieke
|
||||
releasecriteria blijven `not_frozen_without_reviewed_representative_incumbent_baseline`.
|
||||
Ze worden pas vastgesteld uit taakrisico, operationele productvereisten,
|
||||
datakwaliteit en een representatieve, gereviewde incumbentbaseline, en altijd
|
||||
vóór protected-testtoegang.
|
||||
|
||||
## Lokale harnasgates
|
||||
|
||||
De volgende controles zijn in `release-gate-report.json` groen:
|
||||
|
||||
| Gate | Status | Bewijs |
|
||||
| --- | --- | --- |
|
||||
| Alle gedeclareerde taakfamilies | pass | zeven families en 15 capabilities gedeclareerd en geobserveerd |
|
||||
| Split leakage | pass | zes code-owned rollen; exacte/near-duplicate/identity/2-km-gates groen voor de fixture |
|
||||
| Training firewall | pass | protected path/role/lineage en padloze of gewijzigde bytes worden geweigerd |
|
||||
| Geen protected modelselectie | pass | vooraf geregistreerde config; diagnostische curves selecteren niets |
|
||||
| Ruwe voorspellingen | pass | exacte referenties, pre-/postfilteroutputs, config en lineage behouden |
|
||||
| Referentie-implementatie | pass | vier golden cases via de echte `QaService` |
|
||||
| Subgroepcontract | pass | alle 13 dimensies, support, CI en worst-stratum zichtbaar |
|
||||
| Null-semantiek | pass | ongedefinieerd is `null`; promotion blijft uit |
|
||||
|
||||
Deze gates bewijzen dat de evaluator zich lokaal correct gedraagt. Ze bewijzen
|
||||
niet dat het productiemodel voldoet.
|
||||
Een test-only governed-contractfixture met 70 cases bewijst dat de groene route
|
||||
structureel bereikbaar is en dat tampering wordt geweigerd. De gemockte runtime
|
||||
en handgemaakte cases zijn uitdrukkelijk geen productbewijs.
|
||||
|
||||
|
||||
## Productgates
|
||||
|
||||
De volgende actuele gates blokkeren Phase 4:
|
||||
|
||||
| Gate | Status | Objectief bewijs |
|
||||
| --- | --- | --- |
|
||||
| Actief model bereikbaar en hashbaar | not_evaluable | geconfigureerd `/app/models`-asset is lokaal afwezig |
|
||||
| Volledige gezagsportfolio | not_evaluable | geen governed GRB/PICC/UrbIS/DHMV/SPW/MDK-taak-/zonebewijs |
|
||||
| Representatieve menselijke review | not_evaluable | geen checksumgebonden reviewledger; historisch 0/180 |
|
||||
| Ruimtelijke split-onafhankelijkheid | not_evaluable | geen productgebonden geometrische audit; historisch 24 paren <2 km |
|
||||
| Phase-3 leakage opgelost | fail | actuele status `attention` |
|
||||
| Fysieke protected storage isolation | not_evaluable | geen vaultbewijs met hash-chained accesslog |
|
||||
| Uitgevoerde product-incumbent | not_evaluable | geen model/raw/config/CUDA-gebonden productmanifest |
|
||||
| Representatieve subgroup-support | not_evaluable | geen productmetrics over alle 13 dimensies |
|
||||
|
||||
Door `fail > not_evaluable > pass` is de productbenchmarkstatus `fail`. Dat is
|
||||
geen gemeten accuracy failure: de bevestigde leakagegate faalt en de overige
|
||||
productmetingen zijn nog niet evalueerbaar. `promotion_allowed` blijft `false`.
|
||||
|
||||
## Toekomstige numerieke gatefreeze
|
||||
|
||||
Een latere gatefreeze moet per taak minimaal vastleggen:
|
||||
|
||||
- exacte model-, evaluator-, preprocessing-, bron- en splitmanifesthashes;
|
||||
- klasse- en matchbeleid, operating threshold en NMS-configuratie;
|
||||
- globale primaire metric met betrouwbaarheidsinterval;
|
||||
- vereiste regio-, gemeente-, stedelijkheids-, objectgrootte-, bron-, sensor-,
|
||||
resolutie-, seizoen-, datum-, vegetatie-, occlusie-, moeilijkheids- en
|
||||
contextsubgroepen;
|
||||
- minimale onafhankelijke AOI-/objectsupport per groep;
|
||||
- non-inferioritymarge tegenover de incumbent;
|
||||
- harde maxima voor kritieke false negatives, false positives,
|
||||
topologiefouten en calibration error;
|
||||
- abstention/coverage-regel voor onzekere gevallen;
|
||||
- runtime-, GPU-, latency- en resourcecontract waar operationeel relevant.
|
||||
|
||||
Een releasebeslissing is alleen positief wanneer zowel de globale gate als
|
||||
iedere kritieke subgroepgate groen is. `insufficient_support`, `null`, een
|
||||
ontbrekende groep, ongeldige lineage, een checksumverschil of een gemiste
|
||||
blocker/critical anomaly blokkeert.
|
||||
|
||||
## Beschermde evaluatievolgorde
|
||||
|
||||
1. Herstel of excludeer Phase-3-quarantine-items traceerbaar.
|
||||
2. Laat representatieve labels menselijk beoordelen en freeze een nieuwe
|
||||
corpusversie; wijzig V56 niet in place.
|
||||
3. Genereer onafhankelijke `train`, `val`, `calibration`, `test`,
|
||||
`background-test` en sealed `challenge`-manifesten; laat alle leakage-gates
|
||||
slagen.
|
||||
4. Plaats test/background-test en externe challenge-labels in een afzonderlijke
|
||||
vault met beperkte credentials en hash-chained immutable accesslog.
|
||||
5. Voer de incumbent uit en freeze targets op `val`, operating points op
|
||||
`calibration` en operationele vereisten vóór protected toegang.
|
||||
6. Train uitsluitend op `train`; selecteer checkpoints alleen op `val`.
|
||||
7. Pre-registreer één immutable kandidaat en open `test` en `background-test`
|
||||
één keer; challenge-labels blijven sealed.
|
||||
8. Bewaar raw predictions, herbereken paired/subgroepmetrics in-process en neem
|
||||
één fail-closed releasebeslissing.
|
||||
9. Gebruik protected resultaten nooit als feedback voor dezelfde kandidaat- of
|
||||
trainingsfamilie.
|
||||
|
||||
## Actuele fasebeslissing
|
||||
|
||||
Phase 4 blijft `in_progress`: het reproduceerbare lokale harnas is klaar, maar
|
||||
de echte protected productbaseline kan nog niet geldig worden uitgevoerd.
|
||||
Phase 5 blijft `not_ready`. Deze status verandert pas wanneer alle productgates
|
||||
in dezelfde checksumbare workflow groen zijn; documentatie of fixture-scores
|
||||
kunnen die voorwaarde niet omzeilen.
|
||||
|
||||
Normatieve evidence-run: `p4-2.0.1-9677d0ef37db82bcf39b`, gebonden aan
|
||||
codecommit `70fb4b94e5cb7c248beec5a936ce186f38cc183c` en canonieke
|
||||
benchmarkmanifesthash `0ea5ab07f46c509a7a24943b31d5e9bfd6368920609227bc47613e18e52c4642`.
|
||||
@@ -1,33 +0,0 @@
|
||||
# Retirement of the tracked `geointel/` mirror
|
||||
|
||||
## Decision
|
||||
|
||||
The repository root is the only canonical GeoIntel source tree. The stale,
|
||||
tracked copy below `geointel/` was removed during the full-platform remediation
|
||||
because it duplicated backend, frontend, scripts, tests and documentation and
|
||||
could make local tools inspect or execute the wrong implementation.
|
||||
|
||||
## Recovery evidence
|
||||
|
||||
- Source commit: `d39816a4ca1a23a7b90bcf01e5f2b01fd5fb57c4`.
|
||||
- Source tree object: `b66d5987f7e2b1f8180acd3b4c768586993c7d5a`.
|
||||
- Tracked files: `1,153`.
|
||||
- The two mirror-only PNG assets remain recoverable from that immutable Git
|
||||
commit; the canonical frontend already contains the current SVG/PNG/WebP
|
||||
icon and wordmark assets used by the application.
|
||||
- Recovery command, if historical inspection is required:
|
||||
`git restore --source d39816a4ca1a23a7b90bcf01e5f2b01fd5fb57c4 -- geointel`.
|
||||
|
||||
The migration deletes no production data, model weights, source datasets or
|
||||
runtime storage. After the tracked mirror was retired, 207 untracked runtime
|
||||
files (about 0.04 GiB) remained below that directory. They were moved intact,
|
||||
without content rewriting, to the ignored recovery directory
|
||||
`.codex-artifacts/retired-nested-runtime-20260830/`. Nothing from that recovery
|
||||
directory is packaged or deployed. Docker already excluded the former mirror,
|
||||
so production runtime paths remain unchanged.
|
||||
|
||||
## Prevention gate
|
||||
|
||||
`python scripts/verify_repository_layout.py` fails when canonical source
|
||||
markers appear under a new nested `geointel/` directory. The release-readiness
|
||||
workflow runs this check so repository ambiguity cannot silently return.
|
||||
@@ -1,60 +0,0 @@
|
||||
# V73 Vlaamse foutremediatie
|
||||
|
||||
## Uitkomst
|
||||
|
||||
V73 heeft de datadekking aantoonbaar verbreed, maar geen beter productiemodel
|
||||
opgeleverd. Daarom blijft het actieve model ongewijzigd. Dit is een geslaagde
|
||||
fail-closed beslissing: twee nieuw getrainde GPU-kandidaten zijn afgewezen op
|
||||
de vooraf bevroren en ruimtelijk onafhankelijke V72-calibratieportfolio.
|
||||
|
||||
## Nieuwe dekking
|
||||
|
||||
- twaalf nieuwe Vlaamse train-only AOI's;
|
||||
- woonwijken, lintbebouwing, landelijke kernen, industrie, haven, bos, duinen
|
||||
en landbouwcontext;
|
||||
- officiële orthofoto en GRB als primaire gebouwreferentie;
|
||||
- 48 canonieke niet-overlappende tegels met 1.710 labels;
|
||||
- drie lege tegels en meerdere moeilijke, dun bebouwde contexten;
|
||||
- minimale afstand tot een V72-calibratie-AOI: 9.203 meter, tegenover de gate
|
||||
van 2.000 meter.
|
||||
|
||||
De oorspronkelijke Maaseik-grensselectie werd door de provider terecht
|
||||
geweigerd wegens nuldekking binnen de Vlaamse orthofotozone. De gecheckpointte
|
||||
acquisitie is hervat met een vooraf geregistreerde inlandse vervanging in Peer.
|
||||
|
||||
## Visuele controle
|
||||
|
||||
Alle 48 uiteindelijke tegels zijn via twee contact sheets gecontroleerd. De
|
||||
eerste export maakte een bestaande edge-coverzwakte zichtbaar: rasters die iets
|
||||
groter dan 1024 pixels waren, leverden vrijwel identieke tegels op de laatste
|
||||
pixeloffset. Zestig zulke overlappende tegels zijn vóór training verwijderd en
|
||||
de nieuwe experimentele exporter bevat hiervoor een regressiegate.
|
||||
|
||||
De controle is AI-assisted en dus expliciet geen vervanging voor de vereiste
|
||||
onafhankelijke menselijke labelreview. Het corpus en de modellen blijven
|
||||
daardoor niet-promoveerbaar.
|
||||
|
||||
## GPU-resultaten
|
||||
|
||||
| Model | Precision | Recall | mAP50 | mAP50-95 | Besluit |
|
||||
|---|---:|---:|---:|---:|---|
|
||||
| Actief | 0,1577 | 0,1178 | 0,0568 | 0,0218 | behouden |
|
||||
| V73 agressief, 20 epochs | 0,0124 | 0,2557 | 0,0189 | 0,0038 | afgewezen |
|
||||
| V73 gecontroleerd, 10 epochs | 0,0179 | 0,3247 | 0,0222 | 0,0057 | afgewezen |
|
||||
|
||||
Beide kandidaten verhogen recall maar produceren veel te veel foutpositieven.
|
||||
Een drempel- of gemiddelde-scoretruc rechtvaardigt hier geen promotie: precision
|
||||
en beide mAP-maten regresseren ernstig.
|
||||
|
||||
## Conclusie en resterende grens
|
||||
|
||||
De huidige detector is nog niet nauwkeurig genoeg om landelijke, regionale of
|
||||
"100% correcte" gebouwclaims te dragen. V73 voorkomt wel dat een slechter model
|
||||
in productie komt en levert nieuwe, herleidbare foutdekking voor een latere
|
||||
training. Voor een echte volgende kwaliteitsstap zijn minimaal een grotere
|
||||
onafhankelijk menselijk beoordeelde trainset, meer pure-backgroundtegels en
|
||||
governed PICC/UrbIS-contracten nodig. Tot dan moeten resultaten als
|
||||
modelvoorstellen met bronvergelijking en onzekerheid worden gepresenteerd.
|
||||
|
||||
Alle ruwe manifests, matrices, hashes en contact sheets staan onder
|
||||
`artifacts/evidence/accuracy/model-training/20260810-v73-flanders-remediation/`.
|
||||
@@ -1,71 +0,0 @@
|
||||
# V74 foutoorzaak en authority-first resultaten
|
||||
|
||||
## Uitkomst
|
||||
|
||||
V74 heeft geen nieuw productiemodel opgeleverd. De actieve checkpoint blijft
|
||||
ongewijzigd omdat zowel de experimentele proposal-filter als twee
|
||||
rehearsal-kandidaten op de bevroren V72-calibratie slechter presteren. GeoIntel
|
||||
presenteert de automatische gebouwanalyse daarom niet langer als één uniforme
|
||||
resultaatlaag: de GRB-vergelijking maakt voortaan zichtbaar welke AI-kandidaten
|
||||
officieel bevestigd zijn, welke alleen modelvoorstellen zijn en welke
|
||||
GRB-gebouwen door AI gemist zijn.
|
||||
|
||||
## Visuele foutanalyse
|
||||
|
||||
De volledige V72-portfolio van 24 onafhankelijke tegels is met het actieve model
|
||||
op confidence 0,30 gerenderd. De contact sheet toont terugkerende foutpositieven
|
||||
op spoorlijnen, voertuigen, bomen, schaduwen en andere contrastrijke structuren.
|
||||
Daarnaast ontbreken veel gebouwen. Dit ondersteunt de conclusie dat extra
|
||||
epochs op alleen de nieuwe Vlaamse shard de hoofdoorzaak niet oplossen.
|
||||
|
||||
De review is AI-assisted en niet menselijk. Het bewijs mag dus geen menselijke
|
||||
acceptatie of promotiegate vervangen.
|
||||
|
||||
## Afgewezen proposal-filter
|
||||
|
||||
Een experimentele ResNet18-filter werd op afzonderlijke V73-AOI's getraind om
|
||||
building proposals van moeilijke negatieve patches te onderscheiden. De interne
|
||||
V73-validatie behaalde F1 0,8068, maar die score generaliseerde niet naar V72.
|
||||
De beste globale V72-combinatie behaalde precision 0,2161, recall 0,2241 en F1
|
||||
0,2200. Het actieve model zonder filter behaalt op confidence 0,30 F1 0,2504.
|
||||
De filter kan precision verhogen bij een vaste detectordrempel, maar halveert
|
||||
dan de recall. Hij blijft daarom experimenteel en wordt niet geladen in
|
||||
productie.
|
||||
|
||||
## Afgewezen rehearsal-training
|
||||
|
||||
De trainingsset combineert 180 historische trainingstegels met de 48 nieuwe
|
||||
V73-tegels, waarbij V73 tweemaal voorkomt. V72 is alleen evaluatie en komt niet
|
||||
in de fitdata voor.
|
||||
|
||||
| Model | Precision | Recall | mAP50 | mAP50-95 | Besluit |
|
||||
|---|---:|---:|---:|---:|---|
|
||||
| Actief | 0,1577 | 0,1178 | 0,0568 | 0,0218 | behouden |
|
||||
| Rehearsal, optimizer auto, 10 epochs | 0,0710 | 0,0776 | 0,0262 | 0,0098 | afgewezen |
|
||||
| Rehearsal, AdamW 0,0001, 6 epochs | 0,0839 | 0,1034 | 0,0349 | 0,0136 | afgewezen |
|
||||
|
||||
De eerste run bracht bovendien een reproduceerbaarheidsfout aan het licht:
|
||||
Ultralytics `optimizer=auto` negeerde de gevraagde learning rate en koos AdamW
|
||||
0,002. De wrapper bindt daarom nu expliciet `optimizer=AdamW` en legt dit vast
|
||||
in het trainingsmanifest. De gecorrigeerde low-learning-rate-run bleef eveneens
|
||||
onder de actieve baseline.
|
||||
|
||||
## Productcorrectheid
|
||||
|
||||
Voor actuele gebouwvalidatie in Vlaanderen is GRB de gezagsbron binnen de
|
||||
beschikbare editie en dekking. De kaartwerkstroom laadt na detectie automatisch
|
||||
het bewaarde QA-bewijs en toont afzonderlijk:
|
||||
|
||||
- GRB-bevestigde AI-kandidaten;
|
||||
- AI-only, onbevestigde onderzoeksvoorstellen;
|
||||
- officiële GRB-gebouwen die het model miste.
|
||||
|
||||
AI-only voorstellen worden niet als officiële gebouwen voorgesteld. Dit maakt
|
||||
de productuitvoer aantoonbaar correcter zonder de zwakke modelscore te verbergen
|
||||
of een niet-bewezen nauwkeurigheidsclaim te maken.
|
||||
|
||||
## Evidence
|
||||
|
||||
Alle ruwe contact sheets, foutmanifesten, filtermatrices, trainingssamenvattingen
|
||||
en modelhashes staan onder
|
||||
`artifacts/evidence/accuracy/model-training/20260810-v74-root-cause/`.
|
||||
@@ -1,39 +0,0 @@
|
||||
# Runtime model provenance remediation — 2026-08-23
|
||||
|
||||
## Outcome and claim boundary
|
||||
|
||||
The active detection checkpoint can receive a truthful narrow runtime sidecar
|
||||
because its surviving training artifacts now establish an exact byte chain.
|
||||
This remediation binds model bytes, retained checkpoint, base model, dataset
|
||||
contract inputs and the surviving Ultralytics training receipts. It does not
|
||||
retroactively assert a missing historical code commit/container, signed human
|
||||
review, protected-test independence, national validity or a new promotion.
|
||||
|
||||
## Recovered immutable evidence
|
||||
|
||||
| Artifact | SHA-256 |
|
||||
|---|---|
|
||||
| active model and retained `best.pt` | `a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1` |
|
||||
| base model | `a8a79cf5b0bdc19a0245acc322cf77232c335e222bd5f3c00a17d5f29402c196` |
|
||||
| training `args.yaml` | `2b482e6bbef26f433d4406e1acb5cbbf4ce63a63644b180a2d51b93f8c8f0dcb` |
|
||||
| training `results.csv` | `6f83fdea2c59cfc5f3e4fe9673494e073c4e0054980b3020bad0289d0118b777` |
|
||||
| training summary | `6d438308c923f50d885dc777d381f469fa215a0557f0f3e9d3facc2f75ce0b8e` |
|
||||
| dataset YAML | `3a2ea97c35a18072a1ab6738cd673c0ecec5344b19461c91d72a15e138d46e8d` |
|
||||
| dataset summary | `49b2a07d2105d08356431757b83eafc1498eaf1fb76965b1efe05b776824942a` |
|
||||
|
||||
The checkpoint embeds an Ultralytics detection task, class mapping
|
||||
`0: building`, framework version `8.4.93`, 30 epochs, image size 640, seed 0
|
||||
and deterministic mode. The dataset summary retains 198 tiles, 180 training
|
||||
tiles, 18 validation tiles and 58,820 labels.
|
||||
|
||||
## Guarded migration
|
||||
|
||||
`scripts/migrate_runtime_model_provenance.py` performs the migration. It fails
|
||||
closed on any mismatched file or recorded checksum, is dry-run by default,
|
||||
writes the sidecar atomically and reuses only an identical immutable database
|
||||
snapshot. The production check then validates the sidecar against the
|
||||
server-owned `model` registry and snapshot before model loading.
|
||||
|
||||
The operational source version is
|
||||
`sprint174-20260713-smallbld-minpx3-img640-ft30`. This is a recovered runtime
|
||||
artifact identity, not an accuracy or release-level claim.
|
||||
@@ -1,422 +0,0 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"program": "GeoIntel Accuracy Improvement Program",
|
||||
"phase": "P4",
|
||||
"generated_at": "2026-08-30T05:58:29+02:00",
|
||||
"scope": {
|
||||
"product": "Belgium and the Belgian North Sea",
|
||||
"active_building_model_claim": "Mol/Kempen only, operator review required",
|
||||
"national_building_validation": false,
|
||||
"result_authority_policy": "Task-appropriate official sources remain decisive for product results; AI output is a reviewable proposal unless a governed task-specific release gate proves otherwise."
|
||||
},
|
||||
"baseline": {
|
||||
"branch": "codex/geointel-accuracy-program",
|
||||
"repository_commit": "0c019bb22f816db1e4b7a68379bcad08924d9a21",
|
||||
"database_migration_head": "202607260001",
|
||||
"phase2_migration_revision": "202608010001",
|
||||
"phase2_migration_live_disposable_verified": true,
|
||||
"phase2_migration_production_deployed": false,
|
||||
"phase1_mutation_scope": "audit tooling, tests, documentation and retained evidence only"
|
||||
},
|
||||
"phase1": {
|
||||
"status": "complete",
|
||||
"meaning": "The forensic inventory, reproducible baseline, lineage assessment, risk register, metric contract, implementation roadmap and retained evidence exist.",
|
||||
"does_not_mean": [
|
||||
"release ready",
|
||||
"nationally validated",
|
||||
"human-reviewed corpus",
|
||||
"strictly independent protected test",
|
||||
"calibrated confidence",
|
||||
"fully trained"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"status": "blocked",
|
||||
"promotion_allowed": false,
|
||||
"scope_widening_allowed": false,
|
||||
"training_allowed_now": false,
|
||||
"training_unlock_gate": "A corrected checksum-frozen corpus, independent splits, representative human acceptance and every applicable pre-registered training gate must pass before a new governed run.",
|
||||
"activation_gate": "Activation requires the exact candidate key and model SHA-256 bound to a passing governed Phase-4/5 release-gate report and its benchmark-manifest SHA-256; a legacy diagnostic promotion report alone has no activation authority.",
|
||||
"critical_risk_count": 8,
|
||||
"high_risk_count": 17,
|
||||
"medium_risk_count": 4
|
||||
},
|
||||
"phase2": {
|
||||
"status": "in_progress",
|
||||
"meaning": "The source/provenance foundation is implemented and verified in a disposable PostGIS environment; the full P2 roadmap and its training/release gates are not complete.",
|
||||
"roadmap": "docs/accuracy-program/06-implementation-roadmap.md",
|
||||
"first_work_package": "P2-00",
|
||||
"required_order": [
|
||||
"P2-00",
|
||||
"P2-01",
|
||||
"P2-02",
|
||||
"P2-03",
|
||||
"P2-04",
|
||||
"P2-05",
|
||||
"P2-06",
|
||||
"P2-07",
|
||||
"P2-08",
|
||||
"P2-09",
|
||||
"P2-10",
|
||||
"P2-11",
|
||||
"P2-12"
|
||||
],
|
||||
"protected_test_rule": "Open exactly once for a pre-registered immutable candidate after all pre-test gates pass; never feed its results back into that candidate family."
|
||||
},
|
||||
"phase2_source_provenance": {
|
||||
"status": "implemented_and_verified_in_disposable_environment",
|
||||
"evidence_root": "artifacts/evidence/accuracy/P2",
|
||||
"implemented": [
|
||||
"server-owned source registry and immutable source snapshots",
|
||||
"versioned vector, raster, label and PyTorch model contracts",
|
||||
"checksum-bound dataset and dataset-version provenance",
|
||||
"lineage graph, quarantine propagation and consumption gates",
|
||||
"live disposable PostGIS upgrade, guard and downgrade verification"
|
||||
],
|
||||
"does_not_mean": [
|
||||
"all legacy records are provenance complete",
|
||||
"physical quarantine or protected-test storage isolation is proven",
|
||||
"every UI result has end-to-end provenance rendering evidence",
|
||||
"the full P2 roadmap is complete",
|
||||
"training, promotion or national validation is allowed"
|
||||
]
|
||||
},
|
||||
"phase3": {
|
||||
"status": "local_complete_production_inventory_pending",
|
||||
"meaning": "All 1013 safe local files in the configured GeoIntel roots were scanned read-only; three declared external production boundaries were recorded explicitly and still require a controlled server-side inventory.",
|
||||
"scanner": "scripts/run_accuracy_phase3_full_data_scan.py",
|
||||
"scanner_version": "3.1.0",
|
||||
"scan_id": "p3-eb67185e61107cc7",
|
||||
"evidence_root": "artifacts/evidence/accuracy/P3",
|
||||
"content_hash": "f4ea193d2bdd96a5b391cf7d9d93685cc58e98742c40e4513bcbc434907e720a",
|
||||
"reconciliation": {
|
||||
"examined": 1013,
|
||||
"skipped": 0,
|
||||
"unreachable": 3,
|
||||
"inventory_total": 1016,
|
||||
"reconciles": true
|
||||
},
|
||||
"anomaly_count": 711,
|
||||
"quarantine_item_count": 682,
|
||||
"does_not_mean": [
|
||||
"the total production inventory is complete",
|
||||
"all anomalies are repaired",
|
||||
"AOI split independence is proven",
|
||||
"GRB ground truth is locally available",
|
||||
"training, promotion or national validation is allowed"
|
||||
]
|
||||
},
|
||||
"phase4": {
|
||||
"status": "in_progress",
|
||||
"meaning": "The content-addressed local evaluation harness passes, but the governed product benchmark fails on confirmed Phase-3 leakage and remains not evaluable for missing product evidence.",
|
||||
"workflow": "scripts/run_accuracy_phase4_benchmark.py",
|
||||
"workflow_version": "2.0.1",
|
||||
"evaluator_version": "2.1.0",
|
||||
"split_generator_version": "1.3.0",
|
||||
"local_harness_status": "pass",
|
||||
"product_benchmark_status": "fail",
|
||||
"phase4_done": false,
|
||||
"evidence_run_id": "p4-2.0.1-9677d0ef37db82bcf39b",
|
||||
"evidence_root": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b",
|
||||
"repository_commit": "70fb4b94e5cb7c248beec5a936ce186f38cc183c",
|
||||
"benchmark_manifest_sha256": "0ea5ab07f46c509a7a24943b31d5e9bfd6368920609227bc47613e18e52c4642",
|
||||
"benchmark_file_sha256": "868dd7eb2dfa8344e417879ed3f5dd7c7d9e5673add7e3e2294c5cbde4b75d57",
|
||||
"evidence_manifest_file_sha256": "fdc15a95ee2a0754dfa169f4b41036e084b8d8909afc37fd8ea68ee6b9210f98",
|
||||
"release_gate_report_file_sha256": "e5f1c9c43c8da22acfa5486e641c010a278431f90634f91335b039ab7bdb50a4",
|
||||
"product_gate_evidence_sha256": "c9f5e3de3ab6d64911f8807b26caa661ccf911a5fd6b995107edda2004836e0c",
|
||||
"case_count": 9,
|
||||
"task_family_count": 7,
|
||||
"implemented_capability_count": 15,
|
||||
"failure_example_count": 14,
|
||||
"split_counts": {
|
||||
"background-test": 2,
|
||||
"calibration": 2,
|
||||
"challenge": 4,
|
||||
"test": 7,
|
||||
"train": 3,
|
||||
"val": 3
|
||||
},
|
||||
"blockers": [
|
||||
"configured active model bytes are not locally accessible",
|
||||
"no governed seven-task product baseline manifest with current CUDA receipt exists",
|
||||
"Phase-3 leakage status is attention and therefore a failing product gate",
|
||||
"no checksum-bound representative human review ledger exists",
|
||||
"no governed zero-under-2-km product split audit exists",
|
||||
"no protected vault evidence with hash-chained access log exists",
|
||||
"no complete task-zone authority portfolio exists",
|
||||
"no representative support over all thirteen subgroup dimensions exists"
|
||||
],
|
||||
"does_not_mean": [
|
||||
"Phase 4 is complete",
|
||||
"production accuracy is measured",
|
||||
"Phase 5 is ready",
|
||||
"training or promotion is allowed"
|
||||
]
|
||||
},
|
||||
"phase5": {
|
||||
"status": "not_ready",
|
||||
"meaning": "Phase 5 remains blocked until every governed Phase-4 product gate passes in the same checksum-bound workflow.",
|
||||
"blocked_by": "phase4"
|
||||
},
|
||||
"runtime": {
|
||||
"cuda_available": true,
|
||||
"device": "NVIDIA GeForce RTX 4080 SUPER",
|
||||
"configured_device": "cuda:0",
|
||||
"python": "3.11.2",
|
||||
"torch": "2.11.0+cu128",
|
||||
"cuda_runtime": "12.8",
|
||||
"ultralytics": "8.4.99",
|
||||
"active_model": {
|
||||
"model_id": "yolo-configured",
|
||||
"model_version": "",
|
||||
"path": "/app/models/geointel-building-yolov8s-smallbld-minpx3-img640-ft30.pt",
|
||||
"sha256": "a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1",
|
||||
"size_bytes": 22516074,
|
||||
"validated_area_names": [
|
||||
"Mol",
|
||||
"Kempen"
|
||||
],
|
||||
"nationally_validated": false
|
||||
},
|
||||
"gpu_smoke": {
|
||||
"status": "passed",
|
||||
"read_only": true,
|
||||
"tile_crs": "EPSG:31370",
|
||||
"tile_sha256": "134a9e86850c92c577c73bc6ee57a9df7d4c1c513ae6450263e800b6dd47b6ee",
|
||||
"manifest_sha256": "6ab8a96bf2a1405e224932afb90255311a09bbeaed4e9a2fdcdf8b1bc2230abd",
|
||||
"raw_detection_count": 17,
|
||||
"inference_seconds": 0.8836944859940559,
|
||||
"claim_boundary": "Runtime execution only; no accuracy, calibration, generalization or release claim."
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"mode": "read_only_audit",
|
||||
"storage_references_checked": 5816,
|
||||
"storage_references_missing": 0,
|
||||
"table_counts": {
|
||||
"projects": 1097,
|
||||
"areas": 387,
|
||||
"datasets": 3377,
|
||||
"dataset_versions": 1671,
|
||||
"vector_features": 6689447,
|
||||
"analysis_runs": 1146,
|
||||
"detections": 299233,
|
||||
"segmentations": 0,
|
||||
"detection_reviews": 0,
|
||||
"quality_checks": 697,
|
||||
"metrics": 4182,
|
||||
"jobs": 4460,
|
||||
"exports": 768,
|
||||
"aoi_operations": 4,
|
||||
"aoi_operation_partitions": 61
|
||||
},
|
||||
"lineage_gaps": {
|
||||
"datasets_missing_observed_at": 2377,
|
||||
"datasets_missing_source_version": 1761,
|
||||
"detection_runs_with_empty_model_version": 1146,
|
||||
"detections_with_empty_model_version": 299233,
|
||||
"detection_runs_missing_model_hash": 3,
|
||||
"detection_runs_missing_tile_manifest_hash": 1146
|
||||
},
|
||||
"geometry": {
|
||||
"areas_invalid_or_wrong_srid": 0,
|
||||
"vector_features_invalid_or_wrong_srid": 0,
|
||||
"detections_outside_epsg4326_domain": 4,
|
||||
"outside_domain_interpretation": "Four Geel detections contain Lambert-domain coordinates while persisted under SRID 4326."
|
||||
}
|
||||
},
|
||||
"ml_data": {
|
||||
"model_asset_count": 26,
|
||||
"training_checkpoint_count": 229,
|
||||
"training_json_report_count": 424,
|
||||
"operator_manifest_count": 36,
|
||||
"v56": {
|
||||
"sample_count": 180,
|
||||
"reviewed_sample_count": 0,
|
||||
"review_complete": false,
|
||||
"input_feature_count": 31452,
|
||||
"accepted_feature_count": 30662,
|
||||
"below_resolvable_pixel_size": 326,
|
||||
"created_after_imagery_period": 464,
|
||||
"pure_empty_background_count": 3,
|
||||
"pure_empty_background_by_region": {
|
||||
"flanders": 2,
|
||||
"wallonia": 1,
|
||||
"brussels": 0
|
||||
},
|
||||
"minimum_cross_split_aoi_distance_m": 95.72033647650719,
|
||||
"cross_split_pairs_below_2000_m": 24,
|
||||
"exact_cross_split_raster_hash_duplicates": 0,
|
||||
"perceptual_pairs_hamming_at_or_below_4": 0,
|
||||
"split_independence_proven": false
|
||||
},
|
||||
"candidate_evidence": {
|
||||
"v58_v62_kind": "calibration-only tile-level bbox metrics",
|
||||
"threshold_0_15_aggregate_f1": 0.512905360688286,
|
||||
"threshold_0_15_flanders_recall": 0.0,
|
||||
"protected_test_evidence": false,
|
||||
"background_test_release_evidence": false,
|
||||
"promotion_evidence": false
|
||||
},
|
||||
"protected_test_isolation": false,
|
||||
"human_label_acceptance": false,
|
||||
"latest_independent_ai_visual_review": {
|
||||
"review_id": "20260830-independent-ai-visual-review",
|
||||
"evidence": "artifacts/evidence/accuracy/model-training/20260830-independent-ai-visual-review.json",
|
||||
"human_reviewer": false,
|
||||
"corpus_accepted": false,
|
||||
"training_gate": "blocked",
|
||||
"promotion_allowed": false,
|
||||
"claim_boundary": "Independent AI visual inspection is triage evidence only; it is not representative human acceptance, protected-test evidence or an accuracy measurement."
|
||||
}
|
||||
},
|
||||
"verification": {
|
||||
"backend_full_suite": {
|
||||
"status": "passed",
|
||||
"passed": 1702,
|
||||
"skipped": 1,
|
||||
"failed": 0,
|
||||
"duration_seconds": 279.63,
|
||||
"classification": "The complete canonical backend suite passes with deprecations promoted to errors. The single skip is the Windows-host symlink fixture; the symlink refusal path remains covered by static and Linux-targeted release checks."
|
||||
},
|
||||
"backend_ci_entrypoint": {
|
||||
"status": "passed",
|
||||
"collected": 1703,
|
||||
"result": "1702 passed, 1 skipped",
|
||||
"note": "The canonical backend test import boundary, deployment contracts, guest analysis flow and governed raster handoff all collect and pass."
|
||||
},
|
||||
"phase1_tooling_tests": {
|
||||
"status": "passed",
|
||||
"passed": 4
|
||||
},
|
||||
"new_phase1_code_ruff": {
|
||||
"status": "passed"
|
||||
},
|
||||
"repository_ruff": {
|
||||
"status": "passed",
|
||||
"finding_count": 0,
|
||||
"note": "Repository-wide Ruff validation passes across backend, scripts and tests without policy weakening."
|
||||
},
|
||||
"frontend_unit": {
|
||||
"status": "passed",
|
||||
"test_files": 40,
|
||||
"tests": 170,
|
||||
"command": "npm run test:unit"
|
||||
},
|
||||
"frontend_typecheck": {
|
||||
"status": "passed"
|
||||
},
|
||||
"frontend_build": {
|
||||
"status": "passed"
|
||||
},
|
||||
"frontend_lint": {
|
||||
"status": "missing",
|
||||
"error": "npm run lint: Missing script"
|
||||
},
|
||||
"openapi_contract": {
|
||||
"status": "passed",
|
||||
"implemented_routes": 155,
|
||||
"explicit_non_envelope_endpoints": 12
|
||||
},
|
||||
"alembic": {
|
||||
"status": "passed_offline_and_disposable_postgis",
|
||||
"heads": [
|
||||
"202608230001"
|
||||
],
|
||||
"offline_upgrade_rendered": true,
|
||||
"offline_downgrade_rendered": true,
|
||||
"live_migration_tested_locally": true,
|
||||
"production_migration_deployed": false
|
||||
},
|
||||
"phase2_source_provenance": {
|
||||
"status": "passed_in_disposable_environment",
|
||||
"source_registry_definitions": 40,
|
||||
"migration_revision": "202608010001",
|
||||
"migration_guards": "artifacts/evidence/accuracy/P2/postgres-migration-guards.json",
|
||||
"static_inventory": "artifacts/evidence/accuracy/P2/source-contract-inventory.json",
|
||||
"claim_boundary": "This is not a production migration deployment, corpus-release, accuracy or promotion result."
|
||||
},
|
||||
"phase4_evaluation": {
|
||||
"status": "local_pass_product_fail",
|
||||
"targeted_tests": {
|
||||
"passed": 60,
|
||||
"duration_seconds": 22.28
|
||||
},
|
||||
"relevant_regression_tests": {
|
||||
"passed": 103,
|
||||
"duration_seconds": 27.61,
|
||||
"shell_provider": "C:/Program Files/Git/bin/bash.exe",
|
||||
"note": "The Windows Store WSL bash stub was unavailable; the same shell syntax test passed with the installed Git Bash provider."
|
||||
},
|
||||
"ruff": "pass",
|
||||
"format_check": "pass",
|
||||
"compileall": "pass",
|
||||
"python_typecheck": "not_configured",
|
||||
"alembic_head": "202608010001",
|
||||
"migration_and_provenance_tests": {
|
||||
"passed": 29,
|
||||
"duration_seconds": 5.73
|
||||
},
|
||||
"workflow_reproduction": {
|
||||
"allow_product_blocked_exit": 0,
|
||||
"default_exit": 2,
|
||||
"byte_identical": true,
|
||||
"status_bookkeeping_stable": true
|
||||
},
|
||||
"claim_boundary": "Local harness and contract gates pass. Product accuracy is not measured; Phase-3 leakage fails and missing governed product evidence remains not evaluable."
|
||||
},
|
||||
"golden_qa": {
|
||||
"semantic_results_stable": true,
|
||||
"byte_identical": false,
|
||||
"reason": "UUID4-backed run identity"
|
||||
}
|
||||
},
|
||||
"reproduced_contract_violations": [
|
||||
"P1-COV-001",
|
||||
"P1-CRS-001",
|
||||
"P1-CRS-002",
|
||||
"P1-AUTH-001",
|
||||
"P1-AI-001",
|
||||
"P1-COV-002",
|
||||
"P1-API-001"
|
||||
],
|
||||
"critical_blockers": [
|
||||
"ACC-R01",
|
||||
"ACC-R02",
|
||||
"ACC-R03",
|
||||
"ACC-R04",
|
||||
"ACC-R06",
|
||||
"ACC-R09",
|
||||
"ACC-R16",
|
||||
"ACC-R17"
|
||||
],
|
||||
"documents": [
|
||||
"docs/accuracy-program/00-execution-contract.md",
|
||||
"docs/accuracy-program/01-system-inventory.md",
|
||||
"docs/accuracy-program/02-data-lineage.md",
|
||||
"docs/accuracy-program/03-baseline-and-gaps.md",
|
||||
"docs/accuracy-program/04-risk-register.md",
|
||||
"docs/accuracy-program/05-metric-framework.md",
|
||||
"docs/accuracy-program/06-implementation-roadmap.md",
|
||||
"docs/accuracy-program/07-source-authority-matrix.md",
|
||||
"docs/accuracy-program/08-data-contracts.md",
|
||||
"docs/accuracy-program/09-full-data-scan.md",
|
||||
"docs/accuracy-program/10-evaluation-protocol.md",
|
||||
"docs/accuracy-program/11-baseline-benchmark.md",
|
||||
"docs/accuracy-program/12-release-gates.md",
|
||||
"docs/accuracy-program/13-nested-mirror-retirement.md"
|
||||
],
|
||||
"evidence_root": "artifacts/evidence/accuracy/P1",
|
||||
"evidence_manifest": "artifacts/evidence/accuracy/P1/evidence-manifest.json",
|
||||
"latest_verification_evidence_manifest": "artifacts/evidence/accuracy/P1/evidence-manifest-20260830-verification.json",
|
||||
"phase2_evidence_root": "artifacts/evidence/accuracy/P2",
|
||||
"phase2_evidence_manifest": "artifacts/evidence/accuracy/P2/evidence-manifest.json",
|
||||
"phase3_evidence_root": "artifacts/evidence/accuracy/P3",
|
||||
"phase3_manifest": "artifacts/evidence/accuracy/P3/full-scan-manifest.json",
|
||||
"phase4_evidence_root": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b",
|
||||
"phase4_evidence_manifest": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b/evidence-manifest.json",
|
||||
"phase4_benchmark_manifest": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b/benchmark-manifest.json",
|
||||
"phase4_release_gate_report": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b/release-gate-report.json",
|
||||
"phase4_metric_report": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b/metric-report.json",
|
||||
"phase4_failure_gallery": "artifacts/evidence/accuracy/P4/runs/p4-2.0.1-9677d0ef37db82bcf39b/failure-gallery.json"
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
# Reviewed accuracy challenger - 2026-07-15
|
||||
|
||||
## Scope
|
||||
|
||||
This pass closes the evidence requirement from the preceding FP/FN review. It
|
||||
adds complete, training-only orthophoto/GRB AOIs outside all protected
|
||||
operational holdouts, trains one inactive local challenger and compares both
|
||||
models through the current persisted GeoIntel workflow. No model was
|
||||
downloaded and the active runtime configuration was not changed.
|
||||
|
||||
- Active model: `geointel-building-yolov8s-smallbld-minpx3-img640-ft30-pt`
|
||||
- Active SHA256: `a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1`
|
||||
- Challenger: `geointel-building-yolov8s-reviewedexp6-minpx3-img640-ft20-pt`
|
||||
- Challenger SHA256: `038f1f97a6afd534f29e1f392a730a58207b928ca01e31ab8d8fed6106705820`
|
||||
- Fixed profile: tile `512`, overlap `64`, confidence `0.15`, QA IoU `0.25`
|
||||
|
||||
## Data and training
|
||||
|
||||
Six new training-only centers were added in Arendonk, Dessel, Meerhout,
|
||||
Laakdal, Nijlen and Hulshout. Every center is in its documented municipality,
|
||||
uses a complete paged GRB GBG export and remains at least 2 km from every
|
||||
protected positive holdout.
|
||||
|
||||
- New GRB references: 9,964 features
|
||||
- Corpus: 252 tiles, 234 positive and 18 negative
|
||||
- Split: 234 training and 18 validation tiles
|
||||
- Labels: 79,192
|
||||
- Dataset audit: `ok`, zero invalid or missing labels
|
||||
- Visual audit: 64 tiles across 28 retained sources, zero invalid or
|
||||
low-variance selections
|
||||
- Fine-tuning: 20 CPU epochs from the active local model, image size `640`
|
||||
- Best checkpoint: epoch 16, validation precision `0.700`, recall `0.406`,
|
||||
mAP50 `0.369`, mAP50-95 `0.159`
|
||||
|
||||
## Coverage-aligned result
|
||||
|
||||
Both assets were rerun after the current coverage-aware QA logic was deployed.
|
||||
Each zone comparison uses the same evaluated reference population; older runs
|
||||
with different edge coverage are not used for the decision.
|
||||
|
||||
| Zone | Active F1 | Challenger F1 | Delta |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Mol Achterbos | 0.6694 | 0.6850 | +0.0156 |
|
||||
| Mol Donk | 0.5894 | 0.6259 | +0.0365 |
|
||||
| Mol Gompel | 0.6564 | 0.6694 | +0.0131 |
|
||||
| Mol Postel | 0.4749 | 0.4753 | +0.0005 |
|
||||
| Retie | 0.6325 | 0.6491 | +0.0166 |
|
||||
| Turnhout | 0.5919 | 0.5988 | +0.0069 |
|
||||
| Westerlo | 0.6336 | 0.6700 | +0.0364 |
|
||||
|
||||
| Aggregate | Active | Challenger |
|
||||
| --- | ---: | ---: |
|
||||
| Mean precision | 0.6141 | 0.6251 |
|
||||
| Mean recall | 0.6062 | 0.6293 |
|
||||
| Mean F1 | 0.6069 | 0.6248 |
|
||||
| Matches | 5,711 | 5,919 |
|
||||
| False positives | 3,568 | 3,506 |
|
||||
| False negatives | 3,416 | 3,208 |
|
||||
|
||||
## Promotion decision
|
||||
|
||||
| Pure-empty control | Active detections | Challenger detections |
|
||||
| --- | ---: | ---: |
|
||||
| Arendonk-heide | 0 | 0 |
|
||||
| Lommel-heide | 0 | 0 |
|
||||
| Postel-bos | 0 | 2 |
|
||||
|
||||
Decision: **retain the active model**. The challenger improves every positive
|
||||
zone but violates the zero-detection Postel-bos gate. The formal promotion
|
||||
report therefore recommends the existing active key
|
||||
`geointel-building-yolov8s-smallbld-minpx3-img640-ft30-pt|512|64|0.15`.
|
||||
Positive-score gains do not override a failed fail-closed background control.
|
||||
|
||||
Persistent evidence is stored below
|
||||
`/app/storage/operator-data/model-review/reviewed-accuracy-expansion/` and
|
||||
`/app/storage/operator-evidence/mol-operational-validation/`. Generated rasters,
|
||||
weights and large evidence JSON files remain outside Git.
|
||||
@@ -1,71 +0,0 @@
|
||||
# Small-building model review - 2026-07-15
|
||||
|
||||
## Scope
|
||||
|
||||
This review uses persisted configured-YOLO detections, persisted GRB building
|
||||
features and the exact orthophoto inference tiles from Geel, Herentals and
|
||||
Turnhout. It does not infer labels from QA status alone and does not alter the
|
||||
active model.
|
||||
|
||||
- Model asset: `geointel-building-yolov8s-smallbld-minpx3-img640-ft30-pt`
|
||||
- SHA256: `a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1`
|
||||
- Canonical QA method: candidate polygon versus GRB footprint IoU `0.25`
|
||||
- False-positive cards reviewed: 48
|
||||
- False-negative cards reviewed: 48
|
||||
- False negatives outside persisted inference-tile coverage: 731, excluded
|
||||
|
||||
Every card was checked against its orthophoto and the persisted candidate and
|
||||
reference overlays. Geometric overlap diagnostics were used to distinguish a
|
||||
model error from box/footprint or one-to-one matching effects. Ambiguous cards
|
||||
remain excluded from training.
|
||||
|
||||
## Decisions
|
||||
|
||||
| Evidence | Confirmed model error | QA alignment | Reference gap/change | Uncertain/obscured |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| False positive | 5 | 34 | 5 | 4 |
|
||||
| False negative | 10 | 25 | 5 | 8 |
|
||||
| Total | 15 | 59 | 10 | 12 |
|
||||
|
||||
The dominant finding is not a model error. In 59 of 96 reviewed cards, a real
|
||||
candidate and reference overlap but the canonical box-versus-footprint or
|
||||
one-to-one assignment does not count that pair as a match. Those records must
|
||||
not become positive or negative training labels.
|
||||
|
||||
## Training-readiness audit
|
||||
|
||||
The active tile corpus already uses Geel and Herentals as training sources and
|
||||
keeps Turnhout excluded as an operation-level holdout.
|
||||
|
||||
| Confirmed evidence | Geel | Herentals | Turnhout holdout |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| False positive | 3 | 1 | 1 |
|
||||
| False negative | 0 | 4 | 6 |
|
||||
|
||||
- The four confirmed false negatives in Herentals already exist as GRB labels
|
||||
in the current training source. Re-adding them would not add new ground
|
||||
truth; it would only change sample weighting.
|
||||
- Confirmed false-positive detections in Geel and Herentals occur on urban
|
||||
source tiles that also contain valid GRB buildings. Treating those complete
|
||||
tiles as empty hard negatives would create false negative labels.
|
||||
- The seven confirmed errors in Turnhout remain holdout evidence and cannot be
|
||||
used for training without invalidating the independent benchmark.
|
||||
|
||||
Result: **0 novel, leakage-free training labels are available from this review
|
||||
bundle.** A new fine-tuning run is therefore rejected. The active model and
|
||||
confidence `0.15` remain unchanged.
|
||||
|
||||
## Required next evidence before training
|
||||
|
||||
1. Collect new training-only orthophoto AOIs outside all Mol/Turnhout/Retie/
|
||||
Westerlo operational holdouts.
|
||||
2. Label the complete contents of each selected tile from an authoritative
|
||||
reference snapshot; never label only the reviewed detection box.
|
||||
3. Add enough independent confirmed small-building and true empty-background
|
||||
examples to justify a separate candidate.
|
||||
4. Keep the candidate inactive until it passes the same positive-AOI,
|
||||
pure-empty-background and Mol holdout gates.
|
||||
|
||||
The review CSVs, contact sheets and validator outputs remain under the
|
||||
persistent operator-data mount and are intentionally not committed as generated
|
||||
repository artifacts.
|
||||
@@ -1,303 +0,0 @@
|
||||
# AI-assisted building checkpoint review — 2026-08-09
|
||||
|
||||
## Outcome
|
||||
|
||||
GeoIntel still runs the proven active building checkpoint. A new 12-epoch GPU
|
||||
fine-tune was rejected because it reduced mAP and introduced three detections
|
||||
on pure-background validation tiles. A wider checkpoint comparison identified
|
||||
the older `reviewedexp6` checkpoint as the strongest non-protected validation
|
||||
challenger, but it was not promoted.
|
||||
|
||||
The production runtime was verified healthy after the review with:
|
||||
|
||||
- image `geointel-all-in-one:0209167cfd37-wip25e7de62cde9-ai`;
|
||||
- active weights SHA-256
|
||||
`a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1`;
|
||||
- NVIDIA RTX 4080 SUPER inference; and
|
||||
- the existing Kempen validation-scope enforcement.
|
||||
|
||||
## Metric review
|
||||
|
||||
The checkpoint matrix used only the 36-image non-protected validation split:
|
||||
18 positive images and 18 declared pure-background images. The active model
|
||||
measured mAP50 `0.345426` and mAP50-95 `0.140719`. The `reviewedexp6`
|
||||
challenger measured `0.368177` and `0.155438` respectively.
|
||||
|
||||
A later exact cross-tile reconstruction established that this 512 px corpus
|
||||
uses stride 256. Across the full corpus, 74,113 interior label rows represent
|
||||
34,082 unique reconstructed objects; 40,031 rows are overlap repetitions and
|
||||
one object can occur four times. No reconstructed object crosses the
|
||||
train/validation boundary, but the tile rows are not statistically independent.
|
||||
The matrix therefore remains useful only for relative non-protected candidate
|
||||
ranking. Its mAP values are not an independent object-level accuracy estimate
|
||||
or a basis for narrow confidence claims.
|
||||
|
||||
At confidence `0.25` and match IoU `0.25`, the active model measured F1
|
||||
`0.633058`; the challenger measured `0.642599`. Both produced zero detections
|
||||
on the 18 pure-background validation tiles at this threshold. At confidence
|
||||
`0.15`, however, the challenger still reproduces the two background detections
|
||||
that blocked its July promotion.
|
||||
|
||||
## Visual review
|
||||
|
||||
The error sheets were inspected at original resolution. Green denotes a
|
||||
matched prediction, red a false positive, magenta a false negative and yellow
|
||||
the reference footprint. The challenger reduces missed-building pressure,
|
||||
particularly in Westerlo, but dense Turnhout tiles still show extensive
|
||||
low-IoU disagreement.
|
||||
|
||||
A major part of that disagreement is not safely resolved by additional epochs:
|
||||
the aerial image shows a roof while GRB GBG represents the building footprint
|
||||
at ground level. Perspective, roof overhang and acquisition-date differences
|
||||
can therefore shift visible roofs relative to the authoritative footprint.
|
||||
These cases remain review candidates; they were not relabelled automatically.
|
||||
|
||||
This is explicitly an AI-assisted inspection, not a signed human review. No
|
||||
human-review gate or label-acceptance record was fabricated.
|
||||
|
||||
## Fail-closed production decision
|
||||
|
||||
The existing seven-zone API benchmark was started with the challenger at
|
||||
confidence `0.25`, but the current provenance gate stopped it before model
|
||||
loading. The historical checkpoint predates the required neighbouring
|
||||
`.geointel-model.json` runtime manifest and its governed database snapshot.
|
||||
That control was not bypassed and no production inference from the unbound
|
||||
checkpoint was accepted.
|
||||
|
||||
The challenger may only be reconsidered after its original training evidence
|
||||
is migrated without invented lineage, followed by the same seven positive
|
||||
zones and three pure-background controls. Until then, the active checkpoint is
|
||||
the only safe production choice.
|
||||
|
||||
Machine-readable hashes, metrics, paths and the exact decision are in
|
||||
`artifacts/evidence/accuracy/model-training/20260809-v68-checkpoint-and-threshold-review.json`.
|
||||
|
||||
## Provenance migration follow-up
|
||||
|
||||
The original July training directory was audited after the threshold review.
|
||||
It retains exact weights, Ultralytics arguments, result curves, dataset YAML,
|
||||
dataset summary and a structural quality audit. This recovers useful facts,
|
||||
including seed `0`, deterministic mode, the base-model hash and all dataset
|
||||
counts.
|
||||
|
||||
It does not retain the complete evidence required to construct a current
|
||||
production sidecar truthfully. In particular, the exact training commit,
|
||||
container digest, dependency/runtime receipt, immutable corpus and label
|
||||
release manifests, independent split audit and accepted human-review ledger
|
||||
are absent. The current review validator reproduces four failures:
|
||||
|
||||
- `accepted_human_review_evidence_missing`;
|
||||
- `review_audit_manifest_not_immutable`;
|
||||
- `review_audit_spatial_leakage_not_ok`; and
|
||||
- `review_complete_not_true`.
|
||||
|
||||
No UUID, upstream checksum, historical runtime or reviewer decision was
|
||||
invented. Consequently no runtime sidecar or database source snapshot was
|
||||
created, and the challenger remains unavailable to production inference. The
|
||||
full machine-readable audit is retained in
|
||||
`artifacts/evidence/accuracy/model-training/20260809-reviewedexp6-provenance-migration-audit.json`.
|
||||
|
||||
## Completed AI-assisted AOI ledger
|
||||
|
||||
At the user's explicit request, the existing 64-tile contact sheet was
|
||||
reviewed again at original resolution and recorded as AI-assisted evidence.
|
||||
The sheet represents 28 AOIs and renders 21,611 labels. Twenty-six represented
|
||||
training AOIs were classified as eligible for experimental training;
|
||||
Grobbendonk and Vosselaar remain non-protected validation only. Lommel-heide
|
||||
and Postel-bos were visually retained as pure-empty examples, while six sparse
|
||||
contexts remain explicitly distinct from pure background.
|
||||
|
||||
The ledger identifies `openai-codex` as an AI assistant and sets `human=false`.
|
||||
It explicitly cannot satisfy the human-review release gate. The production
|
||||
training wrapper reproduced that boundary and no bypass was added. The exact
|
||||
ledger is retained in
|
||||
`artifacts/evidence/accuracy/model-training/20260809-reviewedexp6-ai-assisted-review-ledger.json`.
|
||||
|
||||
The renderer was subsequently paginated and the review expanded from the
|
||||
64-tile sample to all 252 retained tiles. Four immutable pages now account for
|
||||
all 79,192 labels with zero missing images, missing label files, invalid rows
|
||||
or low-variance tiles. No exact or IoU>=0.90 duplicate box pair was found. A
|
||||
separate containment probe identified 43 potentially nested pairs across 36
|
||||
tiles (0.0543% relative to rendered labels); these remain human-adjudication
|
||||
candidates and were neither rewritten nor automatically excluded.
|
||||
|
||||
The 36 flagged tiles were then rendered on a separate high-resolution sheet.
|
||||
AI-assisted inspection found no systematic duplicate-label pattern: the
|
||||
relationships predominantly represent adjacent or complex building components
|
||||
in dense GRB contexts. All tiles remain available for experimental analysis,
|
||||
while the exact 43 pairs stay visible for human release adjudication.
|
||||
|
||||
A second focused render now binds the relationship manifest back to the exact
|
||||
YOLO label-row indices. It highlights all 86 implicated rows: cyan for exact
|
||||
duplicates, red for near duplicates and magenta for possible nesting. The sheet
|
||||
contains only magenta relationship marks, confirming visually and
|
||||
machine-readably that there are no exact or high-IoU duplicates in this set.
|
||||
The nesting cases are geographically dispersed and commonly combine a larger
|
||||
GRB object envelope with a smaller component. They are not deterministic
|
||||
rewrite candidates. Excluding the 36 complete tiles would also discard 17,167
|
||||
unflagged labels, so no automatic tile exclusion or label mutation was made.
|
||||
The checksum-bound highlighted sheet and summary are recorded in the AI review
|
||||
ledger.
|
||||
|
||||
## Row-level geometry and overlap follow-up
|
||||
|
||||
The complete 79,192-label corpus was additionally audited at label-row level.
|
||||
The immutable manifest identifies 6,657 unique rows with at least one geometric
|
||||
training-risk signal: 1,812 rows have a width or height below 4 pixels, 26 have
|
||||
aspect ratio at least 8 and 5,079 touch a tile edge. The categories were
|
||||
rendered separately. All 23 extreme-aspect tiles and all 198 small-dimension
|
||||
tiles were inspected, plus a 64-tile edge sample.
|
||||
|
||||
The extreme-aspect group predominantly shows plausible elongated sheds and
|
||||
building components. Sixteen of its 26 rows are also below 4 pixels, allowing
|
||||
the resolution floor to address most ambiguous extremes without deleting valid
|
||||
long structures. The small-dimension sheets contain many visually marginal
|
||||
miniature targets. The next immutable experimental corpus should therefore use
|
||||
the exporter's normal minimum dimension of at least 4 pixels instead of this
|
||||
legacy corpus's 3-pixel override. This finding does not justify mutating the
|
||||
frozen corpus or retroactively changing its checkpoint.
|
||||
|
||||
The edge sample shows expected clipped buildings under the 0.35 minimum-visible
|
||||
policy. Raising that value may reduce partial-target pressure, but it must be a
|
||||
separately versioned ablation because removing all 5,079 rows without checking
|
||||
the original visible fraction would be unsound.
|
||||
|
||||
## Derived min-4px experimental corpus
|
||||
|
||||
The row-level finding was converted into a new immutable derived corpus rather
|
||||
than changing the historical dataset. The derivation is checksum-bound to the
|
||||
79,192-label source summary and removes only labels whose smallest 512-tile
|
||||
dimension is below 4 pixels. It retains all 252 tiles and 77,380 labels; no
|
||||
positive tile became empty, and no source file was overwritten.
|
||||
|
||||
Fresh audits report zero sub-4-pixel labels, zero invalid or missing label
|
||||
files, zero exact/high-IoU duplicates and zero reconstructed cross-split
|
||||
object groups. Extreme-aspect labels fall from 26 to 10, possible nesting from
|
||||
43 to 41 and tile-edge rows from 5,079 to 4,840. The complete four-page visual
|
||||
render was inspected again. Pure-background tiles remain visibly empty, sparse
|
||||
contexts remain distinct and the ten remaining elongated labels predominantly
|
||||
match plausible long structures.
|
||||
|
||||
The generic quality auditor still reports `needs_attention` because normalized
|
||||
median box area `0.000641` is below its conservative `0.001` warning threshold.
|
||||
That corresponds to median dimensions near 12 by 13 pixels at source tile
|
||||
resolution and is not a failed minimum-dimension gate. The warning remains
|
||||
visible; it was not suppressed or relabelled as success.
|
||||
|
||||
This min-4px version is the preferred experimental successor to the legacy
|
||||
min-3px corpus. It explicitly remains ineligible for governed training until
|
||||
real human review and all release-contract evidence exist.
|
||||
|
||||
## Non-overlapping checkpoint re-evaluation
|
||||
|
||||
The 36-tile checkpoint matrix was traced to a 512 px validation corpus with
|
||||
stride 256. It contained nine views each of Turnhout, Westerlo, Postel-bos and
|
||||
Arendonk-heide. Visual inspection then exposed that all Arendonk-heide views
|
||||
are blank/no-data imagery, not meaningful pure-background observations. The
|
||||
historical claim of 18 background images is therefore corrected: nine were
|
||||
blank no-data and nine represented Postel under overlap.
|
||||
|
||||
A training-disabled validation view now covers each 1024 px AOI with four
|
||||
non-overlapping 512 px tiles. Four blank Arendonk representatives are excluded
|
||||
with explicit reason codes. The resulting set contains eight positive tiles
|
||||
from Turnhout/Westerlo, four real Postel background tiles and 2,551 labels.
|
||||
Exact reconstruction finds 2,384 unique interior objects, 167 edge labels and
|
||||
zero repeated interior objects. The view has empty train directories, a
|
||||
checksum-bound `NO_TRAINING.json`, and the training wrapper rejects that marker.
|
||||
|
||||
On the Tower RTX 4080 SUPER, the active checkpoint measures precision
|
||||
`0.542632`, recall `0.435317`, mAP50 `0.342034` and mAP50-95 `0.141316`.
|
||||
The reviewedexp6 challenger measures `0.581715`, `0.462300`, `0.368364` and
|
||||
`0.155318` respectively. At background confidence 0.15 the active checkpoint
|
||||
has zero Postel detections and the challenger has one. At 0.25 both have zero.
|
||||
Thus the refined evidence confirms the challenger's relative metric advantage
|
||||
and its threshold sensitivity, but still does not authorize promotion.
|
||||
|
||||
Non-overlap is not overstated as statistical independence: the positive tiles
|
||||
remain adjacent and come from only two AOIs, edge objects can remain split, and
|
||||
there is only one real background AOI. The production model remains unchanged.
|
||||
|
||||
## Training/evaluation membership correction
|
||||
|
||||
The evaluation AOIs were subsequently checked against the exact tile summaries
|
||||
of both compared checkpoints. `turnhout` and `westerlo` do not occur in either
|
||||
train split. `postel_bos`, however, occurs in both: the active corpus contains
|
||||
20 training AOIs and the challenger corpus 26, with Postel included in each.
|
||||
The Postel image is real rather than blank/no-data, but it is training-seen.
|
||||
|
||||
Consequently the positive Turnhout/Westerlo metrics remain a non-protected,
|
||||
adjacent-AOI candidate ranking; the Postel detection counts are only
|
||||
training-seen sanity/regression observations. They are not independent
|
||||
pure-background validation and cannot support release, threshold or
|
||||
generalisation claims. The earlier wording about a "real background AOI" must
|
||||
be read with this correction.
|
||||
|
||||
The checkpoint evaluator now accepts exact training summaries and, in governed
|
||||
mode, fails before PyTorch import, model loading or GPU inference when any
|
||||
evaluation AOI overlaps any supplied train split. The reproduced gate blocked
|
||||
on `postel_bos` for both checkpoints. Its immutable machine-readable record is
|
||||
`artifacts/evidence/accuracy/model-training/20260809-v70-evaluation-independence-gate.json`.
|
||||
|
||||
## Full model-lineage correction
|
||||
|
||||
The preceding correction still considered only the final fine-tune corpus of
|
||||
each checkpoint. Exact retained Ultralytics arguments establish a longer
|
||||
ancestry: the active checkpoint was initialized from
|
||||
`geointel-building-yolov8s-aoi1024expandedminpx4vis035e50`, which was initialized
|
||||
from the generic `yolov8s.pt`; the challenger was then initialized from the
|
||||
active checkpoint. The copied model assets and retained `best.pt` files match
|
||||
byte-for-byte at each building-model stage.
|
||||
|
||||
The ancestral expanded corpus exposes all three evaluation AOIs: `postel_bos`
|
||||
as train, and `turnhout` plus `westerlo` as validation. Therefore none of the
|
||||
v69 AOIs is independent of the complete model family. Turnhout/Westerlo can
|
||||
still be used as familiar regression diagnostics, but their metrics are not a
|
||||
fresh candidate-ranking result and must not support accuracy, uncertainty,
|
||||
generalisation or release claims.
|
||||
|
||||
The gate now requires every ancestral corpus summary and checks every recorded
|
||||
split, including validation and calibration. A reproduced Tower run blocked on
|
||||
all three AOIs before PyTorch import, model loading or GPU inference. Evidence:
|
||||
`artifacts/evidence/accuracy/model-training/20260809-v71-full-lineage-independence-gate.json`.
|
||||
The byte-matching parent/output chain is retained separately in
|
||||
`artifacts/evidence/accuracy/model-training/20260809-v71-model-lineage-receipt.json`.
|
||||
Fresh geographically separated AOIs with complete spatial and lineage checks
|
||||
are required for the next meaningful evaluation.
|
||||
|
||||
## Fresh V72 calibration portfolio
|
||||
|
||||
Six AOIs were pre-registered before inference and acquired again from the
|
||||
governed regional orthophoto and building adapters: two each in Vlaanderen,
|
||||
Wallonië and Brussel. All six are absent from every split of the retained model
|
||||
lineage. A raster-bound spatial audit resolved all 31 ancestral AOIs and found
|
||||
the nearest new AOI at 4,869.63 metres, above the frozen 2 km floor.
|
||||
|
||||
The initial generic edge-cover tiling would have counted 54 tiles because its
|
||||
final-row/final-column coverage nearly duplicated the preceding 512 px cells.
|
||||
That view was rejected. The corrected evaluation-only exporter retains exactly
|
||||
24 full grid cells, excludes 30 overlapping edge-cover views with reason codes,
|
||||
and writes no training tiles. Both the corpus and tile view contain bound
|
||||
`NO_TRAINING.json` markers.
|
||||
|
||||
All 24 tiles and 348 retained labels were visually inspected. Havelange is a
|
||||
positive village context despite its pre-registered `field-cal-bg` name.
|
||||
Assenede and Laeken contain sparse official building labels and are difficult
|
||||
contexts, not pure-empty backgrounds. The evaluator now refuses to accept a
|
||||
pure-background prefix when any corresponding label file is non-empty.
|
||||
|
||||
On the RTX 4080 SUPER the active model scores mAP50 `0.056779` and mAP50-95
|
||||
`0.021750`; the challenger scores `0.044705` and `0.016004`. At confidence 0.25
|
||||
and match IoU 0.25 their F1 scores are `0.231527` and `0.235885`. These low
|
||||
values expose substantial domain-generalisation failure. The active model stays
|
||||
in production because the challenger has weaker mAP, only a marginal F1 gain,
|
||||
missing historical release provenance and no valid promotion bundle.
|
||||
|
||||
The active model's aggregate calibration F1 peaks at threshold 0.30
|
||||
(`0.250356`), but its Flemish subgroup becomes worse than at lower thresholds.
|
||||
No threshold was changed because a global average may not mask that subgroup
|
||||
regression. PICC and UrbIS remain diagnostic-only while their regional semantic
|
||||
harmonisation contracts are pending; no national release claim is made.
|
||||
|
||||
Complete evidence is retained under
|
||||
`artifacts/evidence/accuracy/model-training/20260809-v72-fresh-calibration/`
|
||||
and summarized by `20260809-v72-fresh-calibration-summary.json`.
|
||||
@@ -1,410 +0,0 @@
|
||||
# Model And Reference Catalog Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add a read-only local model asset catalog and make official reference providers visually distinct from AI model selection.
|
||||
|
||||
**Architecture:** Model files remain runtime assets in the mounted model directory; persisted domain state remains in jobs, analysis runs, detections, datasets and vector features. Detection runs keep `model_id="yolo-configured"` and optionally include a validated `model_asset_id` resolved by a dedicated backend service.
|
||||
|
||||
**Tech Stack:** FastAPI, Pydantic, SQLAlchemy, React, TypeScript, Vite, MapLibre, existing GeoIntel API envelope helpers.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
- Create `backend/app/services/model_asset_catalog_service.py`: read-only scanner and resolver for local model assets.
|
||||
- Modify `backend/app/core/config.py`: add `YOLO_MODELS_DIR` setting with safe default `/app/models`.
|
||||
- Modify `backend/app/schemas/detection.py`: add model asset response schemas and optional request fields.
|
||||
- Modify `backend/app/api/routes/detection.py`: add model asset endpoint and pass selected asset IDs to preflight/detection.
|
||||
- Modify `backend/app/services/detection_service.py`: resolve selected model asset into run-local YOLO settings and persist selection in parameters.
|
||||
- Modify `backend/app/services/yolo_preflight_service.py`: accept selected asset ID and preflight against that asset path.
|
||||
- Add `backend/tests/test_model_asset_catalog.py`: unit tests for scanning, resolving and envelope behavior.
|
||||
- Add or extend `backend/tests/test_sprint8b_yolo_foundation.py`: detection run parameter persistence for selected assets.
|
||||
- Modify `frontend/src/types.ts`: add model asset types and optional request fields.
|
||||
- Modify `frontend/src/services/api/detection.ts`: add model asset endpoint and preflight query param.
|
||||
- Modify `frontend/src/hooks/useDetectionWorkflow.ts`: load/select model assets and send selected asset ID.
|
||||
- Modify `frontend/src/components/detection/DetectionLab.tsx`: add local model asset picker and clearer model state.
|
||||
- Modify `frontend/src/components/providers/ProviderPanel.tsx`: sharpen reference-provider catalog copy.
|
||||
- Update docs listed in the design document.
|
||||
|
||||
## Task 1: Backend Catalog Tests
|
||||
|
||||
**Files:**
|
||||
|
||||
- Create: `backend/tests/test_model_asset_catalog.py`
|
||||
|
||||
- [ ] **Step 1: Write catalog unit tests**
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
|
||||
from app.core.config import Settings
|
||||
from app.services.model_asset_catalog_service import ModelAssetCatalogService
|
||||
|
||||
|
||||
def test_model_asset_catalog_lists_supported_files(tmp_path: Path) -> None:
|
||||
model_file = tmp_path / "building-detector.pt"
|
||||
model_file.write_bytes(b"local model")
|
||||
ignored_file = tmp_path / "notes.txt"
|
||||
ignored_file.write_text("ignore me", encoding="utf-8")
|
||||
settings = Settings(yolo_models_dir=str(tmp_path), yolo_model_path=str(model_file), yolo_enabled=True)
|
||||
|
||||
response = ModelAssetCatalogService.list_assets(settings=settings)
|
||||
|
||||
assert response.total == 1
|
||||
asset = response.items[0]
|
||||
assert asset.filename == "building-detector.pt"
|
||||
assert asset.active is True
|
||||
assert asset.model_path == str(model_file)
|
||||
assert asset.size_bytes == len(b"local model")
|
||||
assert len(asset.sha256) == 64
|
||||
assert asset.will_download_models is False
|
||||
|
||||
|
||||
def test_model_asset_catalog_resolves_known_asset(tmp_path: Path) -> None:
|
||||
model_file = tmp_path / "building-detector.pt"
|
||||
model_file.write_bytes(b"local model")
|
||||
settings = Settings(yolo_models_dir=str(tmp_path), yolo_enabled=True)
|
||||
|
||||
asset = ModelAssetCatalogService.resolve_asset("building-detector-pt", settings=settings)
|
||||
|
||||
assert asset.filename == "building-detector.pt"
|
||||
assert asset.model_path == str(model_file)
|
||||
|
||||
|
||||
def test_model_asset_catalog_rejects_unknown_asset(tmp_path: Path) -> None:
|
||||
settings = Settings(yolo_models_dir=str(tmp_path), yolo_enabled=True)
|
||||
|
||||
try:
|
||||
ModelAssetCatalogService.resolve_asset("missing-model", settings=settings)
|
||||
except Exception as exc:
|
||||
assert getattr(exc, "code", "") == "DETECTION_MODEL_ASSET_NOT_FOUND"
|
||||
else:
|
||||
raise AssertionError("unknown model asset should fail")
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the tests to verify they fail before implementation**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python -m pytest tests/test_model_asset_catalog.py -q
|
||||
```
|
||||
|
||||
Expected: import failure for `model_asset_catalog_service`.
|
||||
|
||||
## Task 2: Backend Catalog Implementation
|
||||
|
||||
**Files:**
|
||||
|
||||
- Create: `backend/app/services/model_asset_catalog_service.py`
|
||||
- Modify: `backend/app/core/config.py`
|
||||
- Modify: `backend/app/schemas/detection.py`
|
||||
|
||||
- [ ] **Step 1: Add settings and schemas**
|
||||
|
||||
Add `yolo_models_dir` to settings:
|
||||
|
||||
```python
|
||||
yolo_models_dir: str = Field(default="/app/models", validation_alias="YOLO_MODELS_DIR")
|
||||
```
|
||||
|
||||
Add schemas:
|
||||
|
||||
```python
|
||||
class ModelAssetRead(BaseModel):
|
||||
model_asset_id: str
|
||||
filename: str
|
||||
display_name: str
|
||||
model_path: str
|
||||
suffix: str
|
||||
framework: str
|
||||
task_type: str
|
||||
size_bytes: int
|
||||
sha256: str
|
||||
active: bool
|
||||
status: str
|
||||
limitation_message: str
|
||||
will_download_models: bool = False
|
||||
|
||||
|
||||
class ModelAssetListResponse(BaseModel):
|
||||
items: list[ModelAssetRead]
|
||||
total: int
|
||||
model_directory: str
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Implement the scanner and resolver**
|
||||
|
||||
Implement a service that:
|
||||
|
||||
- resolves `YOLO_MODELS_DIR`;
|
||||
- scans `.pt`, `.onnx`, `.engine`;
|
||||
- uses deterministic slug IDs such as `building-detector-pt`;
|
||||
- computes SHA-256;
|
||||
- marks active file by comparing resolved paths;
|
||||
- raises `AppError(code="DETECTION_MODEL_ASSET_NOT_FOUND", status_code=404)` for unknown IDs.
|
||||
|
||||
- [ ] **Step 3: Run focused tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python -m pytest tests/test_model_asset_catalog.py -q
|
||||
```
|
||||
|
||||
Expected: pass.
|
||||
|
||||
## Task 3: API And Service Wiring
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `backend/app/api/routes/detection.py`
|
||||
- Modify: `backend/app/services/detection_service.py`
|
||||
- Modify: `backend/app/services/yolo_preflight_service.py`
|
||||
- Modify: `backend/app/schemas/detection.py`
|
||||
- Test: `backend/tests/test_model_asset_catalog.py`
|
||||
|
||||
- [ ] **Step 1: Add endpoint test**
|
||||
|
||||
Add a FastAPI test that calls `GET /api/v1/detection/model-assets` and asserts:
|
||||
|
||||
```python
|
||||
assert "data" in response.json()
|
||||
assert response.json()["data"]["total"] == 1
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add optional request fields**
|
||||
|
||||
Extend `DetectionRunRequest` with:
|
||||
|
||||
```python
|
||||
model_asset_id: str | None = None
|
||||
```
|
||||
|
||||
Extend preflight query handling with `model_asset_id: str | None = None`.
|
||||
|
||||
- [ ] **Step 3: Wire endpoint**
|
||||
|
||||
Add route:
|
||||
|
||||
```python
|
||||
@router.get("/model-assets", response_model=dict)
|
||||
def list_detection_model_assets() -> dict:
|
||||
return envelope(ModelAssetCatalogService.list_assets().model_dump())
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Resolve selected asset in detection service**
|
||||
|
||||
When `model_asset_id` is present and `model_id` equals the configured YOLO model ID:
|
||||
|
||||
- resolve the asset through `ModelAssetCatalogService`;
|
||||
- copy settings with `yolo_model_path=asset.model_path`;
|
||||
- persist `model_asset_id`, `model_asset_path`, and `model_asset_sha256` in run parameters.
|
||||
|
||||
- [ ] **Step 5: Resolve selected asset in preflight**
|
||||
|
||||
When `model_asset_id` is present:
|
||||
|
||||
- resolve the asset;
|
||||
- preflight against that asset path;
|
||||
- include `model_asset_id` in the response.
|
||||
|
||||
- [ ] **Step 6: Run focused tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python -m pytest tests/test_model_asset_catalog.py tests/test_sprint8b_yolo_foundation.py -q
|
||||
```
|
||||
|
||||
Expected: pass.
|
||||
|
||||
## Task 4: Frontend Model Asset Selection
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `frontend/src/types.ts`
|
||||
- Modify: `frontend/src/services/api/detection.ts`
|
||||
- Modify: `frontend/src/hooks/useDetectionWorkflow.ts`
|
||||
- Modify: `frontend/src/components/detection/DetectionLab.tsx`
|
||||
|
||||
- [ ] **Step 1: Add frontend types and API call**
|
||||
|
||||
Add:
|
||||
|
||||
```ts
|
||||
export interface ModelAssetRead {
|
||||
model_asset_id: string
|
||||
filename: string
|
||||
display_name: string
|
||||
model_path: string
|
||||
suffix: string
|
||||
framework: string
|
||||
task_type: string
|
||||
size_bytes: number
|
||||
sha256: string
|
||||
active: boolean
|
||||
status: string
|
||||
limitation_message: string
|
||||
will_download_models: boolean
|
||||
}
|
||||
|
||||
export interface ModelAssetListResponse {
|
||||
items: ModelAssetRead[]
|
||||
total: number
|
||||
model_directory: string
|
||||
}
|
||||
```
|
||||
|
||||
Add `model_asset_id?: string | null` to `DetectionRunRequest` and preflight params.
|
||||
|
||||
- [ ] **Step 2: Add hook state**
|
||||
|
||||
Add:
|
||||
|
||||
```ts
|
||||
const [modelAssets, setModelAssets] = useState<ModelAssetRead[]>([])
|
||||
const [selectedModelAssetId, setSelectedModelAssetId] = useState('')
|
||||
const [modelAssetError, setModelAssetError] = useState<string | null>(null)
|
||||
```
|
||||
|
||||
Load assets alongside detection models and default to the active asset when one exists.
|
||||
|
||||
- [ ] **Step 3: Send selected asset**
|
||||
|
||||
Send `model_asset_id: selectedModelAssetId || null` in:
|
||||
|
||||
- `getYoloPreflight`;
|
||||
- `run`.
|
||||
|
||||
- [ ] **Step 4: Add UI picker**
|
||||
|
||||
In `DetectionLab`, render a local model asset picker when `selectedDetectionModelId === "yolo-configured"`.
|
||||
|
||||
Show:
|
||||
|
||||
- filename;
|
||||
- active badge;
|
||||
- size in MB;
|
||||
- checksum prefix;
|
||||
- no-download warning.
|
||||
|
||||
- [ ] **Step 5: Typecheck**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
Expected: pass.
|
||||
|
||||
## Task 5: Provider Catalog Clarity
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `frontend/src/components/providers/ProviderPanel.tsx`
|
||||
|
||||
- [ ] **Step 1: Update copy and grouping**
|
||||
|
||||
Keep existing provider cards but add a concise heading that states:
|
||||
|
||||
- GRB/OSM are source capabilities, not model choices;
|
||||
- manual upload is the currently configured reference data path;
|
||||
- fixture is test/demo only.
|
||||
|
||||
- [ ] **Step 2: Build**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
Expected: pass.
|
||||
|
||||
## Task 6: Documentation
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `docs/API_CONTRACTS.md`
|
||||
- Modify: `docs/AI_PIPELINES.md`
|
||||
- Modify: `backend/README.md`
|
||||
- Modify: `frontend/README.md`
|
||||
- Modify: `docs/CODEX_EXECUTION_LOG.md`
|
||||
- Modify: `CHANGELOG.md`
|
||||
- Modify: `docs/TODO.md`
|
||||
|
||||
- [ ] **Step 1: Document backend API**
|
||||
|
||||
Document:
|
||||
|
||||
- `GET /api/v1/detection/model-assets`;
|
||||
- optional `model_asset_id` on preflight and run;
|
||||
- no model downloads;
|
||||
- `YOLO_MODELS_DIR`.
|
||||
|
||||
- [ ] **Step 2: Document UI behavior**
|
||||
|
||||
Document:
|
||||
|
||||
- model assets are local runtime files;
|
||||
- GRB/OSM are reference data providers;
|
||||
- manual upload remains the configured reference path.
|
||||
|
||||
## Task 7: Full Validation
|
||||
|
||||
**Files:** none unless validation reveals a bug.
|
||||
|
||||
- [ ] **Step 1: Run backend compile**
|
||||
|
||||
```bash
|
||||
python -m compileall backend/app
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run backend tests**
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python -m pytest
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Run readiness**
|
||||
|
||||
```bash
|
||||
bash scripts/run_readiness_check.sh
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run frontend typecheck and build**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run typecheck
|
||||
npm run build
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Run migration checks**
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python -m alembic heads
|
||||
python -m alembic upgrade head --sql
|
||||
bash ../scripts/live_migration_smoke.sh
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Runtime smoke after deploy**
|
||||
|
||||
Call:
|
||||
|
||||
```bash
|
||||
curl http://192.0.2.10:1202/api/v1/detection/model-assets
|
||||
curl "http://192.0.2.10:1202/api/v1/detection/yolo/preflight?model_asset_id=<asset>&tile_manifest_path=<manifest>"
|
||||
```
|
||||
|
||||
Expected: canonical envelopes and no model downloads.
|
||||
@@ -1,63 +0,0 @@
|
||||
# YOLO Label QA Contact Sheets Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Build an operator-only visual QA script that creates deterministic contact-sheet PNG artifacts from existing YOLO tile datasets.
|
||||
|
||||
**Architecture:** Add a standalone script under `scripts/` with no backend/API/database changes. The script reads `yolo_tile_dataset_summary.json`, resolves image and label paths, selects a bounded deterministic tile subset, draws normalized YOLO labels using Pillow, and writes JSON/Markdown/PNG artifacts.
|
||||
|
||||
**Tech Stack:** Python standard library, Pillow, pytest subprocess-based script tests.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Regression Test
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py`
|
||||
|
||||
- [ ] Write a failing test that creates a tiny YOLO dataset with train/val images, valid labels, an invalid label row and a missing label path.
|
||||
- [ ] Run `python -m pytest backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py -q`.
|
||||
- [ ] Expected result: failure because `scripts/render_operator_yolo_label_qa_contact_sheets.py` does not exist.
|
||||
|
||||
### Task 2: Script Implementation
|
||||
|
||||
**Files:**
|
||||
- Create: `scripts/render_operator_yolo_label_qa_contact_sheets.py`
|
||||
|
||||
- [ ] Implement CLI arguments:
|
||||
- `--summary-path`
|
||||
- `--output-dir`
|
||||
- `--max-tiles`
|
||||
- `--columns`
|
||||
- `--thumb-size`
|
||||
- [ ] Implement summary loading and `/app/...` path resolution consistent with existing operator scripts.
|
||||
- [ ] Implement YOLO label parsing with invalid/missing counts.
|
||||
- [ ] Implement deterministic tile selection.
|
||||
- [ ] Implement Pillow rendering to PNG contact sheets.
|
||||
- [ ] Implement JSON and Markdown reports.
|
||||
- [ ] Run the targeted test and keep the implementation minimal until it passes.
|
||||
|
||||
### Task 3: Documentation
|
||||
|
||||
**Files:**
|
||||
- Modify: `scripts/README.md`
|
||||
- Modify: `docs/TODO.md`
|
||||
- Modify: `docs/CODEX_EXECUTION_LOG.md`
|
||||
|
||||
- [ ] Document the command and intended usage.
|
||||
- [ ] Mark visual contact sheets as implemented in TODO.
|
||||
- [ ] Record local and Tower validation evidence.
|
||||
|
||||
### Task 4: Verification And Deploy
|
||||
|
||||
**Commands:**
|
||||
- `python -m pytest backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py -q`
|
||||
- `python -m pytest backend/tests/test_sprint146_operator_yolo_dataset_quality_audit.py backend/tests/test_sprint167_operator_yolo_label_qa_contact_sheets.py -q`
|
||||
- `bash scripts/run_readiness_check.sh`
|
||||
- `powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_tower.ps1`
|
||||
- Tower script run against `/app/storage/operator-data/yolo-building-aoi1024-cleanpx12vis035/yolo_tile_dataset_summary.json`
|
||||
|
||||
- [ ] Commit and push after local readiness.
|
||||
- [ ] Redeploy Tower.
|
||||
- [ ] Generate Tower contact sheets.
|
||||
- [ ] Commit and push evidence docs.
|
||||
@@ -1,56 +0,0 @@
|
||||
# YOLO Low-Variance Negative Filter Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add opt-in filtering for blank/low-variance negative tiles in the operator YOLO tile exporter.
|
||||
|
||||
**Architecture:** Keep the behavior inside `scripts/export_operator_yolo_tile_dataset.py` because this is operator-only dataset construction, not application inference. Compute low-variance from the raster window image array, skip only negative tiles when explicitly enabled, and expose all decisions in `yolo_tile_dataset_summary.json`.
|
||||
|
||||
**Tech Stack:** Python, pytest, rasterio/Pillow runtime helpers already used by the exporter.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Regression Test
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/tests/test_sprint130_operator_yolo_tile_dataset.py`
|
||||
|
||||
- [x] Add a test that monkeypatches `image_array_from_raster_window` and verifies `export_sample_tiles` skips only low-variance negative tiles when `drop_low_variance_negatives=True`.
|
||||
- [x] Run the targeted test and confirm it fails because the exporter does not yet accept/report the new filter fields.
|
||||
|
||||
### Task 2: Exporter Implementation
|
||||
|
||||
**Files:**
|
||||
- Modify: `scripts/export_operator_yolo_tile_dataset.py`
|
||||
|
||||
- [x] Add CLI/env options:
|
||||
- `--drop-low-variance-negatives`
|
||||
- `--blank-range-threshold`
|
||||
- [x] Add a helper to detect low visual variance from an image array.
|
||||
- [x] Thread the options into `export_sample_tiles`.
|
||||
- [x] Skip only negative low-variance tiles when the option is enabled.
|
||||
- [x] Add `low_visual_variance` to kept tile records.
|
||||
- [x] Add skipped records with `skip_reason="low_visual_variance_negative"`.
|
||||
- [x] Add summary fields for the option, threshold and skipped count.
|
||||
|
||||
### Task 3: Documentation
|
||||
|
||||
**Files:**
|
||||
- Modify: `scripts/README.md`
|
||||
- Modify: `docs/CODEX_EXECUTION_LOG.md`
|
||||
- Modify: `docs/TODO.md`
|
||||
|
||||
- [x] Document the new operator export flags and intended Tower command.
|
||||
- [x] Record local validation and known limitation.
|
||||
- [x] Mark the low-variance export filter item as implemented after validation.
|
||||
|
||||
### Task 4: Validation and Handoff
|
||||
|
||||
**Files:**
|
||||
- No additional file changes expected.
|
||||
|
||||
- [x] Run targeted pytest for the exporter/contact-sheet tests.
|
||||
- [x] Run `bash scripts/run_readiness_check.sh`.
|
||||
- [x] Commit and push.
|
||||
- [x] Rebuild/deploy Tower if code changed.
|
||||
- [x] Regenerate the AOI1024 dataset with the new filter enabled, then render contact sheets and record the result.
|
||||
@@ -1,217 +0,0 @@
|
||||
# Model And Reference Catalog Design
|
||||
|
||||
## Goal
|
||||
|
||||
Make GeoIntel operationally clearer for V1 users by separating two concepts that currently look too similar in the UI:
|
||||
|
||||
- local AI model assets that can be selected for configured YOLO inference;
|
||||
- official or contextual reference data providers such as GRB, OSM, manual uploads and fixtures.
|
||||
|
||||
This pass must not download model weights, fetch live GRB/OSM data, add training, add auth, or bypass the existing dataset, job, analysis run and detection persistence architecture.
|
||||
|
||||
## Current State
|
||||
|
||||
Detection currently exposes a model capability list with:
|
||||
|
||||
- `yolo-placeholder`;
|
||||
- one configured slot, `yolo-configured`, backed by `YOLO_MODEL_PATH`;
|
||||
- `manual-fixture-detector`.
|
||||
|
||||
This is import-safe and honest, but it does not feel like a model picker. A user can place multiple files in `/app/models`, yet the UI can only show the single configured environment slot.
|
||||
|
||||
Reference data currently exposes provider capabilities for:
|
||||
|
||||
- `grb`;
|
||||
- `osm`;
|
||||
- `manual`;
|
||||
- `fixture`.
|
||||
|
||||
This is architecturally correct, but the UI does not yet make the distinction explicit enough between authoritative reference sources and AI model assets.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- No automatic model downloads.
|
||||
- No bundled production model files in git.
|
||||
- No live GRB WFS or OSM Overpass import.
|
||||
- No direct writes from providers into `vector_features`.
|
||||
- No new database tables for model assets in this pass.
|
||||
- No training studio, model management workflow, LiDAR, reports, copilot or multi-user scope.
|
||||
|
||||
## Options Considered
|
||||
|
||||
### Option A: Keep Only `YOLO_MODEL_PATH`
|
||||
|
||||
Keep the current single configured model slot and document that users must edit `.env`.
|
||||
|
||||
Benefits:
|
||||
|
||||
- smallest code change;
|
||||
- preserves all existing contracts.
|
||||
|
||||
Drawbacks:
|
||||
|
||||
- poor operator experience;
|
||||
- no visible list of available local model files;
|
||||
- users cannot tell whether the model directory contains other usable files.
|
||||
|
||||
### Option B: Filesystem-Backed Model Asset Catalog
|
||||
|
||||
Scan a configured model directory, expose local model files through an API, and let the UI select one asset for `yolo-configured` runs.
|
||||
|
||||
Benefits:
|
||||
|
||||
- aligns with the current runtime model mount (`/app/models`);
|
||||
- no database migration;
|
||||
- no downloads or fake model metadata;
|
||||
- can show file existence, size, checksum and active environment model;
|
||||
- keeps actual inference inside `DetectionService` and `YoloDetectionAdapter`.
|
||||
|
||||
Drawbacks:
|
||||
|
||||
- metadata is limited unless optional sidecar files are added later;
|
||||
- model classes are not guaranteed without loading the model.
|
||||
|
||||
### Option C: Persisted Model Registry
|
||||
|
||||
Create database tables for model registry records, model versions, model artifacts and model lifecycle state.
|
||||
|
||||
Benefits:
|
||||
|
||||
- strong long-term foundation for training studio and MLOps;
|
||||
- full metadata and auditability.
|
||||
|
||||
Drawbacks:
|
||||
|
||||
- too broad for V1;
|
||||
- adds migration and lifecycle complexity before runtime needs justify it;
|
||||
- risks distracting from core GIS workflow completion.
|
||||
|
||||
## Recommended Approach
|
||||
|
||||
Use Option B.
|
||||
|
||||
Add a filesystem-backed model asset catalog for local runtime model files. It should scan `YOLO_MODELS_DIR`, defaulting to `/app/models`, and fall back to the parent directory of `YOLO_MODEL_PATH` when appropriate. It should only report local files with known model suffixes such as `.pt`, `.onnx` and `.engine`.
|
||||
|
||||
The catalog must be read-only. It must never download, create, mutate, move or delete model files.
|
||||
|
||||
Detection runs should still use `model_id="yolo-configured"` for the real YOLO execution path, but may include a selected `model_asset_id`. The backend resolves that ID to a path inside the configured model directory and uses that path for the run. This avoids arbitrary path injection while keeping the existing detection contract compatible.
|
||||
|
||||
## Backend Design
|
||||
|
||||
Create `ModelAssetCatalogService`.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- resolve the model directory from settings;
|
||||
- scan known model file suffixes;
|
||||
- return deterministic asset IDs derived from file names;
|
||||
- compute SHA-256 and size for visible provenance;
|
||||
- mark which asset matches the active `YOLO_MODEL_PATH`;
|
||||
- resolve a selected asset ID to a local path;
|
||||
- reject missing, unknown or out-of-directory model assets.
|
||||
|
||||
Add schemas:
|
||||
|
||||
- `ModelAssetRead`;
|
||||
- `ModelAssetListResponse`.
|
||||
|
||||
Add endpoint:
|
||||
|
||||
- `GET /api/v1/detection/model-assets`
|
||||
|
||||
Extend existing endpoints without breaking older clients:
|
||||
|
||||
- `GET /api/v1/detection/yolo/preflight` accepts optional `model_asset_id`;
|
||||
- `POST /api/v1/detection/run` accepts optional `model_asset_id`.
|
||||
|
||||
When `model_asset_id` is supplied, `DetectionService` should use a settings copy with `yolo_model_path` replaced by the resolved asset path. The run parameters should persist the selected asset ID and path for reproducibility.
|
||||
|
||||
## Frontend Design
|
||||
|
||||
Detection Lab should show:
|
||||
|
||||
- model capability cards;
|
||||
- a local model asset picker for configured YOLO;
|
||||
- active model indicator;
|
||||
- asset size and checksum prefix;
|
||||
- selected asset passed to preflight and detection run;
|
||||
- clear warning that GeoIntel does not download weights.
|
||||
|
||||
Provider panel should show:
|
||||
|
||||
- official reference source catalog;
|
||||
- GRB as authoritative but not configured for live fetch;
|
||||
- OSM as contextual and not configured for live fetch;
|
||||
- manual uploads as the configured way to add real reference datasets now;
|
||||
- fixtures as demo/test only.
|
||||
|
||||
## Data Flow
|
||||
|
||||
```text
|
||||
/app/models/*.pt
|
||||
-> ModelAssetCatalogService
|
||||
-> GET /api/v1/detection/model-assets
|
||||
-> Detection Lab model asset picker
|
||||
-> POST /api/v1/detection/run model_id=yolo-configured + model_asset_id
|
||||
-> DetectionService resolves local path
|
||||
-> YoloDetectionAdapter loads selected local model
|
||||
-> Job + AnalysisRun + Detection persistence
|
||||
```
|
||||
|
||||
Reference data remains:
|
||||
|
||||
```text
|
||||
Provider registry
|
||||
-> capabilities/status/limitations
|
||||
-> manual upload or future provider import
|
||||
-> DatasetService / VectorFeatureService
|
||||
-> vector_features
|
||||
-> detection/segmentation QA
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Unknown `model_asset_id`: `DETECTION_MODEL_ASSET_NOT_FOUND`.
|
||||
- Model asset outside configured directory: `DETECTION_MODEL_ASSET_INVALID`.
|
||||
- Missing configured YOLO dependencies: existing dependency unavailable behavior.
|
||||
- Missing tile manifest: existing tile manifest required behavior.
|
||||
- Missing model file after catalog resolution: existing model unavailable behavior.
|
||||
|
||||
## Tests
|
||||
|
||||
Backend tests should cover:
|
||||
|
||||
- catalog lists only supported local model files;
|
||||
- catalog marks the active model;
|
||||
- checksum and size are reported;
|
||||
- invalid assets are ignored;
|
||||
- unknown asset ID fails cleanly;
|
||||
- selected model asset is persisted in job and analysis run parameters;
|
||||
- model assets endpoint uses canonical envelope;
|
||||
- preflight accepts selected asset without model downloads.
|
||||
|
||||
Frontend tests should cover:
|
||||
|
||||
- Detection Lab exposes local model asset selection;
|
||||
- selected model asset is sent to run and preflight requests;
|
||||
- Provider Panel copy distinguishes reference providers from model assets.
|
||||
|
||||
## Documentation
|
||||
|
||||
Update:
|
||||
|
||||
- `docs/API_CONTRACTS.md`;
|
||||
- `docs/AI_PIPELINES.md`;
|
||||
- `backend/README.md`;
|
||||
- `frontend/README.md`;
|
||||
- `docs/CODEX_EXECUTION_LOG.md`;
|
||||
- `CHANGELOG.md`;
|
||||
- `docs/TODO.md`.
|
||||
|
||||
## Future Work
|
||||
|
||||
- Sidecar model metadata files, for example `model.pt.json`, for class names, source, license and intended task;
|
||||
- optional model compatibility smoke per selected asset;
|
||||
- persisted model registry after V1 foundation is stable;
|
||||
- live GRB/OSM imports through provider contracts;
|
||||
- official reference dataset browser after live provider imports exist.
|
||||
@@ -1,73 +0,0 @@
|
||||
# YOLO Label QA Contact Sheets Design
|
||||
|
||||
## Goal
|
||||
|
||||
Add an operator-only visual QA helper that renders existing YOLO tile images with
|
||||
their YOLO bbox labels overlaid into deterministic contact-sheet PNG artifacts.
|
||||
|
||||
## Scope
|
||||
|
||||
This is not a product feature and does not change API contracts, database
|
||||
schema, model activation, detection inference, provider fetching or training.
|
||||
It only reads an already exported YOLO tile dataset and writes visual evidence
|
||||
artifacts for human inspection before another training run.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `yolo_tile_dataset_summary.json` from `scripts/export_operator_yolo_tile_dataset.py`.
|
||||
- Existing tile image files referenced by the summary.
|
||||
- Existing YOLO label files referenced by the summary.
|
||||
|
||||
## Outputs
|
||||
|
||||
- `operator_yolo_label_qa_summary.json`
|
||||
- `operator_yolo_label_qa_contact_sheet.md`
|
||||
- One or more PNG contact sheets under the chosen output directory.
|
||||
|
||||
Each selected tile preview shows the image, label boxes and compact metadata:
|
||||
sample slug, split, label count and background category when present.
|
||||
|
||||
## Selection Strategy
|
||||
|
||||
The first implementation should be deterministic and small:
|
||||
|
||||
- include tiles with the highest label counts;
|
||||
- include tiles from low-label positive/context samples;
|
||||
- include a small number of negative tiles;
|
||||
- limit total rendered tiles with `--max-tiles`.
|
||||
|
||||
This is enough to catch common issues such as shifted imagery, clipped labels,
|
||||
wrong class files, empty positives and mislabeled background tiles.
|
||||
|
||||
## Rendering Strategy
|
||||
|
||||
Use Pillow, already available in the project runtime. Draw boxes from normalized
|
||||
YOLO labels directly onto the tile image. Invalid or missing label files are
|
||||
reported in JSON/Markdown and skipped for box drawing, not silently ignored.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Missing summary file: fail with a clear process error.
|
||||
- Missing image files: record skipped image count and continue if other selected
|
||||
images can be rendered.
|
||||
- Missing label files: record missing label count and render the image without
|
||||
boxes.
|
||||
- Invalid label rows: record invalid row count and render only valid boxes.
|
||||
|
||||
## Tests
|
||||
|
||||
Add focused tests that create tiny fixture images and YOLO labels in a temporary
|
||||
dataset directory, run the script and assert:
|
||||
|
||||
- JSON and Markdown reports are created;
|
||||
- contact-sheet PNG exists;
|
||||
- selected tile count is deterministic;
|
||||
- invalid labels are counted;
|
||||
- missing label files are counted;
|
||||
- rendered output is not blank.
|
||||
|
||||
## Acceptance
|
||||
|
||||
The helper is acceptable when local targeted tests pass, full readiness passes,
|
||||
the all-in-one Tower runtime is redeployed, and the clean AOI1024 dataset emits
|
||||
contact sheets on Tower.
|
||||
@@ -1,34 +0,0 @@
|
||||
# YOLO Low-Variance Negative Filter Design
|
||||
|
||||
## Goal
|
||||
|
||||
Prevent blank/no-data pure-empty negative tiles from entering the next operator YOLO training dataset while keeping the exporter conservative and auditable.
|
||||
|
||||
## Scope
|
||||
|
||||
This pass changes only operator-side YOLO tile export tooling. It does not change backend APIs, database schema, frontend behavior, model activation, training behavior, provider fetching or inference.
|
||||
|
||||
## Approach
|
||||
|
||||
Add an opt-in filter to `scripts/export_operator_yolo_tile_dataset.py` that evaluates raster tile image variance before writing negative tiles. The filter applies only after labels are computed and only when a tile is negative. Positive tiles are never dropped by this gate, even if visually low-variance, because dropping labeled data silently would be a worse failure mode.
|
||||
|
||||
The filter will use the same simple max-min grayscale range heuristic as the contact-sheet QA script. A tile with range at or below `OPERATOR_YOLO_BLANK_RANGE_THRESHOLD` is treated as low-variance. When `--drop-low-variance-negatives` is enabled, that negative tile is skipped and recorded in summary fields instead of being written into `images/` and `labels/`.
|
||||
|
||||
## Reporting
|
||||
|
||||
The dataset summary must include:
|
||||
|
||||
- `drop_low_variance_negatives`
|
||||
- `blank_range_threshold`
|
||||
- `skipped_low_variance_negative_tile_count`
|
||||
- skipped tile records with `skip_reason="low_visual_variance_negative"`
|
||||
|
||||
Kept tile records should include `low_visual_variance` so downstream contact-sheet and audit tooling can expose the signal.
|
||||
|
||||
## Validation
|
||||
|
||||
Add a regression test that constructs a blank negative raster window and a patterned negative raster window, enables the filter, and verifies that only the blank negative is skipped for `low_visual_variance_negative`.
|
||||
|
||||
## Known Limitation
|
||||
|
||||
The heuristic is intentionally simple. It identifies blank/no-data tiles, not semantic quality. Operator visual QA remains required before another training run.
|
||||
Reference in New Issue
Block a user