mapv10 Current Checkpoint - 2026-05-06
Status: SUPERSEDED by Wave 2 (forbidZ0UnderlayAtPrimaryZ + MAX_ANCESTOR_Z_DISTANCE = 1)
This checkpoint describes the resolver/sidecar/loader state as of 2026-05-06,
before the LOD/Data Coherence Foundation chain landed. Wave 2 redesigned the
resolver+sidecar contract: MAX_ANCESTOR_Z_DISTANCE = 1
(viewer/src/renderer/lod/RenderResolver.ts) caps ancestor promotion at a
single z step, the structural-parent walk replaces bounds-containment-alone
selection, and the isFullyResident AND-gate (RenderResolver.ts) requires
both CPU and GPU residency before a tile can act as a fallback source.
Wave 1 introduced the typed gate vocabulary (forbidZ0UnderlayAtPrimaryZ,
ancestorZDistanceMax, sidecarReadyForActiveMeshes,
noPlaceholderTextureBound, coverageHoleMax, labelTextUniqueness,
labelTextMinDistinctCount, labelMaxDuplicatesForText) in
viewer/src/scenarios/scenarioTypes.ts, evaluated by
viewer/scripts/scenario-gates.mjs. The text below is preserved verbatim for
provenance — it describes the pre-Wave-2 picture and must not be cited as the
current resolver, fallback, or sidecar contract. For current behavior read
architecture.md § "Streaming, LOD Selection, And Cache",
docs/viewer.md § "Ancestor-fallback 'kicking'", and
docs/performance-and-streaming-hardening-spec.md §7.3.
This checkpoint records the current mapv10 state after the latest browser/debug hardening pass. It exists so future work does not reopen already-closed loader, preview, and lifecycle issues by accident.
What Changed In This Checkpoint
- The 5443 viewer target was verified at
http://100.97.188.110:5443/?manifest=/mapv10/runs/continent-lod6/manifest.json. - The browser console issue was split into two causes:
classifier.js/ TensorFlow backend registration messages are injected browser-extension noise.Unexpected token '<'was a real viewer-load failure caused by Vite returning the HTML shell for a JSON artifact path.
viewer/src/data/rasterLoader.tsnow checks JSON response media type and reports artifact-specific failures such as:manifest expected JSON from /continent-lod6/manifest.json but got text/html.viewer/src/data/manifestLoader.tsnow uses the same JSON-aware helper for the top-level run manifest and validation summary.viewer/src/ui/manifestUrl.tsnormalizes browser query values before load: no value,/continent, or/continent-lodmeans the canonical/mapv10/runs/continent-lod6/manifest.json, and run-directory inputs such as/continent-lod6become/mapv10/runs/continent-lod6/manifest.json. The loader should not be asked to parse the Vite app shell from shorthand paths such as/continent.viewer/server/mapv10ArtifactMiddleware.tsmakes generated runs a first-class artifact namespace./mapv10/runs/<run-id>/...serves run files with JSON content types, range support for large binary products, run-status/list endpoints, and typedapplication/problem+jsonfailures. Legacy/continent-lod6/...paths are intercepted as protected compatibility paths so missing artifacts no longer fall through to the Vite app shell.- The viewer now surfaces load progress as first-class UX: manifest fetch, generated product loading, validation, renderer setup, and first tile residency emit typed progress events. The shell shows a boot progress panel and a persistent stream panel for network queue, terrain/data residency, and frame-budget work, so map loading state is visible without opening the developer HUD.
- Load failures now use user-facing diagnosis instead of repeating raw exceptions across the chrome. HTML-app-shell JSON fallbacks are presented as missing generated fixture/artifact states with a clear recovery action and a collapsed technical detail. The dev HUD is hidden by default and remains available through F3; selection and scale readouts stay hidden until a run is actually loaded.
viewer/src/data/__tests__/rasterLoader.test.tscovers Vite HTML fallback for the manifest path, byte-checked product JSON path, and malformed JSON.- The Products debug drawer is lazy. It no longer renders product rows or preview images until the drawer is opened.
- The drawer loads only global overview previews. Per-tile previews stay in the artifact tree and are summarized in the drawer instead of creating thousands of hidden image requests.
viewer/scripts/verify-browser.mjsnow records preview-request counts and fails the browser proof if normal map loading fetchespreviews/ortiles/previews/debug images.- The browser proof now captures all current map modes at both continent overview and location detail: terrain, political, routes, elevation, slope, and normals.
- The terrain resolver no longer renders deeper loaded parent/ancestor underlay beneath direct-resident child terrain. Parent terrain is still used for real missing-child fallback; a single z0 root remains as broad background context.
- Terrain commits are opaque once resident. Continuity comes from resolver fallback instead of alpha-crossfading two different terrain LOD rasters, which was creating temporal shimmer around water masks and coastlines.
- Continuous terrain sidecar textures now use mipmapped linear filtering with modest anisotropy. Discrete semantic textures such as province IDs, biome enums, LUTs, and selection masks stay nearest-sampled.
- Terrain LOD selection now gates on both geometric height SSE and raster/material sample footprint SSE. This prevents the root z0 water/splat/coast masks from staying active through slow continent-to-realm zooms, which was the source of the coarse crawling shoreline noise in the manual screenshots.
- Open-sea fragments from terrain tiles are discarded when they are outside the global location-id mask; the dedicated ocean base owns that surface so coarse sea-mask texels no longer write depth over it.
- The browser proof now captures a nine-step slow zoom screenshot sequence between full-continent and close-realm scale and asserts that terrain monotonically refines off z0 before the coarse coast raster can magnify.
- The render resolver keeps a single resident z0 terrain root as background context behind refined primary tiles, while reserving deeper parent underlays for real missing-child fallback. This prevents the refined focal tile from becoming a rectangular island over the ocean during slow zoom.
- Coarse terrain levels now use full-coverage selection while the selected level remains small enough to fit inside the full-coverage budget. On the lod6 continent this keeps z1 and z2 stable while panning at the same camera distance instead of swapping a target-centred patch against the z0 context surface.
- The browser proof now captures a five-step constant-distance camera-move sequence and asserts that the selected z2 coverage and visibility signature stay stable while the camera target moves.
viewer/scripts/verify-browser.mjsnow owns local screenshot baselines for visual regression.--update-baselinesnapshots the canonical proof images underviewer/baselines/browser/<run-id>, and--check-baselinecompares a fresh proof run against that manifest with changed-pixel ratio, RGB RMS, max channel delta, and diff PNG output on failure.- Label placement reserves fixed UI regions, so close-up labels no longer sit under the HUD, mode bar, layer panel, inspector, or scale ruler.
- Current shoreline fix owner: open sea must be a generated water mesh derived
from
seaRegions.jsonwith land polygons as holes. Terrain outside-land clipping must use the global location-id semantic raster; the per-tilewaterMaskremains a topology/material hint and must not own open-sea clipping.
Current Verification Evidence
Latest local checks:
npm test -> pass, 17 files / 239 tests
npm run build -> pass
artifact namespace HTTP probes -> pass
/mapv10/runs/continent-lod6/manifest.json -> 200 application/json
/continent-lod6/manifest.json -> 200 application/json (legacy protected)
/mapv10/runs/missing-run/manifest.json -> 404 application/problem+json
Range: height.f32.bin bytes=0-15 -> 206 partial content
browser failure UX smoke -> pass
verification/ux-friendly-load-error.png
browser ready UX smoke -> pass
verification/ux-ready-no-debug-hud.png
node scripts/verify-browser.mjs
--proof-name artifact-namespace-proof
--timeout-ms 180000
--port 5195 -> pass
npm run verify:browser:baseline:update
-- --port 5196 -> pass, 33 baseline screenshots written
npm run verify:browser:baseline
-- --port 5197 -> pass, 33 screenshots compared
maxChangedRatio 0.0002752544
maxRms 1.7784523
npm run verify:browser:baseline
-- --port 5198
--proof-name m10-lod6-visual-baseline-zero-threshold
--baseline-pixel-tolerance 0
--baseline-max-changed-ratio 0
--baseline-max-rms 0 -> expected fail, 8/33 diffs written
git diff --check -- examples/map/mapv10
-> pass
Latest browser proof network summary:
totalRequests: 3161
uniqueRequests: 3150
previewRequests: 0
tilePreviewRequests: 0
forbiddenRootHighDetailFetches: []
The proof covers continent overview, province cluster, close route detail, boundary views, zoom-back-out, all six current map modes at overview/detail, a dedicated slow zoom sequence, a constant-distance camera-move sequence, and the missing-required-product failure case.
Current Work Queue Interpretation
next-work.md currently marks the renderer hardening chain as resolved through:
- lifecycle/hitch metrics and warn/fail budgets
- label lifecycle candidate gating and frame-budgeted residency
- strict parent fallback contract
- terrain geometric-error SSE
- terrain lifecycle pacing
- route adaptive batching and upload pacing
That means the next active lane should not be another generic lifecycle-metrics pass unless new scenario evidence opens a fresh owner.
Valenar integration is deferred. Valenar must continue to use its dummy
world-42 fixture while mapv10 is still being refined.
The immediate mapv10 work stays on the producer/render side:
- wire visual baseline checks into CI/local clean-fixture verification
- keep verifying fully zoomed-out, slow-zoom, constant-distance camera-move, and close geographic views in the real browser
- continue fixing any newly evidenced base-map visual owner through generated products and scenario proof, not ad hoc shader parameter drift
- keep the browser proof checking JSON loader failures and forbidden preview requests
- only produce/export data structures from mapv10; do not wire Valenar runtime consumption yet