Backend-only. For strict-boundary motorized routes, turn MVUM-closed segments into
buffered Valhalla exclude_polygons so routing actively avoids them. pragmatic/emergency
keep Layer-1 annotate-only behavior; foot is never excluded.
- mvum_exclude.py (new): build_exclude_polygons(start,end,mode,spatial_index,on_date,
boundary_mode) -> GeoJSON Polygon dicts, or None when not applicable (foot / non-strict
/ no index / unmappable mode). Queries the Layer-0 index over a 5km-expanded bbox,
keeps only features closed to the mode (via mvum_annotate._status_for_feature), buffers
each ~15m (lat-corrected), emits one Polygon per part (MultiPolygon split). Caps at 500
with a warning.
- router.py: route() computes self._exclude_polygons once per call (after mode validation;
has boundary_mode), so each Auto candidate probes against its own exclusions. Both
Valhalla /route builders (_route_D_network_only and _valhalla_route) inject
exclude_polygons in array-of-rings form (outer ring per Polygon); omitted when None/empty.
- 6 tests: strict builds polygons, pragmatic/emergency/foot -> None, open not excluded,
1000 closed -> capped at 500 + warning.
No frontend changes (Layer-1 closure warning still fires for residual closures). Wilderness
pathfinder, Layer-0 index, and Layer-1 annotation untouched.
Co-authored-by: Matt <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>