Fixes charging - #104
Fixes charging#104
Conversation
Two related charging-accuracy fixes: 1. Charge energy delta baselines now use State() strictly before StartedAt instead of at StartedAt, since Fleet Telemetry can emit the session-start batch after energy has already begun accumulating, causing undercounted energy in both the live handler and the completed-session tracker. 2. New Tesla Supercharger invoice overlay: ChargingHandler.Get resolves the vehicle's VIN and matches it against tesla_charging_history via a new FindBestMatch repo method (closest charge_start_datetime within a 2h window). When a match is found, billed energy/cost/currency/rate are added to the response and preferred for display on the frontend KPI tiles, with vehicle-measured energy shown as a secondary subtitle.
Treat spurious trip-meter resets and implausible counter jumps as discontinuities instead of driven distance. Adds reset/restore cursor logic and tests so include_fields zero snap-backs do not inflate FSD or driving aggregates.
Adds a live Grok powertrain read to Driving Dynamics using motor and chassis signals, with interpretation logic and tests. Also adds shared client-side pagination for FSD insight lists and DataTable-backed FSD tables.
Adds honesty-focused UI across the fleet dashboard, status bar, charging, battery, driving, and FSD views. Surfaces Supercharger bill site/fee metadata, preserves signal ingest timestamps for Tesla physics clocks, paginates physics evidence instead of truncating it, and fixes nav highlighting to prefer the most specific active route.
Add trip selection and date-scoped motor history, preserve active drives, and evenly sample backend history responses across the selected window.
Preserve and backfill charge coordinates without creating geofences from stale GPS, use Tesla billed energy for tariff pricing, and resolve date windows in the vehicle timezone.
Expand the drive detail FSD insights range to look around 24 hours so sparse counter bookends are included, preventing unknown/blank attribution for valid deltas. Adds backend and frontend regression coverage for the wider range behavior.
Adds drive_id support for FSD insights with a 7-day bookend lookup and focused attribution, while filtering negligible fidget drives so they do not steal sparse counter deltas. Updates drive detail and list UI to use the drive-scoped hook and omit unknown FSD badges.
|
One or more custom setup steps configured for this repository failed during this Copilot code review run: Setup steps run before each review. If the review above is missing context, or no review was posted at all, the failing step above may be the cause. See the workflow run for failure details, fix your setup steps configuration, and re-request a review. Note You can configure setup steps for Copilot code review separately from Copilot cloud agent with a |
There was a problem hiding this comment.
Note
Copilot was unable to run its full agentic suite in this review.
Pull request overview
This PR expands “honesty” semantics and vehicle-timezone correctness across the web UI, while adding new driving/charging/battery insight panels and backend support for drive-scoped analytics, billed Supercharger data overlay, and ingest-time provenance.
Changes:
- Add telemetry honesty taxonomy + UI meters (status bar + dashboard) with i18n.
- Make date presets/ranges timezone-aware and query charging/driving windows using RFC3339 instants.
- Add new insights/panels (drive physics debrief, driving dynamics trip scoping + Grok briefing, Supercharger bill-vs-pack truth, vampire drain culprit), alongside backend improvements (received_at ingest time, drive-scoped FSD insights, Tesla billing match, even sampling for motor history).
Reviewed changes
Copilot reviewed 122 out of 122 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/types/charging.ts | Adds billed (invoice) fields to charging session type. |
| web/src/lib/fleetHonesty.ts | Introduces honesty taxonomy helpers and tallies. |
| web/src/lib/fleetHonesty.test.ts | Tests honesty mapping and tallying. |
| web/src/lib/dateRange.ts | Adds timezone civil-date helpers and generalized day addition. |
| web/src/lib/datePresets.test.ts | Tests “today” preset respects vehicle timezone. |
| web/src/lib/tests/dateRange.test.ts | Adds tests for new civil-date helpers. |
| web/src/i18n/en/usage-manifest.json | Registers honesty namespace/keys in manifests. |
| web/src/i18n/en/shell.json | Adds honesty strings for shell UI. |
| web/src/i18n/en/runtime-manifest.json | Adds honesty to runtime manifest. |
| web/src/i18n/en/locale-driving.json | Adds driving “debrief” + experiment/spotlight copy. |
| web/src/i18n/en/locale-dashboard.json | Adds fleet operations “actions” copy. |
| web/src/i18n/en/locale-charging.json | Adds bill-vs-pack copy and billed-energy help text. |
| web/src/i18n/en/locale-battery.json | Adds vampire culprit copy and actions. |
| web/src/hooks/useRangeState.ts | Resolves timezone once and passes it into preset resolution. |
| web/src/features/vehicles/pages/TeslaOnlyPage.test.tsx | Tests ingest time display + client pagination behaviors. |
| web/src/features/driving/pages/DrivingDynamicsPage.tsx | Adds drive scoping, range picker, Grok panel, and drive window motor history. |
| web/src/features/driving/pages/DrivesListPage.test.tsx | Updates expectations after removing “FSD unknown” badge. |
| web/src/features/driving/pages/DriveDetailPage.tsx | Uses drive-scoped FSD insights and adds physics debrief panel. |
| web/src/features/driving/pages/DriveDetailPage.test.tsx | Updates mocks/tests for drive-scoped FSD hook and new panel. |
| web/src/features/driving/lib/fsdCommuteExperiment.ts | Builds “same-route experiment” model from insights. |
| web/src/features/driving/lib/fsdCommuteExperiment.test.ts | Tests experiment builder logic. |
| web/src/features/driving/components/fsd-insights/useClientPagination.ts | Adds shared client pagination hook for in-memory lists. |
| web/src/features/driving/components/fsd-insights/FsdTopDays.tsx | Enables DataTable pagination. |
| web/src/features/driving/components/fsd-insights/FsdObservatoryPanel.tsx | Adds pagination to observatory timeline + commute stories. |
| web/src/features/driving/components/fsd-insights/FsdObservatoryPanel.test.tsx | Tests pagination behaviors. |
| web/src/features/driving/components/fsd-insights/FsdDriveAnalyticsPanels.test.tsx | Updates panel count + adds pagination tests. |
| web/src/features/driving/components/fsd-insights/FsdCommuteExperimentPanel.tsx | Adds “same-route experiment” panel. |
| web/src/features/driving/components/fsd-insights/FsdCommuteExperimentPanel.test.tsx | Tests experiment panel renders. |
| web/src/features/driving/components/driving-dynamics/useMotorStats.ts | Extends motor stats hook to accept history window query. |
| web/src/features/driving/components/driving-dynamics/pickDynamicsDrive.ts | Adds drive selection/merge/window helpers. |
| web/src/features/driving/components/driving-dynamics/pickDynamicsDrive.test.ts | Tests drive pick/merge/window helpers. |
| web/src/features/driving/components/driving-dynamics/index.ts | Exports new driving dynamics components. |
| web/src/features/driving/components/driving-dynamics/tests/grokDynamics.test.ts | Tests Grok dynamics interpretation logic. |
| web/src/features/driving/components/driving-dynamics/tests/GrokDynamicsBriefing.test.tsx | Tests Grok briefing shell/loading/error/reading states. |
| web/src/features/driving/components/driving-dynamics/tests/DriveAnalyticsSection.test.tsx | Removes tests for now-moved date range UI. |
| web/src/features/driving/components/driving-dynamics/SummaryStats.tsx | Passes history window query into motor stats. |
| web/src/features/driving/components/driving-dynamics/MotorHistoryCharts.tsx | Uses new useMotorHistory query object + drive window. |
| web/src/features/driving/components/driving-dynamics/MotorEfficiencyInsights.tsx | Passes history window query into motor stats. |
| web/src/features/driving/components/driving-dynamics/DynamicsTripToolbar.tsx | Adds trip selection toolbar for drive-scoped panels. |
| web/src/features/driving/components/driving-dynamics/DrivingTips.tsx | Uses drive-scoped motor stats for tips. |
| web/src/features/driving/components/driving-dynamics/DriveAnalyticsSection.tsx | Removes embedded range picker (moved to page header). |
| web/src/features/driving/components/drive-detail/index.ts | Exports new physics debrief panel. |
| web/src/features/driving/components/drive-detail/drivePhysicsDebrief.ts | Adds pure “drive physics debrief” interpretation logic. |
| web/src/features/driving/components/drive-detail/drivePhysicsDebrief.test.ts | Tests debrief interpretation. |
| web/src/features/driving/components/drive-detail/DrivePhysicsDebriefPanel.tsx | Renders debrief badges and beat list. |
| web/src/features/driving/components/DriveCard.tsx | Removes “FSD unknown” badge rendering. |
| web/src/features/driving/components/DriveCard.test.tsx | Updates tests for removed badge. |
| web/src/features/dashboard/components/fleet-posture/index.ts | Exports new fleet honesty meter. |
| web/src/features/dashboard/components/fleet-posture/FleetHonestyMeter.tsx | Adds honesty badge summary meter. |
| web/src/features/dashboard/components/FleetOperationsBrief.tsx | Adds honesty meter to fleet operations brief. |
| web/src/features/charging/pages/ChargingListPage.tsx | Uses instant ranges (RFC3339) and passes timezone to range UI. |
| web/src/features/charging/pages/ChargingListPage.test.tsx | Tests fetch uses RFC3339 instants (not date-only). |
| web/src/features/charging/pages/ChargingDetailPage.tsx | Prefers billed energy/cost for KPIs and adds bill-truth panel. |
| web/src/features/charging/pages/ChargingDetailPage.test.tsx | Tests KPI preference for billed values + vehicle energy preserved. |
| web/src/features/charging/lib/chargeBillTruth.ts | Adds pure billed-vs-pack derivation logic. |
| web/src/features/charging/lib/chargeBillTruth.test.ts | Tests bill-truth derivation. |
| web/src/features/charging/components/ChargeBillTruthPanel.tsx | Adds bill-truth UI panel. |
| web/src/features/charging/components/ChargeBillTruthPanel.test.tsx | Tests bill-truth panel rendering. |
| web/src/features/battery/pages/VampireDrainPage.tsx | Adds vampire culprit panel to page. |
| web/src/features/battery/lib/vampireCulprits.ts | Adds pure culprit derivation logic. |
| web/src/features/battery/lib/vampireCulprits.test.ts | Tests culprit derivation. |
| web/src/features/battery/components/VampireCulpritPanel.tsx | Adds vampire culprit UI panel. |
| web/src/features/battery/components/VampireCulpritPanel.test.tsx | Tests vampire culprit panel rendering. |
| web/src/components/layout/status-bar/HonestyMeterSegment.tsx | Adds status-bar honesty segment with tooltip + announcer. |
| web/src/components/layout/status-bar/HonestyMeterSegment.test.tsx | Tests honesty segment rendering. |
| web/src/components/layout/sidebar/compactNav.ts | Adds exclusive active-path resolution. |
| web/src/components/layout/sidebar/tests/compactNav.test.ts | Tests exclusive active-path behavior. |
| web/src/components/layout/sidebar/tests/LinearSidebar.test.tsx | Tests exclusive active highlighting in sidebar. |
| web/src/components/layout/sidebar/NotionSidebar.tsx | Switches to exclusive active-path logic. |
| web/src/components/layout/sidebar/LinearSidebar.tsx | Switches to exclusive active-path logic and passes end. |
| web/src/components/layout/StatusBar.tsx | Renders new honesty segment. |
| web/src/components/layout/StatusBar.test.tsx | Mocks and asserts honesty segment. |
| web/src/components/layout/Layout.tsx | Uses most-specific nav entry + exclusive active-path. |
| web/src/components/forms/RangePicker.tsx | Adds timezone prop and passes it into preset resolution. |
| web/src/api/types.ts | Adds billed invoice fields to API charging session type. |
| web/src/api/hooks/useVehicles.ts | Extends motor history hook to accept start/end window. |
| web/src/api/hooks/useVehicles.test.tsx | Tests motor history start/end params and enabled=false. |
| web/src/api/hooks/useAnalytics.ts | Adds drive-scoped FSD insights hook. |
| web/src/api/hooks/useAnalytics.test.tsx | Tests drive-scoped query params and enabled behavior. |
| internal/signal/state_reader_log_test.go | Updates window scan to include received_at and tests it. |
| internal/signal/state_reader_log.go | Adds received_at to timeline window query and rawEvent. |
| internal/signal/state_reader.go | Adds ReceivedAt to TimelineRow (not marshaled). |
| internal/signal/pivot_test.go | Tests merging keeps later received_at. |
| internal/signal/pivot.go | Carries ReceivedAt through forwardFold and merge logic. |
| internal/models/system/geofence_rate.go | Adds charging location backfill candidate struct. |
| internal/database/tesla/charging_history_repo_test.go | Tests FindBestMatch behavior. |
| internal/database/tesla/charging_history_repo.go | Adds FindBestMatch and factors shared scan/columns. |
| internal/database/geofence/repo_rates_test.go | Updates SQL substring assertions for new billable energy usage. |
| internal/database/geofence/repo_rates.go | Prices sessions using billed cabinet kWh when present. |
| internal/database/geofence/repo_discovery_test.go | Tests new missing charge location candidates query and bill overlay SQL. |
| internal/database/geofence/repo_discovery.go | Adds missing charge location candidates and uses billable energy for estimate. |
| internal/database/geofence/repo_charging_summary.go | Adds billed-usage subquery and uses it for repricing/preview/apply. |
| internal/api/teslaphysics/types.go | Adds ingest time + live marker, and increases exclusive session cap. |
| internal/api/teslaphysics/handler.go | Uses new exclusive session limit for drive/charge lists. |
| internal/api/teslaphysics/exclusive_test.go | Tests stored ingest time and keeping all samples/evidence. |
| internal/api/teslaphysics/exclusive.go | Surfaces ingest time in clocks and avoids truncating samples/evidence. |
| internal/api/teslaphysics/coerce.go | Adds cloneTime helper. |
| internal/api/telemetry/telemetry_sessions_charge_tracking_test.go | Adds tests for coord recovery and energy baseline exclusion. |
| internal/api/motor/handler_test.go | Tests even-sampling behavior and limit handling. |
| internal/api/motor/handler.go | Applies even sampling and clamps motor history limit. |
| internal/api/fsd/handler_test.go | Tests drive_id query behavior and lookaround/focus. |
| internal/api/fsd/handler.go | Adds drive_id mode with lookaround and focus support. |
| internal/api/fsd/drive_types.go | Adds FocusDriveID to analytics input. |
| internal/api/fsd/drive_repo.go | Adds DriveByID and ErrDriveNotFound. |
| internal/api/fsd/drive_aggregate_test.go | Adds tests for lookaround, fidget filtering, and focus. |
| internal/api/fsd/drive_aggregate.go | Filters negligible drives and uses reset-safe trip meter stepping. |
| internal/api/fsd/counter_advance_test.go | Tests counter restore/implausible/step behavior. |
| internal/api/fsd/counter_advance.go | Adds trip-meter restore + plausibility logic. |
| internal/api/fsd/aggregate_test.go | Tests spurious zero restore and implausible jump handling. |
| internal/api/fsd/aggregate.go | Uses trip-meter stepping in accumulation. |
| internal/api/charging/handler_test.go | Tests exclusive baseline for live energy and Tesla bill overlay. |
| internal/api/charging/handler.go | Overlays Tesla billed fields and excludes start batch from energy baseline. |
Suppressed comments (5)
web/src/lib/dateRange.ts:1
Intl.DateTimeFormatwill throw aRangeErrorfor an invalid IANA timezone string. Sincetimezoneis now passed through multiple UI paths (RangePicker/useRangeState/date presets), a single bad value can crash range resolution. Wrap the formatter creation in a try/catch and fall back to'UTC'(or a validated resolved timezone) to keep the UI resilient.
web/src/features/battery/lib/vampireCulprits.ts:1- The
sentryevidence ternary always returns'live'wheneverparkKnownis true, regardless ofsentryOn/sentry_reported. That makes theevidencesignal meaningless and looks like an accidental copy/paste. Simplify toparkKnown ? 'live' : 'missing'or (if intended) return different evidence states based on whether Sentry was actually observed/reported.
web/src/features/charging/components/ChargeBillTruthPanel.tsx:1 - This will render currency codes as prefixes (e.g.
USD21.80) rather than localized currency formatting ($21.80). Since the rest of the charging UI usesformatCurrency(...), consider using the same formatter here (or mapping codes to symbols) so billed totals and per-kWh values display consistently and correctly across currencies/locales.
web/src/features/charging/lib/chargeBillTruth.ts:1 - When only
billedCostis present (butbilledEnergyWhand/orbilledRatePerKwhare missing),hasInvoicebecomes true andhonestyis set to'live'even though the invoice is incomplete and key derivations (delta, impliedEnergyCost, unexplainedCost) may be impossible. Consider tighteninghasInvoice(e.g., requirebilledEnergyWhfor an energy invoice) or adjustinghonestyto'stale'/'missing'unless the fields needed for the displayed conclusions are present.
web/src/features/charging/lib/chargeBillTruth.ts:1 - When only
billedCostis present (butbilledEnergyWhand/orbilledRatePerKwhare missing),hasInvoicebecomes true andhonestyis set to'live'even though the invoice is incomplete and key derivations (delta, impliedEnergyCost, unexplainedCost) may be impossible. Consider tighteninghasInvoice(e.g., requirebilledEnergyWhfor an energy invoice) or adjustinghonestyto'stale'/'missing'unless the fields needed for the displayed conclusions are present.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| func plausibleCounterAdvance(delta float64, dt time.Duration) bool { | ||
| if delta <= 0 || !signalcounter.Valid(delta) { | ||
| return true | ||
| } | ||
| if dt < minAdvanceInterval { | ||
| dt = minAdvanceInterval | ||
| } | ||
| return delta <= maxAttributableSpeedMps*dt.Seconds() | ||
| } |
| applyExact := ` | ||
| UPDATE charging_sessions AS cs | ||
| SET cost_decimal = ROUND((` + billableEnergyExpr() + `)::numeric * $3::numeric, 6), | ||
| cost_currency = $4, | ||
| rate_id = $2, | ||
| cost_source = 'geofence_tariff' | ||
| WHERE geofence_id = $1 | ||
| AND ended_at IS NOT NULL | ||
| AND total_energy_added_wh IS NOT NULL | ||
| AND started_at >= $5 | ||
| AND ($6::timestamptz IS NULL OR started_at < $6) | ||
| WHERE cs.geofence_id = $1 | ||
| AND cs.ended_at IS NOT NULL | ||
| AND ` + billableEnergyExpr() + ` IS NOT NULL |
Keep ChargingDetailPage share-session UI from muse-spark and billed-energy display from main (#104). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Description
Closes #
Type of Change
Checklist
Screenshots (if applicable)