Files
arah2/.planning/phases/05-routing-route-display/05-02-SUMMARY.md
T

13 KiB
Raw Blame History

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions requirements-completed duration completed
05-routing-route-display 02 routing
routing
fixtures
osrm-demo
polyline6
corpus-gate
offline-gate
golden-pairs
tdd
odbl
phase provides
05-routing-route-display/01 the routing workspace — polyline6 codec (decode/encode round-trip law), haversineM, createFixtureRoutingSource/getPairOrigin/getPairs, the committed empty route-fixtures.json seed schema, the 200 m origin-tolerance matching law
phase provides
04-destination-search-kl-gazetteer the KL gazetteer (search/src/data/kl-gazetteer.json) — the destinationId namespace and the public landmark coordinates the D-12 proof keys off
committed 15-pair fixture dataset (routing/src/data/route-fixtures.json) — real OSRM-demo geometry, 1–3 verbatim polyline6 routes per pair, 8 pairs with ≥ 2 alternates
routing/test/fixtures/golden-pairs.json — the hand-authored pinned corpus (pairIds = the ?fixpair= knob namespace for 05-05; klBbox, 100 KB gz budget, probe id, alternatives floor)
routing/scripts/fetch-route-fixtures.mjs — the maintainer build-time tool (overpass-topup.mjs pattern): D-12 boundary header, pre-flight public-coordinate proof, mandatory UA, 1200 ms delay, collect-then-write, --only=<pairId> repair merge
routing/scripts/route-corpus.mjs — measurePairs() measurement core + CLI reporter; the RT1–RT10 offline tolerance gate
routing/test/corpus.test.mjs — the in-suite Nyquist gate asserting the same measurements (npm run routing:test)
root npm delegate routing:fixtures; routing workspace fixtures/corpus scripts
05-04 web route surface
05-05 gates (?fixpair= + BA9 budget)
phase-6 guidance
added patterns
build-time fixture precompute: committed snapshot makes a free best-effort demo server safe (a policy change breaks the regeneration script, never the product)
mechanical privacy proof: RT2b joins the committed dataset to the gazetteer within 1e-4 deg — 'public data between public places' enforced by test, not by promise
one measurement, two reporters: exported measurePairs consumed by both the CLI and the in-suite gate (gazetteer-corpus.mjs precedent)
collect-then-write regeneration: any per-pair hard failure leaves the committed file untouched; --only repairs one pair without churning fourteen
created modified
routing/test/fixtures/golden-pairs.json
routing/scripts/fetch-route-fixtures.mjs
routing/scripts/route-corpus.mjs
routing/test/corpus.test.mjs
routing/src/data/route-fixtures.json (empty seed → 15 real OSRM-demo pairs)
package.json (routing:fixtures delegate)
routing/package.json (fixtures + corpus scripts)
routing/test/loader-env.test.mjs (L3 armed
serves pair 1 / honest null at 300 m)
routing/test/contract.test.mjs (C6 re-pinned from empty-seed to populated-corpus state)
C6 re-arm: 05-01's contract test pinned the seed as EMPTY with the message 'plan 05-02's build-time script populates it' — the same documented handoff as L3, re-pinned to the populated state (10..20 pairs) with the ODbL header assertions unchanged
measurePairs takes an OPTIONAL 4th parameter (fixturesPath, default = the committed dataset URL relative to the script) so RT9 gzips the COMMITTED file per the RT9 spec while the plan's 3-arg call shape still works for both reporters
alternatives=2 is best-effort at the demo server: 7 of 15 pairs returned a single route; 8 pairs carry 2 routes — comfortably above the RT10 floor of 4, and alternatives floor data is real, not padded
the fetch script validates the ENTIRE corpus pre-flight (nothing leaves the machine unless every pair is proven public) rather than validating per-pair lazily — the strongest reading of D-12
RTNG-01
RTNG-02
9min 2026-10-23

Phase 5 Plan 2: Fixture Corpus — Golden Pairs + OSRM-Demo Precompute + Offline Tolerance Gate Summary

The fixture corpus is REAL: 15 pinned KL pairs precomputed from the public OSRM demo server (23 verbatim polyline6 routes, 8 with alternates), pinned behind the RT1–RT10 offline tolerance gate — CLI and in-suite reporters green, the D-12 "public data between public places" law mechanically proven against the gazetteer, 16.6 KB gzipped against the 100 KB early-warning budget.

