Vehicle History Rebuild
Audience
Maintainers and agents rebuilding per-vehicle historical facts from stored telemetry.
Source Of Truth
This runbook is canonical for the rebuild_vehicle_history maintenance workflow and its post-replay enrichment behavior.
What The Rebuild Does
apps/api/src/bin/rebuild_vehicle_history.rs rebuilds durable per-vehicle history from telemetry by:
- clearing existing
tripsrows for the target vehicle - rebuilding state periods
- rebuilding telemetry-derived charge evidence without deleting canonical
charge_sessions - replaying Rivian completed-session payloads back into canonical matching
- canonicalizing duplicate charge rows and recovering API-only charge history
- replaying trips and telemetry
trip_idlinks - reattaching geofence/address matches and queueing route-aware outside-temperature enrichment
The rebuild is intentionally self-healing for trip presentation and efficiency analysis. A completed rebuild should leave /v1/trips with human-readable start/destination labels when enrichment is available and /v1/efficiency/vs-temp with rebuilt trips included once outside temperatures are restored.
Command
cargo run --bin rebuild_vehicle_history -- [--vehicle <uuid>]
Run from apps/api with DATABASE_URL set.
Supporting charge-session maintenance commands:
cargo run --bin diagnose_charge_sessions -- [--vehicle <uuid>]
cargo run --bin canonicalize_charge_sessions -- [--vehicle <uuid>]
Diagnostics First
Before changing live history, capture the current enrichment gap report for the affected vehicle:
cargo run --bin report_trip_enrichment_gaps -- --vehicle <uuid>
The report groups gaps per vehicle and per UTC day so maintainers can distinguish:
- total trips
- missing trip start/end address IDs
- missing trip start/end geofence IDs
- missing trip
outside_temp_c - address gaps that still have usable coordinates
- address gaps that can be satisfied from cached local addresses
- outside-temperature gaps that still have usable start coordinates
- outside-temperature gaps that are unrecoverable because no usable start coordinates remain
Treat the DB counts as the source of truth. Logs alone are not enough to accept a repair.
Post-Replay Enrichment Behavior
- Trip geofence and address IDs are reattached after replay through the shared trip enrichment service.
- Rebuilt trips enqueue the same idempotent route-aware weather jobs used for new drives. The rebuild does not issue synchronous start-location weather calls.
- Rebuild completion logs now include filled/failed counts for:
- trip geofence matches
- trip address matches
- trip outside-temperature backfills
- Standalone repair commands also support
--vehicle <uuid>and log scanned/filled/failed/skipped counts for targeted repair passes.
Operational Tradeoffs
- Address enrichment can run during the rebuild. Weather restoration is asynchronous and remains pending while Open-Meteo is disabled.
- Reverse geocoding and weather lookups fail gracefully; a rebuild can still finish even when some trips remain partially enriched.
- Because enrichment is external, rebuilds can take longer than pure local replay and may show non-zero failed counts when providers are unavailable or rate-limited.
Verification
Use staged repair for historical gaps:
- Run
report_trip_enrichment_gaps -- --vehicle <uuid>and capture the baseline. - Run targeted trip enrichment backfills for the affected vehicle:
cargo run --bin backfill_geofence_matches -- --vehicle <uuid>
cargo run --bin backfill_trip_addresses -- --vehicle <uuid>
cargo run --bin backfill_outside_temp -- --vehicle <uuid>
- Keep the API worker running, then re-run
report_trip_enrichment_gaps -- --vehicle <uuid>after queued jobs complete and confirm the missing-field counts actually improved. - Run
diagnose_charge_sessions -- --vehicle <uuid>before and after any charge-session rebuild or repair. - Only if coordinate-bearing trips are still missing enrichment should you run
rebuild_vehicle_history -- --vehicle <uuid>. - Immediately rerun the diagnostics report after a rebuild. A rebuild is only accepted when the post-run counts improve and charge-session diagnostics no longer show canonical overlaps, null
sourcerows, or unresolved payload gaps.
After a targeted repair or rebuild, verify the affected vehicle through the shared product seams:
GET /v1/trips?vehicle_id=<uuid>&from=<iso>&to=<iso>returns readablestart_place/start_addressandend_place/end_addresswhere enrichment exists.GET /v1/efficiency/vs-temp?vehicle_id=<uuid>&from=<iso>&to=<iso>returns bins for rebuilt trips once outside temperatures are backfilled.- Focused regression tests:
pnpm -C apps/web exec vitest run src/test/tripColumns.test.tsx src/test/dashboardChartWidget.test.tsx src/test/apiClient.test.ts
Use targeted API integration tests for rebuild/enrichment behavior rather than relying on broad workspace validation when unrelated SQLx or frontend failures are noisy.