The half-day handshake so E's build_towns.py can fetch road geometry (ledger #1). Optional roads[]
on the town cache carries real OSM way geometry; plan_osm's graph lift (consuming it) follows in the
next commit. v1 caches (roads absent) stay valid — the marched fallback — so nothing shipped regresses.
- validateTownCache accepts schema procity-town-cache/1 AND /2; when roads[] is present each road must be
{ kind:string, pts:[[lat,lon],…] } with >=2 finite points (else rejected); <2 pts dropped, unmapped
highway kind → 'side' (warnings). ROAD_KIND maps OSM highway=* → CityPlan edge kind (main/side/lane/arcade).
- Full v2 contract in web/assets/towns/README.md (the doc E builds to): shape, road validity, the kind map,
the fidelity knob (charter risk #4), and the bbox-bound-the-roads rule.
- E's 5 existing v1 caches re-validate clean; selfcheck ALL GREEN.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>