Files
arah2/.planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-03-SUMMARY.md
T

116 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 08-alt-landmark-preprocessing-routing-backend-v2
plan: 03
subsystem: routing
tags: [alt, landmarks, astar, bidirectional, potentials, sentinel, typed-arrays, structural-pins, tdd]
requires:
- phase: 08-alt-landmark-preprocessing-routing-backend-v2 (plan 08-02)
provides: the ARG2 RoadGraph fields (landmarkCount/landmarkQuantumS/landmarkTo/landmarkFrom) the potential consumes, and landmark.ts's table builder the A-suite fixtures flow through
- phase: 06-turn-by-turn-guidance-live-driving
provides: the proven BH skeleton (reductions, balanced alternation, meet probes, stop rule, real-seconds reconstruction) this plan leaves byte-identical, and A1's 625-pair Dijkstra-equivalence seal
provides:
- ALT steering live inside routeAstar — per-search Float64Array(L) constant tables in quanta (0xFFFF → NaN = search-scoped landmark drop), lazy per-node max over the four triangle families with RAW u16 sentinel compares, haversine max-fallback (Pattern 3 containment)
- the A-suite extended to A1–A11 — A9 island sweep (169 pairs, anchors pinned in one component), A10 search-scoped-skip sweep (16 anchorless pairs), A11 structural pin (landmark-table reads in CODE, one sentinel spelling)
- routing/test/rollout.test.mjs — RO1 upload-format-agnostic + RO2 one-decode-path structural pins: the D-01 rollout locks enforced suite-side (T-08-08), not customary
- the optimality seal re-proven under ALT — A1's exhaustive 625-pair Dijkstra-equivalence sweep green with the potentials live
affects: [08-04 (build script landmark stage feeds these tables at KL scale), 08-05 (CPU gate + optimality campaign measures THIS search), docs retirement record (c3 class evidence)]
tech-stack:
added: []
patterns:
- "ALT max-rule: h = max(haversine bound, best triangle bound) — max of two consistent admissible heuristics stays consistent + admissible; sentinel-flooded nodes degrade to exactly the pre-ALT behavior"
- "search-scoped skip law: landmark drop decisions live ONLY in the per-search constant tables (0xFFFF stored as NaN); per-node sentinel cells just skip their ℓ — never a per-node ℓ-mask mid-max (max-of-Lipschitz consistency)"
- "raw-u16-before-float sentinel discipline: `tv === 0xffff` on the Uint16Array read, one spelling (never the decimal), so the sentinel can never masquerade as a finite bound"
key-files:
created:
- routing/test/rollout.test.mjs
modified:
- routing/src/astar.ts (potential() + its init + doc-comments ONLY — every other function pinned)
- routing/test/astar.test.mjs (case index A1–A11, buildIslandFixture helper, A9/A10/A11)
key-decisions:
- "The per-direction ℓ-loop factored into one local `bound()` helper (plan allows executor naming/shape) — the two cache-miss branches mirror through it instead of duplicating the family loop; the pf tail stays byte-identical"
- "A9/A10 written to PASS at RED as baseline-equivalence seals and to stay green as containment seals after the swap (the plan's TDD shape); A11 is the RED gate"
- "A9's anchor set is HAND-PINNED ([0, 8] inside component A) through landmarkTables, never derived — the island precondition (every B cell 0xFFFF in both families) is asserted as a fixture law before the sweep"
patterns-established:
- "Structural pins for rollout locks: RO1/RO2 copy A8's comment-stripping grep shape so a doc mention can never satisfy a format-agnosticism law"
- "Seconds-only equivalence assertions for steering changes (never node-path equality) — D-03's tie law carried into every new case"
requirements-completed: [SC3, SC4]
duration: ~9min
completed: 2026-10-25
---
# Phase 8 Plan 08-03: ALT Potentials + Rollout Pins Summary
**ALT steering is live in routeAstar — h_f/h_b are now max(ALT triangle bounds, haversine) over the ARG2 landmark tables inside the byte-identical BH skeleton, with A1's 625-pair Dijkstra-equivalence sweep re-proving optimality under ALT, dedicated island/skip containment cases, and RO1/RO2 pins locking the upload/router seams format-agnostic (routing 79/79 + bot 126/126 + both typechecks green).**
## Performance
- **Duration:** ~9 min (10:55–11:04 UTC)
- **Started:** 2026-10-25T10:55:12Z
- **Completed:** 2026-10-25T11:04:00Z
- **Tasks:** 2/2 (task 1 with full RED→GREEN gate commits)
- **Files modified:** 3 (1 created, 2 modified)
## Accomplishments
- **The entire runtime change of Phase 8 landed in one function**: `routeAstar`'s `potential()` now derives h_f/h_b from `graph.landmarkTo`/`landmarkFrom`/`landmarkQuantumS` — four per-search constant tables hoisted in quanta (0xFFFF written as NaN drops that landmark for the WHOLE search), then a lazy per-node max over the four triangle families (toward-goal A/B, toward-origin A/B) with RAW u16 sentinel compares before any float conversion, max-combined with the existing haversine bound. The (h_f−h_b)/2 combination, reductions, balanced alternation, meet probes, stop rule, and real-seconds reconstruction are byte-identical — the survey's (πf−πr)/2 is what p_f already was.
- **Optimality re-proven under ALT**: A1's exhaustive 25×25 = 625-pair brute-force Dijkstra-equivalence sweep is green with the potentials live, plus A9 (169-pair island sweep: A-internal pairs with real ALT bounds, B-internal pairs on the haversine fallback, 72 cross pairs → null) and A10 (16 anchorless-component pairs — all families dropped at search scope, still exactly optimal).
- **The D-01 rollout locks are mechanical**: new `rollout.test.mjs` pins upload-road-graph.mjs's KEY/BUCKET + zero format tokens in comment-stripped code (RO1), and worker-router.ts's unchanged GRAPH_KEY + exactly ONE decodeGraph call + no version branch (RO2) — the campaign (08-05) cannot silently grow format awareness (T-08-08 enforced, not customary).
- **Full battery green at the final commit**: routing:test 79/79 (A1 seal + A9/A10/A11 + RO1/RO2 + untouched L/G/A/P/R/S suites), bot 126/126 — the FIRST commit where the RT trunks and guidance-cron run with ALT potentials reading real tables on their ARG2 corridor graphs — and routing+bot typechecks clean. `git diff --stat` on worker-router.ts and upload-road-graph.mjs is empty.
## Task Commits
Each task was committed atomically (task 1 carried its RED→GREEN gates):
1. **task 1: ALT potentials in routeAstar + the containment A-cases** — `92b97fc` (test, RED: A11 failing for the right reason, A9/A10 baseline-equivalent) → `ddd2f3c` (feat, GREEN)
2. **task 2: Rollout pins (RO1/RO2) + the full-battery seal** — `8fac68b` (test)
## Files Created/Modified
- `routing/src/astar.ts` — ALT per-search constant tables + `bound()` helper + `potential()` swap + ALT doc paragraphs (module header + routeAstar BH block; Ikeda history intact); NO other function touched, no new imports
- `routing/test/astar.test.mjs` — case index A1–A8 → A1–A11; `buildIslandFixture` (two-component synthetic whose tables flow through the ONE landmark module); A9 island sweep, A10 search-scoped-skip sweep, A11 structural pin (landmark tokens in comment-stripped CODE, one sentinel spelling, A8's no-Map law unchanged)
- `routing/test/rollout.test.mjs` — created: RO1/RO2 structural pins in the harness's zero-dep shape
## Decisions Made
- **One `bound()` helper instead of a duplicated ℓ-loop**: the plan's sketch marks shape/naming as the executor's; both cache-miss branches mirror through the same allocation-free loop, keeping the family logic in exactly one place while the `const value = (hf - hb) / 2` tail stays byte-identical.
- **A9/A10 pass at RED by design**: they assert seconds-only Dijkstra equivalence, which the pre-ALT haversine implementation already satisfies — they are baseline-equivalence at RED and containment seals at GREEN; A11 (structural) is the RED gate and fails for exactly the right reason ("must reference landmarkTo in code").
- **Fixture anchors pinned, not derived**: `buildIslandFixture(anchors)` takes the anchor array and routes it through `landmarkTables` — the island precondition (every component-B cell is the 0xFFFF sentinel in both families) is asserted as a fixture law inside A9 before any routing assertion.
## Deviations from Plan
None - plan executed exactly as written. (One in-task compliance edit: the GREEN comment initially cited the sentinel's decimal value; the plan's own acceptance grep `65535 = 0` caught it before the commit — reworded, no behavior change, contained in `ddd2f3c`.)
## TDD Gate Compliance
Task 1 ran full RED→GREEN with separate commits: `92b97fc` (test — A11 FAIL verified for the right reason, 76/77 passing) BEFORE `ddd2f3c` (feat — 77/77). No gate skipped; no refactor commit needed (the swap landed clean).
## Issues Encountered
- None beyond the in-task comment reword above. The full battery passed on its first run after each gate.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- **08-04 (build script):** the preprocessing stage now has its live consumer — `build-road-graph.mjs` still encodes WITHOUT landmarks until its stage lands; once it emits ARG2 the real binary steers with these exact potentials.
- **08-05 (campaign):** the search-side surface is final; the CPU gate (p95 ≤ 8) and the D-03 optimality gate measure THIS code. The D-02 remediation knob (raise L, rebuild) touches build parameters only — the reductions/stop rule are pinned untouched by A1/A8/A11 and RO1/RO2.
- **Known state:** the real KL binary on disk is still ARG1 → decodes null → router-pending (designed, D-01) until 08-04/08-05 rebuild + re-upload; the committed fixtures all carry tables, so every suite surface runs ALT live.
---
*Phase: 08-alt-landmark-preprocessing-routing-backend-v2*
*Completed: 2026-10-25*
## Self-Check: PASSED
All 3 claimed files exist on disk; all 3 task commits (`92b97fc`, `ddd2f3c`, `8fac68b`) exist in git history. Final battery at `8fac68b`: routing:test 79/79, bot 126/126, routing:typecheck + bot:typecheck clean; `git diff --stat bot/src/routing/worker-router.ts routing/scripts/upload-road-graph.mjs` empty.