feat(05-05): ?fixpair harness knob + pinned-corpus origin lookup (GREEN)
- route-profiles.ts: HARNESS-ONLY module — sentinel ROUTE_PROFILE_HARNESS_ONLY + getRouteProfileOrigin wrapping getPairOrigin; D-12 header (pinned PUBLIC origin only, no coordinate params) + BA5 exclusion note - index.html: ?fixpair=<pair-id> knob resolves the pair's pinned public origin as the mock's telegramFix (accuracy 12, heading null); unknown pairId keeps the default fix; knob documented in the profile comment - [Rule 1 - Bug] main.ts never passed bootMap's opts.onLoad — route sources never existed and setRouteDrawn's setData silently no-op'd (cards rendered, the line never painted; invisible to the RS fakes). Wiring added + RS2 boot-wiring gate pins it - [Rule 1 - Bug] consult raced the map load: harness session stubs resolve the location chain before WebGL/style init, so draw landed on missing sources and the post-load empty install discarded it (probe: ROUTE token fired before RAMS-BASEMAP-READY). Consult now awaits mapLayersReady, resolved in the load handler after installRouteLayers (never wedges — finally-resolved; cards-only boots resolve immediately) - Capture run: CAPTURE OK — 13/13; route line verified painted, alt swap renders ROUTE 2/2 +1 MIN VS ROUTE 1, pending card honest, dark PX-02 - npm test -w web: 76 passed (new RS2 boot-wiring gate included)
This commit is contained in:
+35
-5
@@ -48,7 +48,7 @@ import { createFixtureRoutingSource } from "@araharah/routing/src/index.ts";
|
||||
import { createRouteController, type RouteState } from "./route/route.ts";
|
||||
import { buildRouteCard, buildRoutePendingCard } from "./route/route-card.ts";
|
||||
import { attachRouteEndpoints, removeRouteEndpoints } from "./route/route-markers.ts";
|
||||
import type { MapLike } from "./route/route-layers.ts";
|
||||
import { installRouteLayers, type MapLike } from "./route/route-layers.ts";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -97,8 +97,37 @@ async function boot(): Promise<void> {
|
||||
mainEl.appendChild(mapEl);
|
||||
appRoot.appendChild(mainEl);
|
||||
|
||||
const map = bootMap(document.getElementById("map")!);
|
||||
if (!map) document.body.dataset.map = "absent"; // WebGL2 absent — the shell still renders
|
||||
// The route consult waits on this: the harness session stubs resolve the
|
||||
// location chain faster than WebGL/style init, so consult+setData could
|
||||
// land BEFORE the map's load event — the draw would hit sources that do
|
||||
// not exist yet and the empty post-load install would silently discard it
|
||||
// (found by the 05-05 capture legs: card rendered, line never painted).
|
||||
// Resolves in map.ts's ONE load handler, right after installRouteLayers;
|
||||
// a cards-only boot (map === null) resolves immediately. The Promise
|
||||
// executor runs synchronously, so the resolver is assigned before any
|
||||
// caller below reaches it.
|
||||
let resolveMapLayersReady!: () => void;
|
||||
const mapLayersReady: Promise<void> = new Promise((res) => {
|
||||
resolveMapLayersReady = res;
|
||||
});
|
||||
const map = bootMap(document.getElementById("map")!, {
|
||||
// The route layers install at map load, inside the ONE load handler
|
||||
// (after building-3d, before the ready log — map.ts hosts the hook).
|
||||
// 05-05 capture-leg fix: without this callback the sources never exist
|
||||
// and setRouteDrawn's setData silently no-ops — cards rendered, the
|
||||
// line never painted (the fakes in the RS gates could not see it).
|
||||
onLoad: (m) => {
|
||||
try {
|
||||
installRouteLayers(m as unknown as MapLike);
|
||||
} finally {
|
||||
resolveMapLayersReady(); // the consult never wedges, even on install failure
|
||||
}
|
||||
},
|
||||
});
|
||||
if (!map) {
|
||||
document.body.dataset.map = "absent"; // WebGL2 absent — the shell still renders
|
||||
resolveMapLayersReady(); // cards-only degradation: nothing to wait for
|
||||
}
|
||||
|
||||
let follow: ReturnType<typeof createFollowController> | null = null;
|
||||
const marker = createPositionMarker(); // created here, attached in the guarded block below
|
||||
@@ -426,10 +455,11 @@ async function boot(): Promise<void> {
|
||||
// Auto-consult (the state-coexistence law): the fixture RoutingSource is
|
||||
// consulted ONCE per boot, only when the location chain is live AND a
|
||||
// destination resolved — destination-unavailable and no-destination
|
||||
// boots never make a route request.
|
||||
// boots never make a route request. The consult itself waits for the
|
||||
// map's load (route sources installed) — see mapLayersReady above.
|
||||
if (destination !== null && !routeConsulted) {
|
||||
routeConsulted = true;
|
||||
void routeController.consult(fix, destination);
|
||||
void mapLayersReady.then(() => routeController.consult(fix, destination));
|
||||
}
|
||||
if (!tickStarted) startTick();
|
||||
// emitted UNCONDITIONALLY (outside the map guard above): a WebGL2-absent
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* route-profiles.ts — HARNESS-ONLY ?fixpair= origin lookup (05-05).
|
||||
* ----------------------------------------------------------------------------
|
||||
* D-12: the pinned origin is COMMITTED PUBLIC FIXTURE DATA. The pair corpus
|
||||
* is public-data routes between public places (RT2b proves every origin
|
||||
* equals a gazetteer landmark within 1e-4 deg), so the harness delivers no
|
||||
* user coordinate — it re-delivers a coordinate that is already committed
|
||||
* to the repo. The ?fixpair knob accepts a pairId ONLY; arbitrary lat/lng
|
||||
* query params are never read (T-05-14: a coordinate-parameter knob would
|
||||
* reintroduce the coordinate-in-URL surface the fixture world exists to
|
||||
* avoid).
|
||||
*
|
||||
* BA-EXCLUSION: this module is imported ONLY from the index.html harness
|
||||
* block, inside `if (__ARAHARAH_HARNESS__)` — Vite's define replaces that
|
||||
* identifier with `false` in the production build, so the dynamic import is
|
||||
* dead-code-eliminated and the module never ships. The
|
||||
* ROUTE_PROFILE_HARNESS_ONLY sentinel below joins BA5's token scan: if this
|
||||
* module ever leaks into web/dist, the build fails.
|
||||
*/
|
||||
import { getPairOrigin } from "@araharah/routing/src/index.ts";
|
||||
|
||||
/** BA5 sentinel — must NEVER appear in any web/dist artifact. */
|
||||
export const ROUTE_PROFILE_HARNESS_ONLY = true;
|
||||
|
||||
/** pairId -> the pair's pinned public origin, or null when the pairId is
|
||||
* unknown (the harness keeps its default fix — an unknown pairId must not
|
||||
* wedge the boot). Pure lookup over the committed corpus; the ONLY origin
|
||||
* source the harness can deliver. */
|
||||
export function getRouteProfileOrigin(pairId: string): { lat: number; lng: number } | null {
|
||||
return getPairOrigin(pairId);
|
||||
}
|
||||
Reference in New Issue
Block a user