Background / Context
The ORS Control App exposes a region picker and a vehicle-type switcher. Changing the vehicle type currently updates the CONFIG.VEHICLE_TYPE column in six skill schemas, which only filters the projection views over SYNTHETIC_DATASETS.UNIFIED. Downstream analytical thresholds (SLA, geofence, route deviation, H3 granularity, speeding) remain hardcoded and vehicle-agnostic, producing unrealistic demo results (e.g. an HGV loading dock judged against the same SLA as an e-bike restaurant pickup).
The data generation engine (server/studio/profiles.ts) already encodes realistic per-vehicle parameters, but none of these values are reflected in the SQL pipelines that analyze the generated data.
User Story
As a demo presenter
I want vehicle-type selection to automatically apply realistic per-vehicle thresholds across every demo
So that switching from taxi to e-bike to HGV produces operationally plausible SLA alerts, geofence behaviour, deviation flags, and congestion heatmaps.
Acceptance Criteria
AC-1: Vehicle-aware threshold reference table exists
- A new table
VEHICLE_THRESHOLDS is created in every skill schema that currently has a CONFIG table (6 schemas: DWELL_ANALYSIS, ROUTE_DEVIATION, FLEET_INTELLIGENCE_TAXIS, FLEET_INTELLIGENCE_FOOD_DELIVERY, RETAIL_CATCHMENT, ROUTE_OPTIMIZATION).
- The table is pre-seeded for all supported vehicle types (
car, ebike, hgv) so no row-level mutations are required when the vehicle type changes.
- All objects include the required
COMMENT tracking tag per AGENTS.md.
AC-2: Dwell analysis uses vehicle-aware SLA thresholds
DT_SLA_ALERTS joins VEHICLE_THRESHOLDS on VEHICLE_TYPE = (SELECT VEHICLE_TYPE FROM CONFIG LIMIT 1) AND LOCATION_TYPE.
- Switching vehicle type in the UI changes the warning/critical minute thresholds applied to open dwell sessions (verified via reading
DT_SLA_ALERTS before and after the switch).
AC-3: Dwell analysis uses vehicle-aware geofence radii
GEOFENCE_POLYGONS CTAS uses the GEOFENCE_RADIUS_M column from VEHICLE_THRESHOLDS instead of the current hardcoded IFF(LOCATION_TYPE = 'WAREHOUSE', 200, 100) logic.
- HGV gets larger buffers than e-bike (per values in the Threshold Matrix below).
AC-4: Route deviation threshold is vehicle-aware
route-deviation/references/seed-data.sql hardcoded 20% deviation check is replaced by a lookup against VEHICLE_THRESHOLDS.DEVIATION_PCT.
- HGV deviation flag fires at 10% while e-bike deviation flag fires at 25%.
AC-5: Live Operations UI reads threshold from DB
.cortex/skills/build-routing-solution/openrouteservice_app/services/ors_control_app/src/components/dwell/LiveOperations.tsx no longer hardcodes 30 minutes.
- The SLA threshold used in the live dashboard comes from
VEHICLE_THRESHOLDS for the currently active vehicle type.
AC-6: Vehicle-type switch endpoint works end-to-end
POST /api/fleet-config/vehicle-type updates CONFIG.VEHICLE_TYPE in all 6 skill schemas (existing behaviour preserved).
- After the call completes, downstream DTs refresh with thresholds appropriate to the new vehicle type (within one DT refresh cycle: 5-10 minutes).
- A new endpoint
GET /api/fleet-config/thresholds returns the currently active vehicle's threshold values for display in the UI.
AC-7: Documentation and cleanup
- Each affected skill's
SKILL.md has a ## Thresholds section documenting the per-vehicle-type values.
AGENTS.md is updated to note the new VEHICLE_THRESHOLDS pattern.
- Cleanup sections in affected skills include
DROP TABLE VEHICLE_THRESHOLDS.
Proposed Data Model
CREATE TABLE VEHICLE_THRESHOLDS (
VEHICLE_TYPE VARCHAR NOT NULL, -- 'car' | 'ebike' | 'hgv'
LOCATION_TYPE VARCHAR NOT NULL, -- 'WAREHOUSE' | 'DESTINATION' | 'REST_STOP' | 'STORE' | 'DETOUR' | '*'
SLA_WARNING_MIN NUMBER,
SLA_CRITICAL_MIN NUMBER,
GEOFENCE_RADIUS_M NUMBER,
DEVIATION_PCT NUMBER(5,2),
SPEED_LIMIT_FACTOR NUMBER(3,2),
H3_RESOLUTION NUMBER(2),
PRIMARY KEY (VEHICLE_TYPE, LOCATION_TYPE)
) COMMENT = '{"origin":"sf_sit-is-fleet", ...}';
Threshold Matrix (Required Seed Values)
SLA Thresholds (minutes: WARNING / CRITICAL)
| Location Type |
Car |
E-Bike |
HGV |
| WAREHOUSE |
8 / 20 |
5 / 12 |
30 / 90 |
| DESTINATION |
5 / 15 |
3 / 8 |
20 / 60 |
| REST_STOP |
10 / 25 |
5 / 15 |
45 / 90 |
| STORE |
3 / 10 |
2 / 6 |
15 / 45 |
| DETOUR |
3 / 8 |
2 / 5 |
5 / 15 |
Geofence Radii (meters)
| Location Type |
Car |
E-Bike |
HGV |
| WAREHOUSE |
150 |
80 |
300 |
| DESTINATION |
80 |
50 |
200 |
| REST_STOP |
120 |
60 |
250 |
| STORE |
80 |
40 |
200 |
| DETOUR |
80 |
50 |
200 |
Global Vehicle-Level Thresholds (LOCATION_TYPE = '*')
| Parameter |
Car |
E-Bike |
HGV |
| Deviation % |
15 |
25 |
10 |
| Speed limit factor |
1.10 |
1.05 |
1.05 |
| H3 resolution |
8 |
9 |
7 |
Files to Modify
| # |
File |
Change |
| 1 |
.cortex/skills/dwell-analysis/references/seed-data.sql |
Add VEHICLE_THRESHOLDS DDL + inserts for all vehicle types |
| 2 |
.cortex/skills/dwell-analysis/references/sql-pipeline.sql |
GEOFENCE_POLYGONS and DT_SLA_ALERTS JOIN VEHICLE_THRESHOLDS |
| 3 |
.cortex/skills/route-deviation/references/seed-data.sql |
Add table, replace hardcoded 20% with lookup |
| 4 |
.cortex/skills/fleet-intelligence-taxis/references/seed-data.sql |
Add table (speed factor) |
| 5 |
.cortex/skills/fleet-intelligence-food-delivery/references/seed-data.sql |
Add table (speed + delivery SLA) |
| 6 |
.cortex/skills/retail-catchment/references/seed-data.sql |
Add table (stub, future use) |
| 7 |
.cortex/skills/route-optimization/references/seed-data.sql |
Add table (stub, future use) |
| 8 |
openrouteservice_app/services/ors_control_app/src/components/dwell/LiveOperations.tsx |
Replace hardcoded 30 with DB lookup |
| 9 |
openrouteservice_app/services/ors_control_app/server/index.ts |
Add GET /api/fleet-config/thresholds endpoint |
| 10 |
.cortex/skills/dwell-analysis/SKILL.md |
Document Thresholds section |
| 11 |
.cortex/skills/route-deviation/SKILL.md |
Document Thresholds section |
| 12 |
AGENTS.md |
Document VEHICLE_THRESHOLDS pattern |
Out of Scope
- H3 resolution per vehicle type is deferred. Dynamic Tables cannot use subqueries inside
H3_POINT_TO_CELL_STRING(). Implement a fixed compromise (R8) for now; parameterize in a follow-up ticket once a stored-procedure DT rebuild pattern is agreed.
- Region-specific overrides (e.g. London vs rural region): tracked in a separate ticket.
escooter vehicle type is referenced in the UI but has no profiles.ts template; threshold seeding for it is deferred until the profile exists.
- Auto-sync between
profiles.ts and VEHICLE_THRESHOLDS: manual for now.
Test Plan
Open Questions
- Should
escooter ship with a best-guess threshold set or be explicitly unsupported until a profiles.ts template exists?
- Should thresholds be region-aware in this iteration, or strictly vehicle-aware?
- Should UI show a "Thresholds in use" panel so demo presenters can see what changed?
Background / Context
The ORS Control App exposes a region picker and a vehicle-type switcher. Changing the vehicle type currently updates the
CONFIG.VEHICLE_TYPEcolumn in six skill schemas, which only filters the projection views overSYNTHETIC_DATASETS.UNIFIED. Downstream analytical thresholds (SLA, geofence, route deviation, H3 granularity, speeding) remain hardcoded and vehicle-agnostic, producing unrealistic demo results (e.g. an HGV loading dock judged against the same SLA as an e-bike restaurant pickup).The data generation engine (
server/studio/profiles.ts) already encodes realistic per-vehicle parameters, but none of these values are reflected in the SQL pipelines that analyze the generated data.User Story
As a demo presenter
I want vehicle-type selection to automatically apply realistic per-vehicle thresholds across every demo
So that switching from taxi to e-bike to HGV produces operationally plausible SLA alerts, geofence behaviour, deviation flags, and congestion heatmaps.
Acceptance Criteria
AC-1: Vehicle-aware threshold reference table exists
VEHICLE_THRESHOLDSis created in every skill schema that currently has aCONFIGtable (6 schemas:DWELL_ANALYSIS,ROUTE_DEVIATION,FLEET_INTELLIGENCE_TAXIS,FLEET_INTELLIGENCE_FOOD_DELIVERY,RETAIL_CATCHMENT,ROUTE_OPTIMIZATION).car,ebike,hgv) so no row-level mutations are required when the vehicle type changes.COMMENTtracking tag perAGENTS.md.AC-2: Dwell analysis uses vehicle-aware SLA thresholds
DT_SLA_ALERTSjoinsVEHICLE_THRESHOLDSonVEHICLE_TYPE = (SELECT VEHICLE_TYPE FROM CONFIG LIMIT 1)ANDLOCATION_TYPE.DT_SLA_ALERTSbefore and after the switch).AC-3: Dwell analysis uses vehicle-aware geofence radii
GEOFENCE_POLYGONSCTAS uses theGEOFENCE_RADIUS_Mcolumn fromVEHICLE_THRESHOLDSinstead of the current hardcodedIFF(LOCATION_TYPE = 'WAREHOUSE', 200, 100)logic.AC-4: Route deviation threshold is vehicle-aware
route-deviation/references/seed-data.sqlhardcoded20%deviation check is replaced by a lookup againstVEHICLE_THRESHOLDS.DEVIATION_PCT.AC-5: Live Operations UI reads threshold from DB
.cortex/skills/build-routing-solution/openrouteservice_app/services/ors_control_app/src/components/dwell/LiveOperations.tsxno longer hardcodes30minutes.VEHICLE_THRESHOLDSfor the currently active vehicle type.AC-6: Vehicle-type switch endpoint works end-to-end
POST /api/fleet-config/vehicle-typeupdatesCONFIG.VEHICLE_TYPEin all 6 skill schemas (existing behaviour preserved).GET /api/fleet-config/thresholdsreturns the currently active vehicle's threshold values for display in the UI.AC-7: Documentation and cleanup
SKILL.mdhas a## Thresholdssection documenting the per-vehicle-type values.AGENTS.mdis updated to note the newVEHICLE_THRESHOLDSpattern.DROP TABLE VEHICLE_THRESHOLDS.Proposed Data Model
Threshold Matrix (Required Seed Values)
SLA Thresholds (minutes: WARNING / CRITICAL)
Geofence Radii (meters)
Global Vehicle-Level Thresholds (LOCATION_TYPE = '*')
Files to Modify
.cortex/skills/dwell-analysis/references/seed-data.sqlVEHICLE_THRESHOLDSDDL + inserts for all vehicle types.cortex/skills/dwell-analysis/references/sql-pipeline.sqlGEOFENCE_POLYGONSandDT_SLA_ALERTSJOINVEHICLE_THRESHOLDS.cortex/skills/route-deviation/references/seed-data.sql.cortex/skills/fleet-intelligence-taxis/references/seed-data.sql.cortex/skills/fleet-intelligence-food-delivery/references/seed-data.sql.cortex/skills/retail-catchment/references/seed-data.sql.cortex/skills/route-optimization/references/seed-data.sqlopenrouteservice_app/services/ors_control_app/src/components/dwell/LiveOperations.tsx30with DB lookupopenrouteservice_app/services/ors_control_app/server/index.tsGET /api/fleet-config/thresholdsendpoint.cortex/skills/dwell-analysis/SKILL.md.cortex/skills/route-deviation/SKILL.mdAGENTS.mdOut of Scope
H3_POINT_TO_CELL_STRING(). Implement a fixed compromise (R8) for now; parameterize in a follow-up ticket once a stored-procedure DT rebuild pattern is agreed.escootervehicle type is referenced in the UI but has noprofiles.tstemplate; threshold seeding for it is deferred until the profile exists.profiles.tsandVEHICLE_THRESHOLDS: manual for now.Test Plan
dwell-analysisskill, verifyVEHICLE_THRESHOLDSexists with rows for car/ebike/hgv.DT_SLA_ALERTSuses HGV thresholds (warehouse warning = 30 min, not 5 min).GEOFENCE_POLYGONSuses 80m warehouse buffer (not 200m).LiveOperations.tsxSLA count changes when vehicle type changes.GET /api/fleet-config/thresholdsreturns the current vehicle's values.python3 .cortex/skills/evals/run_evals.pyto confirm no skill eval regressions.VEHICLE_THRESHOLDStables are dropped.Open Questions
escootership with a best-guess threshold set or be explicitly unsupported until aprofiles.tstemplate exists?