Er was nergens een error boundary: geen componentDidCatch, geen
getDerivedStateFromError. Eén component die gooit nam de hele werkbank mee,
inclusief de kaart en de navigatie. Nu blijft de schil staan, ziet de gebruiker
welk werkblad het liet afweten, en wist wegnavigeren de fout.
Daarnaast een patroon dat op zeven plekken half was toegepast: een optionele
keten die te vroeg stopt. report?.items?.filter(...) stond geguard, twintig
regels verderop stond report.items.map(...) zonder. Half geguard is de
eigenlijke fout, want het wekt zekerheid zonder die te bieden. Waar de lijst op
meerdere plekken gebruikt wordt staat nu één normalisatie aan de kop.
De brondetails hadden geen enkele afhandeling en werden met .catch(() => null)
overgeslagen; die melden nu wel. De overige elf catch-blokken bleken bovenop
hooks te staan die de fout al zelf opvangen en tonen, wat ik heb nagemeten door
een verzoek te laten mislukken.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Achttien bevindingen uit de audit, met de metingen erbij in de betreffende
CSS-secties.
Fundament. Dertien tokens werden op 87 plaatsen aangeroepen zonder ooit
gedefinieerd te zijn; in de browser gaf getPropertyValue('--gi-text') een lege
string terug, dus die kleurregels vielen terug op overerving. Vorm en hoogte
zijn terug naar de schaal: radius via token van 17% naar 81%, unieke schaduwen
van 115 naar 71, losse kleurwaarden van 928 naar 352.
Typografie. De stylesheets declareerden negen gewichten terwijl er per familie
twee gezichten geladen werden, en font-synthesis-weight: none verbiedt
namaakvet. Alles van 650 tot 850 kwam dus als 600 op het scherm: 138 van de 148
declaraties rendereden identiek. Nu vier stappen die alle vier ook geladen
worden, en Manrope draagt de koppen zoals op de landingspagina.
Donkere werkstand. De werkbank staat tegen luchtbeelden aan; een lichte schil
daarnaast laat de kaart altijd verliezen. De landingspagina blijft licht.
Kaart. De ondergrond wordt ontkleurd en gedempt zodat alleen de eigen data nog
kleur draagt, en de symbologie staat niet langer als losse hexwaarden in
GeoMap. De zes zwevende vlakken zijn er drie: statuskaart, staprail en
resultaatchip bleken al één component te zijn die de opmaak over drie hoeken
van de kaart uiteentrok.
Schil. Eén kopbalk in plaats van drie (215px chroom naar 100px), het raster van
AI-vragen zonder botsingen, kapitalen op één niveau in plaats van 57
declaraties, en het leverancierslogo uit de navigatiebalk.
Van 47 echte !important naar 1, gemeten door telkens twee productiebuilds op
berekende stijlen te vergelijken. Contrast: nul tekstelementen onder AA op zes
werkbladen, in beide werkstanden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The recommended detection profile showed operators precision 0.614, recall
0.606 and F1 0.607. Those three numbers appear nowhere in this repository
except the file that publishes them and a test that pinned them as literal
strings. The only recorded evaluation of that model at that operating point —
tile 512, overlap 64, threshold 0.15, the exact key its promotion report
recommended — reported 0.590, 0.577 and 0.582. The published figures were about
two and a half points more flattering than anything that was measured, on the
profile labelled "aanbevolen", and the test made sure nobody would correct
them. They now carry the measured values.
Worse in kind: the conservative profile reported "gemeten achtergrondfouten 0".
Its nine-sample hard-negative matrix at threshold 0.35 recorded 198 background
detections with 55 in the worst sample. The one number that tells an operator
whether a high-precision model invents buildings on empty terrain said zero
where the evidence said 55.
Those zeros are not simply wrong everywhere, which is why the fix is not just a
number. The other two profiles genuinely produced zero — against a strict
pure-empty gate of three samples, a different and much weaker test than the
nine-sample hard-negative matrix. Printing 0, 0 and 55 side by side invites a
comparison the evidence does not support, so each profile now states its gate,
its background sample count and the evaluation behind its figures, and the
panel shows them.
A test refuses any published figure that does not appear in the evidence
record, with a negative control so it cannot pass by matching nothing. Pinning
the numbers as literal strings is what let an unsourced precision survive; that
assertion is gone.
Also ignoring .codex-artifacts/ — ~300 MB of the rejected SAM2 and
edge-alignment trials plus a deploy bundle. Kept on disk, out of the repository.
No credentials in it; the two token scripts generate from settings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Threshold calibration ran the model over every tile once per threshold — three
GPU passes to compare 0.50, 0.25 and 0.15 on a hundred-tile raster. The answer
is already in a single run at the lowest value: detections above a higher cut
are a subset of it, and duplicate suppression walks candidates in descending
confidence, so a lower-confidence box can never displace a higher-confidence
one. The kept set above any cut is identical whichever threshold the run used,
which is what makes one pass sufficient rather than merely cheaper.
QA now takes calibration_thresholds and reads each operating point off the same
precision/recall walk it already performs, marking the F1-optimal cut. The lab
runs inference once and fills its table from the sweep.
The contract test asserted the per-threshold loop by name, pinning the waste it
was meant to describe. It now states what calibration owes an operator: a row
per requested threshold, from one run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
/detection/runs/{id}/detections and its GeoJSON sibling returned every
persisted detection, as did the segmentation equivalents. A regional run holds
tens of thousands, and these are the endpoints the results table and the map
overlay call after every run.
They now take limit and offset, default to 2.000, and report total, limit,
offset and truncated so the complete population stays visible while what is
transferred does not. The GeoJSON responses carry the same window in a
geointel_result_window foreign member.
Rows are ordered by confidence, so a capped overlay draws the strongest
detections rather than an arbitrary slice, and the lab says how many of how
many are being shown rather than silently presenting a page as the whole run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The backend now says when a result covers a different area than was drawn, or
when a score belongs to one confidence cut only. None of that helps an
operator while it stays in the response body.
- the raster selection adapters carry the model-coverage and widened-cell
warnings into the map panel and mark the result an estimate when either
applies, so an existing warning slot renders them;
- the map workspace shows the selection-edge disclosure next to the object
count;
- the detection panel shows average precision and the F1-optimal threshold
beside the single-threshold figures, and the box-versus-footprint
interpretation when candidates are detector boxes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>