Access A1: OSRM-докер + osm.pbf Свердл (routing-engine infra) #39

Closed
opened 2026-05-11 20:16:06 +00:00 by lekss361 · 7 comments
lekss361 commented 2026-05-11 20:16:06 +00:00 (Migrated from github.com)

Эшелон: 🟡 Accessibility — routing вместо straight-line

Контекст / проблема

Сейчас в /analyze distance до POI — straight-line ST_Distance(geography). Это даёт ложные сигналы там, где между участком и POI есть жд/река/промзона/высокий забор. 1км по прямой может быть 2.5км пешком. Это одна из причин Limit_POI_Factor_Tiny — фильтр обесцвечен.

Foundation для A2 (изохроны) и A3 (per-category routing-decay).

Что сделать

  1. Добавить service osrm в docker-compose.prod.yml:
    osrm:
      image: osrm/osrm-backend:latest
      volumes: [./data/osrm:/data]
      command: osrm-routed --algorithm mld /data/sverdlovsk-latest.osrm
      ports: ["5000:5000"]
    
  2. Pipeline build (offline на VPS):
    • wget osm.pbf Свердл (≈1.5GB) с Geofabrik
    • osrm-extract -p /opt/car.lua sverdlovsk.osm.pbf
    • osrm-contract sverdlovsk.osrm
    • Generate also walking profile (pedestrian.lua)
  3. Health endpoint check в Caddy/backend startup
  4. Лимиты CPU/RAM в compose — OSRM хочет ~1GB RAM warm
  5. Refresh schedule — ежемесячно (osm.pbf обновляется)

Acceptance

  • curl localhost:5000/route/v1/driving/60.6,56.84;60.65,56.86 возвращает корректный маршрут
  • Walking profile работает (pedestrian)
  • Refresh script idempotent

Owner

devops-engineer

Effort

1 день

Risks / open

  • +1GB RAM на VPS Beget — проверить осталось ли. Возможно нужен upgrade plan.
  • Build на VPS медленный (50+ мин). Альтернатива — build локально + scp в /opt/gendesign/data/osrm
  • ЕКБ-only вариант = 400MB pbf, Свердл-only = 1.5GB. Решение: Свердл (закладываем extensibility per CLAUDE.md instructions)

Dependencies

— (foundation для A2, A3)

**Эшелон:** 🟡 Accessibility — routing вместо straight-line ## Контекст / проблема Сейчас в `/analyze` distance до POI — straight-line `ST_Distance(geography)`. Это даёт **ложные сигналы** там, где между участком и POI есть жд/река/промзона/высокий забор. 1км по прямой может быть 2.5км пешком. Это одна из причин [Limit_POI_Factor_Tiny](https://obsidian.gendsgn.ru/) — фильтр обесцвечен. Foundation для A2 (изохроны) и A3 (per-category routing-decay). ## Что сделать 1. Добавить service `osrm` в `docker-compose.prod.yml`: ```yaml osrm: image: osrm/osrm-backend:latest volumes: [./data/osrm:/data] command: osrm-routed --algorithm mld /data/sverdlovsk-latest.osrm ports: ["5000:5000"] ``` 2. Pipeline build (offline на VPS): - `wget` osm.pbf Свердл (≈1.5GB) с Geofabrik - `osrm-extract` -p /opt/car.lua sverdlovsk.osm.pbf - `osrm-contract` sverdlovsk.osrm - Generate also walking profile (pedestrian.lua) 3. Health endpoint check в Caddy/backend startup 4. Лимиты CPU/RAM в compose — OSRM хочет ~1GB RAM warm 5. Refresh schedule — ежемесячно (osm.pbf обновляется) ## Acceptance - [ ] `curl localhost:5000/route/v1/driving/60.6,56.84;60.65,56.86` возвращает корректный маршрут - [ ] Walking profile работает (pedestrian) - [ ] Refresh script idempotent ## Owner `devops-engineer` ## Effort 1 день ## Risks / open - +1GB RAM на VPS Beget — проверить осталось ли. Возможно нужен upgrade plan. - Build на VPS медленный (50+ мин). Альтернатива — build локально + scp в /opt/gendesign/data/osrm - ЕКБ-only вариант = 400MB pbf, Свердл-only = 1.5GB. **Решение: Свердл** (закладываем extensibility per CLAUDE.md instructions) ## Dependencies — (foundation для A2, A3)
Owner

