docs(06): create phase plans (8 plans, 4 waves)

This commit is contained in:
araharah-executor
2026-10-24 07:46:13 +08:00
parent 6f747b4cb1
commit 7fe8c6aa65
9 changed files with 1986 additions and 10 deletions
@@ -0,0 +1,172 @@
---
phase: 06-turn-by-turn-guidance-live-driving
plan: 08
type: execute
wave: 4
depends_on: [06-06, 06-07]
files_modified:
- web/src/mock/telegram-mock.ts
- web/scripts/capture.mjs
autonomous: false
requirements: [GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03]
must_haves:
truths:
- "The capture harness replays a committed drive fixture through the LIVE shell via ?drive=<name> (D-16's browser leg)"
- "All seven guidance capture legs exist and assert ARAHARAH-GUIDE state tokens (never coordinates in console)"
- "The DSGN-02 guidance gallery compares the captures against active_route_guidance/screen.png"
- "ONE REAL DRIVE demonstrates: banner legibility, silent reroute self-heal, minimize → turn-cards, resume, trip-end deletion messaging (D-16 device gate)"
artifacts:
- path: "web/src/mock/telegram-mock.ts"
provides: "?drive= fixture-replay fix source with pause/resume controls"
- path: "web/scripts/capture.mjs"
provides: "the 7 guidance legs + gallery composite"
key_links:
- from: "web/src/mock/telegram-mock.ts"
to: "web/test/fixtures/drives/*.json"
via: "import.meta.glob fixture loading; the mock's fix source replays the drive"
pattern: "fixtures/drives"
- from: "web/scripts/capture.mjs"
to: "web/src/mock/telegram-mock.ts"
via: "?drive= profiles + scripted taps drive the legs"
pattern: "drive="
---
<objective>
The phase's verification close (D-16): extend the Mock-Telegram harness with the ?drive= fixture-replay knob, capture the seven guidance legs + DSGN-02 gallery, and run the ONE REAL DRIVE device gate — banner legibility, silent self-heal, minimize/turn-cards, resume, trip-end deletion.
Purpose: replays proved the brain in Node (06-02); captures prove the SHELL renders it; the real drive proves the ROAD behaves. This is the phase's declared protocol (the 03/04 precedent) and its exit gate.
Output: harness knob + 7 captures + gallery artifact + a recorded real-drive verdict.
</objective>
<execution_context>
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
@$HOME/.config/opencode/get-shit-done/templates/summary.md
</execution_context>
<context>
@.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-VALIDATION.md
@.planning/phases/06-turn-by-turn-guidance-live-driving/06-RESEARCH.md
<interfaces>
<!-- Capture profiles table (06-UI-SPEC — BINDING names + asserts):
harness knob ?drive=<fixture>: the mock's Telegram fix source replays the D-16 JSON stream
through the live shell; pairs with ?dest= + ?fixpair= carriers; asserts ARAHARAH-GUIDE
state=<state> tokens (state tokens only — no coordinates in console, D-15 hygiene)
shell-guidance-active.png mock=android&dest=<golden-id>&fixpair=<pair>&drive=<corridor> light
→ banner (GUIDE // NEXT, arrow, distance, street) + compact strip + guidance card + progress bar + locked pose
shell-guidance-list.png same, after a scripted banner tap → list expanded, NEXT row lamp (collapsed-default proof = the active leg's complement)
shell-guidance-rerouting.png drive=<missed-turn> captured INSIDE the REROUTING window → calm banner (reroute copy, — distance, gantry), NO red anywhere
shell-guidance-confirm.png scripted END TRIP tap → confirm card bottom register, both CTAs, no red
shell-guidance-tripend.png scripted YES, ABANDON → trip-ended card (center), guidance chrome cleared
shell-guidance-dark.png active profile, scheme=dark → PX-02 chrome re-slots, banner Rams-constant
guidance-gallery-compare.png DSGN-02 side-by-side vs stitch_minimalist_route_navigator/active_route_guidance/screen.png -->
<!-- Mock harness (web/src/mock/telegram-mock.ts) + capture script (web/scripts/capture.mjs):
follow their EXISTING leg/profile/carrier patterns exactly (phase 3/4/5 legs stay
unchanged); fixture loading via import.meta.glob over ../test/fixtures/drives/*.json;
expose window.__ARAHARAH_DRIVE = { pause(), resume() } so the capture script can freeze
the replay mid-stream for the REROUTING leg's timing window and drive taps between fixes. -->
<!-- The real-drive checklist (06-VALIDATION manual-only row + D-16):
start a route on a real device → banner + haptic at approach/maneuver → miss a turn
deliberately → silent recalculation (no dialog, no blame) → minimize mid-drive →
turn-cards arrive in chat → re-open (or tap OPEN GUIDANCE) → guidance resumes at the
progressed position → END TRIP → "trip ended" messaging → (optional KV spot-check:
guidance:* key gone). Record the verdict + any defects verbatim. -->
</interfaces>
**The captures assert STATE TOKENS, never coordinates** (the Phase 5 capture law). The gallery is DSGN-02's phase artifact — fidelity review rides the same blocking checkpoint as the drive.
</context>
<tasks>
<task type="auto">
<name>task 1: ?drive= replay knob + the seven guidance capture legs + gallery</name>
<files>web/src/mock/telegram-mock.ts, web/scripts/capture.mjs</files>
<read_first>
- web/src/mock/telegram-mock.ts IN FULL (the mock fix-source architecture — ?drive= extends its source selection; the existing ?fixpair= carrier pattern)
- web/scripts/capture.mjs IN FULL (leg/profile structure, theme carrier, composite/gallery pattern from Phase 5's route legs, console-capture assert style)
- web/test/fixtures/drives/ (the four committed fixtures — ?drive= names map to these files)
- .planning/phases/06-turn-by-turn-guidance-live-driving/06-UI-SPEC.md Capture Profiles table (BINDING: names, profiles, asserts)
</read_first>
<behavior>
- `mock=android&dest=<golden-id>&fixpair=<pair>&drive=corridor-follow` boots into the route state and, past the 30 m activation gate, plays the fixture's fixes on their recorded schedule through the LIVE shell (real pump, real builders, real camera — not the Node fakes)
- window.__ARAHARAH_DRIVE.pause()/resume() freezes/resumes the replay clock (the REROUTING leg captures inside the window; the confirm/tripend legs run after resume)
- each leg's console capture shows the asserted ARAHARAH-GUIDE state tokens and ZERO coordinate-bearing log lines
- all seven PNGs exist under the capture output dir; the gallery composite places them beside the mockup screen.png
- existing legs (boot, denied, route, captures from phases 3–5) still pass unchanged
</behavior>
<action>
1. `web/src/mock/telegram-mock.ts`: add the ?drive= knob — read `drive` from location.search (the existing carrier style), validate against the import.meta.glob record of `../test/fixtures/drives/*.json` (unknown name → honest console token + fall back to the default source, never a crash); the drive source emits each Fix at `t0 + (fix.ts − fixes[0].ts)` on a replay clock that __ARAHARAH_DRIVE.pause()/resume() controls (paused clock stops emission, resume continues mid-stream — the REROUTING leg needs the freeze); console emits nothing but the state-token family.
2. `web/scripts/capture.mjs`: add the seven legs EXACTLY per the UI-SPEC table (names, profiles, asserts): active (light), list (scripted banner tap — page.click on the banner button), rerouting (drive=missed-turn-excursion + pause inside the REROUTING window — poll the console for the `ARAHARAH-GUIDE state=rerouting` token then shoot), confirm (scripted END TRIP tap), tripend (scripted YES, ABANDON tap), dark (scheme=dark), and the gallery-compare composite (the existing Phase 5 composite pattern with active_route_guidance/screen.png). Each leg asserts its state tokens via the existing console-capture helper + the DOM text checks the table names (GUIDE // NEXT, register words); add a NO-RED assertion to the rerouting/confirm legs (scan the captured banner/confirm element's computed colors or the absence of the functional-red token class — the cheapest honest check: assert the elements' class lists contain no red-token class).
3. Run the full capture suite; commit the seven PNGs + gallery; record the guidance gallery path in the SUMMARY for the DSGN-02 review.
</action>
<verify>
<automated>npm run web:capture 2>&1 | tail -20 && node -e "const fs=require('fs');const legs=['shell-guidance-active','shell-guidance-list','shell-guidance-rerouting','shell-guidance-confirm','shell-guidance-tripend','shell-guidance-dark','guidance-gallery-compare'];for(const l of legs){if(!fs.existsSync('web/captures/'+l+'.png'))process.exit(1)};console.log('7 guidance legs ok')"</automated>
</verify>
<acceptance_criteria>
- all 7 PNGs exist under web/captures/ (adjust the path prefix to capture.mjs's actual output dir — verify by reading the script first)
- telegram-mock.ts contains `import.meta.glob` over fixtures/drives and the __ARAHARAH_DRIVE pause/resume surface
- capture.mjs contains the 7 leg names from the UI-SPEC table and asserts ARAHARAH-GUIDE tokens
- prior capture legs unbroken (the suite's existing legs green)
- captures/summary output shows zero coordinate-bearing console assertions
</acceptance_criteria>
<done>The shell is proven on film: seven legs covering active, list, calm rerouting, confirm, trip-end, dark, and the mockup comparison — driven by real committed drive fixtures</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>task 2: The ONE REAL DRIVE — the phase's device gate (D-16) + DSGN-02 gallery review</name>
<what-built>
Live turn-by-turn guidance end-to-end: Rams maneuver banner + collapsible list + guidance card with honest ETA, haptic cues, silent engine-A rerouting, minimize → chat turn-cards via the Worker cron, seamless resume, BackButton full state graph with the abandon confirmation, and trip-end deletion messaging. Seven capture legs + the DSGN-02 guidance gallery are committed for review beside stitch_minimalist_route_navigator/active_route_guidance/screen.png.
</what-built>
<action>
Blocking human checkpoint (automation-first: task 1's captures + all three workspace suites + the CPU gate are green BEFORE this runs). The user performs Part A (gallery fidelity review) and Part B (the one real drive with the 7-step checklist below). No OpenCode automatable step remains: physical GPS, real road geometry, and human legibility/haptic judgment are the declared device-gate protocol (D-16, phases 3–5 precedent). The executor records the per-step verdict verbatim in the SUMMARY; a FAIL holds the phase open (the Phase 3 UNVERIFIED precedent) rather than silently closing it.
</action>
<how-to-verify>
Part A — gallery (5 min): open the guidance gallery composite (path in 06-08's SUMMARY). Confirm fidelity: banner ink hierarchy (white distance, beige street, orange arrow), no red in guidance chrome, radius-0, token-pure. Approve or list deviations (tokens.css wins over mockup; the spec records calls).
Part B — the drive (one real drive, phone mounted, safe location to start):
1. Deploy fresh (`npm run deploy -w bot` with the graph uploaded — 06-04) and open the Mini App from the bot.
2. Pick a golden destination, start driving. VERIFY: banner shows distance + arrow + street; compact strip; guidance card ETA progresses without whiplash; haptic at ~300 m approach and at the maneuver.
3. Miss a turn DELIBERATELY. VERIFY: no dialog, no blame — the banner calmly shows the rerouting state, then the new route snaps in.
4. Minimize the app mid-drive. VERIFY: within ~3–4 minutes a turn-card arrives in chat (glyph + ETA + distance + OPEN GUIDANCE).
5. Re-open via the card's OPEN GUIDANCE. VERIFY: guidance resumes at the progressed position (resuming state, then live).
6. Tap END TRIP → confirm card → YES, ABANDON. VERIFY: "trip ended" messaging; chat cards stop.
7. (Optional, executor-assisted) KV spot-check: `npx wrangler kv key list --namespace-id=<chat_sessions id> --prefix "guidance:"` shows no stale keys.
Record PASS/FAIL per step + anything that felt wrong (legibility in sunlight, haptic feel, card lag).
</how-to-verify>
<resume-signal>Type "approved" (drive + gallery pass) or list the failing steps/deviations</resume-signal>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Capture harness → live shell | The replay knob feeds the REAL pump with committed fixtures — no test-only bypasses of validation |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-06-04 | Information Disclosure (capture hygiene) | mock + capture console asserts | mitigate | Legs assert STATE TOKENS and assert the ABSENCE of coordinate-bearing log lines (the D-15 hygiene law carried into captures); no new logging is introduced by this plan. |
| — | Privacy (the drive itself) | real-drive protocol | mitigate | The drive uses the product's own privacy posture: no location history exists to leak; the KV spot-check proves the post-trip deletion promise (D-14) on real infrastructure. |
| — | Tampering (fixture/kernel mismatch) | ?drive= knob | mitigate | Unknown drive names fail honest (token + default source) rather than replaying arbitrary data; fixtures are committed and attributed. |
</threat_model>
<verification>
- `npm run web:capture` green with the 7 new legs; prior legs unbroken
- Gallery composite committed (DSGN-02 artifact for the phase)
- The real-drive checklist recorded with a per-step verdict (the phase's exit gate — a FAIL holds the phase open, per the Phase 3 UNVERIFIED precedent)
</verification>
<success_criteria>
D-16 is satisfied on both legs: the recorded drives prove the machine, the captures prove the shell, and ONE REAL DRIVE proves the road — banner, self-heal, turn-cards, resume, deletion — with the gallery review closing DSGN-02 for the phase.
</success_criteria>
<output>
After completion, create `.planning/phases/06-turn-by-turn-guidance-live-driving/06-08-SUMMARY.md`
</output>