From 48627d4102dd6bbe2a45dfb8fd8a9be2558d0bb7 Mon Sep 17 00:00:00 2001 From: araharah-executor Date: Sat, 24 Oct 2026 05:10:36 +0800 Subject: [PATCH] docs(05-03): complete guidance-session contract freeze plan --- .../05-routing-route-display/05-03-SUMMARY.md | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 .planning/phases/05-routing-route-display/05-03-SUMMARY.md diff --git a/.planning/phases/05-routing-route-display/05-03-SUMMARY.md b/.planning/phases/05-routing-route-display/05-03-SUMMARY.md new file mode 100644 index 0000000..a35532c --- /dev/null +++ b/.planning/phases/05-routing-route-display/05-03-SUMMARY.md @@ -0,0 +1,131 @@ +--- +phase: 05-routing-route-display +plan: 03 +subsystem: bot +tags: [kv, types-only-contract, guidance-sessions, ttl, envelope, privacy, tdd, source-introspection] + +# Dependency graph +requires: + - phase: 05-routing-route-display + plan: 01 + provides: the polyline6 storage format the snapshot's geometry field cites by name (routing workspace, 05-01) and the RouteResult summary fields (distanceM/durationS) the snapshot headlines + - phase: 03-mini-app-shell-geolocation + provides: the SessionClaim field-freeze law (bot/src/kv/sessions.ts "a 5th property means drift") and the location-pin TTL precedent (bot/src/kv/location-pin.ts) D-07 aligns with +provides: + - "GuidanceSessionEnvelope — the frozen Phase 6 contract: EXACTLY [id, chat_id, route_snapshot, created_at]" + - "GuidanceRouteSnapshot — the INLINE route record (D-07): destinationId/Name, distanceM/durationS, polyline6 geometry, startedAtSec" + - "GUIDANCE_SESSION_TTL_SECONDS = 7200 — the ~2h TTL as a documented constant awaiting its Phase 6 consumer" + - "guidance: key-scheme documentation in the module header" + - "GE1–GE7 — seven mechanical gates pinning the types-only boundary (field freeze, inline snapshot, TTL value, no runtime behavior, no new namespace, no Env field, no premature consumer)" +affects: [phase-6 guidance turn-card service, bot privacy gates] + +# Tech tracking +tech-stack: + added: [] # zero dependencies — a types-only module + patterns: + - "Types-only frozen contract: interface + TTL constant + key-scheme doc, with source-introspection gates proving no runtime shadow (extends the privacy.test.mjs grep-gate family)" + - "Negative-space boundary gates: guards over files that must NOT change are green by construction and redden only on drift (05-01 C4/C5/C6 precedent)" + +key-files: + created: + - bot/src/kv/guidance-sessions.ts + - bot/test/guidance-envelope.test.mjs + modified: [] # zero existing files touched + +key-decisions: + - "Module header says 'No KV binding' instead of naming the KVNamespace type — the plan's own acceptance gate requires that token to appear NOWHERE in the file, comments included (grep -rc = 0); same law, gate-clean wording" + - "GE5–GE7 (no new namespace / no Env field / no consumer) are RED-green-by-construction boundary guards: they scan files that must NOT change, so they pass before and after this plan and redden only on future drift — documented in the suite header per the 05-01 C4/C5/C6 precedent" + +patterns-established: + - "Contract-freeze gate naming: GE* gates live in the consuming workspace's test dir and lazy-import the contract module so a missing module is a per-case RED, not a suite load failure" + - "Phase-6 handoff note in gate doc-comments: when the service legitimately adds the binding/field/consumer, updating GE4–GE7 is THAT plan's responsibility" + +requirements-completed: [] # plan frontmatter requirements: [] — the GUID-05/06 upstream obligation, not a tracked requirement ID + +# Metrics +duration: 5min +completed: 2026-10-23 +--- + +# Phase 5 Plan 3: Guidance-Session Contract Freeze (Types-Only) Summary + +**The `guidance_sessions` envelope frozen as a types-only Phase 6 contract — 4-field envelope + inline 6-field route snapshot (D-07: one key, one TTL) + the 7200 s TTL constant + `guidance:` key scheme, with zero runtime behavior and seven GE gates proving the boundary mechanically.** + +## Performance + +- **Duration:** 5 min +- **Started:** 2026-10-23T21:05:12Z +- **Completed:** 2026-10-23T21:09:35Z +- **Tasks:** 1/1 (TDD RED→GREEN) +- **Files modified:** 2 (both created; zero existing files touched) + +## Accomplishments + +- **The Phase 6 contract exists in code** (D-06): `GuidanceSessionEnvelope` (EXACTLY `id`, `chat_id`, `route_snapshot`, `created_at` — the SessionClaim field-freeze law) and `GuidanceRouteSnapshot` (EXACTLY `destinationId`, `destinationName`, `distanceM`, `durationS`, `geometry`, `startedAtSec`), the `guidance:` key scheme, and `GUIDANCE_SESSION_TTL_SECONDS = 7200` — pinned by GE1/GE2 so drift reddens the suite. +- **D-07 is mechanical, not aspirational**: `route_snapshot: GuidanceRouteSnapshot` is typed INLINE (GE3), the tokens `snapshotRef`/`snapshot_ref` are banned across all of `bot/src`, and the TTL law means one key, one expiry — nothing outlives 2h, nothing is reconstructable after expiry. +- **The types-only boundary cannot leak this phase** (T-05-08): GE4 comment-strips the module and bans every behavior token (KV binding type, `.put(`, `.get(`, `.delete(`, function exports, imports); GE5 pins wrangler.jsonc to EXACTLY ONE kv namespace (`chat_sessions`); GE6 pins `Env` free of any guidance field; GE7 bans any `bot/src` import of the module — no runtime shadow, no premature consumer. +- **Zero existing bot files modified**: `wrangler.jsonc` and `config.ts` are untouched; the full bot suite is green at 72/72 (65 pre-existing + 7 GE gates) and `bot:typecheck` exits 0 (the module sits inside the bot tsconfig's `include: ["src"]`). + +## Task Commits + +Each gate of the TDD cycle was committed atomically: + +1. **task 1: the frozen envelope types + the types-only gate suite** + - `0b8671e` test(05-03): add failing guidance-envelope types-only gates (GE1-GE7) (RED) + - `d5c2bc0` feat(05-03): freeze guidance_sessions envelope as types-only contract (GREEN) + +**Plan metadata:** committed separately (docs, force-added — `.planning/` is gitignored) + +## TDD Gate Compliance + +- RED gate: `0b8671e` — GE1–GE4 fail on the absent module (ERR_MODULE_NOT_FOUND / ENOENT, verified as the exact failure modes); GE5–GE7 pass as documented green-by-construction boundary guards. +- GREEN gate: `d5c2bc0` — 72/72 pass, typecheck exit 0. +- REFACTOR gate: not needed — 58 lines of pure types + one constant; nothing to clean. + +## Files Created/Modified + +- `bot/src/kv/guidance-sessions.ts` — the frozen contract: module header (types-only law, D-06/D-07 citations, `guidance:` key scheme), `GUIDANCE_SESSION_TTL_SECONDS = 7200`, `GuidanceRouteSnapshot` (6 fields), `GuidanceSessionEnvelope` (4 fields). No imports, no functions, no class. +- `bot/test/guidance-envelope.test.mjs` — GE1–GE7: TTL constant value; interface-body field-freeze regex (`^\s{2}\w+:` between `interface X {` and `\n}`); inline-snapshot type + repo-wide ref-token ban; comment-stripped behavior-token ban (the routing C4 `stripComments` pattern); comment-stripped JSON.parse of wrangler.jsonc; config.ts token ban; import-statement ban across the recursive `bot/src` tree. + +## Decisions Made + +- **Header wording: "No KV binding" instead of the KVNamespace type name** — the plan's `` header template contains that literal token, but the plan's own acceptance criterion requires `grep -rc 'KvNamespace'` to return 0 with "the word never appears" (comments included). The mechanical gate wins; the law stated is identical. +- **GE5–GE7 declared green-by-construction in the RED commit** — they are negative-space guards over files that must NOT change, so they cannot fail while the boundary holds (their RED state is vacuous). Mirrors 05-01's C4/C5/C6 zero-laws precedent; documented in both the suite header and the RED commit message. + +## Deviations from Plan + +None — plan executed exactly as written. The two items above are judgment calls inside the plan's own acceptance gates, documented for the verifier. + +## Known Stubs + +None — the module ships types + one constant by design (D-06); nothing flows to UI, nothing consumes it at runtime (GE7 pins that). Phase 6 builds the service on this frozen shape. + +## Threat Surface Scan + +No new surface beyond the plan's ``: no endpoints, no auth paths, no file access, no schema at a trust boundary — the module has zero runtime behavior. All three register entries have implemented, gate-covered mitigations: T-05-08 (premature persistence → GE4/GE5/GE6/GE7), T-05-08b (retention → GE1 + GE3 inline snapshot), T-05-08c (contract drift → GE2 exact field sets). No threat flags. + +## Issues Encountered + +- Pre-existing uncommitted working-tree changes to `bot/test/cari.test.mjs` and `bot/test/commands.test.mjs` (a prior session's register-commands scope-shadow fix pins) were present at start. Baseline verified green WITH them (65/65) before any of my commits; they were left untouched and excluded from every commit. Out of scope per the plan-boundary rule. +- Node lives under nvm in this environment — verification commands sourced `~/.nvm/nvm.sh` first (the 05-01 precedent). No project impact. + +## User Setup Required + +None — no external service configuration required. The module ships no behavior; nothing deploys. + +## Next Phase Readiness + +- **Phase 6 (backgrounded turn-card service)**: consumes `GuidanceSessionEnvelope` / `GuidanceRouteSnapshot` / `GUIDANCE_SESSION_TTL_SECONDS` / the `guidance:` key scheme verbatim — the shape cannot have drifted (GE1/GE2 pin it). Phase 6's plan owns: the KV namespace binding + Env field (relaxing GE5/GE6), the consumer import (relaxing GE7), and extending the PG1 same-line-`expirationTtl` grep gate to `guidance:` writes. +- **Phase 5 remaining plans**: none depend on this module (depends_on: [], wave: 1); 05-04/05-05 web-side work is unaffected. + +--- +*Phase: 05-routing-route-display* +*Completed: 2026-10-23* + +## Self-Check: PASSED + +- All 2 created files verified present on disk (guidance-sessions.ts, guidance-envelope.test.mjs). +- Both plan commits verified in git log (0b8671e RED, d5c2bc0 GREEN). +- `npm test -w bot`: 72 passed, 0 failed (PASS GE1…GE7 + all 65 pre-existing cases). `npm run bot:typecheck`: exit 0. +- All seven acceptance greps pass on the module (envelope iface, snapshot iface, TTL const, key scheme, KvNamespace count = 0, inline snapshot). +- Zero existing files modified by this plan; STATE.md and ROADMAP.md untouched (orchestrator-owned writes).