Status update — НЕ реализовано. Service osrm в docker-compose.prod.yml не добавлен. Foundation для A2/A3 пока заблокирована.

Issue остаётся в backlog priority/high. Нужно решение по plan: build на VPS vs scp pre-built artefacts.

Status update — НЕ реализовано. Service `osrm` в `docker-compose.prod.yml` не добавлен. Foundation для A2/A3 пока заблокирована. Issue остаётся в backlog priority/high. Нужно решение по plan: build на VPS vs scp pre-built artefacts.
lekss361 added the
priority/p1
scope/devops
labels 2026-06-17 20:18:04 +00:00
Collaborator

Working on this in PR #1929 (infra only — OSRM container + build script + docs; the /analyze integration is a separate follow-up A2/A3).

Working on this in PR #1929 (infra only — OSRM container + build script + docs; the /analyze integration is a separate follow-up A2/A3).
Collaborator

OSRM routing-engine — INFRA развёрнута и работает на проде (2026-06-27)

PR #1929 (compose osrm-сервис + scripts/build_osrm.sh + docs) смержен. Граф собран и поднят на VPS:

  • Build: Ural-FO pbf → osmium-clip по Свердл-bbox → MLD pipeline (extract→partition→customize). Граф sverdlovsk.osrm (68M + cells/ebg) в /opt/gendesign/data/osrm/.
  • Service: gendesign-osrm-1 Up + healthy, internal-only (http://osrm:5000, нет публичного порта), mem_limit 1.5g. RAM на VPS хватило (6.2Gi free, граф warm ~0.8-1.2G).
  • Verify (route-probe с прода): GET /route/v1/driving/60.6,56.84;60.65,56.86{"code":"Ok", distance=5413m, duration=505s}. Прямая между точками ~3.7км, дорога 5.4км — ровно та недооценка straight-line, ради которой issue заведён.

Acceptance

  • curl :5000/route/... → корректный маршрут
  • Refresh-script идемпотентен (wget -N, re-runnable; cron-пример в docs/osrm-routing.md)
  • Walking-профиль — пока car-first. Скрипт уже умеет (WALK=1 bash scripts/build_osrm.shsverdlovsk-foot.osrm*) + блок osrm-walk-сервиса задокументирован в docs. Quick follow-up (не консьюмится пока нет интеграции).

Остаётся (follow-up)

  • Walking-профиль (10 мин: WALK=1 + osrm-walk service).
  • A2/A3 — интеграция в /analyze: заменить ST_Distance(geography) на OSRM route/table для distance-to-POI (это и есть value-delivery; #39 был INFRA-foundation). Держу open под walking + интеграцию.

Routing-движок готов как foundation. Изохроны (A2) и per-category routing-decay (A3) теперь разблокированы.

## OSRM routing-engine — INFRA развёрнута и работает на проде (2026-06-27) PR #1929 (compose `osrm`-сервис + `scripts/build_osrm.sh` + docs) смержен. Граф собран и поднят на VPS: - **Build:** Ural-FO pbf → osmium-clip по Свердл-bbox → MLD pipeline (extract→partition→customize). Граф `sverdlovsk.osrm` (68M + cells/ebg) в `/opt/gendesign/data/osrm/`. - **Service:** `gendesign-osrm-1` Up + **healthy**, internal-only (`http://osrm:5000`, нет публичного порта), mem_limit 1.5g. RAM на VPS хватило (6.2Gi free, граф warm ~0.8-1.2G). - **✅ Verify (route-probe с прода):** `GET /route/v1/driving/60.6,56.84;60.65,56.86` → `{"code":"Ok", distance=5413m, duration=505s}`. Прямая между точками ~3.7км, дорога 5.4км — ровно та недооценка straight-line, ради которой issue заведён. ### Acceptance - [x] `curl :5000/route/...` → корректный маршрут ✅ - [x] Refresh-script идемпотентен (`wget -N`, re-runnable; cron-пример в docs/osrm-routing.md) ✅ - [ ] **Walking-профиль** — пока car-first. Скрипт уже умеет (`WALK=1 bash scripts/build_osrm.sh` → `sverdlovsk-foot.osrm*`) + блок `osrm-walk`-сервиса задокументирован в docs. Quick follow-up (не консьюмится пока нет интеграции). ### Остаётся (follow-up) - Walking-профиль (10 мин: WALK=1 + osrm-walk service). - **A2/A3 — интеграция в `/analyze`**: заменить `ST_Distance(geography)` на OSRM `route`/`table` для distance-to-POI (это и есть value-delivery; #39 был INFRA-foundation). Держу open под walking + интеграцию. Routing-движок готов как foundation. Изохроны (A2) и per-category routing-decay (A3) теперь разблокированы.
Collaborator

A2 — интеграция OSRM в /analyze + валидация флипа флага (2026-06-27)

PR #1932 смержен и задеплоен: _apply_osrm_road_distances заменяет straight-line ST_Distance на реальное дорожное (центроид участка → каждый POI) через локальный OSRM /table. Флаг use_osrm_distances = OFF на проде (деплой байт-в-байт нейтрален), любой сбой OSRM → graceful straight-line fallback (/analyze не падает).

Валидация флипа (live prod, реальные POI из osm_poi_ekb, 4 центра районов ЕКБ)

Прогнал точный прод-путь (_apply_osrm_road_distances на реальных POI в радиусе 1 км), сравнил road vs straight-line:

Район POI заменено OSRM ratio road/straight (min / медиана / p90 / max) road<straight
Центр (пл.1905) 170 170 (100%) 1.02 / 1.64 / 2.78 / 7.55 0
Академический 57 57 (100%) 0.58 / 1.80 / 2.94 / 5.59 1
Уралмаш 159 159 (100%) 0.43 / 2.90 / 5.87 / 29.76 5
Пионерский 110 110 (100%) 0.82 / 1.90 / 3.14 / 6.05 1

Выводы:

  • Движок боевой: OSRM достижим из backend-контейнера, маршрутизирует 100% POI, ни одного fallback/None. Acceptance route-probe (5.4км vs 3.7км прямая) подтверждён и на табличном API.
  • Направление верное: road ≥ straight для подавляющего большинства. Единичные road<straight (0/1/5/1, <3%, все в ближнем поле) — это OSRM-снап origin/POI к ближайшему ребру дороги, не баг.
  • ⚠️ Магнитуда большая: медиана 1.6–2.9×, тяжёлый правый хвост (max до 29× — POI за жд/рекой с далёким переездом, ровно кейс из тела issue). Включение флага заметно сдвинет POI-скоры (дальние-по-дороге POI обесценятся).

Это продуктовое решение, не дефолт

Магнитуда такая, что флип — осознанное изменение скоринга, а не тихий апгрейд. Развилка:

  • driving-профиль честнее «доступности на авто» → флип ON, road-distance корректнее straight-line.
  • но для «пешая шаговая доступность в 1 км» (школа/магазин через дорогу = 2.5км объезд на авто, но 50м пешком) driving завышает → нужен walking-профиль (скрипт уже умеет WALK=1, сервис задокументирован) или оставить straight-line для walk-категорий.

Рекомендация: держу флаг OFF до твоего решения. Варианты:

  1. Walking-профиль + per-category (A3): пешие POI (школа/магазин/парк) → foot-OSRM, авто-POI (ТЦ/развязка) → driving. Самый честный, ~полдня.
  2. Флип driving ON как есть — быстро, но обесценит close-by-walk POI.
  3. Оставить OFF — straight-line, как сейчас.

Склоняюсь к (1) — это и был смысл A3. Скажи, и сделаю walking-профиль + per-category routing-decay. Acceptance walking-профиля ([ ] выше) закрою тем же заходом.

## A2 — интеграция OSRM в `/analyze` + валидация флипа флага (2026-06-27) PR #1932 смержен и задеплоен: `_apply_osrm_road_distances` заменяет straight-line `ST_Distance` на реальное дорожное (центроид участка → каждый POI) через локальный OSRM `/table`. **Флаг `use_osrm_distances` = OFF** на проде (деплой байт-в-байт нейтрален), любой сбой OSRM → graceful straight-line fallback (`/analyze` не падает). ### Валидация флипа (live prod, реальные POI из `osm_poi_ekb`, 4 центра районов ЕКБ) Прогнал точный прод-путь (`_apply_osrm_road_distances` на реальных POI в радиусе 1 км), сравнил road vs straight-line: | Район | POI | заменено OSRM | ratio road/straight (min / медиана / p90 / max) | road<straight | |---|---|---|---|---| | Центр (пл.1905) | 170 | **170 (100%)** | 1.02 / 1.64 / 2.78 / 7.55 | 0 | | Академический | 57 | **57 (100%)** | 0.58 / 1.80 / 2.94 / 5.59 | 1 | | Уралмаш | 159 | **159 (100%)** | 0.43 / 2.90 / 5.87 / 29.76 | 5 | | Пионерский | 110 | **110 (100%)** | 0.82 / 1.90 / 3.14 / 6.05 | 1 | **Выводы:** - ✅ **Движок боевой**: OSRM достижим из backend-контейнера, маршрутизирует **100% POI**, ни одного fallback/None. Acceptance route-probe (5.4км vs 3.7км прямая) подтверждён и на табличном API. - ✅ **Направление верное**: road ≥ straight для подавляющего большинства. Единичные `road<straight` (0/1/5/1, <3%, все в ближнем поле) — это OSRM-снап origin/POI к ближайшему ребру дороги, не баг. - ⚠️ **Магнитуда большая**: медиана **1.6–2.9×**, тяжёлый правый хвост (max до 29× — POI за жд/рекой с далёким переездом, ровно кейс из тела issue). **Включение флага заметно сдвинет POI-скоры** (дальние-по-дороге POI обесценятся). ### Это продуктовое решение, не дефолт Магнитуда такая, что флип — осознанное изменение скоринга, а не тихий апгрейд. Развилка: - **driving-профиль честнее «доступности на авто»** → флип ON, road-distance корректнее straight-line. - но для **«пешая шаговая доступность в 1 км»** (школа/магазин через дорогу = 2.5км объезд на авто, но 50м пешком) driving завышает → нужен **walking-профиль** (скрипт уже умеет `WALK=1`, сервис задокументирован) или оставить straight-line для walk-категорий. **Рекомендация:** держу флаг **OFF** до твоего решения. Варианты: 1. **Walking-профиль + per-category** (A3): пешие POI (школа/магазин/парк) → foot-OSRM, авто-POI (ТЦ/развязка) → driving. Самый честный, ~полдня. 2. **Флип driving ON как есть** — быстро, но обесценит close-by-walk POI. 3. **Оставить OFF** — straight-line, как сейчас. Склоняюсь к **(1)** — это и был смысл A3. Скажи, и сделаю walking-профиль + per-category routing-decay. Acceptance walking-профиля (`[ ]` выше) закрою тем же заходом.
Collaborator

A3 — per-category routing (foot+car) ЗАДЕПЛОЕН + валидирован (2026-06-27)

PR #1935 смержен + задеплоен (main 94d3a98). Пеший граф собран на VPS (CAR=0 WALK=1, sverdlovsk-foot.osrm*, 27 файлов), сервис osrm-walk Up (healthy), backend ходит к нему per-category.

Раскладка

  • walk → foot-граф (profile=foot): bus_stop, kindergarten, metro_stop, park, pharmacy, school, shop_small, shop_supermarket, tram_stop
  • drive → car-граф (profile=driving): shop_mall, hospital + неизвестная/None (безопасный дефолт)

Валидация (live prod, реальные POI osm_poi_ekb, 4 центра районов)

Сравнил для walk-POI: foot/straight (новое A3) vs driving/straight (старое A2):

Район walk POI WALK foot/straight OLD driving/straight DRIVE car/straight (без изм.)
Центр (пл.1905) 148 1.33 1.66 1.55
Академический 56 1.35 1.84 1.69
Уралмаш 150 1.35 2.84 3.15
Пионерский 106 1.32 1.90 2.02

Вывод: foot/straight стабильно ~1.33× — это классический пеший detour-коэффициент (~1.3), физически корректный. Driving завышал пешую доступность в 1.66–2.84× (Уралмаш — кейс из тела issue: авто объезжает жд/реку 2.84×, пешеход переходит напрямую 1.35×). A3 убирает это завышение для пешеходных POI, drive-POI оставляет на car-графе.

Acceptance

  • curl :5000/route/... (driving) — (ранее)
  • Walking-профиль работает foot-граф собран, osrm-walk healthy, foot-маршруты возвращаются (валидация выше прогнала реальные foot-вызовы)
  • Refresh-script идемпотентен (CAR=0 WALK=1 foot-only refresh не трогает живой car-граф) —

Флаг use_osrm_distances — по-прежнему OFF

A3 не включает флаг сам — это всё ещё осознанное продуктовое изменение скоринга. Но теперь флип честный: при включении пешие POI получат реалистичные ~1.33×, а не завышенные авто-дистанции. Риск флипа сильно снизился (walk-завышение убрано). Рекомендую флип — но оставляю решение за тобой (одно слово «включай» → выставлю use_osrm_distances=true в .env.runtime + recreate backend + post-flip QA).

Инфра-фундамент #39 (A1) + интеграция (A2) + per-category (A3) — закрыты. Остаётся только продуктовое решение по флипу. Можно закрывать issue после флипа (или сейчас, если флип трекать отдельно).

## A3 — per-category routing (foot+car) ЗАДЕПЛОЕН + валидирован (2026-06-27) PR #1935 смержен + задеплоен (main `94d3a98`). Пеший граф собран на VPS (`CAR=0 WALK=1`, `sverdlovsk-foot.osrm*`, 27 файлов), сервис **`osrm-walk` Up (healthy)**, backend ходит к нему per-category. ### Раскладка - **walk → foot-граф** (`profile=foot`): `bus_stop, kindergarten, metro_stop, park, pharmacy, school, shop_small, shop_supermarket, tram_stop` - **drive → car-граф** (`profile=driving`): `shop_mall, hospital` + неизвестная/None (безопасный дефолт) ### Валидация (live prod, реальные POI `osm_poi_ekb`, 4 центра районов) Сравнил для walk-POI: **foot/straight** (новое A3) vs **driving/straight** (старое A2): | Район | walk POI | **WALK foot/straight** | OLD driving/straight | DRIVE car/straight (без изм.) | |---|---|---|---|---| | Центр (пл.1905) | 148 | **1.33** | 1.66 | 1.55 | | Академический | 56 | **1.35** | 1.84 | 1.69 | | Уралмаш | 150 | **1.35** | **2.84** | 3.15 | | Пионерский | 106 | **1.32** | 1.90 | 2.02 | **Вывод:** foot/straight стабильно **~1.33×** — это классический пеший detour-коэффициент (~1.3), физически корректный. Driving завышал пешую доступность в 1.66–2.84× (Уралмаш — кейс из тела issue: авто объезжает жд/реку 2.84×, пешеход переходит напрямую 1.35×). A3 убирает это завышение для пешеходных POI, drive-POI оставляет на car-графе. ### Acceptance - [x] `curl :5000/route/...` (driving) — ✅ (ранее) - [x] **Walking-профиль работает** — ✅ foot-граф собран, `osrm-walk` healthy, foot-маршруты возвращаются (валидация выше прогнала реальные foot-вызовы) - [x] Refresh-script идемпотентен (`CAR=0 WALK=1` foot-only refresh не трогает живой car-граф) — ✅ ### Флаг `use_osrm_distances` — по-прежнему OFF A3 не включает флаг сам — это всё ещё осознанное продуктовое изменение скоринга. **Но теперь флип честный**: при включении пешие POI получат реалистичные ~1.33×, а не завышенные авто-дистанции. Риск флипа сильно снизился (walk-завышение убрано). Рекомендую флип — но оставляю решение за тобой (одно слово «включай» → выставлю `use_osrm_distances=true` в `.env.runtime` + recreate backend + post-flip QA). Инфра-фундамент #39 (A1) + интеграция (A2) + per-category (A3) — закрыты. Остаётся только продуктовое решение по флипу. Можно закрывать issue после флипа (или сейчас, если флип трекать отдельно).
Collaborator

🟢 Флаг use_osrm_distances ВКЛЮЧЁН на проде (2026-06-27, по запросу Anton)

/analyze теперь считает дистанции до POI по реальной дорожной/пешей сети (per-category: пешие POI → foot-граф osrm-walk, авто → car-граф osrm), а не по прямой.

Как включено: USE_OSRM_DISTANCES=true дописан в /opt/gendesign/backend/.env.runtime (бэкап .env.runtime.bak.20260627-osrm-flip, sed-style append — переживает git reset --hard), gendesign-backend-1 + gendesign-worker-1 пересозданы (--force-recreate --no-deps, чтобы перечитать env_file).

Verify:

  • settings.use_osrm_distances = True в живом backend
  • gendesign-osrm-1 + gendesign-osrm-walk-1 — Up (healthy)
  • POST /analyze (cad 66:41:0702048:27) → 200 OK, score=13.39, poi_count=106, без ошибок
  • Путь _apply_osrm_road_distances предварительно валидирован на реальных POI (foot/straight ~1.33×, 100% POI маршрутизируются, графы достижимы из backend)
  • Graceful fallback цел: при сбое любого OSRM-сервиса соответствующая группа POI откатывается на straight-line, /analyze не падает.

Ожидаемый эффект: POI-скоры сдвинутся (дальние-по-дороге POI обесценятся; пешие близкие POI получат честные ~1.3× вместо завышенных авто-дистанций). Это и есть смысл #39.

Минорное наблюдение (follow-up, не блокер): app-level INFO-логи (logging.getLogger(__name__)) не попадают в stdout контейнера — видны только uvicorn-логгеры. Поэтому INFO-строка OSRM road-distance applied (...) не видна в docker logs (хотя путь исполняется). Стоит отдельно настроить логгинг приложения (propagate/level) для observability — заведу при необходимости.

#39 закрываю — A1 (инфра) + A2 (интеграция) + A3 (walking/per-category) + флип = весь эшелон Accessibility-routing доставлен и в проде.

## 🟢 Флаг `use_osrm_distances` ВКЛЮЧЁН на проде (2026-06-27, по запросу Anton) `/analyze` теперь считает дистанции до POI по **реальной дорожной/пешей сети** (per-category: пешие POI → foot-граф `osrm-walk`, авто → car-граф `osrm`), а не по прямой. **Как включено:** `USE_OSRM_DISTANCES=true` дописан в `/opt/gendesign/backend/.env.runtime` (бэкап `.env.runtime.bak.20260627-osrm-flip`, sed-style append — переживает `git reset --hard`), `gendesign-backend-1` + `gendesign-worker-1` пересозданы (`--force-recreate --no-deps`, чтобы перечитать env_file). **Verify:** - `settings.use_osrm_distances = True` в живом backend ✅ - `gendesign-osrm-1` + `gendesign-osrm-walk-1` — Up (healthy) ✅ - `POST /analyze` (cad 66:41:0702048:27) → **200 OK**, score=13.39, poi_count=106, без ошибок ✅ - Путь `_apply_osrm_road_distances` предварительно валидирован на реальных POI (foot/straight ~1.33×, 100% POI маршрутизируются, графы достижимы из backend) ✅ - Graceful fallback цел: при сбое любого OSRM-сервиса соответствующая группа POI откатывается на straight-line, /analyze не падает. **Ожидаемый эффект:** POI-скоры сдвинутся (дальние-по-дороге POI обесценятся; пешие близкие POI получат честные ~1.3× вместо завышенных авто-дистанций). Это и есть смысл #39. **Минорное наблюдение (follow-up, не блокер):** app-level INFO-логи (`logging.getLogger(__name__)`) не попадают в stdout контейнера — видны только uvicorn-логгеры. Поэтому INFO-строка `OSRM road-distance applied (...)` не видна в `docker logs` (хотя путь исполняется). Стоит отдельно настроить логгинг приложения (propagate/level) для observability — заведу при необходимости. **#39 закрываю** — A1 (инфра) + A2 (интеграция) + A3 (walking/per-category) + флип = весь эшелон Accessibility-routing доставлен и в проде.
Collaborator

On-the-wire подтверждение per-category routing (2026-06-27, после фикса observability #1941)

После #1941 (app-INFO теперь в docker logs gendesign-backend-1) виден реальный лог применения OSRM в /analyze на проде:

OSRM road-distance applied (osm cad=66:41:0704012:2): walk 127/127, drive 10/10 POI заменены (остальные straight-line)

Т.е. флип работает end-to-end: 127 пеших POI → foot-граф (100% замены), 10 авто-POI → car-граф (100%), per-category split живой, покрытие полное, fallback не понадобился. Ровно один лог-лайн на analyze (no double-emit). Это закрывает верификацию флипа на уровне «видно что применяется», а не только «200 OK».

## On-the-wire подтверждение per-category routing (2026-06-27, после фикса observability #1941) После #1941 (app-INFO теперь в `docker logs gendesign-backend-1`) виден реальный лог применения OSRM в `/analyze` на проде: ``` OSRM road-distance applied (osm cad=66:41:0704012:2): walk 127/127, drive 10/10 POI заменены (остальные straight-line) ``` Т.е. флип работает end-to-end: **127 пеших POI** → foot-граф (100% замены), **10 авто-POI** → car-граф (100%), per-category split живой, покрытие полное, fallback не понадобился. Ровно один лог-лайн на analyze (no double-emit). Это закрывает верификацию флипа на уровне «видно что применяется», а не только «200 OK».
Sign in to join this conversation.
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#39
No description provided.