- DESIGN.md: full design incl. driving-trip requirements (R1-R4), stays model, focus mode, mobile, provenance rules - SURVEY.md: open-source landscape - mock/: interaction mock (Florence itinerary, focus mode, stays, region stops, mobile layout) - router/: Go module (stdlib-only) with Router interface (Valhalla + OSRM backends), stop_cost, optimize_stops, corridor, routectl CLI, bench (5 real NE-corridor tasks, 26 checks passing), integration tests, and setup-osrm.sh for the self-hosted router - osm/: NH+MA+CT+NY PBFs (gitignored) + setup artifacts |
||
|---|---|---|
| .. | ||
| cmd | ||
| internal | ||
| scripts | ||
| go.mod | ||
| README.md | ||
maps/router — route-aware planning primitives
The Go backend for the "search along the route" capability (DESIGN.md, "Driving trips" section). Everything the LLM would otherwise guess about a trip — route shape, travel times, detour costs — is computed here and returned with provenance.
What's in here
internal/geo/ dependency-free geodesy (haversine, point-to-line)
internal/route/ Router interface + backends
- valhalla.go: hosted/self-hosted Valhalla (works today;
no geometry on the hosted instance → chord fallback)
- osrm.go: local OSRM (full geometry; scripts/setup-osrm.sh)
internal/plan/ the primitives:
- stopcost.go: stop_cost = route(A,C via B) − route(A,C)
- optimize.go: optimize_stops (exhaustive ≤10 stops, greedy above)
- corridor.go: corridor = buffer band around the route
cmd/routectl/ manual CLI: route | stopcost | optimize
cmd/bench/ benchmark runner (bench/tasks.json)
bench/tasks.json 5 real NE-corridor tasks with recorded goldens
scripts/setup-osrm.sh self-host OSRM over the NH+MA+CT+NY extract
Zero third-party Go dependencies (stdlib only).
Try it (hosted Valhalla, no setup)
go run ./cmd/routectl route --from 44.054,-71.650 --to 40.729,-73.966
# Lincoln NH → Queens NY: ~5h32m, 531 km, I-93/90/495/290 (NOT via Boston)
go run ./cmd/routectl stopcost --from 44.054,-71.650 --to 40.729,-73.966 \
--stop 42.2767,-71.806:60:cascade \
--stop 43.507,-71.548:50:ladd \
--stop 43.642,-71.156:120:mtmajor
# cascade detour= 6 min (on the I-495 corridor)
# ladd detour=17 min
# mtmajor detour=80 min (off-corridor)
go run ./cmd/routectl optimize --from 44.054,-71.650 --to 40.729,-73.966 --k 2 \
--stop 42.2767,-71.806:60:cascade --stop 43.507,-71.548:50:ladd \
--stop 43.902,-71.64:60:plymouth --stop 42.425,-71.68:60:brewsters
# order: ladd -> cascade detour: 23 min
Tests
go test ./... # unit tests, offline, fast
go test -tags integration ./... # live router (Valhalla by default)
ROUTER_BACKEND=osrm ROUTER_URL=http://localhost:5000 \
go test -tags integration ./... # against local OSRM
The integration tests encode the key regression: the fastest Lincoln→Queens drive stays ≥15 km from Boston (it goes via Worcester, I-90/I-495/I-290). That is exactly the fact an LLM confidently gets wrong.
Benchmark
go run ./cmd/bench # run all tasks, assert goldens + corridor checks
go run ./cmd/bench --record # re-record goldens (after a backend/extract change)
Tasks are real OD pairs across NH/MA/CT/NY with real POI candidates and dwell times. Check types:
| type | meaning |
|---|---|
golden_route_min |
direct route time within a recorded band (±10%) |
route_avoids |
route stays ≥ N km from a point (geometry, or bbox when the backend has none) |
stop_free / stop_detour_at_least / stop_detour_band |
computed detour of a candidate vs an expected band |
optimize_order |
the exhaustive optimum matches the recorded order |
crosscheck |
single multi-waypoint route ≈ matrix-summed prediction (≤ maxPct drift) |
Current state: 26 PASS / 0 FAIL against hosted Valhalla.
Self-hosted OSRM (full geometry, exact corridors)
scripts/setup-osrm.sh builds OSRM 26.4.1 from source (Boost header-only),
extracts the 4-state PBFs (pre-downloaded in ../osm/), partitions,
customizes, and serves on :5000. Then:
go run ./cmd/routectl route --backend osrm --from 44.054,-71.650 --to 40.729,-73.966
With OSRM, Route.Geometry is populated, so the corridor is exact
(distances to the actual routed polyline) instead of the chord fallback
used with the hosted Valhalla. This is what makes
search_along_route's spatial pre-filter (PostGIS ST_DWithin on the
corridor polygon in the v1 design) sound.
Design notes
- The route is computed, never narrated. No function in this module
returns a time estimate from model knowledge; every number is router
output (
computedprovenance per DESIGN.md R4). - Matrix via pairwise route calls. Valhalla's
sources_to_targetscaps at 150 km, so the common path isBuildMatrix(pairwise/route). OSRM'sTableservice is available for the local backend when a single-call matrix matters. - optimize_stops semantics: the user asked for k stops ("two
hikes"), so the objective minimizes total = detour + dwell + overhead
over ordered subsets of exactly k, with fallback (a) to the best
feasible smaller set when a time budget is given, then (b) to the best
exactly-k ignoring the budget, flagged
Feasible=false. "At most k" without a budget degenerates (zero stops always wins). - Stop coordinates are POI centroids. The router snaps to the network; a 200 m centroid error moves a 531 km route's detour by seconds, not minutes.