docs(01-design-tokens-rams-foundation): create phase plan (4 plans, 3 waves)

This commit is contained in:
araharah-planner
2026-10-22 02:33:01 +08:00
commit 16eb089cc3
13 changed files with 1825 additions and 0 deletions
+188
View File
@@ -0,0 +1,188 @@
# Roadmap: araharah
## Overview
araharah turns Telegram into a privacy-respecting turn-by-turn navigator for KL: a bot handles
identity, search, and launch; a Telegram Mini App renders Rams-styled route guidance; Valhalla
routing, self-hosted Photon lookup, OpenFreeMap tiles, and MapLibre GL JS v6 supply the OSM
geodata layer; one Cloudflare Worker (static assets + webhook + `/api/*`) serves it all with
KV-only TTL storage. The roadmap follows the research's strict dependency funnel — design tokens
first (design fidelity is the flagged #1 sink for v1), then the bot/identity security floor,
then the Mini App shell with geolocation, then KL destination search, then routing and route
display, then live turn-by-turn guidance including backgrounded chat turn-cards, and finally a
hardening pass that earns the private launch. Two phases deliberately surface the project's
biggest unknowns early: WebView geolocation quirks (Phase 3) and KL search quality (Phase 4).
## Phases
**Phase Numbering:**
- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
Decimal phases appear between their surrounding integers in numeric order.
- [ ] **Phase 1: Design Tokens + Rams Foundation** - Distill the Telemetry Rams system into a single token package and Rams-styled map basemap, with a mockup-vs-implementation approval artifact — before any screen is built
- [ ] **Phase 2: Bot Skeleton + initData Security** - grammY bot on one Cloudflare Worker: /start, command menu, /privacy, and HMAC-validated identity with TTL-only KV storage
- [ ] **Phase 3: Mini App Shell + Geolocation** - Telegram WebApp shell that boots, authenticates, and reads a reliable live location across the Android/iOS/Desktop client matrix
- [ ] **Phase 4: Destination Search + KL Gazetteer** - Free-text KL search that resolves landmarks despite Malay abbreviations and typos, venue cards, and Mini App launch with destination preloaded
- [ ] **Phase 5: Routing + Route Display** - Valhalla-backed route calculation shown as a Rams route line with quiet alternative cards; the full search→route→render loop lands
- [ ] **Phase 6: Turn-by-Turn Guidance (Live Driving)** - Client guidance state machine: maneuver banner, missed-turn auto-recalculation, honest ETA, haptics, seamless resume, and backgrounded chat turn-cards
- [ ] **Phase 7: Hardening + Private Launch** - Device-matrix QA, graceful failure states, privacy-by-construction audit, and golden-route regression before real drivers
## Phase Details
### Phase 1: Design Tokens + Rams Foundation
**Goal**: The Telemetry Rams design system exists as one centralized, importable token set — including map basemap cartography — with a user-approved mockup-vs-implementation gallery proving the fidelity bar before any product screen is built.
**Depends on**: Nothing (first phase)
**Requirements**: DSGN-01, DSGN-02
**Success Criteria** (what must be TRUE):
1. Every rendered Rams component derives exclusively from the centralized token set (exacted palette, 8px grid, radius-0, typography) — an audit sweep finds zero off-token color/spacing/typography values in the component sheet (DSGN-01)
2. A side-by-side gallery comparing the rendered token/component sheet against the `stitch_minimalist_route_navigator/` mockup screens exists and is approved by the user — establishing the DSGN-02 approval artifact mechanism reused by every later UI phase
3. A Rams-styled MapLibre basemap (OpenFreeMap `liberty` style forked to Rams tokens: grayscale grounding, muted land/water, prepared accent for route highlighting) renders in a browser (DSGN-01, map cartography)
4. Design authority is singular: the duplicate inline Tailwind token blocks and the conflicting root `DESIGN.md` typography are superseded by the token package as the one source of truth (resolves the CONCERNS.md design-source conflict)
**Plans**: 4 plans
Plans:
- [ ] 01-01-PLAN.md — Repo hygiene + Tailwind v4 token package (`theme/`) + self-hosted fonts + DESIGN.md supersession (D-01/02/04/05/06/07/16)
- [ ] 01-02-PLAN.md — Component sheet: `theme/src/components.css` + `sheet.html` consuming tokens only (D-03/D-11)
- [ ] 01-03-PLAN.md — Rams basemap: token-derived OpenFreeMap liberty fork + KL preview (D-08/09/10)
- [ ] 01-04-PLAN.md — Off-token audit (D-13) + Playwright captures (D-14) + DSGN-02 approval gallery (D-12), blocking user checkpoint
Notes:
- Repo hygiene lands here first: scrub `*:Zone.Identifier` artifacts, `.gitignore` for OS junk/`node_modules`/secrets (pre-dates any credential handling).
- Project skill `.agents/skills/design-taste-frontend/` applies to all UI phases under its *existing brand/design system* special case: keep the Rams palette/type, app-screen house rules for dashboard-like surfaces, real-browser inspection for the gallery artifact. Telemetry Rams tokens are binding where skill defaults would differ.
- Standard patterns (no research phase needed): mockups are the spec; token extraction from the mockup Tailwind config.
**UI hint**: yes
### Phase 2: Bot Skeleton + initData Security
**Goal**: Users can reach araharah through Telegram with a working command surface, and the backend's identity + privacy architecture is provably sound from the first deploy — the initData validator is the first backend artifact.
**Depends on**: Phase 1
**Requirements**: ONBD-01, PRIV-01, PRIV-02
**Success Criteria** (what must be TRUE):
1. A new user sends /start and receives a concise explanation plus an always-available command menu (/help, /privacy) that answers correctly (ONBD-01)
2. /privacy gives an honest, visible statement of what araharah stores and does not store (PRIV-01) — the in-app "trip ended, data deleted" messaging half completes with guidance in Phase 6, riding this requirement's message design
3. Tampered, stale, and replayed initData payloads are rejected with CI test vectors and known-good HMAC cases passing; only validated identities receive a one-time session token (security gate — the phase's exit criterion)
4. A storage spot-check shows KV with TTL-only namespaces and zero persistent coordinates or user profiles — privacy by construction holds from the first line of backend code (PRIV-02; re-audited in Phase 7)
**Plans**: TBD
Notes:
- One Cloudflare Worker deployable (static assets + webhook + `/api/*`); KV `chat_sessions` (minutes TTL) is the first namespace; the `guidance_sessions` (~2h TTL) envelope is only designed with its consumer in Phase 5.
- Standard patterns (no research phase needed): grammY + Workers hosting is first-class documented; verify exact grammY initData typings at phase start (research gap).
**UI hint**: no
### Phase 3: Mini App Shell + Geolocation
**Goal**: The Mini App opens inside Telegram, establishes a validated session, and obtains the user's live location reliably — with every fallback path that keeps location flowing when the primary path dies, verified on real devices.
**Depends on**: Phase 2
**Requirements**: GEO-01, GEO-02, GEO-03, PX-02
**Success Criteria** (what must be TRUE):
1. On a real Android phone and iOS phone, the user grants location and sees their live position rendered on the Rams basemap; the permission grant persists across session restarts via LocationManager (version-gated) (GEO-01)
2. When in-app location fails (Desktop Telegram without geolocation, or denied permission), the chat "send location" keyboard fallback recovers the origin and the app proceeds with it (GEO-02)
3. Location denial shows a deliberate denied state (never a blank map), and the app renders correctly under Telegram light and dark themes while the map keeps Rams cartography constant (PX-02, platform themes)
4. No coordinate written anywhere persists: storage remains TTL-ephemeral only, spot-checkable at phase exit (GEO-03)
5. Device-matrix exit pass: Android + iOS + Desktop + plain browser each demonstrate boot → session → position, exercising the full fallback chain (pitfall research device-matrix criterion)
**Plans**: TBD
Notes:
- Highest platform-integration uncertainty in the project — research recommends `/gsd-research-phase` (Android LocationManager stale-fix workaround, `getLiveData()` wrapper, WebView permission bridges, browser testing harness).
- BackButton wiring and safe-area groundwork are built here as shell infrastructure; the observable PX-01/PX-03 behaviors are claimed by Phase 6 where the full state graph exists.
**UI hint**: yes
### Phase 4: Destination Search + KL Gazetteer
**Goal**: Users type a destination the way locals actually write it and get the right KL-metro landmark back, then step into the Mini App already aimed at their destination.
**Depends on**: Phase 3
**Requirements**: SRCH-01, SRCH-02, SRCH-03, ONBD-02, ONBD-03
**Success Criteria** (what must be TRUE):
1. Typing "KLCC" — plus the golden query set ("Sunway Pyramid", "DUKE", mall and kampung-style queries) — returns the right KL landmark in a shortlist (SRCH-01)
2. Abbreviated, typo'd, and missing-space queries ("Jln Ampang" ↔ "Jalan Ampang", "Tmn", glued words) resolve to the same result as the canonical spelling (SRCH-02)
3. Choosing a result sends a native venue card in chat confirming the destination before navigation opens (SRCH-03)
4. Tapping through from the search result launches the Mini App with the destination preloaded — no re-entry in the webview (ONBD-02); adding araharah to the phone home screen and launching from there lands in the app ready to search (ONBD-03)
5. The self-hosted Photon KL bake-off is concluded against the real-query acceptance corpus with the decision (and any gazetteer/fallback escalation) documented — the search-quality experiment closes, it doesn't stay open
**Plans**: TBD
Notes:
- Budgeted bake-off: research recommends `/gsd-research-phase` (gazetteer sourcing/structure ~200 entries, Malay normalizer, photon-vs-fallback decision; funds a GraphHopper MY dump on the VPS).
- VPS provisioning (Photon + Valhalla hosting) begins here — free-first infrastructure mandate (Oracle Cloud Always Free candidate).
**UI hint**: no
### Phase 5: Routing + Route Display
**Goal**: The product exists end-to-end: current location to Rams-drawn route with quiet alternative choices, on routing infrastructure fast enough for the guidance phase to build on.
**Depends on**: Phase 4
**Requirements**: RTNG-01, RTNG-02
**Success Criteria** (what must be TRUE):
1. A user sees their calculated route drawn on the Rams-styled map — grayscale basemap grounding with the accent route line — from their current location to the chosen destination (RTNG-01)
2. The user can choose among up to 3 alternatives presented as quiet Rams cards (time, distance, one-line difference) and the selection redraws (RTNG-02)
3. The golden-route corpus (10–20 real KL origin/destination pairs) routes cleanly through self-hosted Valhalla (Malaysia extract) behind the Worker proxy — no dead ends, no geometry failures, latency and Worker subrequest budgets holding with instrumentation visible
**Plans**: TBD
Notes:
- GUID-05/06 upstream design obligations land here deliberately: the route model carries step geometry + snapped-progress support from day one, and the ephemeral `guidance_sessions` KV envelope (id, chat ref, route snapshot ref, ~2h TTL) is designed here so the backgrounded turn-card service in Phase 6 has its session contract already defined.
- Standard patterns (no research phase needed): documented preprocess pipeline for Valhalla + the graph/tiles build; no exotic APIs.
**UI hint**: yes
### Phase 6: Turn-by-Turn Guidance (Live Driving)
**Goal**: While driving, araharah behaves like real navigation — prominent maneuvers, silent self-healing recalculation, honest ETAs, haptic cues, seamless resume — and guidance survives the app being minimized via best-effort chat turn-cards.
**Depends on**: Phase 5
**Requirements**: GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03
**Success Criteria** (what must be TRUE):
1. During a drive, the user sees a prominent next-maneuver banner (distance + arrow + street name) with a collapsible full maneuver list (GUID-01), ETA and remaining distance progressing with each location fix without visible whiplash (GUID-03), and a haptic cue at maneuver points (GUID-04)
2. After a missed turn, the app silently recalculates from the current position — no asking, no blaming — and reroute storms are held back by the debounce/hysteresis state machine (GUID-02, verified via recorded-drive replays plus a real drive)
3. Minimizing the app mid-drive switches the bot to pushing chat turn-cards (map snapshot + next maneuver + ETA, best-effort projection) for the remainder of the trip (GUID-05, served by the Phase 5-designed ephemeral guidance session); re-opening mid-trip resumes live guidance seamlessly at the progressed position (GUID-06)
4. The Telegram BackButton walks the full app states (search → routes → guidance → back to search) and never dead-ends (PX-01 — full state graph only exists now); closing during guidance requires passing the "abandon route?" confirmation, with safe areas respected and vertical-swipe-close disabled during guidance (PX-03)
5. Ending a trip deletes the ephemeral guidance session and shows the "trip ended, data deleted" messaging — completing the in-app half of PRIV-01's promise at the trip boundary
**Plans**: TBD
Notes:
- Highest behavioral uncertainty (reroute triggers, ETA smoothing, battery) — research recommends `/gsd-research-phase` (backgrounded turn-card "best-effort projection" framing + static map snapshot generation; product decision needed for what "good enough" means minimized).
- Schedule slack budgeted here per research; backgrounded turn-cards are folded into this phase per roadmap instructions with the session contract pre-designed upstream (Phase 5).
**UI hint**: yes
### Phase 7: Hardening + Private Launch
**Goal**: Real KL drivers get an honest, robust experience: every failure state designed, the privacy promise holding under audit, performance within free-tier budgets, and a known-limitations document that tells the truth — then the launch.
**Depends on**: Phase 6
**Requirements**: PX-04
**Success Criteria** (what must be TRUE):
1. Guidance supports fullscreen and remains usable in landscape (driving posture) across the full real device matrix — Android, iOS, Desktop, browser (PX-04) — folded into the phase's device-matrix QA pass including the battery drain target (<10%/hr during guidance)
2. Every empty/error/timeout/off-road/no-geometry state renders gracefully (no blank screens, no broken layouts); version-gating fallbacks behave sanely on older Telegram clients
3. Privacy verification passes: an architecture audit shows no persistent per-user location history or profile anywhere — coordinates exist only in TTL-expiring KV, and logs carry no coordinate data (re-verifies PRIV-02, GEO-03 end-to-end)
4. The golden-route regression pass is green, Worker budgets audit clean (subrequests/CPU, cache hit-rate), and the "known limitations" doc (OSM data gaps, no traffic confidence, no lane guidance) ships before the first real drivers
**Plans**: TBD
Notes:
- No exclusive feature requirements beyond PX-04 — this phase hardens the outcomes of Phases 1–6 and is the last chance to catch the "looks done but isn't" failures for a navigation tool whose empty states ARE the polish surface.
**UI hint**: no
## Requirements Coverage
| Phase | Requirements |
|-------|--------------|
| 1 | DSGN-01, DSGN-02 |
| 2 | ONBD-01, PRIV-01, PRIV-02 |
| 3 | GEO-01, GEO-02, GEO-03, PX-02 |
| 4 | SRCH-01, SRCH-02, SRCH-03, ONBD-02, ONBD-03 |
| 5 | RTNG-01, RTNG-02 |
| 6 | GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03 |
| 7 | PX-04 |
**Coverage:** 22/22 v1 requirements mapped — no orphans, no duplicates. (PRIV-01's in-app trip-boundary messaging and PX-01/PX-03 groundwork are noted where they're staged, but each requirement maps to its owning phase exactly once.)
## v1.x Candidates (post-v1, not roadmap phases)
Per research: voice guidance (gated on iOS WKWebView TTS spike), live trip share via `sendLocation(live_period)`, toll vs toll-free toggle (Valhalla `use_tolls`), speed-limit display where OSM `maxspeed` exists. These hang off validated routing + guidance — plan a v1.x milestone after user validation, do not pull into the spine above.
## Progress
**Execution Order:**
Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Design Tokens + Rams Foundation | 0/TBD | Not started | - |
| 2. Bot Skeleton + initData Security | 0/TBD | Not started | - |
| 3. Mini App Shell + Geolocation | 0/TBD | Not started | - |
| 4. Destination Search + KL Gazetteer | 0/TBD | Not started | - |
| 5. Routing + Route Display | 0/TBD | Not started | - |
| 6. Turn-by-Turn Guidance (Live Driving) | 0/TBD | Not started | - |
| 7. Hardening + Private Launch | 0/TBD | Not started | - |
---
*Roadmap created: 2026-10-22*