The maneuver banner renders distance + arrow + street per the UI-SPEC anatomy, with REROUTING/RESUMING/NO REROUTE calm states and the machine-blink gantry (GUID-01, D-04/D-06)
The maneuver list collapses/expands over the map with NEXT/FUTURE/PAST row states and tap-out collapse (GUID-01)
The guidance card shows ETA + remaining + progress bar + END TRIP — the route card evolved (D-06)
The abandon-route confirm card guards every guidance exit with the exact en/ms copy (D-09/PX-03)
Haptics fire through capability-guarded calls and no-op cleanly on old clients (GUID-04/D-08)
Close protection engages on guidance start and releases at trip end (disableVerticalSwipes 7.7+, closing confirmation 6.2+) (PX-03)
All guidance copy lives in the strings module in en + ms — never inline (the copy gates)
path
provides
web/src/guidance/glyphs.ts
the 8-glyph committed set as raw SVG (single source; PNGs rasterize from these files in plan 07)
the 18 new ShellStrings keys, en + ms, exact UI-SPEC copy
from
to
via
pattern
web/src/guidance/banner.ts
web/src/i18n/strings.ts
every label via strings[locale] — zero inline copy
strings[locale]
from
to
via
pattern
web/src/guidance/banner.ts
web/src/guidance/glyphs.ts
inline SVG from the committed glyph sources
GLYPHS
from
to
via
pattern
web/src/guidance/close-protection.ts
web/src/telegram/webapp.ts
optional members + isVersionAtLeast guards
isVersionAtLeast
The guidance cockpit surface per 06-UI-SPEC: the 8-glyph committed set, the maneuver banner + collapsible list + guidance card + abandon-confirm + trip-end builders, the close-protection and haptics capability guards, and all copy in the strings module — every element token-only, radius-0, no shadows, machine-instant state swaps.
Purpose: GUID-01/PX-03's visible behavior and GUID-04's haptic channel. Builders are pure DOM composition (Node-testable, the route-card law); plan 06 wires them to the state machine.
Output: glyphs + 5 builders + 2 guard modules + webapp contract members + strings keys + shell.css guidance rules + the guidance-surface suite + RS10/BA9/copy-gate bumps.
@.planning/PROJECT.md
@.planning/phases/06-turn-by-turn-guidance-live-driving/06-UI-SPEC.md
@.planning/phases/06-turn-by-turn-guidance-live-driving/06-CONTEXT.md
@.planning/phases/06-turn-by-turn-guidance-live-driving/06-PATTERNS.md
task 1: The 8-glyph committed set + glyphs.ts + strings keys
web/src/guidance/glyphs/*.svg, web/src/guidance/glyphs.ts, web/src/i18n/strings.ts, web/test/copy-gate.test.mjs
- .planning/phases/06-turn-by-turn-guidance-live-driving/06-UI-SPEC.md "The 8-glyph set" table (the EXACT geometry per glyph) + "Maneuver Banner" ink hierarchy
- web/src/i18n/strings.ts (the ShellStrings interface + en/ms records — append, never reorder)
- web/test/copy-gate.test.mjs (what it enumerates — extend in the same change)
- theme/src/tokens.css (verify --color-signal-orange #EB8008 — SVGs use currentColor; PNG rasterization in plan 07 injects the literals)
- glyphs.ts exports GLYPHS: Record for exactly ["depart","straight","left","right","slight-left","slight-right","uturn","arrive"], each value the raw SVG string of the committed file (?raw import — the committed SVGs are the single source)
- every SVG: viewBox "0 0 32 32", stroke currentColor, stroke-width 3, square linecaps, orthogonal/45° segments only (the geometry table verbatim: depart = 4×4 filled square + vertical shaft; uturn = machined staple, no arc; arrive = shaft ending on a 12×12 filled square)
- every new ShellStrings key exists in BOTH en and ms with the exact UI-SPEC values (the interface gains the 18 keys with doc comments)
1. Create the 8 SVG files in `web/src/guidance/glyphs/` per the UI-SPEC geometry table — hand-authored, 32×32 grid, `fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="square" stroke-linejoin="miter"`, filled squares as ``. Keep every segment orthogonal or 45° (the orthogonal law — the uturn staple is the proof case).
2. `web/src/guidance/glyphs.ts`: `import depart from "./glyphs/depart.svg?raw"; …` (Vite ?raw), `export type GlyphKind = "depart" | "straight" | "left" | "right" | "slight-left" | "slight-right" | "uturn" | "arrive";`, `export const GLYPH_KINDS: readonly GlyphKind[]` (the 8 in order), `export const GLYPHS: Record`, and `export function svgHost(kind: GlyphKind): SVGSVGElement` — a `` whose innerHTML is set from the STATIC `GLYPHS[kind]` constant (the ONE sanctioned innerHTML site: a static import value, never a name-derived or runtime string — the surface gate whitelists exactly this line), returning the parsed `
<threat_model>
Trust Boundaries
Boundary
Description
Telegram client → WebApp APIs
Client capabilities vary across Bot API 6.1–8.0+; every new call is capability-guarded
STRIDE Threat Register
Threat ID
Category
Component
Disposition
Mitigation Plan
T-06-06
Tampering (crash/doS on old clients)
haptics.ts, close-protection.ts
mitigate
Version gates BEFORE every call + ?. optional-member chains + no-throw fakes proven in tests (RESEARCH Pitfall 5). Graceful degradation is the D-08 law.
—
Spoofing (UI overlay confusion)
confirm card
accept
The confirm card is plain DOM in the app's own register band; no privileged surface to spoof; Telegram chrome is out of scope.
—
Information Disclosure
banner/list/card
mitigate-by-design
Builders render only route-model data the user is already looking at; no coordinates are ever logged (no console in builders — structural gate).
—
DoS
gantry blink interval
mitigate
startGantryBlink stores one interval per element and stopGantryBlink clears it; state swaps always stop the previous blink (wired in plan 06; the API makes a leak visible in review).
</threat_model>
- `npm test -w web && npm run web:typecheck` green (existing suites + guidance-surface + copy gate)
- RS10 (≥24) and BA9 (budget printed, ≤204800) green with the guidance family counted
- Zero inline copy, zero off-token CSS values, zero red in guidance chrome
<success_criteria>
The guidance cockpit exists as pure, tested builders + guards: banner five-slot discipline with the calm REROUTING/RESUMING/NO REROUTE states, collapsible honest list, evolved guidance card with progress bar, ONE confirm surface with the exact privacy copy, trip-end card, capability-safe haptics and close protection — every word in strings.ts, every pixel from tokens.
</success_criteria>
After completion, create `.planning/phases/06-turn-by-turn-guidance-live-driving/06-05-SUMMARY.md`