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

98 lines
8.4 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
slug: routing-route-display
status: final
nyquist_compliant: true
wave_0_complete: false
created: 2026-10-24
updated: 2026-10-24
---
# Phase 5 — Validation Strategy
> Per-phase validation contract for feedback sampling during execution.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | Existing hand-rolled harnesses (`bot/test/runner.mjs`, `web/test/runner.mjs`, `search/test/runner.mjs`); plan 05-01 adds the fifth workspace's identical pair (`routing/test/runner.mjs` + `routing/test/harness.mjs`, copied verbatim) — no new framework |
| **Config file** | None — suites are discovered by filename convention (`*.test.mjs`) per workspace |
| **Quick run command** | `npm run routing:test` / `npm test -w web` / `npm test -w bot` |
| **Full suite command** | `npm run routing:test && npm test -w web && npm test -w bot && npm test -w search && npm run audit -w theme` + typechecks + `npm run routing:corpus` |
| **Corpus gate command** | `npm run routing:corpus` (fixture-pair tolerance gate; also asserted in-process by `routing/test/corpus.test.mjs` so `npm run routing:test` fails on a pair regression) |
| **Estimated runtime** | ~20 seconds (hand-rolled runners are sub-second; the capture harness and the production-build BA9 gate are plan-scoped legs) |
---
## Sampling Rate
- **After every task commit:** Run the touched workspace's suite (`npm run routing:test`, or `npm test -w web` / `npm test -w bot`) plus that workspace's typecheck.
- **After every plan wave:** Run the full suite (`npm run routing:test && npm test -w web && npm test -w bot`) **plus** `npm run routing:corpus` — the golden-pair gate must hold at every wave merge, not just at the end.
- **Before `/gsd-verify-work`:** Full suite green + corpus gate green + BA9 bundle-budget gate green (production build).
- **Max feedback latency:** 20 seconds (excluding the plan-scoped capture harness and the production build the BA gate requires — per-plan legs, not per-commit legs).
---
## Per-task Verification Map
| task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 05-01-T1 (workspace + contracts + route model) | 01 | 1 | RTNG-01, D-01/D-07 | T-05-01/06/07 | typed RoutingSource seam; day-one step-geometry + snapped-progress fields pinned by tests; no logging/storage | unit | `npm run routing:test` + `npm run routing:typecheck` | ❌ W0 | ⬜ pending |
| 05-01-T2 (polyline6 codec) | 01 | 1 | RTNG-01 | T-05-02 | pure codec; round-trip law; malformed-input refusal (never NaN points) | unit | `npm run routing:test` | ❌ W0 | ⬜ pending |
| 05-01-T3 (fixture backend + lazy loader + index) | 01 | 1 | RTNG-01, D-03/D-04/D-05 | T-05-03/04 | null = honest pending; 200 m tolerance law; lazy index; three-environment loader proof; empty-fixture schema committed | unit + bundle | `npm run routing:test` + esbuild bundle marker | ❌ W0 | ⬜ pending |
| 05-03-T1 (guidance_sessions envelope types + gates) | 03 | 1 | D-06/D-07 | T-05-08 | types-only: no KV namespace, no runtime writes, TTL constant 7200 | gates + typecheck | `npm test -w bot` + `npm run bot:typecheck` | ❌ W0 | ⬜ pending |
| 05-02-T1 (golden-pairs corpus + fetch script) | 02 | 2 | RTNG-01/02, D-02/D-12 | T-05-05 | public coords only; UA mandatory; per-pair hard-fail on non-Ok; 10–20 pairs committed | fixture-driven | `npm run routing:test` | ❌ W0 | ⬜ pending |
| 05-02-T2 (offline tolerance gate + corpus runner) | 02 | 2 | RTNG-01/02 | T-05-05/12 | geometry↔summary consistency offline; codec round-trip per fixture; alternatives floor; fixture size early-warning | corpus | `npm run routing:corpus` + `npm run routing:test` | ❌ W0 | ⬜ pending |
| 05-04-T1 (route layers + markers + camera) | 04 | 2 | RTNG-01, D-09 | T-05-09 | addLayer-after-building-3d ordering; zero style re-set; verbatim hex constants; pitch 35 preserved | unit + typecheck | `npm test -w web` + `npm run web:typecheck` | ❌ W0 | ⬜ pending |
| 05-04-T2 (route card + chips + pending card + strings) | 04 | 2 | RTNG-02, D-03/D-08/D-10 | T-05-10 | COPY5 strings-module law; no per-card padding overrides; chips = `<button type="button">`; no start-guidance affordance | unit | `npm test -w web` | ❌ W0 | ⬜ pending |
| 05-04-T3 (main.ts wiring + BackButton two-state walk) | 04 | 2 | RTNG-01/02, D-10 | T-05-10/11 | auto route consult after live+destination; no route request when destination unavailable; back always walks to root | unit | `npm test -w web` | ❌ W0 | ⬜ pending |
| 05-05-T1 (BA9 bundle-budget gate) | 05 | 3 | RTNG-01, D-11 | T-05-12 | fixture+route code ≤ 200 KB gz over production-shaped artifacts | build-artifact | `npm test -w web` (after `npm run build -w web`) | ❌ W0 | ⬜ pending |
| 05-05-T2 (route capture legs + ?fixpair knob + gallery) | 05 | 3 | RTNG-01/02 | T-05-14/15 | state-token signals only (no coordinates in console); pairId-only harness knob; harness module provably excluded; route drawn/alt/pending/dark legs non-blank | capture | `npm run web:capture` | ✅ extend | ⬜ pending |
| 05-05-T3 (no-`/api/route` + no-user-coordinate gates) | 05 | 3 | D-05/D-12 | T-05-16/05 | Worker gains no route proxy; fixtures carry zero user-coordinate risk surface | gates | `npm test -w bot` + `npm run routing:test` | ❌ W0 | ⬜ pending |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
---
## Wave 0 Requirements
All new this phase (the repo has no routing infrastructure today). The owning tasks are marked; a task's `<verify>` may reference a suite created in the SAME task (RED-first per the repo's TDD convention).
- [ ] `routing/test/runner.mjs` + `routing/test/harness.mjs` — the fifth workspace's harness pair, copied verbatim from `search/test/` (05-01-T1)
- [ ] `routing/test/contract.test.mjs` — RoutingSource shape, day-one model fields, null-pending contract (05-01-T1)
- [ ] `routing/test/polyline.test.mjs` — codec vectors + round-trip + malformed-input refusal (05-01-T2)
- [ ] `routing/test/fixture-source.test.mjs` + `routing/test/loader-env.test.mjs` — matching law, tolerance boundary, lazy index, no-logging/no-storage, three-environment loader proof (05-01-T3)
- [ ] `routing/test/fixtures/golden-pairs.json` — the pinned 10–20 pair corpus with tolerances (05-02-T1)
- [ ] `routing/scripts/fetch-route-fixtures.mjs` + `routing/scripts/route-corpus.mjs` + `routing/test/corpus.test.mjs` — the maintainer tool + the offline tolerance gate (05-02)
- [ ] `bot/test/guidance-envelope.test.mjs` — types-only envelope gates (05-03-T1)
- [ ] `web/test/route-surface.test.mjs` — layer order/paint constants, card/chips structure, camera constants, BackButton walk (05-04)
- [ ] **Extend (not new):** `web/test/copy-gate.test.mjs` (COPY1 floor + route keys verbatim), `web/test/build-artifact.test.mjs` (BA9 bundle budget), `web/test/no-storage.test.mjs` (explicit `web/src/route/` case note), `bot/test/privacy.test.mjs` or new bot structural gate (no `/api/route`), `web/scripts/capture.mjs` + `web/index.html` (?fixpair legs)
*The corpus runner is the phase's primary acceptance instrument (D-02's tolerance gates) — it is both a script and an in-suite gate, so `npm run routing:test` fails whenever a committed pair regresses.*
---
## Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Route card + chips render legibly on a real device | RTNG-01/02 | Visual truth on real Telegram clients (the automated legs prove structure + capture the 390×844 viewport) | Optional: open the Mini App with `?dest=suria-klcc` on device after deploy; confirm the orange route, card, and chips against `web/screenshots/shell-route-fixture.png` |
*One optional manual leg only — the fixture world removes the real-device blocker Phase 3/4 carried. The phase's "router pending on device" behavior is covered by the pending capture leg.*
---
## Validation Sign-Off
- [x] All tasks have `<automated>` verify or Wave 0 dependencies
- [x] Sampling continuity: no 3 consecutive tasks without automated verify (every task carries an automated verify)
- [x] Wave 0 covers all MISSING references
- [x] No watch-mode flags
- [x] Feedback latency < 20s (excluding plan-scoped capture/build gates)
- [x] `nyquist_compliant: true` set in frontmatter
**Approval:** planner-complete (2026-10-24) — statuses flip to ✅ during execution