Performance

  • Duration: 9 min
  • Started: 2026-10-23T21:11:43Z
  • Completed: 2026-10-23T21:20:27Z
  • Tasks: 2/2
  • Files touched: 9 (4 created, 5 modified)

Accomplishments

  • The data product exists (D-02): routing/src/data/route-fixtures.json carries 15 golden pairs — 5.2 km KL Tower→KL Sentral to 23.1 km Mid Valley→IOI City Mall — each with 1–3 best-first routes stored as VERBATIM polyline6 strings from the OSRM demo (alternatives=2&overview=full&geometries=polyline6), ODbL header fields preserved (T-05-06). The 05-01 empty seed is resolved.
  • The maintainer tool follows the repo-tool law (D-12): fetch-route-fixtures.mjs documents the maintainer-machine boundary verbatim in its header, validates the whole corpus against the gazetteer BEFORE any request leaves the machine (origin ≡ landmark within 1e-4 deg, destination known), sends a mandatory descriptive User-Agent, spaces requests 1200 ms apart, retries once on network/5xx, and writes only on total success (collect-then-write); --only=<pairId> repairs one pair without churning the rest.
  • The phase's primary acceptance instrument is armed (amended SC3): measurePairs() performs RT1–RT10 fully OFFLINE — corpus size, schema + RT2b public-origin proof, route shape, probe exclusion, haversine↔summary band [0.85, 1.10] + bbox+0.05 deg, speed sanity [1.0, 30] m/s, codec round-trip per route, ODbL header surfaces, gz budget (measured 16,576 B / 102,400 B), alternatives floor (8 multi-route pairs / floor 4). The CLI (npm run routing:corpus) and the suite (npm run routing:test) assert the SAME numbers.
  • 05-01's deferred gates armed themselves exactly as designed: loader-env L3 now proves the default source serves pair 1 at its pinned origin and resolves honest null ~300 m away; F8's positive half runs its assertions now that pairs exist; C6 re-pinned from the empty-seed state to the populated corpus.
  • Suite state: 35 passed, 0 failed (C1–C6, F1–F8, L1–L3, P1–P8, RT1–RT10); npm run routing:typecheck exit 0; zero fetch( occurrences in the gate (only the maintainer tool touches the network).

Task Commits

Each task followed RED→GREEN with atomic commits:

  1. task 1: pinned golden-pairs corpus + fetch script + populated committed dataset
    • 01b0ed6 test(05-02): tighten loader-env L3 to require pair 1 serving at pinned origin (RED)
    • 4e89cff feat(05-02): pinned golden-pair corpus + OSRM-demo fetch tool + populated committed dataset (GREEN)
  2. task 2: the offline corpus tolerance gate (CLI + in-suite Nyquist gate)
    • 63ef408 test(05-02): add failing offline corpus tolerance gate suite RT1-RT10 (RED)
    • 6c0880b feat(05-02): offline corpus tolerance gate — measurePairs core + CLI + in-suite RT1-RT10 (GREEN)

Files Created/Modified

  • routing/test/fixtures/golden-pairs.json — the 15-pair pinned corpus verbatim from the plan (pairId, originId, pinned origin + label, destinationId), plus klBbox, fixtureGzipBudgetBytes (102400), pendingProbeDestinationId (national-museum), alternativesFloorPairs (4)
  • routing/scripts/fetch-route-fixtures.mjs — the build-time tool: pre-flight D-12 proof, UA araharah-fixtures/1.0, 1200 ms delay, one retry, hard-fail diagnostics naming the pair, 2-space JSON + trailing newline, header fields preserved from the committed file
  • routing/src/data/route-fixtures.json — 15 pairs / 23 routes committed (was pairs: [])
  • routing/scripts/route-corpus.mjs — measurePairs(corpus, fixtures, gazetteer, fixturesPath?) + CLI with per-check table, measured gz size, fixed escalation ladder (--only repair → regenerate → re-gate); imports decode/encode/haversine from ../src/index.ts; direct-invocation guard
  • routing/test/corpus.test.mjs — one test() per RT check asserting violations.length === 0 with named messages; prints gz size + multi-route count so suite output and CLI output agree
  • routing/test/loader-env.test.mjs — L3 armed (RED commit); header comment updated
  • routing/test/contract.test.mjs — C6 re-pinned to populated corpus (10..20 pairs), ODbL assertions unchanged
  • package.json — "routing:fixtures" delegate
  • routing/package.json — "fixtures" + "corpus" scripts

Decisions Made

  • C6 re-arm (05-01 documented the handoff on the test itself: "the seed ships EMPTY — plan 05-02's build-time script populates it"): the empty-state pin became a populated-state pin (10..20 pairs); the ODbL header gate (T-05-06) is unchanged. Same category as the plan-ordered L3 update.
  • Optional 4th fixturesPath parameter on measurePairs — RT9's spec gzips the committed file; the default (dataset URL relative to the script) keeps the plan's 3-arg signature valid at both call sites.
  • Whole-corpus pre-flight validation in the fetch script — nothing is sent until every pair is proven public, the strongest reading of D-12's red line.
  • No padding of alternates — the demo server returned 1 route for 7 pairs; the floor is met by 8 genuine multi-route pairs. Fabricating extra routes would poison RT5/RT7.

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Stale state pin] C6 empty-seed assertion re-armed to the populated corpus

  • Found during: task 1 GREEN verification
  • Issue: 05-01's contract.test.mjs C6 asserted pairs.length === 0 ("the seed ships EMPTY — plan 05-02's build-time script populates it"), which the plan's task-1 acceptance ("05-01's suites pass against REAL data") supersedes; the plan explicitly ordered the analogous L3 update but C6's identical handoff pin needed the same treatment
  • Fix: re-pinned C6 to assert 10..20 pairs; ODbL header assertions unchanged
  • Files modified: routing/test/contract.test.mjs
  • Commit: 4e89cff

