Files
arah2/.planning/phases/05-routing-route-display/05-CONTEXT.md

9.2 KiB
Raw Permalink Blame History

Phase 5: Routing + Route Display - Context

Gathered: 2026-10-24 Status: Ready for planning — with a roadmap amendment (SC3 rewording, below)

## Phase Boundary

The route EXPERIENCE ships end-to-end in fixture world: a RoutingSource interface (mirroring SearchSource), a fixture backend whose geometries for 10–20 real KL pairs were precomputed at build time, Rams route rendering (orange casing on the grayscale map), up-to-3 alternatives as a bottom card + chips, selection redraw with camera refit, and an honest "router pending" state for arbitrary origins. The guidance_sessions envelope is designed as a types-only frozen contract for Phase 6. No VPS, no Worker route proxy, no third-party routing calls — the engine itself is deferred to the WASM-router OSS track (client-side routing, backend #2), with Valhalla-on-VPS documented as backend #3.

ROADMAP AMENDMENT (planning must apply): SC3 is reworded from "routes cleanly through self-hosted Valhalla … behind the Worker proxy" to: "the golden-route corpus (10–20 real KL pairs) routes cleanly through the fixture RoutingSource backend with bundle-size and type gates holding; the RoutingSource interface carries the documented backend ladder (fixtures → client-side WASM router → Valhalla-on-VPS) and the 'router pending' state is deliberate and designed." RTNG-01's "calculated route" is satisfied by fixture calculation; the arbitrary-origin router is a documented deferral, not an omission.

## Implementation Decisions

Routing infrastructure — THE PIVOT (user decision, supersedes roadmap SC3 v1)

  • D-01: No VPS this phase. No third-party routing API ever at runtime (origin+destination to a third party is a core-value privacy leak). Routing is a RoutingSource interface with a backend ladder: #1 fixtures (this phase) → #2 client-side WASM router (OSS track, deferred) → #3 Valhalla-on-VPS (documented, provision scripts as a documented path, not shipped).
  • D-02: Backend #1 = fixture routes for the 10–20 golden KL pairs, geometries precomputed at BUILD time by a repo script hitting the public OSRM demo server once (build machine, fixed public coordinates — no user data, no runtime dependency), committed as compact encoded polylines. Each pair pins expected distance/duration tolerances.
  • D-03: Arbitrary origin/destination combinations return an honest "router pending" state — a designed, deliberate Rams surface (UI-SPEC scope), never a blank map, never a fake route, never a silent failure.
  • D-04: The WASM-router track (client-side routing in the webview — origin+destination never touch a server; static-hosted; fork-perfect) is captured as the post-v1 OSS project that becomes RoutingSource backend #2, exactly parallel to the search backend #2 pattern. The user's static-hosting/fork-model intent is preserved as the architectural direction, not abandoned.
  • D-05: The Worker gains no /api/route this phase. Fixtures ride in the web bundle (gazetteer precedent). The interface stays backend-shaped so a server backend could slot in later without client rework.

guidance_sessions envelope (Phase 6's contract, frozen now)

  • D-06: Types-only contract: guidance_sessions envelope = { id, chat ref, route snapshot (inline), created_at } with a ~2h TTL — shipped as code types + docs, no KV namespace, no service, no runtime writes. Phase 6 builds the service on the frozen shape.
  • D-07: Route snapshot lives inline in the envelope record — one key, one TTL; nothing outlives 2h, nothing reconstructable after expiry. Consistent with the location-pin TTL precedent (Phase 3). The route model itself carries step geometry + snapped-progress support fields from day one (GUID-05/06 upstream obligation).

Route UX surface (UI-SPEC scope; phase-terminal)

  • D-08: Alternatives present as a bottom card + chips: one card for the selected route (time, distance, one-line difference vs best) with compact alternates as selectable chips — tap → redraw. Map stays dominant.
  • D-09: Route line = signal-orange casing (dark under-line for grayscale contrast) + orange center line — Phase 1's reserved accent, per the navigate_map_overview mockup. Destination pin keeps venue semantics; origin = subdued ring. Camera fits route bounds on draw.
  • D-10: Display-only terminal surface: selection redraws + camera refits; a restart/search-again affordance returns to the destination state. No start-guidance button, no turn instructions, no progress UI — Phase 6. No placeholder-shaped furniture (Phase 3 D-08 law).

Gates replacing SC3's latency/subrequest budgets

  • D-11: Bundle budget: fixture geometry + route-model code ≤ ~200KB gzipped added to the web bundle, enforced as a BA build-artifact gate. Type gates: route model readiness (step geometry + snapped-progress fields) pinned by tests. "Router pending" state covered by UI-SPEC + captures. Latency/subrequest budgets are not applicable to fixture world (documented as such, not faked).

Privacy (carried + made specific)

  • D-12: Fixture geometries are public-data routes between public places — no user coordinate ever enters a fixture. The build-time OSRM fetch happens on the maintainer's machine against fixed public points; the script documents this boundary. Runtime: origin stays in memory only (Phase 3 law); no route persists (envelope is types-only this phase).

OpenCode's Discretion

  • Fixture encoding format (encoded-polyline vs simplified GeoJSON) within the ≤200KB budget
  • RoutingSource interface shape (async, backend-tagged results, tolerance metadata)
  • Which Phase 4 corpus destinations become the 10–20 pairs; realistic origins list
  • One-line-difference copy per alternative card (en/ms, clinical tone); "router pending" copy
  • Chip/card visual details within the Rams system (UI-SPEC will bind exact geometry)
## Specific Ideas
  • The route experience should feel like the mockup distilled: the orange line is THE accent on a grayscale world — nothing else competes.
  • "Router pending" copy should be honest and calm: the app knows what routing is, states it isn't wired yet, offers search again. Same clinical register as the denied card.
  • Fixture pairs double as the demo script: the 10–20 pairs are the routes a reviewer walks to see the product work.

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Phase scope + decisions

  • .planning/ROADMAP.md §Phase 5 — goal, success criteria + this file's SC3 amendment (planning applies it)
  • .planning/REQUIREMENTS.md §RTNG-01/02 (+ GUID-05/06 upstream obligations)
  • .planning/phases/04-destination-search-kl-gazetteer/04-CONTEXT.md — SearchSource pattern to mirror; backend-ladder pattern; fork-model law (GPL-3.0)
  • .planning/phases/03-mini-app-shell-geolocation/03-CONTEXT.md — map boot, marker/follow controller, memory-only law, location-pin TTL precedent

Codebase

  • web/src/map/ — MapLibre boot (style never re-set — route layers must be addLayer, not style mutation), marker, follow controller
  • web/src/search/resolve-destination.ts — the preloaded destination this phase routes TO
  • search/ — the interface+backend+ladder pattern to mirror
  • web/scripts/capture.mjs + mock profiles — the capture harness the route display must extend (?dest= profiles exist)
  • bot/src/i18n/strings.ts pattern — copy discipline for card/difference strings

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • search/ workspace: interface + ladder + loader + corpus-gate patterns to mirror for routing/
  • Phase 4 corpus gate (D-13/D-14) — the fixture-pair tolerance gate follows its shape
  • Mock harness profiles (?dest=) — route-state capture profiles extend these
  • BA build-artifact gates — the bundle-budget gate joins them

Established Patterns

  • npm workspaces + delegate scripts; TDD RED→GREEN; hand-rolled runners
  • Interface + documented backend ladder (SearchSource → RoutingSource)
  • Types-only frozen contracts (session envelope) with TTL-only storage law
  • UI-SPEC gate applies this phase (UI hint: yes) — planning routes through it

Integration Points

  • Destination resolver → route destination input (Phase 4 hands off where Phase 5 begins)
  • Route model step geometry + snapped-progress fields → Phase 6 guidance consumes
  • guidance_sessions envelope types → Phase 6 bot service implements

</code_context>

## Deferred Ideas
  • WASM-router OSS project — client-side routing in the webview (RoutingSource backend #2); static-hosted, privacy-maximal, fork-perfect; its own post-v1 project
  • Valhalla-on-VPS — RoutingSource backend #3; docker-compose + Caddy + provision scripts as a documented path (Oracle Always Free candidate; full-MY extract chosen if provisioned)
  • Worker /api/route proxy — only meaningful with a server backend
  • Real routing for arbitrary origins — arrives with backend #2/#3; the "router pending" state is the honest interim
  • Turn instructions/progress UI — Phase 6 (GUID-*)
  • Toll-avoidance / costing knobs — v1.x

Phase: 05-routing-route-display Context gathered: 2026-10-24