- BA9/BA10 + BA5 sentinel extension, five ?fixpair-raced capture legs (13/13), RP1/RP2 Worker privacy gates - two Rule-1 boot fixes (onLoad wiring + consult-after-load) documented - STATE.md and ROADMAP.md untouched (orchestrator-owned)
16 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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-routing-route-display | 05 | verification-gates |
|
|
|
|
|
|
|
|
|
19min | 2026-10-23 |
Phase 5 Plan 5: Verification Gates — BA9/BA10 + Route Capture Legs + Worker Privacy Gates Summary
The phase closes on mechanical proof: BA9 prints the route payload at 35,076 / 204,800 gz bytes and BA10 proves every committed pairId rides the shipped bundle, five new capture legs race the ARAHARAH-ROUTE state token through the new ?fixpair knob (13/13 non-blank, the orange line verified painted), and RP1/RP2 gate the Worker out of the routing path — the amended SC3's "bundle-size and type gates holding" is now read from gate output, not memory.
Performance
- Duration: 19 min
- Started: 2026-10-23T21:44:12Z
- Completed: 2026-10-23T22:03:31Z
- Tasks: 3/3
- Files touched: 7 (2 created, 5 modified)
Accomplishments
- D-11 is a gate, not a hope: BA9 sums
gzipSyncover the fixtures dataset + everyrouting/src*.ts + everyweb/src/route*.ts (production-shaped by construction), asserts ≤ 204800 bytes, and PRINTSBA9 route bundle budget: 35076 / 204800 gz byteson every run — the failure message carries the measurement and the overshoot. BA10 (the BA7 analog) asserts every one of the 15 committed pairIds appears in the concatenatedweb/dist/assets/*.js— a stale bundle that lost the fixtures is unshippable. BA5's harness-leak scan gainedROUTE_PROFILE_HARNESS_ONLY; the production build provably excludes the module (0 occurrences in web/dist — theif (__ARAHARAH_HARNESS__)dynamic import dead-code-eliminates, verified by grep after build). - The five route capture legs pass against the production-shaped harness bundle (8 → 13 expected artifacts): fixture (state=drawn + destination name + MIN + 2000ms tile settle), alt (first
.route-chiptap →/ROUTE \d\/\d/register — ROUTE 2/2, +1 MIN VS ROUTE 1 verified in the shot), pending (state=pending+ "not wired up yet" — the honest D-03 card with the privacy clause, never a fabricated geometry), dark (PX-02 theme-slot honesty check — chrome re-slots, orange route + grayscale basemap Rams-constant), and the DSGN-02 route-gallery-compare besidenavigate_map_overview/screen.png. All legs are data-driven:demoPairis picked at runtime from the committed corpus, and the destination name is read from the gazetteer at capture time. - The ?fixpair knob closes the coordinate surface it opens:
?fixpair=<pair-id>resolves throughgetRouteProfileOrigin→getPairOrigin— the ONLY origin source is the committed public corpus (D-12); a?lat/?lngknob is deliberately absent (T-05-14). Unknown pairId keeps the default fix — the boot never wedges. - D-05 is mechanically gated: RP1 (zero
/api/route,registerRoute,routeProxyin comment-stripped bot/src) and RP2 (zero@araharah/routingimports) — the Worker cannot route even accidentally. Teeth-proven: a planted violating file fails both gates; removed, the bot suite runs 74/0. - Two real bugs found and fixed by the new legs (the plan's stated purpose for them): see Deviations.
Task Commits
- task 1: BA9 + BA10 + BA5 sentinel extension (gate file over already-shipped artifacts — no failing RED exists; mechanism teeth proven by a bogus-pairId probe returning false on the real bundle)
29ad451test(05-05): BA9 bundle-budget + BA10 fixture-parity gates + BA5 harness-sentinel extension
- task 2: ?fixpair knob + five route capture legs (strict RED→GREEN)
c9b1128test(05-05): add five route capture legs racing ARAHARAH-ROUTE (RED) — the drawn legs failed exactly as predicted (default fix outside the demo pair's 200 m tolerance → state=pending)af744e4feat(05-05): ?fixpair harness knob + pinned-corpus origin lookup (GREEN) — includes the two Rule-1 boot fixes below
- task 3: Worker-side no-route-proxy gates (gates over a clean tree; RED = planted-violation teeth proof)
6302901test(05-05): Worker no-route-proxy gates RP1+RP2 (D-05)
Files Created/Modified
web/test/build-artifact.test.mjs— BA9 (measured, printed, budget-gated), BA10 (pairId parity withpairs.length >= 10real-dataset guard), BA5 token list + header inventoryweb/scripts/capture.mjs—ARAHARAH-ROUTEin SIGNALS/seen-map/diagnostics;waitMode: "route"(30s race, state= parse, expectText DOM polls, PX-02 honesty check, 2s settle);interact(page)pre-shot hook; the five legs;composeCompareshared composer; 13-artifact missing/undersized/failures gateweb/index.html—?fixpairknob inside the harness block (dynamic import of the profile module; knob documented in the profile comment line)web/src/mock/route-profiles.ts— HARNESS-ONLY module: sentinel +getRouteProfileOrigin; D-12 + BA-exclusion headerweb/src/main.ts— [Rule 1]bootMap(..., { onLoad: (m) => installRouteLayers(...) })+ themapLayersReadygate ahead of the auto-consultweb/test/route-surface.test.mjs— RS2 boot-wiring gate (the composition-root wiring the fakes could not see)bot/test/route-privacy.test.mjs— RP1/RP2 structural gates over bot/src
Decisions Made
- BA9 approximates minified gz with source gz — conservative in the gate's favor at these sizes; documented in the gate's comment per the plan.
- demoPair picked at runtime, destination name read from the gazetteer at capture time — the legs track the dataset instead of hardcoding literals (the capture_contract's own snippet).
- mapLayersReady resolves in
finally— an install failure must degrade to "no route drawn", never wedge the consult (the RS4 exception-path law applied to the boot gate). - RS2 boot-wiring gate added to the web suite (a file outside the plan's
files_modified) — Rule 1's "add a test if applicable" clause: the missing-callback bug was invisible to every fake-driven gate, so the wiring itself is now grep-pinned.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] main.ts never passed bootMap's opts.onLoad — the route line never painted
- Found during: task 2 (first GREEN capture run: card + pin + camera all rendered, zero orange on the map)
- Issue:
bootMap(document.getElementById("map")!)was called without the onLoad callback, soinstallRouteLayersnever ran in the real boot;setRouteDrawn'sgetSource(...)?.setData(...)silently no-op'd. Invisible to RS3/RS4 (recording fakes) and RS2 (map.ts textual position only). - Fix: wire
onLoad: (m) => installRouteLayers(m as unknown as MapLike); add the RS2 boot-wiring gate pinning it. - Files modified: web/src/main.ts, web/test/route-surface.test.mjs
- Commit:
af744e4
2. [Rule 1 - Bug] route consult raced the map load — the draw landed on sources that did not exist yet
- Found during: task 2 (after fix 1 the line STILL didn't paint; a headless probe showed
ARAHARAH-ROUTE state=drawnfiring BEFORERAMS-BASEMAP-READY layers=115) - Issue: the harness session stubs resolve the location chain faster than WebGL/style init, so consult + setData ran before the load handler installed (empty) sources — the drawn data was discarded. The 05-04 assumption "the load hook precedes the location chain" is false under stubbed session latency (and plausible in production on fast networks).
- Fix:
mapLayersReadypromise resolved in the load handler afterinstallRouteLayers(finally-resolved — install failure degrades, never wedges; cards-only boots resolve immediately); the auto-consult awaits it. Probe after: READY precedes ROUTE, and the orange line paints (verified in all three drawn captures). - Files modified: web/src/main.ts
- Commit:
af744e4
Judgment calls within plan laws (not deviations)
- Task 1 and task 3 gate artifacts that already hold (fixtures shipped in 05-02/05-04; the Worker tree is clean) — a failing RED run does not exist for them; both were teeth-proven instead (bogus-pairId probe for BA10's mechanism; planted violating file for RP1/RP2). Task 2's RED is genuine.
- The plan's inline
resolve(REPOROOT, ..., "utf8")snippet misplaced a paren; implemented with the intended semantics (utf8 read of the resolved path).
TDD Gate Compliance
- task 2 is the plan's real RED→GREEN:
c9b1128(legs fail: 3× state mismatch + missing gallery input, exit 1) →af744e4(13/13). The GREEN commit also carries the two Rule-1 fixes the RED run exposed. - tasks 1 and 3 carry
tdd="true"but gate already-true invariants (the plan frontmatter istype: execute, so no plan-level RED/GREEN ladder applies). Teeth were demonstrated without polluting the tree: BA10'sincludes()discriminates on the real bundle (bogus pairId absent); RP1/RP2 fail against a planted violation and pass on the clean tree. No fake RED commits were made.
Known Stubs
None. The ?fixpair knob, the five legs, and both gate files are fully wired to committed data. (web/screenshots/* are regenerated gitignored artifacts by design — the capture harness's own contract.)
Threat Surface Scan
No new surface beyond the plan's <threat_model>: the knob accepts pairIds only and resolves them exclusively through the committed public corpus (T-05-14 mitigated, runtime-proven by the pending leg); BA9 gives T-05-12 its build-gate tier (35 KB measured vs 204,800 allowed); the BA5 sentinel extension enforces T-05-15 (0 sentinel occurrences in web/dist); RP1/RP2 enforce T-05-16 (0 banned tokens in bot/src). The capture signals carry state tokens only — no coordinates in any console line (D-15). No threat flags.
Issues Encountered
- Node lives under nvm; non-interactive shells need
source ~/.nvm/nvm.shfirst (all prior 05-xx plans noted the same). No project impact. - A block-comment in the first draft of route-privacy.test.mjs terminated early on a
*/insidebot/src/**/*.ts— caught by the suite loader as a syntax error, fixed by rewording. No gate semantics changed. - Playwright's ESM resolution fails from /tmp scripts; the debug probe imported it by absolute path. The probe script lived outside the repo and was never committed.
User Setup Required
None — no external service configuration. The captures run against the committed corpus and local builds; tiles come from the existing OpenFreeMap runtime fetch.
Next Phase Readiness
- Phase verification / the amended SC3 evidence chain is complete: RT1–RT10 (corpus routes cleanly, corpus gate PASS) + BA9/BA10 (bundle-size gate, measurement printed) + the 05-01 C2 type gates + the pending capture (deliberate, designed) — all four clauses have a green instrument.
- Phase 6 (guidance): the route state machine is now visually verified against the production bundle; the painted-route boot ordering (consult-after-load) is the exact precondition guidance's turn-card flow inherits; the capture harness's state-token race pattern extends to guidance signals.
- Verifier hooks: BA1–BA10, RS1–RS10 (+ boot-wiring), COPY gates, RT1–RT10, RP1/RP2, and the 13-leg capture gate are all mechanical.
Phase: 05-routing-route-display Completed: 2026-10-23
Self-Check: PASSED
- All created files verified present on disk (web/src/mock/route-profiles.ts, bot/test/route-privacy.test.mjs); all modified files verified in the commits.
- All 4 plan commits verified in git log:
29ad451,c9b1128,af744e4,6302901(task 2 strict RED→GREEN). npm test -w web: 76 passed, 0 failed — output containsPASS BA9,PASS BA10,BA9 route bundle budget: 35076 / 204800 gz bytes.npm run web:capture: exit 0,CAPTURE OK — 13/13 non-blank captures; the five new artifacts exist; the orange line visually verified in fixture/alt/dark shots; the pending card honest.npm test -w bot: 74 passed, 0 failed —PASS RP1,PASS RP2; tree greps for/api/routeand@araharah/routingin bot/src both return 0.npm run routing:test35/0;npm run routing:corpusPASS (gz 16,576 B; multi-route 8 / floor 4); web/bot/routing typechecks exit 0.- STATE.md and ROADMAP.md untouched (orchestrator-owned writes); only 05-05-SUMMARY.md added (force-add, .planning/ ignored).