5.7 KiB
5.7 KiB
Tasks: enterprise-heightmap-tiles
Change ID: enterprise-heightmap-tiles
Package: @suaveplan/heightmap-tiles
Target path: universal/geo/heightmap-tiles
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/geo, @suaveplan/serialize
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create
universal/geo/heightmap-tiles/withsrc/,tests/,src/__benchmarks__/and all feature subdirectories per the layout inproposal.md. - Write
package.jsonat version0.1.0with"type": "module","sideEffects": false, correctexportsmap,dependencies, anddevDependencies. - Write
tsconfig.jsonextending@suaveplan/typescript-config/library.json. - Write
vitest.config.tsusingcreateTestConfig()from@suaveplan/testing/config. - Add
lint,typecheck,test,test:coverage,build,docs:checkscripts.
2. Types + errors
src/types/common.ts—TileCoord,BitDepth,HeightmapTile,ElevationResult,EncodeOptions,PyramidBuilderOptions,BuildLevelOptions,HeightmapTileStore(interface),ContourLine.src/types/common.md(≥200 words, both examples, API reference).src/error-codes.ts—HeightmapErrorCode(6 codes), metadata, register, eager call.src/types/schemas.ts+schemas.md— Zod schemas.
3. Core modules
src/coords/tile-coords/—latLngToTileCoord,tileCoordToBoundingBox,tileCoordToLatLng,tilesInBoundingBox,tileParent,tileChildren. Tests: known lat/lng → tile at zoom 10, bounding box round-trip, parent/children consistency at multiple zoom levels,tilesInBoundingBoxreturns correct count for small area.src/codec/delta-codec/—deltaEncode(tile): HeightmapTile: converts raw int16/int8 tile to delta-encoded (each cell = cell - previous); first cell = cell value.deltaDecode(tile): HeightmapTile: inverse. Both are lossless for int16/int8. Tests: encode/decode round-trip for flat tile (all zeros), random int16 array, verify delta values are smaller in magnitude for smooth terrain.src/codec/tile-codec/—encodeTile(tile, options?): Uint8Array: serialises header (coord, dimensions, bitDepth, min/maxElevation, encoding) then data via@suaveplan/serializeMessagePack profile.decodeTile(data): HeightmapTile. Tests: encode/decode round-trip for 256×256 uint16 tile, float32 tile, bit depth selection.src/store/memory-store/—createMemoryTileStore(): HeightmapTileStore:get/put/delete/listbacked by aMap<string, HeightmapTile>(key =z/x/y). Tests: CRUD, list by zoom, list with bounding box filter.src/pyramid/pyramid-builder/—TilePyramidBuilder(store, options):addSourceTile(tile): stores at natural zoom;buildLevel(zoom): for each tile atzoom+1, generates parent by bilinear down-sampling the 4 children (or nearest available);buildAll(minZoom, maxZoom). Tests: single source tile at zoom 12 → can build zoom 11 and 10; bilinear average matches expected value for flat 4-cell grid.src/elevation/elevation-lookup/—lookupElevation(store, lat, lng, zoom?): fetches tile at computed coord + 3 neighbours; bilinear interpolation from 4 nearest pixels. ReturnsElevationResult. Tests: exact pixel hit →confidence: 'exact', between pixels →confidence: 'interpolated', no tile →elevation: NaN.src/elevation/contour-extractor/—extractContours(tile, intervalMetres): ContourLine[]: marching-squares algorithm over tile grid; groups adjacent edge crossings into polylines; closes loops. Tests: flat tile → no contours, slope tile → contours at expected elevations, closed contour for circular hill shape.
4. OTel instrumentation
- Span
heightmap.pyramid_buildwith attributeheightmap.zoom; counterheightmap.tile_encode_total; histogramheightmap.encode_duration_ms.
5. Property-based tests (tests/property.test.ts)
- Delta encode/decode round-trip: for arbitrary
Int16Arrayof length 256,deltaDecode(deltaEncode(tile)).dataequals original. - Tile coordinate arithmetic:
latLngToTileCoord(tileCoordToLatLng(coord), coord.z)returns same coord for arbitrary valid coords. - Contour bounds: all elevation values in
ContourLine[]fromextractContours(tile, interval)lie within[tile.minElevation, tile.maxElevation].
6. Benchmarks (src/__benchmarks__/heightmap-tiles.bench.ts)
encodeTilefor 256×256 float32 tile.decodeTilefor same.extractContoursfor 256×256 tile with 10 m interval.
7. Docs + verify
- One
.mdper implementation file (≥200 words, both examples, API reference). RootREADME.md. bunx turbo lint typecheck test --filter=@suaveplan/heightmap-tiles— green.bunx turbo test:coverage --filter=@suaveplan/heightmap-tiles— 100%.bun scripts/publish.ts --package @suaveplan/heightmap-tiles.- Archive:
openspec/archive/2026-04-24-enterprise-heightmap-tiles/.