| 06-turn-by-turn-guidance-live-driving |
07 |
bot-cron |
| cron-turn-cards |
| scheduled-handler |
| d11-cadence |
| d12-street-bearing |
| d13-honesty |
| kv-write-budget |
| committed-glyphs |
| sharp |
| tdd |
| continuation |
|
| phase |
plan |
provides |
| 06-turn-by-turn-guidance-live-driving |
03 |
the FROZEN envelope service — getGuidanceSession's defensive read (garbage → null, the cron's only read path), mint/delete lifecycle (no key, no push), chat_id minted from the Bearer claim (T-06-02), and GUIDANCE_KEY_PREFIX — now exported as the ONE key-scheme authority the list scan derives from |
|
| phase |
plan |
provides |
| 06-turn-by-turn-guidance-live-driving |
04 |
loadGraph(env) — the EXPORTED isolate-memoized R2 graph loader (the ONLY one the cron may use), and the @araharah/routing workspace primitives the projection imports: classifyTurn, decodePolyline6, deriveCumulativeDistanceM, snapToGraph (with the additive matched-segment nameId), nameAt, haversineM |
|
| phase |
plan |
provides |
| 06-turn-by-turn-guidance-live-driving |
05 |
web/src/guidance/glyphs/*.svg — the committed 8-glyph single source these PNGs rasterize (one geometry, two renderings), plus the strings-module copy-gate pattern the card keys extend |
|
|
| bot/src/guidance/cron.ts — PURE projectTurnCards(envelope, nowSec, streetAt?) → { due, glyph, caption, maneuverIdx }: linear progress projection along the frozen snapshot, first-turn-ahead register with zero-padded index, cadence gate (nowSec % 180 < 60), dead-trip no-card gate, the 4-line HTML caption per UI-SPEC anatomy; PURE makeStreetAt(graph, points) — snapToGraph → SnapResult.nameId → nameAt(nameId), unnamed sentinel → cardStreetUnnamed, snap miss → null; CARD_CADENCE_S = 180 exported |
| bot/src/webhook.ts — the repo's FIRST Cron Trigger: createExportedHandler({ baseFetch }) factory (offline send capture; production default unchanged) + scheduled() wrapping runGuidanceCronTick in ctx.waitUntil — fail-closed unconfigured gate, paginated guidance: KV list (list_complete respected), loadGraph awaited ONCE per tick, per-key try/catch (one bad key or failed send cannot kill the tick), sendPhoto to envelope.chat_id ONLY, zero KV writes |
| bot/wrangler.jsonc — triggers.crons ["*/1 * * * *"]: 60 s scan, card cadence decided in code (D-11's 60–120 s window); kv_namespaces still exactly ONE (GE5) |
| web/public/glyphs/*.png — the 8 committed 256×256 token-colored glyph PNGs (#EB8008 on #1A1A1A full-bleed), rasterized once from the app's SVG sources; served by the Worker's static handler, fetched by sendPhoto |
| routing/scripts/build-glyphs.mjs + `npm run glyphs -w routing` — the maintainer rasterizer (sharp devDependency, collect-then-write, exit 1 with the kind named on any missing/invalid source, SVG sources never rewritten) |
| bot copy keys — the 20 turn-card strings in en + ms verbatim (8 cardAction* street-bearing verbs, 8 cardActionBare* degradation verbs, cardStreetUnnamed, cardEtaTemplate, cardHonesty, cardOpenButton), copy-gate asserted |
|
| 06-08 verification close (the cron smoke leg + the named snap-CPU ratification item) |
| production deploy (the cron arms on `wrangler deploy`) |
| GUID-06 bridge (the card's OPEN button deep-links ?g=<id> into plan 06's boot reader) |
|
| added |
patterns |
| sharp@0.35.5 (routing devDependency — maintainer glyph rasterization only, zero runtime deps) |
|
| Stateless cadence projection: due = nowSec % CARD_CADENCE_S < SCAN_TICK_S — zero cursor keys, zero KV writes (Pitfall 3's 1,000-writes/day free budget; pinned structurally GC-C6 AND behaviorally by a throwing-put fake KV) |
| Street-bearing by DEFAULT via one-authority reconstruction: snapToGraph → SnapResult.nameId → nameAt(nameId) (never the node index); unnamed sentinel → cardStreetUnnamed; graph-absent or snap miss → bare-verb honest absence, the send still fires (D-03) |
| Injectable ExportedHandler: createExportedHandler(opts) — production default export unchanged, offline tests capture sends through the createBot({ baseFetch }) seam (GC-C1's pattern) |
| waitUntil-wrapped tick + per-key try/catch: delivery variance and corrupt records are category-only skips, never tick failures (D-13) |
| PURE-law module split: cron.ts has no console at all (GC8 structural pin); ALL logging lives in webhook.ts's wiring, category-only ([guidance-cron] skipped/failed) |
| Maintainer rasterizer law: committed SVGs are THE single source, recolor in-memory only (currentColor law preserved), collect-then-write with no partial writes |
|
|
| created |
modified |
| bot/src/guidance/cron.ts |
| bot/test/guidance-cron.test.mjs |
| routing/scripts/build-glyphs.mjs |
| web/public/glyphs/{depart,straight,left,right,slight-left,slight-right,uturn,arrive}.png |
|
| bot/src/webhook.ts |
| bot/wrangler.jsonc |
| bot/src/i18n/strings.ts |
| bot/test/commands.test.mjs |
| bot/src/kv/guidance-sessions.ts |
| bot/test/guidance-envelope.test.mjs |
| routing/package.json |
| package-lock.json |
|
|
| Cards are EN (pickLocale's fallback law): the frozen envelope carries no language field (GE2); the ms table stays in parity via the bot copy gate for the day the contract grows a language surface |
| D-12 stands RATIFIED: street-bearing cards by DEFAULT via the shared loadGraph memo; bare-verb street-less ONLY as graph-absent/snap-miss degradation — the one open CPU question (one snap per carded tick) is a named ratification item in 06-08's blocking checkpoint |
| The card's ETA clock is KL wall time (named KL_UTC_OFFSET_S = 8h constant): Malaysia has no DST, v1 is KL-metro only, and the envelope carries no driver timezone |
| The card's OPEN button uses a web_app url with ?g=<id> (web_app buttons carry only a url — the 04-03 mechanism-correction precedent), resuming a killed webview through plan 06's boot reader (GUID-06 bridge) |
|
|
|
12min |
2026-10-24 |