audit: establish accuracy phase 1 baseline
This commit is contained in:
@@ -12240,3 +12240,71 @@ Open:
|
||||
- De productiedemo toont zeven niet-administratieve werkruimtes, drie detectiemodellen en vier segmentatiemodellen; het geconfigureerde YOLO-model wordt als beschikbaar getoond.
|
||||
- Modelkalibratie, technische modelinstellingen, uploads en systeembeheer zijn niet zichtbaar voor gasten. Een directe gast-POST naar projectbeheer retourneert HTTP 403 `GUEST_READ_ONLY`; het modelregister retourneert HTTP 200 binnen dezelfde sessie.
|
||||
- Visuele browseracceptatie: horizontale overflow `0`; browserconsole `0` waarschuwingen en `0` fouten.
|
||||
|
||||
## 2026-08-01 - Accuracy Improvement Program Phase 1 forensic baseline
|
||||
|
||||
### Executed scope
|
||||
|
||||
- Audited repository root and tracked nested mirror, API/services/schemas,
|
||||
migrations, frontend, CI/readiness, container/deployment configuration,
|
||||
Tower Postgres/PostGIS, direct storage references, active CUDA runtime,
|
||||
mounted models/checkpoints/manifests/evaluations and Belgian building
|
||||
corpus lineage.
|
||||
- Created the seven required documents and machine-readable status under
|
||||
`docs/accuracy-program/`.
|
||||
- Added read-only collectors for repository state, Tower runtime/database,
|
||||
Tower ML/data lineage and one production-adapter GPU inference, plus a
|
||||
deterministic reproducer for seven critical/high contract violations.
|
||||
- Retained JSON, JUnit, SQL and command logs under
|
||||
`artifacts/evidence/accuracy/P1/`; no dataset, checkpoint, cache, output,
|
||||
user-owned untracked file or production database row was deleted or rewritten.
|
||||
|
||||
### Proven findings
|
||||
|
||||
- Reproduced cross-theme coverage contamination, metres-as-degrees buffering,
|
||||
Lambert coordinates persisted under SRID 4326, caller-spoofable official
|
||||
authority, mutable-name YOLO scope, mutable-name legal coverage and silently
|
||||
ignored Area PATCH geometry.
|
||||
- Tower database contains four successful Geel detections with Lambert-domain
|
||||
coordinates while stored as SRID 4326. Direct storage-reference audit checked
|
||||
5,816 references with zero missing; the broader recursive scan timed out and
|
||||
is not counted as a pass.
|
||||
- The building training loop contains a protected-test feedback path. V56 has
|
||||
180 AOIs but 0 human review decisions, only three pure-empty background-test
|
||||
AOIs and 24 cross-split AOI pairs below 2 km. V58/V62 are calibration-only,
|
||||
fail Flanders at the reported operating point and have no protected-test or
|
||||
promotion evidence.
|
||||
- Runtime lineage is incomplete: every persisted detection run has an empty
|
||||
model version and no tile-manifest hash; three runs lack a model hash.
|
||||
- Repository source of truth is ambiguous through 1,153 tracked nested mirror
|
||||
files, including 68 root/mirror differences. Root `.dockerignore` correctly
|
||||
excludes the mirror from the official all-in-one context.
|
||||
|
||||
### Runtime and verification evidence
|
||||
|
||||
- Real read-only inference passed through the production adapter on the Tower
|
||||
RTX 4080 SUPER, PyTorch 2.11.0+cu128/CUDA 12.8, with active model SHA
|
||||
`a9088b8491dfae36694b53e9e9406cb4e3511d334a5712fa34f75078a47759c1`.
|
||||
One existing EPSG:31370 tile produced 17 raw detections in 0.8837 s; this is
|
||||
runtime evidence only and not an accuracy result.
|
||||
- Full backend suite: 1,180 passed, 17 stale source/contract assertions failed.
|
||||
The actual backend CI working directory fails during collection on
|
||||
`scripts.render_operator_polygon_label_qa`.
|
||||
- Phase-1 tooling: 4 tests passed; all new audit files pass Ruff.
|
||||
- Repository Ruff baseline: 112 findings. Frontend `test:unit`: 51/51 passed;
|
||||
typecheck and build passed; the required `npm run lint` script is absent.
|
||||
- OpenAPI audit passed for 147 routes plus 10 declared non-envelope endpoints.
|
||||
Alembic has one head, `202607260001`, and the complete offline upgrade
|
||||
rendered successfully.
|
||||
- Two golden-QA runs produced equal semantic metrics but different retained
|
||||
bytes because run identity uses UUID4.
|
||||
|
||||
### Decision
|
||||
|
||||
- Phase 1 is complete as a forensic and executable baseline.
|
||||
- Release promotion, national validation, scope widening and immediate training
|
||||
remain blocked.
|
||||
- Phase 2 may start only as the dependency-ordered, test-first remediation in
|
||||
`docs/accuracy-program/06-implementation-roadmap.md`: fix CRS/authority/
|
||||
coverage/lineage and protected-test isolation, complete human corpus review,
|
||||
rebuild independent data, freeze metrics, then train on `cuda:0`.
|
||||
|
||||
@@ -1075,3 +1075,37 @@ This file now starts with the current implementation status. Older preparation/b
|
||||
- [x] Sta projectgebonden analyse-, QA-, assistent- en exportacties toe.
|
||||
- [x] Behoud server-side blokkades op instellingen, beheer, uploads, reviews en cross-projectverzoeken.
|
||||
- [x] Verifieer en redeploy de exacte commit naar Tower `/mnt/user/appdata/geointel`.
|
||||
|
||||
# Accuracy Improvement Program Phase 2 (2026-08-01)
|
||||
|
||||
- [x] Complete the Phase-1 forensic inventory, data lineage, reproducible
|
||||
baseline, risk register, metric framework, roadmap, status and retained
|
||||
evidence manifest.
|
||||
- [ ] P2-00: freeze evidence and enforce a promotion/scope-widening lock.
|
||||
- [ ] P2-01: establish one canonical CI command, repair import shadowing,
|
||||
replace 17 stale source assertions with reviewed behavior tests, close the
|
||||
112 Ruff findings and add real frontend lint.
|
||||
- [ ] P2-02: fix CRS ingest, metre buffering and Area geometry/CRS updates;
|
||||
auditably quarantine or repair the four legacy Geel detections.
|
||||
- [ ] P2-03: isolate coverage by source/theme/layer/zone, make official source
|
||||
identity server-attested and replace mutable-name legal/model scope checks.
|
||||
- [ ] P2-04: make derived persistence transactional, require complete
|
||||
RunManifest hashes and expose every fallback/persistence failure.
|
||||
- [ ] P2-05: remove every protected-test feedback path, introduce a test vault
|
||||
and make the sampler reject protected IDs, paths and assessment fields.
|
||||
- [ ] P2-06: complete representative human V56 review; add independent AOIs,
|
||||
Brussels pure backgrounds, difficult negatives and corrected temporal/dense
|
||||
PICC/UrbIS labels; freeze a new immutable corpus rather than changing V56.
|
||||
- [ ] P2-07: implement the metric/null/error-taxonomy contract, stratified
|
||||
incumbent baseline, calibration and reproducibility rerun; freeze numeric
|
||||
gates before protected-test access.
|
||||
- [ ] P2-08: train the pre-registered candidate matrix on the Tower RTX 4080
|
||||
SUPER with pinned PyTorch/CUDA, full hashes, seeds and zero CPU fallback.
|
||||
- [ ] P2-09: run a calibration-only improvement loop; use only independently
|
||||
provisioned, reviewed train data for another corpus version.
|
||||
- [ ] P2-10: open protected test/background-test exactly once for one immutable
|
||||
pre-registered candidate; never retrain that candidate family from its result.
|
||||
- [ ] P2-11: promote and redeploy only after every gate passes, with model card,
|
||||
image/model/config hashes, shadow evidence and tested rollback.
|
||||
- [ ] P2-12: monitor drift into a human reviewqueue without automatic
|
||||
self-training or silent promotion.
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,158 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,250 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,229 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,89 @@
|
||||
# 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”.
|
||||
@@ -0,0 +1,631 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,342 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,261 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"program": "GeoIntel Accuracy Improvement Program",
|
||||
"phase": "P1",
|
||||
"generated_at": "2026-08-01T18:40:00+02:00",
|
||||
"scope": {
|
||||
"product": "Belgium and the Belgian North Sea",
|
||||
"active_building_model_claim": "Mol/Kempen only, operator review required",
|
||||
"national_building_validation": false
|
||||
},
|
||||
"baseline": {
|
||||
"branch": "codex/geointel-accuracy-program",
|
||||
"repository_commit": "0c019bb22f816db1e4b7a68379bcad08924d9a21",
|
||||
"database_migration_head": "202607260001",
|
||||
"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": "P2-08 after P2-00 through P2-07 have passed",
|
||||
"critical_risk_count": 8,
|
||||
"high_risk_count": 17,
|
||||
"medium_risk_count": 4
|
||||
},
|
||||
"phase2": {
|
||||
"status": "ready_for_controlled_remediation",
|
||||
"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."
|
||||
},
|
||||
"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
|
||||
},
|
||||
"verification": {
|
||||
"backend_full_suite": {
|
||||
"status": "failed",
|
||||
"passed": 1180,
|
||||
"failed": 17,
|
||||
"duration_seconds": 70.63,
|
||||
"classification": "stale source/contract assertions; no new audit-tooling failures"
|
||||
},
|
||||
"backend_ci_entrypoint": {
|
||||
"status": "collection_failed",
|
||||
"collected": 1194,
|
||||
"error": "ModuleNotFoundError: scripts.render_operator_polygon_label_qa"
|
||||
},
|
||||
"phase1_tooling_tests": {
|
||||
"status": "passed",
|
||||
"passed": 4
|
||||
},
|
||||
"new_phase1_code_ruff": {
|
||||
"status": "passed"
|
||||
},
|
||||
"repository_ruff": {
|
||||
"status": "failed",
|
||||
"finding_count": 112,
|
||||
"by_code": {
|
||||
"E402": 13,
|
||||
"E701": 2,
|
||||
"E702": 69,
|
||||
"F401": 23,
|
||||
"F403": 1,
|
||||
"F811": 2,
|
||||
"F841": 2
|
||||
}
|
||||
},
|
||||
"frontend_unit": {
|
||||
"status": "passed",
|
||||
"test_files": 16,
|
||||
"tests": 51,
|
||||
"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": 147,
|
||||
"explicit_non_envelope_endpoints": 10
|
||||
},
|
||||
"alembic": {
|
||||
"status": "passed_offline",
|
||||
"heads": [
|
||||
"202607260001"
|
||||
],
|
||||
"offline_upgrade_sql_lines": 496,
|
||||
"live_migration_tested_locally": false
|
||||
},
|
||||
"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"
|
||||
],
|
||||
"evidence_root": "artifacts/evidence/accuracy/P1",
|
||||
"evidence_manifest": "artifacts/evidence/accuracy/P1/evidence-manifest.json"
|
||||
}
|
||||
Reference in New Issue
Block a user