Feat/oleksii bielov snow feat#120
Open
sfc-gh-obielov wants to merge 142 commits into
Open
Conversation
Data Studio's region dropdown previously only loaded once on mount, so newly-provisioned regions did not appear until a manual page refresh. Mirror ServiceManager's 30s poll on /api/ors-readiness, add a visibility/focus listener for instant refresh on tab return, and re-fetch regions when an SSE generation job completes or stops. Bumps ors_control_app image to v1.1.9.
…Snowflake The /session/v1/logout-from-application endpoint only accepts POST. The previous GET redirect produced HTTP 405. Replace with an auto-submitting HTML form so the browser POSTs the redirect_url and Snowflake clears the session, then bounces back to the SPCS app login screen. Bump ors_control_app to v1.1.10.
…ering RetailCatchment now resolves the ORS service key per region (REGION_NAME first, then ORS_REGION_KEY) so UsCalifornia (whose REGION_REGISTRY.ORS_REGION_KEY is the stale 'California') resolves correctly. The dropdown lists every ORS-provisioned region with that region's actual travel profiles, and the ISOCHRONES call uses the resolved key. POI / competitor / density queries now JOIN OPENROUTESERVICE_APP.CORE.REGION_CATALOG and filter via ST_WITHIN(p.GEOMETRY, rc.BOUNDARY) instead of REGION-equality. SanFrancisco keeps its fast path against the cached pipeline tables; every other provisioned region (Germany, UsCalifornia, future ones) reads live from OVERTURE_MAPS__PLACES / __ADDRESSES polygon-clipped server-side. No SQL pipeline or Data Studio change required. AGENTS.md gains a new "Prefer Boundary Polygons over Bounding Boxes" section under Geospatial Conventions establishing the standard JOIN pattern and documenting the narrow exceptions where bbox is still acceptable.
…from logout-from-application) The /session/v1/logout-from-application endpoint returns 404 on this Snowflake account regardless of HTTP method. Switch /logout to clear known SPCS ingress auth cookies via Set-Cookie Max-Age=0 and redirect to /. The SPCS ingress then challenges auth on the next request and shows the Snowflake login screen. Also cache-bust the client-side navigation with a timestamp so the browser does not follow a stale 302 from earlier versions. Bump ors_control_app to v1.1.12.
… de-emphasize others
…/useFitMap utilities
…ess logout unreliable) The /session/v1/logout-from-application endpoint 404s on this account and clearing candidate SPCS ingress cookies did not end the session either. Rather than keep iterating on a broken feature, remove the button and its server route. Users can sign out via Snowsight or by closing the tab. Bump ors_control_app to v1.1.14.
…as no coords; guard deck.gl viewState
Fixes a deck.gl Controller assertion (Mfe ctor) that caused the map to
go blank when running OPTIMIZATION (and other functions) in the
Function Tester.
Root cause: a non-finite viewState (NaN/Infinity in
longitude/latitude/zoom) could be fed to <DeckGL controller={true}>
during the first canvas-sizing tick. The OPTIMIZATION path was the
most exposed because parsed paths/stops/depot were not finiteness-checked.
Changes:
- useFitMap: sanitize the initial viewState (drop non-finite fields
from caller fallback) and export isFiniteVS for downstream use.
- helpers.parseOptimizationResult: filter non-finite [lon,lat] pairs
in path, stops, and depot.
- helpers.bboxCenter: Number.isFinite-validate each component and
fall back to [0, 30] (matches DEFAULT_FALLBACK) instead of [0, 0].
- ResultMap: when result-derived coords are empty/invalid, fit the
map to the selected region's preset boundary (boundaryGeoJson
preferred, bbox corners as secondary). Defer <DeckGL> mount until
container dims AND viewState are both finite, eliminating the
Controller-init race.
- FunctionTester: pass selectedRegion.bbox and boundaryGeoJson to
ResultMap so the preset fallback has data to fit to.
Ghost trailers were being assigned by global per-vehicle Bernoulli sampling, which caused large regions (e.g. UsCalifornia) to concentrate all ghosts in the densest POI cluster (SF Bay), making Asset Velocity look SF-only when the California preset was active. buildFleet() now bins fleet members by 0.5 deg lat/lng cells (~55 km) and samples ghost_count = bin_size * probability per bin with stochastic rounding, preserving the expected total ghost count while spreading ghosts across the whole region. Bumps ors_control_app to v1.1.15. .... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code) Co-Authored-By: Cortex Code <noreply@snowflake.com>
The shared useFitMap hook and MapView component used to re-fit the camera on every coords-signature change, which produced a jarring snap whenever data refreshed (e.g. live polling, filter toggles). Now the camera auto-fits only once per (mount, regionKey) pair: it fits on the first non-empty data load, refits when the active region changes, and otherwise leaves the user's pan/zoom alone. A new RecenterButton overlay (top-right of every map) lets the user re-fit on demand. All 20 useFitMap consumers across the React app (taxis, food delivery, dwell, route deviation, retail catchment, route/asset velocity, backload, matrix viewer, agent playground, intro, function tester) now pass a regionKey and render the Recenter button.
Three changes ensure the Route Optimization page works for any newly provisioned region without requiring a manual region switch (which previously left big regions like UsCalifornia with zero PLACES because the synchronous SPCS auto-seed timed out for ~1.8M Overture rows): 1. PROVISION_REGION_WRAPPER now calls SEED_ROUTE_OPTIMIZATION_REGION on its success path (next to SET_REBUILD_GRAPHS_FLAG and create_region_vroom_service). This runs inside the stored-procedure context with no SPCS request timeout, so PLACES is guaranteed populated by the time STATUS=DEPLOYED. 2. seed-data.sql now loops over every REGION_ORS_MAP STATUS='DEPLOYED' region and seeds each one (idempotent), so a fresh install or re-run guarantees coverage across all already-provisioned regions. 3. The two SPCS auto-seed call sites (POST /api/regions/active and POST /api/fleet/datasets) are now detached (no await) so a slow seed for a large region doesn't block the HTTP response. The existing UI warning already tells users to refresh after a moment. Bumped ors_control_app to v1.1.17. Verified on UsCalifornia: 1,824,125 places seeded, 42,734 within 5km of SF Civic Center. .... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code) Co-Authored-By: Cortex Code <noreply@snowflake.com>
The vehicle profile dropdown previously hardcoded Car/HGV/Bicycle and defaulted
every new vehicle to driving-car. Regions provisioned with a different profile
mix (e.g. UsCalifornia and Germany are HGV-only) caused the optimize call to
fail with: "Parameter 'profile' has incorrect value of 'unknown'".
Now mirrors the pattern from RetailCatchment / FunctionTester:
- On region change, query ORS_STATUS(region) and parse the profiles object.
- Populate the dropdown from those profile keys (with friendly labels).
- Reconcile existing vehicles: any vehicle whose profile is no longer loaded
for the active region is auto-switched to the first available profile.
- Default new vehicles ("+ Add" button and initial state) to availableProfiles[0].
- Disable the Optimize button when no profiles are available with a tooltip
pointing at the region's ORS readiness.
Bumped ors_control_app to v1.1.18.
.... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code)
Co-Authored-By: Cortex Code <noreply@snowflake.com>
Recenter previously fit camera to hex centers (cellToLatLng), which under-sized the bbox by up to one edge length and clipped outer hexes, especially at low resolutions and on extruded+pitched views. - add coordsFromH3Cells() in shared/mapFit.ts using cellToBoundary so the bbox encloses each hex's full footprint (sampled to 2000) - add shared/useH3FitMap.ts wrapper hook with optional extraCoords for mixed point+hex maps - migrate CongestionMap, CourierHeatmap, fleet-taxis HeatMap to the new hook; bump top padding (100/60/60/60) for extruded views to prevent vertical clipping of elevation columns - update MatrixViewer (mixed point+hex) and Intro to use coordsFromH3Cells when computing fit bounds
Previously the fit-once gate in useFitMap was keyed only on regionName, so switching the active matrix (e.g. SF -> California) within the same region left the camera parked over the previous bbox even though fitCoords had fully recomputed for the new matrix. Build a composite fitKey from regionName + activeTable so a matrix switch counts as a region change and the auto-fit gate resets. Bumps image to v1.1.22.
loadRandomOrigin updates state in two commits separated by an await: A sets originHex/originLat/originLon/activeTable while destinations is still []; B then sets destinations(dests) after fetchReachability. With the previous fitKey = regionName|activeTable, commit A flipped the key, useFitMap reset hasFittedRef and fit a single-point bbox at zoom 14 on the new origin, locking hasFittedRef=true. Commit B's full hex extents then hit the early-return gate, so the camera stayed pinned on the origin instead of zooming out to fit the full reachability area. Widen fitKey to also include originHex, mode, destHex, and a hasDests boolean so the destinations-loaded transition flips the key again and the hook re-fits with the complete dataset. driveTimeLimit / slider state is intentionally excluded so adjusting time does not jerk the camera. Bumps ors_control_app image to v1.1.23.
…e echo DevTools probe on v1.1.23 confirmed viewState was pinned to the hardcoded fallback even when 5 layers and the recenter button were mounted. The auto-fit effect's setViewState was being silently reverted by deck.gl 9 echoing the previous viewState back through onViewStateChange in controlled mode. - Tag every programmatic setViewState in useFitMap with transitionDuration: 600 + FlyToInterpolator so deck.gl honors the update as an explicit transition. - One-shot ref guard (echoGuardRef = 2) suppresses the next two onViewStateChange events fired in response to the programmatic update, preventing the revert. User pan/zoom events still flow. - Add coordsRef and dimsRef for closure safety on future imperative paths. Bumps image to v1.1.26 (parallel session bumped past v1.1.23).
… ensureTables Snowflake's ALTER TABLE ADD COLUMN IF NOT EXISTS raises a spurious "ambiguous column name" compile error when the column already exists. This killed startGeneration before any data work began. Two-layer fix: 1. Wrap backfill ALTERs (EVENT_TS, LOG_TEXT) in EXECUTE IMMEDIATE + BEGIN…EXCEPTION so the error never escapes Snowflake. 2. Add catch-block guard for "ambiguous column name" / "already exists" patterns → log as INFO no-op and continue. Deployed as ors_control_app:v1.1.26. .... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code) Co-Authored-By: Cortex Code <noreply@snowflake.com>
…al clarity Adds a UI toggle and editable lat/lon inputs in the Backload Matching solver controls. When enabled, every VROOM vehicle.end is set to the same coordinate so all solved trailer routes converge visually on one point. Defaults to Copenhagen (12.5655, 55.6759) anchor. KPIs are unaffected because EMPTY_KM is computed from pickup-to-dropoff distance, independent of vehicle.end. Bumps ors_control_app to v1.1.27.
…hared hooks Cherry-picks the SUMMIT branch's richer Route Optimiser (VRP) page and adapts it to the current branch's refactored architecture (useFitMap, RecenterButton, coordsFromGeoJSON, availableProfiles from ORS_STATUS, region-aware OPTIMIZATION and ISOCHRONES calls, _OPTIMIZATION_RAW error probe). New UX: - Industry-driven flow (industry first, then search location) - Per-skill capacity, dynamic skill labels from LOOKUP.STYPE - Universal depot selector (DEPOT_CTYPE / DEPOT_LABEL from LOOKUP) — works for SEN Transport (schools) and any other industry that defines a depot category - Job templates editor with maxJobs slider - Fleet recommendation engine (vehicles per skill = jobs / capacity) - Two-tab result panel: Map / Job Assignments with turn-by-turn directions - Unassigned jobs banner with Cortex-generated explanation - POI/Routes/Catchment/Depot layer toggles + dark tooltip with route colour Schema fallbacks: queries against LOOKUP.SOURCE_TABLE/DEPOT_CTYPE/DEPOT_LABEL and JOB_TEMPLATE.INDUSTRY are wrapped in try/catch so the component degrades gracefully on installs that haven't applied the v1.0.185 schema migration.
… + capacity Adds the columns the new VRP UI reads: LOOKUP.SOURCE_TABLE STRING — optional override table (e.g. SEN_STUDENTS) LOOKUP.DEPOT_CTYPE ARRAY — POI categories that can serve as depots LOOKUP.DEPOT_LABEL STRING — human-readable depot label (e.g. "School Destinations") JOB_TEMPLATE.INDUSTRY STRING — links job templates to LOOKUP rows CREATE TABLE statements add the new columns inline; ALTER TABLE ADD COLUMN IF NOT EXISTS statements backfill them on installs predating v1.0.185. The SEED_ROUTE_OPTIMIZATION_REGION procedure is updated to: - Carry the new LOOKUP columns through the cross-region copy path - Emit the canonical 5-industry catalog (healthcare/Food/Cosmetics/Beverages/ SEN Transport) on first seed, with depot configs from SUMMIT - Emit 49 SLOT_START/SLOT_END rows in seconds-from-midnight (matches the new UI's secsToHHMM renderer) - Provision a SEN_STUDENTS override table with synthetic student-pickup addresses derived from real PLACES rows within 15km of any school
Previous default (Copenhagen 12.5655, 55.6759) lay outside non-Nordic routing graphs (Germany etc.), causing OPTIMIZATION to return zero assignments because the vehicle.end fell outside ORS coverage. Now sharedDestLon/Lat default to null and are auto-populated from trailers[0].HOME_LON/HOME_LAT whenever the toggle is enabled and the user has not edited the inputs. The fill re-runs when trailers reload (on region switch), so the default always sits inside the active region. Editing either input pins the user's value. Bumps ors_control_app to v1.1.28.
Spreads home POI assignment and trip destinations evenly across the active region polygon for ANY of the 5,194 regions in REGION_CATALOG, instead of inheriting Overture Maps' POI density (which clustered HGV trips in NRW for Germany, Bay Area for California, Paris for France). - engine/spatial.ts: new region-agnostic helpers (binPoisByLatLng, binDegForArea, bboxAreaKm2, spreadStats). bin_deg auto-derived from REGION_CATALOG.BOUNDARY_AREA_KM2 (5km bins for cities, 1deg for continents), zero per-region branches. - engine/fleet.ts: buildFleetWithDiagnostics rounds-robin home POI assignment over BINS, not POIs, so every populated bin gets ~equal vehicle share. Falls back to original behaviour when < min_bins populated (small regions). - engine/routing.ts: pickDestination bins the candidate pool by spatial cell, picks bin uniformly then POI within. Identical to before when only one bin populated. - profiles.ts: defaultDistanceDistributionForArea fills area-aware defaults (more long trips for larger regions); explicit template values preserved. - routes.ts: resolveRegionAreaKm2 reads BOUNDARY_AREA_KM2; injects region_area_km2 + spatial_spread defaults into config at /generate. - jobs.ts: emits per-bin diagnostics (bin_deg, populated_bins, top_bin_share, vehicles per bin p50/p95) so users can verify spread. - ors_control_app_service.yaml: bump to v1.1.28. Default ON for all regions; user can override bin_deg or disable via config.spatial_spread.
…al offset
When 'Force shared destination' is on, all trailers head toward the
same end point. Previously the loaded-leg GeoJsonLayer painted each
route on top of the previous one with alpha 230, so on the shared
corridor only the last-drawn colour remained visible.
Replace the per-assignment GeoJsonLayer with a single PathLayer that
uses PathStyleExtension({ offset: true }) plus getOffset =
(idx - (N - 1) / 2) * 1.5 px. Routes spread laterally into a parallel
ribbon centred on the real road, so all N assignments are visible
along the shared corridor. Lateral offset is gated to forceSharedDest
to avoid bending naturally diverging routes when the toggle is off.
Bumps ors_control_app to v1.1.29.
This was referenced May 27, 2026
…audit Findings from the post-implementation audit of PR #120 issues: - query_tag missing on 4 SQL modules (01_core_infra, 03_region_management, 04_service_lifecycle, 06_matrix_ops) - per-AGENTS.md requirement. - SQL injection in ESTIMATE_MATRIX_COST (#39): P_REGION user input was concatenated directly into EXECUTE IMMEDIATE under EXECUTE AS OWNER. Sanitised via REPLACE single-quote escape. - ORS_REQUEST_LOG (#56) had no retention; would grow unbounded as V_ORS_METRICS_SUMMARY scans -24h with APPROX_PERCENTILE. Added DATA_RETENTION_TIME_IN_DAYS=1 plus a daily ORS_REQUEST_LOG_PURGE_TASK (cron 0 4 UTC, suspended) deleting rows older than 30 days. - Gateway retry jitter (#50) only produced 3 distinct values (req_id[-2:].count('a') / 2). Replaced with random.uniform(0.75, 1.25) so concurrent callers don't synchronize retries. - _retry_matrix_chunked silently dropped failed chunks at the smallest chunk_size, returning a stitched matrix with missing destination columns and no signal to the caller. Added depth-2 recursion guard plus _partial:true marker + failed_destinations list. - Documented the single-profile canary limitation in waitForOrsGraphReady (#53) so future maintainers don't re-discover the trade-off. Refs PR #120; closes audit follow-ups for #39 #50 #53 #56.
… to v1.1.3 Three bugs discovered during e2e smoke testing of PR #120: 1. Wrong container name in SYSTEM$GET_SERVICE_LOGS call. The procedure was passing container='routing-gateway' but the actual container in routing-gateway-service.yaml is 'reverse-proxy'. SYSTEM$GET_SERVICE_LOGS silently returned empty -> procedure short-circuited with reason='empty_logs' -> ORS_REQUEST_LOG never received any rows. 2. tail_lines = 5000 exceeds the SYSTEM$GET_SERVICE_LOGS hard cap of 1000. Lowered to 1000. The 1-minute task schedule plus the 5-minute overlap window in the default cutoff is enough headroom for typical traffic. 3. Cutoff filter compared TIMESTAMP_LTZ against SYSDATE(). SYSDATE() is TIMESTAMP_NTZ in account TZ (PT for this account), so every parsed metric ts (UTC LTZ) appeared 7+ hours before the cutoff and was filtered out. Switched to CURRENT_TIMESTAMP() (LTZ). After all 3 fixes: ingest parses metric lines, INSERTs them into ORS_REQUEST_LOG, and V_ORS_METRICS_SUMMARY returns valid p50/p95/error_rate. Both ORS_METRICS_INGEST_TASK and ORS_REQUEST_LOG_PURGE_TASK resumed. Also bumped routing_reverse_proxy v1.1.2 -> v1.1.3 (gateway image with random.uniform jitter + _retry_matrix_chunked depth guard from the audit-pr-120 commit) and updated routing-gateway-service.yaml + image-versions.env
Demos exercise the gateway with larger matrices than the default ORS_GUARDRAIL_MATRIX_MAX_LOCATIONS=200 allows: - BackloadMatching: BM_MAX_MATRIX_LOCATIONS = 500 unique locations - Studio routability: BATCH_SIZE = 1 source + 1000 destinations per MATRIX_TABULAR call - AssetVelocity: 50 + 50 = 100 (already fits) Engine-side caps in ors-config.yml are already permissive: matrix.maximum_routes = 2,000,000 (sqrt = 1414), so the gateway env var is the only bottleneck. Set it to 1500 -- covers both demos with headroom under the engine ceiling, and _retry_matrix_chunked still recovers via 50 -> 10 fallback. Also bumped: - ORS_GUARDRAIL_ISOCHRONES_MAX_LOCATIONS 2 -> 5 (what-if comparisons) - Other guardrails kept at engine-aligned defaults. Verified end-to-end: - 250-loc matrix: returns 250 duration rows (was rejected before). - 1000-loc matrix: returns 1000 duration rows. - 2000-loc matrix: still rejected with structured request_too_large error citing the new cap of 1500. No image rebuild; just spec env vars + ALTER SERVICE cycle.
Bug: activateDataset() in server/studio/jobs.ts toggled IS_ACTIVE on the
target DIM_DATASETS row without checking whether that DATASET_ID had any
matching rows in the base tables. Foot-gun: when a placeholder row
(legacy '-seed' recovery rows, or a row whose base data was deleted
out-of-band) gets activated, every V_*_CURRENT view silently returns
zero and the fleet/freight pages are empty with no diagnostic.
Reproduction: delete all non-default datasets for (region, vehicle_type),
switch to the remaining (default/seed) one, watch every fleet page go
empty.
Fix: probe COUNT(*) FROM DIM_FLEET WHERE JOB_ID=<datasetId> before the
UPDATE. If zero, throw with an actionable message ("re-run Data Studio
or pick a different dataset"). The /api/studio/datasets/:id/activate
route already wraps in try/catch and returns 400, so the user sees
the message as a UI toast.
Bumped ors_control_app v1.1.54 -> v1.1.55. Spec + image-versions.env
updated; image already pushed and live in SPCS.
…ult idle threshold The Asset Velocity matrix call passed a dollar-quoted JSON string literal (VARCHAR) to OPENROUTESERVICE_APP.CORE.MATRIX, which only has ARRAY and VARIANT overloads. The planner reported 'Invalid argument types for function MATRIX: (VARCHAR(16), VARCHAR(3636), VARCHAR(12))'. Wrapping with PARSE_JSON(...) selects the (VARCHAR, VARIANT, VARCHAR) overload. Also lower the default idle threshold from 4h to 1h so the panel surfaces idle vehicles on fresh installs (Studio runs only generate ~24h of dwell data, so 4h+ thresholds yield 0 rows). Helper text updated to reflect the new default and recommend raising to 72h+ for ghost-trailer-only views. Bumps ors_control_app image v1.1.55 -> v1.1.56.
…windows; skip break for non-HGV The 'Profile may not be available' message was a guess that fired whenever OPTIMIZATION's TVF returned 0 rows. The TVF flattens resp:routes, so VROOM returning routes:[] yields 0 rows even when the call succeeded. Re-query _OPTIMIZATION_RAW on the empty path and report summary.unassigned plus the first few unassigned descriptions instead. vroom-map The 'Profile may not be available' message was a guess that fired whenever OPTIMIZATION's TVF returned 0 rows. The TVF flattens resp:routes, so VROOM returning routes:[] yields 0 rows even when the call succeeded. Re-query _OPTIMIZATION_RAW on the empty path and report summary.unassigned plus the first few unassigned descriptions instead. vroom-map The 'Profile may not be available' message was a guess that fired whenever OPTIMIZATION's TVF returned 0 rows. The TVF flattens resp:routes, so VROOM returningnd forcing a break inside the shift window makes VROOM drop the vehicle. - capacity[0] raised from 1 to terminals.length so a vehicle isn't capped at one stop. Bumps ors_control_app image v1.1.56 -> v1.1.57.
…ASS_PROFILE
On a fresh SanFrancisco/ebike install, "Solve Backloads" returned
"VROOM placed 0 shipments out of 90. Top reasons: 90x unknown" and
the log showed profile=driving-car for an ebike preset. Four bugs:
1. VW_TRAILERS used DIM_FLEET.BATTERY_RANGE_KM (EV range, not payload)
so ebike vehicles got tiny capacities that no shipment fits.
2. VW_INTERNAL_VOLUMES anchored pickup windows at TRIP_START (past)
while vehicle shift starts at min(ETA) (past); both stale.
3. BackloadMatching.tsx picked provProfile.split(',')[0] - the first
ORS profile provisioned for the region - regardless of the active
vehicle_type, so an ebike preset solved on the driving-car graph.
4. Unassigned reasons read u.reason; VROOM v1.14 returns description,
so every rejection bucketed as "unknown".
Fix: introduce OPENROUTESERVICE_APP.CORE.VEHICLE_CLASS_PROFILE as the
single source of truth for per-class capacity, costs, ORS profile, and
UI label. Eight seeded classes (bicycle, ebike, foot, motorcycle, car,
van, hgv, truck). Init.ts and bootstrap.sql now drive VW_TRAILERS
payload, VW_INTERNAL_VOLUMES + VW_EXTERNAL_OFFERS weights, and pickup
window anchor from the profile. React binds ORS profile to the
vehicle_type's canonical profile and refuses to solve when the region
isn't provisioned with it. Vehicle shift floored to "now". Pre-flight
catches median-shipment-exceeds-capacity and no-window-overlap before
calling VROOM. Unassigned parser reads description ?? reason ?? type.
Class-aware post-mortem prepends a wrong-class hint when 100% fail.
Image v1.1.59 deployed.
.... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code)
Co-Authored-By: Cortex Code <noreply@snowflake.com>
…rks for any class The Optimize Repositioning button was hard-coded for HGV semantics: RESTAURANT terminals demanded a REEFER skill (id=1) but only trucking trailers (with VEHICLE_SUBTYPE) ever offered REEFER. For ebike/SF the class has no subtype, so every restaurant job was unassignable and VROOM returned routes:[]. The new toast surfaced the symptom but not the root cause. Asset Velocity now loads OPENROUTESERVICE_APP.CORE.VEHICLE_CLASS_PROFILE for the active CONFIG.VEHICLE_TYPE (the same loader Backload Matching already uses) and drives the VROOM challenge from that single row: - profile <- klass.ORS_PROFILE (cycling-electric for ebike, etc.) - ENFORCE_BREAK gates the EU-561 mandatory 45-min break (HGV only) - ENFORCE_BREAK gates skill matching (REEFER/FLAT/TANKER/HAZMAT) - capacity <- [maxStops, PAYLOAD_KG_TYP, PAYLOAD_KG_MAX] - service <- 300s for couriers/cars; 600-1800s for trucking by terminal - exclusion <- skill mismatch only when the active class is trucking If VEHICLE_CLASS_PROFILE has no row for the active vehicle_type the page refuses to optimize and surfaces a friendly error instead of silently returning 0 routes. Bumps ors_control_app image to v1.1.60.
…installs
The Observability page renders SQL 422 ("schema does not exist") on accounts
where module 08_observability.sql was never applied. Two-layer fix:
1. SKILL.md deploy loop now includes 07_studio_jobs.sql, 08_observability.sql,
and 15_route_optimization_seed.sql (previously stopped at 06), and resumes
the ORS_METRICS_INGEST_TASK + ORS_REQUEST_LOG_PURGE_TASK after deploy. The
automated scripts/deploy.sh already iterated *.sql so this aligns the
manual SKILL.md path with it.
2. server/lib/init.ts gains ensureObservabilityObjects() which idempotently
creates the OBSERVABILITY schema, ORS_REQUEST_LOG table, and
V_ORS_METRICS_SUMMARY view on every container boot. Mirrors module 08 so
the page renders even on accounts that skipped that module — empty rather
than 422. Procedure + tasks remain owned by module 08 (operator runs that
to actually populate data).
Reduces SQL API round trips ~4x for the per-day telemetry flush in insertTelemetryBatch. A typical 65k-point day previously needed 130 sequential INSERTs (~5 min); 2000-row UNION ALL stays well under Snowflake parser limits and cuts that to ~33 INSERTs.
… flush generateTelemetry now dispatches up to config.parallelism (default 8) vehicle-day workers concurrently within each simulated day instead of running the fleet sequentially. Each worker's ORS route calls, interpolation, and dwell emission run independently; the parent generator drains results race-style via Promise.race over an in-flight map. Telemetry is also yielded incrementally: when the day buffer reaches 2000 points it is flushed mid-day, so INSERT batches overlap with the next vehicles' ORS calls and the SSE progress stream stays alive between days (no more multi-minute apparent pause). Recovery and hard-stop logic are now applied in the parent loop after each worker resolves, with a single-flight tryRecover() helper so parallel workers don't trigger redundant ALTER SERVICE RESUMEs. Per-vehicle RNG seeds are derived up-front from the global rng so any single vehicle's emitted sequence stays self-consistent regardless of worker completion order. Adds optional `parallelism` field to GenerationConfig (default 8, set to 1 for fully sequential reproducible runs). Expected speedup: ~5-8x on the ORS phase (was the dominant cost), so a 50-vehicle 7-day run drops from ~2h to ~25-30 min. Backend is sized for this: ORS_SERVICE_<REGION> already runs 4 instances and ROUTING_GATEWAY_SERVICE 8.
The control-app container is now the orchestrator for parallel Studio generation (up to 8 concurrent vehicle-day workers) and accumulates larger 2k-point telemetry buffers in memory before each flush. The previous 0.5/1 CPU + 0.5/1 GiB ceiling left no headroom for the parallel I/O and was unrelated to ORS itself (which runs in ORS_SERVICE_<REGION>).
…xtend-dim-fleet-hgv view-drop fix 1. AGENTS.md: document the DIM_DATASETS bootstrap invariant (friction-log F4 fix) — init.ts must call ensureUnifiedTables() before V_*_CURRENT views, and ALTER TABLE on DIM_FLEET must DROP the dependent view first. 2. extend-dim-fleet-hgv.sql: add DROP VIEW IF EXISTS V_DIM_FLEET_CURRENT before ADD COLUMN statements to prevent column-count mismatch on next boot. 3. Friction log from today's full deploy captured. .... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code) Co-Authored-By: Cortex Code <noreply@snowflake.com>
…road route on map Switch offers read to VW_OFFER_ENRICHED_V2 for cached ROUTE_GEOMETRY, add useSelectedOfferRoute with live /api/fx/offer-route fallback, and render pickup/dropoff markers plus PathLayer on the map. Bump ors_control_app to v1.1.61. Co-authored-by: Cursor <cursoragent@cursor.com>
…changes Expose activeDatasetId from /api/fleet-config and include it in the page dataKey so Freight Exchange and sibling pages refetch after a Studio rerun. Co-authored-by: Cursor <cursoragent@cursor.com>
…03 on read-only /api/query) The page's regionName useEffect was issuing two UPDATE statements through sfQuery, which posts to /api/query. That endpoint is intentionally read-only (SELECT/SHOW/DESCRIBE/DESC/CALL/WITH) and rejected the UPDATEs with HTTP 403 'Only read-only queries allowed'. The first failure was swallowed silently; the second logged a visible warning whenever the user switched region. CONFIG.REGION + CONFIG.VEHICLE_TYPE (on both BACKLOAD_MATCHING.CONFIG and ROUTE_OPTIMIZATION.CONFIG) are already kept in sync atomically by POST /api/datasets/activate, which runs server-side via runSql and updates all 6 demo CONFIG tables in one round-trip. The page only needs to refetch after the region changes. This mirrors the same v1.1 fix already applied in AssetVelocity.tsx (see comment at AssetVelocity.tsx:71-74).
Expose hybrid orsProfile on /api/fleet-config, add useActivePreset and PresetRoutingControls, and wire all ORS-calling demos to preset region/profile. Co-authored-by: Cursor <cursoragent@cursor.com>
…t profile, gateway multi-isochrone - Fix DIRECTIONS/ISOCHRONES/MATRIX/OPTIMIZATION SQL in freight_exchange.ts (FROM TABLE, arg order) - Resolve routing profile from MARKETPLACE.CONFIG JOIN DIM_DATASETS (active preset) - Add gateway POST /isochrones + SQL multi-point ISOCHRONES overload (routing_reverse_proxy v1.1.4) - Drop client vehicleType from offer-route; bump ors_control_app to v1.1.63 Co-authored-by: Cursor <cursoragent@cursor.com>
Preset-sync effects no longer depend on local selectedRegion/selectedProfile, so changing region or transport type in Directions & Isochrones stays put until the header dataset preset actually changes. Co-authored-by: Cursor <cursoragent@cursor.com>
Tag DATASET_EMPTY and BOOT_INCOMPLETE in activateDataset, map to 409/503 in /api/datasets/activate, gate recovered DIM_DATASETS rows on DIM_FLEET, expose fleetRowCount in GET /api/datasets, and fix DatasetPicker to check res.ok with inline errors and unavailable preset pills (v1.1.65). Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.