21 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 06-turn-by-turn-guidance-live-driving | 06 | web-guidance-wiring |
|
|
|
|
|
|
|
|
|
65min | 2026-10-24 |
Phase 6 Plan 6: Guidance Wiring — Pump, PX-01 Graph, D-10 Camera, Envelope Flows Summary
Guidance is ALIVE in the shell: the ≥30 m start gate mounts the cockpit on the drawn route, accepted fixes drive banner/ETA/progress/haptics through the 06-02 machine, missed turns self-heal through the composed engine-a ladder with a calm banner, minimizing hands off via the keepalive envelope POST (the cron's structural gate), a killed webview resumes at the projected position from ?g=, the BackButton walks search → routes → guidance → confirm → routes → search with zero dead ends and close() only at the true root, and both trip ends delete the envelope and say so — 146 web tests green, every gate re-pinned with the change that invalidated it.
Performance
- Duration: 65 min (wall clock across two interleaved executor passes)
- Started: 2026-10-24T06:29:27Z
- Completed: 2026-10-24T07:34:13Z
- Tasks: 3/3 (all TDD RED→GREEN)
- Files: 6 (1 created, 5 modified) + the test suite
Accomplishments
- The camera rides the snapped line at the UI-SPEC pose (D-10, task 1):
GUIDANCE_CAMERA_PADDING {top:320, bottom:64, left:64, right:64}, pitch 35, zoom 16, 400 ms — bearing NEVER passed (RS11 pins the key's absence). The ease executes through the follow controller (one easing discipline, one unlock law): a programmatic move never reads as a user pan, a user gesture unlocks and the recenter notch clears (RS12), and the no-opts call stays byte-identical for the Phase 3/5 call sites (RS13).onRerouteAppliedis the documented no-op — the new line snaps in via setData and the next per-fix ease settles the viewport. - The BackButton walks the full graph (PX-01, tasks 1+3): the wire grew into a context-aware resolver —
BackAction = hidden | close | callbackconsulted per click,wire.sync()re-applying visibility on every state change. RS7b proves search → routes → guidance → confirm (Back means CONTINUE there) → ended → root with close() recorded ZERO times from pushed states; the legacy (hasOverlay, walkBack) shape composes internally so RS7 and the Phase 5 call sites stay valid. The controller'sbackAction()is the resolver's one authority (E5): driving → the D-09 confirm, confirm → CONTINUE, ended → the search-root walk, idle → Telegram's close. - The pump is live (task 2): watch armed at the route draw (never over pending — G5a), the machine's ≥30 m start gate activates the cockpit (close protection engaged,
[data-guidance="active"], banner + card + collapsed list, the locked pose,state=on_route), accepted fixes re-render the five-slot banner + deadband ETA card + stepping progress bar, OFF_ROUTE keeps the banner calm (no premature signal, G3), REROUTING swaps to the dash + gantry with exactly ONE source.route call and the storm guard holding (G4), failure lands NO REROUTE + the card state line (G5), success snaps the new line in via setData with NO camera jump and the list re-rendered (G6), and END TRIP → confirm → YES ABANDON and the machine's arrival both run the same teardown (G7/G8): watch stopped, protection released, strip restored, trip-ended card centered,state=ended. - The envelope lifecycle is structural (task 3):
deactivatedPOSTs the frozen six-field snapshot (keepalive — the minimize race's belt, G9/E1; EXACTLY the six client-minted fields, id/chat_id/created_at server-minted; never double-minted while live),activatedDELETEs so the cron pauses with no key and no flag while the id is retained (G10), trip end deletes the same id idempotently (404-tolerant, E4), and the?g=boot UUID-validates, GETs, rebuilds the model (synthesizing terminal marks for steps-less envelopes), draws the line, renders GUIDE // RESUMING with the projected numbers (G11/E3' — 100 s elapsed at avg speed ⇒ ~1167 m / 140 s, honestly labeled by the register), pauses the cron NOW (the resume DELETE), arms the watch, and flips live on the first accepted fix through the machine's own resuming path. - The composed ladder is real and code-constructed (task 3): engine-a first, fixture fallback —
(await httpSource.route(req)) ?? (await fixtureSource.route(req))— no env reads in the selection region (G12/E6), so the golden-demo path survives a token-less boot and reroutes hit the real router for the first time. - Gates grew with the change that invalidated them: RS6 re-pinned to the strict guidance-implementation boundary (tokens only on
../guidance/import lines — mechanical teeth viaguidanceView), RS8 re-pinned to the ARAHARAH-ROUTE/GUIDE token families (exactly three console lines: two ROUTE tokens + the one deduping GUIDE funnel). - Suite state: web 146 passed / 0 failed (124 pre-existing untouched-green), bot 103, routing 65; web typecheck clean; zero deletions in any of the six plan commits.
Task Commits
- task 1: guidance camera (locked follow) + BackButton full state graph (TDD)
77b62datest(06-06): failing camera-law + PX-01 full-walk gates — RS7b walk, RS11 pose, RS12 unlock, RS13 no-opts byte-identity (RED)2f12c41feat(06-06): the D-10 locked-follow guidance camera + the context-aware BackButton resolver (GREEN)
- task 2: the guidance pump in route.ts — start, effects, chrome, reroute (TDD)
0316be4test(06-06): failing guidance-pump suite G1-G8 + RS6/RS8 re-pins (RED)14e8dfcfeat(06-06): the guidance pump — start gate, effects dispatch, cockpit chrome, silent reroute (GREEN)
- task 3: envelope flows — minimize POST, resume GET, trip-end DELETE + composed ladder (TDD)
6448e31test(06-06): failing envelope-flow suite G9-G12 — minimize POST/resume GET/trip-end DELETE + the composed-ladder gate (RED)d5e104bfeat(06-06): envelope flows + composed ladder — minimize POST, resume GET, trip-end DELETE (GREEN)
Files Created/Modified
web/src/guidance/camera.ts— the D-10 locked-follow camera: the four named pose constants + easeToSnapped/onRerouteApplied over the follow controllerweb/src/map/follow.ts— FollowOptions (padding/pitch/zoom/durationMs) spread over the Phase 3/5 defaults; the re-lock announceweb/src/telegram/backbutton.ts— BackAction + the resolver wire + sync(); legacy shape composed internallyweb/src/route/route.ts— the pump (watch, start gate, effects, chrome re-renders, reroute, teardown), the envelope lifecycle (POST/DELETE/resume-delete), resume(), guidancePhase, backAction, the logGuideState funnelweb/src/guidance/guidance.ts— guidanceView: banner/card/list view data composed from the snapshot (arrive marks name the arrival road)web/src/main.ts— the composed ladder, the guidance deps wiring (hosts/watch/findGantry/onGuidanceChange), the resolver wire + onEvent guards, the ?g= resume boot, the driving-phase camera guard, the recenter re-lock at the guidance poseweb/test/route-surface.test.mjs— RS7b/RS11–RS13 + G1–G12 + E1–E6 + the RS6/RS8 re-pins; fakeMap grew flyTo/on/emit; fakeDeps' follow rides the REAL follow controller
Decisions Made
See key-decisions: the two-pass merged record, RS6's strict form over the plan's call-site allowance, the split BackButton init semantics, the re-lock announce, the arrive mark's arrival-road rule, the resume projection's dual input shape.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Test bug] The committed RED suites pinned machine-false reroute semantics
- Found during: task 2/3 GREEN verification (G4/G6 failed against a machine-true implementation)
- Issue: G4/G6 asserted the reroute origin against the FIRST excursion fix and counted the consult's source.route call as a reroute; G4 expected the REROUTING register to persist after the reroute had applied. The 06-02 machine (replay-pinned R2/R9) sends the request-carrying fix (the one that completed the grace) and lands reroute-applied directly on_route.
- Fix: the origin asserts now pin the request-carrying fix; the call count measures the reroute delta; G4 hangs the request to assert the calm state honestly (and stops the blink so no interval leaks into the runner).
- Files modified: web/test/route-surface.test.mjs
- Commit:
14e8dfc
2. [Rule 1 - Test bug] G5(a) fed a fix with no watch armed; G12 grepped for a UUID where only the validator's pattern source can exist
- Found during: tasks 2/3 GREEN
- Issue: the pending precondition fed the pump before any watch existed (crash); G12's UUID-shaped grep can never match — a character class in source text is the PATTERN, not eight hex characters.
- Fix: G5(a) asserts watchStarted === 0 over a pending consult (the real invariant); G12 greps the validator's pattern source (
[0-9a-f]{8}-…), which is both honest and stronger. - Files modified: web/test/route-surface.test.mjs
- Commit:
d5e104b
3. [Rule 2 - Missing critical functionality] guidanceView's arrive mark rendered the unnamed fallback
- Found during: task 2 GREEN (G6 "the new street reads" expected "Jalan Baru")
- Issue: the arrive step carries no name; the owning-step rule produced an empty street slot, so the banner showed "Unnamed road" for a named arrival road.
- Fix: arrive marks name the ARRIVAL ROAD — the last named step of the route (the road being arrived on); turn marks keep the owning-step rule.
- Files modified: web/src/guidance/guidance.ts
- Commit:
14e8dfc
4. [Rule 3 - Blocking gate] The plan's RS6 re-pin form was superseded mid-flight
- Found during: task 2 planning (the concurrent pass committed the strict import-lines-only form; my looser call-site form was briefly in the working tree)
- Issue: two competing re-pins of the same gate; the strict form initially looked un-implementable (the card view's progressPct field).
- Fix: adopted the strict form and made it implementable by moving ALL view-data composition into guidanceView (guidance family) — route.ts never writes the banned tokens; the looser re-pin was reverted to the committed strict text.
- Files modified: web/test/route-surface.test.mjs (reverted to the committed strict gate), web/src/guidance/guidance.ts
- Commit:
14e8dfc
Session Continuation Note
Two executor passes ran this plan concurrently on the shared tree (the dispatch's "quiet tree" verification did not hold). The passes converged rather than conflicted: each committed its RED/GREEN pairs with the same TDD discipline, adopted the other's coherent committed work as the base of record, and md5-verified files before staging. Pass A (this session) authored task 1 end-to-end, the slim E-suite, the guidanceView arrive-street fix, and this merged record; the interleaved pass authored the G-suite bodies, the pump/resume/envelope GREEN, and two of the four test fixes above. All six commits verified: zero deletions, correct RED→GREEN interleaving per task, 146/146 web + 103 bot + 65 routing green, typecheck clean.
Known Stubs
None. Every export is fully wired: the pump drives the real machine through the real builders; the envelope flows hit the injected fetch with the frozen contract; resume renders from the envelope's own numbers. The cron consumer (plan 07) and the real-drive gate (plan 08) are future consumers of THIS plan's surface, by design.
Threat Surface Scan
No new surface beyond the plan's <threat_model>: exactly three positions ever leave the device (reroute origins on real excursions, the minimize envelope, nothing else) — the envelope POST carries the frozen route snapshot only (T-06-05, G9's six-field pin); console carries only ARAHARAH-ROUTE/GUIDE state tokens with a structural no-coordinate scan (T-06-04, RS8); wa.onEvent wiring rides typeof guards + optional chains (T-06-06, E6); foreign/absent ?g= ids fall through to the honest Phase 4 boot client-side while the claim check holds server-side (06-03's GW7/GW10, unchanged); only originalEvent-bearing moves unlock the camera (T-03-16, RS12). No threat flags.
Issues Encountered
- The concurrent-executor situation documented above required three working windows and md5 verification before every stage; one commit attempt lost the race cleanly (the other pass committed the same content first) and was abandoned without duplication.
- Node lives under nvm; every shell command sourced
~/.nvm/nvm.shfirst (all prior plans' precedent). No project impact. - The committed G4 initially leaked a gantry interval into the runner (a hung request leaves the blink running); the fix stops the blink at the test's end (GS5's law).
User Setup Required
None — no new bindings, no env vars, no deploy in this plan. The envelope flows target the already-deployed /api/guidance surface (06-03); the ladder hits /api/route (06-04) with the fixture fallback keeping token-less boots golden.
Next Phase Readiness
- 06-07 (cron turn-cards): the envelope lifecycle is live end-to-end from the client side — minimize POSTs, foreground/trip-end DELETEs — so the cron's key scan sees exactly the minimized drives. Reuse the resume projection formula (same avg-speed math) for the turn-card progress line.
- 06-08 (real drive): the pump is the drive surface; the capture knobs (
?drive=) plus the ARAHARAH-GUIDE state tokens are the observability plane. The minimize-race belt (keepalive) and the resume path get their first real-world exercise there. - Verifiers: PX-01's full graph is claimed by RS7b + E5 (wire + controller halves); PX-03's wiring by G1/G7/G8; GUID-02's client half by G3–G6; GUID-05/06 by G9–G11 + E3'.
Phase: 06-turn-by-turn-guidance-live-driving Completed: 2026-10-24