feat(05-01): RoutingSource contract + day-one route model + fixture seed schema
- types.ts: the D-01 backend-ladder seam (fixture -> wasm-router -> valhalla), D-03 null contract documented on the interface, D-07 day-one fields (RouteStep typed + RouteGeometry.cumulativeDistanceM, GUID-05/06 obligation) - route-fixtures.json: committed EMPTY seed with the ODbL header (license/attribution/notice, T-05-06) — plan 05-02 populates it
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"_license": "ODbL-1.0",
|
||||||
|
"_attribution": "© OpenStreetMap contributors",
|
||||||
|
"_notice": "Route geometry © OpenStreetMap contributors, precomputed from the public OSRM demo server (router.project-osrm.org) at build time between fixed public landmark coordinates. ODbL v1.0 — https://opendatacommons.org/licenses/odbl/1-0/",
|
||||||
|
"_source": "OSRM demo server (router.project-osrm.org) — build-time fetch, never a runtime dependency",
|
||||||
|
"version": 1,
|
||||||
|
"originToleranceM": 200,
|
||||||
|
"pairs": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* types.ts — the routing contracts (D-01, D-03, D-05, D-07, D-11).
|
||||||
|
* ----------------------------------------------------------------
|
||||||
|
* RoutePoint / RouteRequest / RouteResult / RoutingSource are the seam
|
||||||
|
* every backend implements: the build-time fixture corpus (backend #1,
|
||||||
|
* "fixture", this phase), the client-side WASM router (backend #2,
|
||||||
|
* "wasm-router" — OSS track, post-v1; origin+destination never touch a
|
||||||
|
* server), and Valhalla-on-VPS (backend #3, documented provision path,
|
||||||
|
* not shipped). The ladder is DOCUMENTED, not switchable: no env read,
|
||||||
|
* no config read, no dynamic backend registry (T-05-04) — the import
|
||||||
|
* site constructs the backend in code (plan 05-04).
|
||||||
|
*
|
||||||
|
* THE NULL CONTRACT IS LOAD-BEARING (D-03): route() resolving to NULL is
|
||||||
|
* the honest "router pending" state — an unknown destination, or an
|
||||||
|
* origin outside the fixture corpus's tolerance. Never a blank map,
|
||||||
|
* never a fake route, never a thrown error for a normal miss.
|
||||||
|
*
|
||||||
|
* No logging, no storage, no network (D-05/D-12/D-15 analog): request
|
||||||
|
* coordinates never leave the caller's frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** A WGS84 point. */
|
||||||
|
export interface RoutePoint {
|
||||||
|
lat: number;
|
||||||
|
lng: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A routing request. The origin is the live fix (memory only — GEO-03/D-07). */
|
||||||
|
export interface RouteRequest {
|
||||||
|
origin: RoutePoint;
|
||||||
|
/** The gazetteer id resolved by the Phase 4 destination resolver. */
|
||||||
|
destinationId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Distance/duration summary. Distances in meters, durations in seconds. */
|
||||||
|
export interface RouteSummary {
|
||||||
|
distanceM: number;
|
||||||
|
durationS: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A maneuver step — DAY-ONE FIELD (D-07, GUID-05/06 upstream obligation).
|
||||||
|
* Fixture-world steps are ALWAYS empty arrays (D-10 defers instructions to
|
||||||
|
* Phase 6): an empty array is honest "not wired"; a fabricated step list
|
||||||
|
* would not be. Real step geometry arrives with backends #2/#3.
|
||||||
|
*/
|
||||||
|
export interface RouteStep {
|
||||||
|
distanceM?: number;
|
||||||
|
durationS?: number;
|
||||||
|
name?: string;
|
||||||
|
/** polyline6-encoded step geometry (backend #2/#3 populate this). */
|
||||||
|
geometry?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decoded geometry + the snapped-progress support field — DAY-ONE FIELD
|
||||||
|
* (D-07, GUID-05/06 upstream obligation): Phase 6's guidance walks a live
|
||||||
|
* fix along cumulativeDistanceM instead of re-deriving it per fix.
|
||||||
|
*/
|
||||||
|
export interface RouteGeometry {
|
||||||
|
points: RoutePoint[];
|
||||||
|
/** Same length as points; [0] === 0; non-decreasing. Meters along the line. */
|
||||||
|
cumulativeDistanceM: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** One routable alternative. options[0] of a result is the BEST route. */
|
||||||
|
export interface RouteOption {
|
||||||
|
geometry: RouteGeometry;
|
||||||
|
summary: RouteSummary;
|
||||||
|
steps: RouteStep[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RouteResult {
|
||||||
|
destinationId: string;
|
||||||
|
origin: RoutePoint;
|
||||||
|
/** 1..3 options, index 0 = best (order preserved from the backend). */
|
||||||
|
options: RouteOption[];
|
||||||
|
/** === the RoutingSource name that produced it. */
|
||||||
|
backend: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pluggable routing seam (D-01). Backends: "fixture" (this phase) →
|
||||||
|
* "wasm-router" (OSS track, backend #2 — client-side, origin+destination
|
||||||
|
* never touch a server) → "valhalla" (VPS, backend #3). Backends #2/#3 do
|
||||||
|
* NOT ship in this phase — the interface exists so they slot in without a
|
||||||
|
* client rewrite, exactly parallel to SearchSource's ladder (D-03/D-04).
|
||||||
|
*
|
||||||
|
* THE NULL CONTRACT IS LOAD-BEARING (D-03): route() resolving to NULL is
|
||||||
|
* the honest "router pending" state — an unknown destination, or an origin
|
||||||
|
* outside the fixture corpus's tolerance. Never a blank map, never a fake
|
||||||
|
* route, never a thrown error for a normal miss.
|
||||||
|
*
|
||||||
|
* No logging, no storage, no network (D-05/D-12/D-15 analog): request
|
||||||
|
* coordinates never leave the caller's frame.
|
||||||
|
*/
|
||||||
|
export interface RoutingSource {
|
||||||
|
readonly name: string;
|
||||||
|
route(req: RouteRequest): Promise<RouteResult | null>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** One committed fixture route — the polyline6 string stored VERBATIM
|
||||||
|
* from the build-time OSRM demo response (RESEARCH Finding 1). */
|
||||||
|
export interface FixtureRoute {
|
||||||
|
/** polyline6, stored VERBATIM from the OSRM demo response. */
|
||||||
|
geometry: string;
|
||||||
|
distanceM: number;
|
||||||
|
durationS: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** One golden origin→destination pair of the fixture corpus (D-02). */
|
||||||
|
export interface FixturePair {
|
||||||
|
/** "<origin-id>-to-<dest-id>", slug charset — also the ?fixpair= knob value. */
|
||||||
|
pairId: string;
|
||||||
|
origin: { lat: number; lng: number; label: string };
|
||||||
|
destinationId: string;
|
||||||
|
/** Best-first, 1..3 entries (OSRM demo returns best-first; preserved). */
|
||||||
|
routes: FixtureRoute[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The committed dataset envelope (route-fixtures.json) — the ODbL
|
||||||
|
* attribution travels INSIDE the file, the gazetteer's three-surfaces
|
||||||
|
* pattern (T-05-06). Tests inject synthetic values of this shape. */
|
||||||
|
export interface RouteFixturesFile {
|
||||||
|
_license: string;
|
||||||
|
_attribution: string;
|
||||||
|
_notice: string;
|
||||||
|
_source: string;
|
||||||
|
version: number;
|
||||||
|
originToleranceM: number;
|
||||||
|
pairs: FixturePair[];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user