Commit the previously-untracked standard directories and catalog them in the
root README alongside proof:
- aac/ — communication cargo class: portable boards + a ten-level
offline-first cascade (Apache-2.0 code / CC-BY-4.0 spec).
- map/ — geospatial cargo class: range-requestable signed tilesets +
an F0–F4 fidelity cascade (Apache-2.0 code / CC-BY-4.0 spec).
- sandbox/— isolated, metered, attested execution across the heterogeneous
compute fabric (Apache-2.0 code / CC-BY-4.0 spec).
- jouleclaw-otel-authz, jouleclaw-trust — new jouleclaw reference crates.
Root README now lists aac, map, sandbox, and proof in the catalog, the tree,
and the contribution guide.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
144 lines
9.6 KiB
Markdown
144 lines
9.6 KiB
Markdown
# Changelog — Map
|
||
|
||
All notable changes to the Map standard and its reference implementation.
|
||
Format follows Keep a Changelog; the standard versions independently of the
|
||
reference crates (which share the `map-rs` workspace version).
|
||
|
||
## [0.1.0] — 2026-06-04
|
||
|
||
Initial draft standard — the protocol spine.
|
||
|
||
### Added
|
||
|
||
- **Specification.** `SPEC.md` (RFC 2119) defining the tile cargo, the 4D cell
|
||
key, canonical serialization + content addressing, the range-requestable
|
||
tileset + signed manifest/revision chain, the F0–F4 fidelity cascade, and the
|
||
JCR-1 receipt. Sub-specs under `spec/`.
|
||
- **`map-schema`** — `CellKey` (S2 + altitude band + time bucket + LOD),
|
||
`ContentId`, `Tile`, `Directory` (Hilbert-sorted + range planner), `Manifest`,
|
||
`Revision`, `verify_chain`, and the `Tier` enum.
|
||
- **`map-cascade`** — `resolve` over a `TileSource`, returning the highest tier
|
||
≤ the request with a guaranteed F1 fallback.
|
||
- **`map-receipt`** — `Receipt`, `Energy`, `Provenance`, JCR-1 sealing/verifying
|
||
(vendored, byte-compatible with the family verifiers).
|
||
- **`map-conformance`** — C1–C5 + C-neg harness (all checks real) and the
|
||
`gen-vectors` generator; published vectors in `conformance/v1/`.
|
||
- **Vocabulary.** `vocab/v1.ttl`, `v1.jsonld`, `v1.shapes.ttl`, `LEXICON.md`.
|
||
|
||
- **`map-index`** — pure-Rust S2 cell geometry (cell ids, projection, lat/lng,
|
||
points, edges, polygons, regions/caps/rects, the region coverer, metrics)
|
||
ported from `joule-s2`, plus a `bridge` to `map-schema`: `cell_key` from
|
||
coordinates, and `cover_region`/`cover_viewport` from a cap, rectangle, or
|
||
**polygon** to sorted `CellKey`s feeding the directory range planner. 75 tests,
|
||
zero clippy warnings.
|
||
- **Fixed (vs. upstream `joule-s2`)** the `polygon` module, which failed its own
|
||
tests upstream: spherical point-in-polygon now uses an orientation-robust
|
||
winding-angle test (was a degenerate ray); area uses the van Oosterom–Strackee
|
||
signed-area fan (was Girard's-formula complement, ≈4π−A); and `S2Polygon` now
|
||
implements `S2Region`, so the coverer accepts arbitrary boundaries / footprints
|
||
/ geofences.
|
||
- **`map-index::volume`** — the recommended 4D discretization scheme ported from
|
||
`joule-spatial3d`: logarithmic `AltBand`s (Mariana Trench → cislunar),
|
||
logarithmic `TimeTier`/`TimeBucket`s (1 s → 100 yr), `SpaceTimePoint`,
|
||
`SpatialKey`, and the `Spatial3DIndex`/`PositionRingBuffer` runtime utilities.
|
||
New bridge functions `alt_band`, `time_bucket`, and `cover_volume` map the
|
||
scheme into `map-schema` `CellKey`s and cover a horizontal region × altitude
|
||
range × time range. (The `chrono` convenience constructors were dropped to keep
|
||
the reference dependency-light.)
|
||
- **`map-tiles`** — tile payload codecs ported from `joule-tiles`: MVT vector,
|
||
raster (PNG/WebP), terrain quantized-mesh, and 3D Tiles, with no S2/geo or
|
||
routing dependency. A `tile` bridge wraps each as a content-addressed
|
||
`map-schema` `Tile` at its cascade tier — terrain → `F1`, raster → `F2`, MVT +
|
||
b3dm → `F3`, splat → `F4` — with stable `codec` tags.
|
||
- **`map-tiles` splat codec** (`map_tiles::splat`) — the `F4:Photoreal` cargo
|
||
codec the tier was missing: a compact SPZ-style container for 3D Gaussian splats
|
||
(positions fixed-point, scales log-quantized, rotation quaternion + colour as
|
||
bytes, gzip-compressed), with `encode_splats`/`decode_splats`. **Spherical
|
||
harmonics**: encodes degree-`n` view-dependent colour as `(n+1)²−1` quantized
|
||
RGB coefficients above the DC term (`sh_degree` in the header). Round-trip
|
||
(incl. degree-1 SH) + compression tests.
|
||
- **`map-tiles` PLY ingest** (`map_tiles::splat::read_ply`) — reads the de-facto
|
||
**INRIA `.ply`** 3DGS interchange format (ASCII + binary-little-endian),
|
||
inverting the trainer's storage conventions (log-scales → `exp`, logit-opacity
|
||
→ `sigmoid`, `(w,x,y,z)` → `(x,y,z,w)` normalized, DC `= 0.5 + C₀·f_dc`,
|
||
channel-major `f_rest` → per-coefficient SH) into `Splat`s that `encode_splats`
|
||
re-encodes into a conforming F4 tile. ASCII + binary + rejection tests.
|
||
- **`map-tiles` b3dm / glTF decode** (`map_tiles::tiles3d::read_b3dm`, `read_glb`)
|
||
— the reader half of the 3D Tiles codec: strips the b3dm header + feature/batch
|
||
tables and decodes the embedded binary glTF (GLB) into a triangle mesh, general
|
||
over accessors/bufferViews (f32 VEC3 positions; u8/u16/u32 indices; accessor +
|
||
bufferView byte offsets and strides; multi-primitive merge). Round-trips
|
||
`B3dmBuilder::encode`; encode/decode + u16-index + rejection tests.
|
||
- **`map-serve` crate** — a transport-agnostic tile-serving core (no HTTP-framework
|
||
dependency): `serve(store, steward, req)` parses a tile request, resolves it
|
||
through the F0–F4 cascade, and returns a content-addressed `Response` with a
|
||
strong `ETag`, `Cache-Control: immutable`, `If-None-Match` → `304`, `X-Map-Tier`
|
||
/ fell-back, and a JCR-1 energy-receipt header. Includes a `MemoryStore`
|
||
reference `TileServer`, plus a filesystem `DirStore` (content-addressed blobs on
|
||
disk + a reloadable JSON index; `std`-only). Pure + unit-tested with a runnable
|
||
doctest.
|
||
- **`map-serve-axum` crate** — an axum/tokio HTTP binding for the serving core:
|
||
`router(store, steward)` exposes `serve` as an axum `Router`, `run(addr, …)` is a
|
||
one-call server. The async stack is isolated here so `map-serve` stays
|
||
framework-free. Verified by `oneshot` tests and a live-socket demo over real HTTP.
|
||
- **`map-route` turn-by-turn + isochrones** — `directions::turn_by_turn` derives
|
||
human maneuvers (depart with cardinal heading, slight/normal/sharp turns,
|
||
U-turn, arrive) from route-segment bearing deltas, merging straight runs into
|
||
one step; `isochrone::isochrone` computes the budget-bounded reachable set from
|
||
a source by travel time or distance (Dijkstra expansion with pruning). Both
|
||
unit-tested.
|
||
- **`map-route` multi-modal + traffic-aware costs** — a `CostModel` trait and a
|
||
built-in `ModeProfile` (car/bicycle/foot) with per-mode road-class access
|
||
matrices, free-flow speeds, and a congestion multiplier; `cost::find_route_with`
|
||
is a generalized A* (admissible time heuristic) that skips inaccessible edges
|
||
and reports mode-specific durations. `RoadType` is now `Copy`. Unit-tested
|
||
(mode access, highway avoidance on foot, traffic slowdown).
|
||
- **`map-route` public-transit routing** (`transit`) — the Connection Scan
|
||
Algorithm over a GTFS-like `Timetable`: earliest arrival from timetabled
|
||
`Connection`s with walking-footpath transfers (manual or auto-generated within a
|
||
radius), reconstructing ride/walk `Leg`s. Times are integer seconds. Unit-tested
|
||
(line with wait, missed connection, faster-of-two, footpath transfer, auto-transfers).
|
||
- **`map-tiles` MVT decoder** — added the reader half (`mvt::decode_tile`,
|
||
`decode_geometry`, `unzigzag`): a minimal protobuf reader inverse to the
|
||
encoder, plus the geometry-command decoder back to absolute tile-local rings /
|
||
line-strings. A conforming reader must decode to render; the encoder shipped
|
||
without it. Encode→decode roundtrip tests cover geometry + properties + closed
|
||
polygons. (Not in upstream `joule-tiles`.)
|
||
- **Real-world robustness fix:** `decode_value` now handles MVT `sint_value`
|
||
(field 6, zigzag), decodes `int_value` (field 4) as a plain varint per spec
|
||
(was wrongly zigzag), and tolerates an empty/unknown value instead of aborting
|
||
the whole tile. Verified by decoding live OpenMapTiles tiles (OpenFreeMap) —
|
||
previously failed with `ProtobufError("empty value")`.
|
||
- **Fixed (vs. upstream `joule-tiles`)** `mvt::encode_polygon`, which clobbered
|
||
the `CMD_MOVE_TO` command word with a coordinate and reset the geometry cursor
|
||
per ring (malformed multi-ring polygons); added the missing regression test.
|
||
Backported to `joule-tiles`.
|
||
- **`map-orbital`** — TLE parsing, SGP4/SDP4 propagation, and ECI/ECEF/geodetic
|
||
transforms ported from `joule-orbital` (no `tracing` dependency; only the
|
||
doctest referenced it). A `bridge` maps a propagated satellite sub-point to a
|
||
`map-schema` `CellKey` — S2 cell at the sub-point, the altitude band for its
|
||
altitude (the ISS lands in the LEO band), and the time bucket for the instant —
|
||
so a live satellite is an `F3` address on the same 4D grid as every tile. Lint
|
||
cleanups only; the 38 SGP4/SDP4 known-answer tests confirm the numerics are
|
||
unchanged.
|
||
- **`map-route`** — local geospatial capabilities over a tileset, ported from
|
||
`joule-maps` (energy metering, tile cache, and the in-memory store dropped —
|
||
redundant with `map-receipt`/`map-tiles`/`map-schema`): WGS84 geometry,
|
||
haversine/bearing/midpoint, point-in-polygon, POI geocoding, Dijkstra + A*
|
||
routing on a weighted graph, and polygon geofencing. Added a **feed-agnostic
|
||
adapter** (`feed::{Entity, Feed}`): any source — flights, vessels, satellites,
|
||
CVEs, incidents, supply-chain nodes, enterprise signals — resolves to a
|
||
`CellKey`, so "swap the feeds and it visualizes anything with a location or a
|
||
time" is a property of the standard, not a per-feed rewrite. Tests cover the
|
||
ported geocode/route/geofence/geometry paths (the upstream tests did not come
|
||
with the extracted subset).
|
||
- **`map-schema`** — `TimeBucket.width_ms` widened `u32 → u64` so the temporal
|
||
axis can express coarse archival buckets (a year, a century); `u32` capped it
|
||
at ~49 days. CBOR encodes integers by magnitude, so existing content ids and
|
||
conformance vectors are byte-identical.
|
||
|
||
### Notes
|
||
|
||
- The remaining substrate crates (`map-index` 4D layer from `joule-spatial3d`,
|
||
`map-tiles`, `map-orbital`, `map-route`) and the demonstrator's `wgpu` renderer
|
||
are not yet in this release — see [`ROADMAP.md`](ROADMAP.md).
|