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

116 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 5: Routing + Route Display - Context
**Gathered:** 2026-10-24
**Status:** Ready for planning — **with a roadmap amendment** (SC3 rewording, below)
<domain>
## 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.
</domain>
<decisions>
## 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)
</decisions>
<specifics>
## 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.
</specifics>
<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>
## 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
</deferred>
---
*Phase: 05-routing-route-display*
*Context gathered: 2026-10-24*