Judgment calls within plan laws (not deviations)

  • measurePairs' optional 4th fixturesPath parameter (RT9 spec requires reading the committed file; default keeps the 3-arg shape)
  • Fetch script validates the entire corpus pre-flight rather than per-pair lazily (D-12 strongest reading)

Known Stubs

None. The 05-01 known stub (route-fixtures.json pairs: []) is resolved by this plan — the corpus is fully populated and gate-pinned.

Threat Surface Scan

No new surface beyond the plan's <threat_model>: the only network touchpoint is the maintainer fetch tool itself (T-05-05b — the declared, documented boundary; the gate is grep-proven offline), the committed dataset ships public data only (RT2b mechanically proven), the gz budget gate gives the T-05-12 early warning (16,576 B / 102,400 B), and the ODbL surfaces are regeneration-proof (RT8). No threat flags.

Issues Encountered

  • Node lives under nvm in this environment; non-interactive shells start without it — every command sourced ~/.nvm/nvm.sh first (05-01 precedent). No project impact.
  • OSRM demo stayed reachable throughout; the plan's unreachable-server checkpoint path never triggered.

User Setup Required

None — no external service configuration. The OSRM demo is touched only by the maintainer tool (npm run routing:fixtures), never by tests, CI, builds, or the runtime.

Next Phase Readiness

  • 05-04 (web route surface): imports createFixtureRoutingSource from @araharah/routing/src/index.ts — the committed corpus now serves 15 real pairs with best-first options, decoded geometry + cumulative distances, honest null for unknown origins (the "router pending" state).
  • 05-05 (gates): ?fixpair=<pairId> values are exactly the 15 committed pairIds (getPairOrigin resolves each); BA9's 200 KB all-in budget has 16.6 KB of fixtures against it; the C4 banned-token gate can grow with the corpus script as planned.
  • Phase 6 (guidance): route snapshots can embed decoded option geometry with cumulativeDistanceM derived at decode — the D-07 fields are live data now, not just types.

Phase: 05-routing-route-display Completed: 2026-10-23

Self-Check: PASSED

  • All 4 created files verified present on disk (golden-pairs.json, fetch-route-fixtures.mjs, route-corpus.mjs, corpus.test.mjs).
  • All 4 plan commits verified in git log: 01b0ed6, 4e89cff, 63ef408, 6c0880b (RED→GREEN per task).
  • npm run routing:corpus exit 0 (RT1–RT10 ok, gz 16576 B); npm run routing:test 35 passed, 0 failed; npm run routing:typecheck exit 0.
  • Committed dataset: 15 pairs, ODbL-1.0 header, zero probe-id destinations.
  • STATE.md and ROADMAP.md untouched (orchestrator-owned writes); only 05-02-SUMMARY.md added (force-add, .planning/ ignored).