Throttle-Cut Policy
When sidewalk detection fires, Levy Vision uses a configurable policy ladder to decide what enforcement to apply: warn the rider, reduce top speed, or cut throttle entirely. This article explains how the ladder works, how restoration is gated, and how to tune it for your fleet.
The ladder runs against the same disableVehicleThrottle() and enableVehicleThrottle() IoT command path you already use elsewhere on the platform — there's no new throttle-control surface, just a new caller.
The default ladder
Out of the box, the policy runs these steps in order within a single ride:
| Event count | Action | What the rider sees |
|---|---|---|
| 1st sidewalk event | warn_push | Sidewalk warning modal + "Move to the road" push |
| 2nd sidewalk event | speed_reduce | Top speed capped at 50%, modal updates |
| 3rd sidewalk event | throttle_cut | Throttle disabled, restore screen with countdown |
Each step is gated by a per-subaccount threshold in Safety > Safety settings. Lower the thresholds for stricter fleets, raise them for ones with looser cities or known false-positive geographies.
When the ladder skips a step
Not every IoT protocol supports every step. The policy engine reads the vehicle's protocol from the database and skips unsupported steps:
- No speed-cap support (Queclink, Zimo, Acton legacy) — speed_reduce step is skipped, the rider goes straight from warn to cut on their next sidewalk event
- No throttle-cut support — only warn fires, no enforcement
- Vehicle unreachable (IoT offline) — the policy logs a
queuedaction that retries when the vehicle reports back, up to 60 seconds; after that, the action is logged as failed
Each step that fires writes a row to cv_violation_actions so you have an audit trail of what was attempted and whether it succeeded.
Configuring the ladder
Open Dashboard > Safety > Safety settings and find the Sidewalk detection section.
Threshold controls
| Setting | Default | What it controls |
|---|---|---|
| Warn threshold | 1 | Sidewalk events before the warning push fires |
| Speed-reduce threshold | 2 | Sidewalk events before mid-ride speed cap |
| Cut threshold | 3 | Sidewalk events before throttle disable |
| Throttle cut enabled | off | Master switch — if off, the cut step is suppressed entirely |
| Fee per event | 0 | Optional fee in cents charged at end-of-ride per sidewalk event |
You can also set thresholds to 0 to disable a specific step without re-ordering the ladder — useful if you want speed-reduce only with no cut.
Per-ride vs cumulative
Thresholds are per-ride. They reset to zero at the start of every new ride, even for repeat-offender riders. If you want a multi-ride accumulator (e.g., "5 events in a month triggers a manual review"), that's a separate use of the Safety > Events feed plus your CRM or operator dashboard — there's no built-in cumulative ban path today.
How throttle restoration works
When a rider gets cut, they see the Throttle restore screen:
- A 30-second countdown
- A small map showing their position
- "I'm back on the road" button (disabled until countdown finishes)
The flow:
- Countdown finishes. The button activates.
- Rider taps I'm back on the road.
- The app posts to
/api/mobile/cv/restore-throttle-requestwith the ride ID. - The server checks 30 seconds of clean telemetry (no sidewalk events in the window).
- If clean:
enableVehicleThrottle()is called, throttle returns, modal dismisses. - If not clean: the rider sees "Still on a sidewalk — try again in 30s" and the countdown restarts.
This gating exists to prevent a rider from immediately resuming sidewalk riding after a cut.
Operator manual restore
Sometimes you need to override — the cut was a false positive, the rider is stuck, the vendor model misfired. Two paths:
From the dashboard
- Open Safety > Events or Safety > Helmet compliance (events feed).
- Find the throttle_cut event row.
- Click Restore throttle in the action menu.
- The IoT command fires; the rider's throttle returns within a few seconds.
The override is logged in cv_violation_actions with action='throttle_restore' and your user as the actor.
From the operator app
The field-tech operator app has a Safety events screen with a one-tap Restore throttle button on each cut row. Same effect as the dashboard path; useful for techs in the field.
Flag the false positive too
When you manually restore, also click Flag false positive on the underlying sidewalk event. That feeds the labeled image (if the vendor sent one) back into the vendor's model improvement pipeline.
End-of-ride fee
If you set Fee per event to a non-zero value, every sidewalk event during the ride adds that amount to the ride's final fare. As with parking-pose, the fee flows through the ride record (not directly into the wallet), so net-deposited and partner-payout math stays correct.
If a rider disputes a sidewalk fee, handle it the same way as any other fare dispute: open the ride, click Adjust fare, and reduce the total. The wallet credit (if any) flows automatically.
Privacy notes
The vendor model runs entirely on-vehicle. Levy Vision receives only normalized events (timestamp, lat/lng, confidence, vendor event ID) — never video, never raw frames. There is no live operator-streamed video on this platform.
City compliance feeds aggregate event lat/lng and timestamps; rider identity is stripped before the MDS export leaves the system. See MDS export for cities for the export schema.
Common questions
Can I disable enforcement on a specific vehicle?
Not via a per-vehicle toggle. The recommended path is a geofence allow-list polygon over that vehicle's territory, or a fleet-wide threshold of 0 for the cut step. If you have a one-vehicle case, contact support.
What if the cut fails because the IoT is offline?
The action is logged as queued and retries for 60 seconds. After that, it's logged as failed. The rider may continue to ride — the failure is a known mode that the rider isn't punished for. The next event triggers the ladder again.
How do I know if the ladder is actually firing in production?
Check Safety > Events for sidewalk_entry events with non-empty side-effects columns. Each fired action writes a cv_violation_actions row visible in the event drawer.