Files
2026-05-27 23:29:53 +01:00

5.7 KiB
Raw Permalink Blame History

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 status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in 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.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create universal/geo/heightmap-tiles/ with src/, tests/, src/__benchmarks__/ and all feature subdirectories per the layout in proposal.md.
  • Write package.json at version 0.1.0 with "type": "module", "sideEffects": false, correct exports map, dependencies, and devDependencies.
  • Write tsconfig.json extending @suaveplan/typescript-config/library.json.
  • Write vitest.config.ts using createTestConfig() from @suaveplan/testing/config.
  • Add lint, typecheck, test, test:coverage, build, docs:check scripts.

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, tilesInBoundingBox returns 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/serialize MessagePack 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/list backed by a Map<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 at zoom+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. Returns ElevationResult. 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_build with attribute heightmap.zoom; counter heightmap.tile_encode_total; histogram heightmap.encode_duration_ms.

5. Property-based tests (tests/property.test.ts)

  • Delta encode/decode round-trip: for arbitrary Int16Array of length 256, deltaDecode(deltaEncode(tile)).data equals original.
  • Tile coordinate arithmetic: latLngToTileCoord(tileCoordToLatLng(coord), coord.z) returns same coord for arbitrary valid coords.
  • Contour bounds: all elevation values in ContourLine[] from extractContours(tile, interval) lie within [tile.minElevation, tile.maxElevation].

6. Benchmarks (src/__benchmarks__/heightmap-tiles.bench.ts)

  • encodeTile for 256×256 float32 tile.
  • decodeTile for same.
  • extractContours for 256×256 tile with 10 m interval.

7. Docs + verify

  • One .md per implementation file (≥200 words, both examples, API reference). Root README.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/.