fix(07-02): refuse <2-point geometries before the draw path — pending card / reroute-failed (T-07-12, FM4)

- consult filters degenerate options (geometry.points < 2) into the pending-card class
- reroute ladder: no drawable option = the honest reroute-failed degradation, never a half-drawn snap-in
- GREEN for FM4; web suite 165/165, typecheck clean
This commit is contained in:
araharah-executor
2026-10-25 04:02:31 +08:00
parent b577bc4687
commit add860bceb
+13 -5
View File
@@ -225,13 +225,19 @@ export function createRouteController(deps: RouteControllerDeps): {
const result: RouteResult | null = await deps.source
.route({ origin: { lat: fix.lat, lng: fix.lng }, destinationId: destination.id })
.catch(() => null); // T-05-04: an exception renders pending — never a half-drawn line
if (result === null || result.options.length === 0) {
// T-07-12 (FM4, 07-02): a geometry decoding to fewer than two points is
// refused BEFORE the draw path — the degenerate option is dropped with
// the empty-answer class, so the pending card renders instead of a
// half-drawn line (the same law main.ts already applies to the ?g=
// envelope's decoded polyline).
const usable = result === null ? [] : result.options.filter((option) => option.geometry.points.length >= 2);
if (result === null || usable.length === 0) {
deps.showRouteCard(deps.buildPendingCard(deps.locale, { onSearchAgain: () => walkBack() }), "center");
setState("pending");
console.log("ARAHARAH-ROUTE state=pending");
return;
}
options = result.options;
options = usable;
selectedIndex = 0;
drawSelection();
setState("route");
@@ -443,14 +449,16 @@ export function createRouteController(deps: RouteControllerDeps): {
result = null; // fail-honest (T-05-04, network edition)
}
if (guidance !== g || g.ended) return; // the trip ended mid-request — drop it
if (result === null || result.options.length === 0) {
// T-07-12 (FM4, 07-02): the same no-geometry law on the reroute ladder —
// an answer with no drawable (>= 2-point) option is the honest
// reroute-failed degradation, never a half-drawn snap-in.
const option = result === null ? undefined : result.options.find((o) => o.geometry.points.length >= 2);
if (option === undefined || result === null) {
g.snap = stepGuidance(g.snap, { type: "reroute-failed" }, now()).snap;
logGuideState(g.snap.state);
renderCockpit();
return;
}
const option = result.options[0];
if (option === undefined) return;
const model: GuidanceRouteModel = {
points: option.geometry.points,
cumulative: option.geometry.cumulativeDistanceM,