# Task 3 Report: Final Mileage Election Projector

## Outcome

Implemented `ProjectDailyMileage` in `go/vehicle-gateway/internal/stats/source_mileage.go` and added focused projector coverage in `go/vehicle-gateway/internal/stats/source_mileage_test.go`.

## RED

Before implementation, the new projector test failed as expected because the function did not exist yet:

```text
internal/stats/source_mileage_test.go:87:9: undefined: ProjectDailyMileage
```

That confirmed the test was exercising the missing task-3 surface rather than passing accidentally.

## GREEN

After implementation:

- `go test ./internal/stats -run TestProjectDailyMileageSelectsCandidateAndMarksSource -count=1`
- `go test ./internal/stats -count=1`

Both passed.

## What Changed

- Added `maxSelectedDailyMileageKM = 1000`.
- Added `ProjectDailyMileage(...)` with three SQL steps:
  - clear `is_selected` for the VIN/date/protocol slice,
  - project the elected row from `vehicle_daily_mileage_source` into `vehicle_daily_mileage`,
  - mark the winning source row as selected.
- Kept the candidate identity intact: `source_key` still carries protocol + phone/device + source IP, while the data-source join uses protocol + source IP.
- Added a focused test that asserts the clear/project/mark sequence and the key SQL fragments.

## Files Changed

- `go/vehicle-gateway/internal/stats/source_mileage.go`
- `go/vehicle-gateway/internal/stats/source_mileage_test.go`

## Self-Review

- The projector stays aligned with the existing stats schema and helper conventions.
- The SQL ordering and join logic preserve the intended source identity split; there is no IP-only simplification.
- I did not add an unrelated schema migration because the current repository state already contained the needed `vehicle_daily_mileage_source` and `vehicle_daily_mileage` columns/indexes for this projector.
- The only notable follow-up risk is that the final selection query relies on MySQL-style `INSERT ... SELECT ... LIMIT 1 ON DUPLICATE KEY UPDATE` behavior, which matches the rest of the stats package but should still be exercised against the target DB in an integration run.

## Commit

`aa12317b5` - `feat(stats): project elected mileage source`

## Fix (reviewer findings)

Applied the reviewer correction for the trusted source endpoint contract:

- In `go/vehicle-gateway/internal/stats/source_mileage.go`, `projectDailyMileageSQL` now writes `trusted_source_endpoint` from `vehicle_data_source.latest_source_endpoint` via `COALESCE(NULLIF(ds.latest_source_endpoint, ''), s.source_endpoint)` so latest connection metadata is authoritative with a simple fallback.
- Replaced hardcoded quality predicate with the existing constant using `s.quality_status = '` + QualityOK + `'` in `projectDailyMileageSQL`.
- Updated `go/vehicle-gateway/internal/stats/source_mileage_test.go` to assert both the endpoint expression and constant-based quality predicate.

Validation commands:

```bash
cd go/vehicle-gateway && go test ./internal/stats -run TestProjectDailyMileageSelectsCandidateAndMarksSource -count=1
# PASS: lingniu-vehicle-ingest/go/vehicle-gateway/internal/stats

cd go/vehicle-gateway && go test ./internal/stats -count=1
# PASS: lingniu-vehicle-ingest/go/vehicle-gateway/internal/stats
```

## Fix (reviewer findings #2)

Corrected the remaining `projectDailyMileageSQL` contract issue so `trusted_source_endpoint` uses only `vehicle_data_source.latest_source_endpoint`:

- In `go/vehicle-gateway/internal/stats/source_mileage.go`, changed the projection from:
  `COALESCE(NULLIF(ds.latest_source_endpoint, ''), s.source_endpoint)`
  to:
  `ds.latest_source_endpoint`.
- In `go/vehicle-gateway/internal/stats/source_mileage_test.go`, extended `TestProjectDailyMileageSelectsCandidateAndMarksSource` assertions to:
  - require `ds.latest_source_endpoint` is selected, and
  - explicitly verify no fallback expression using `s.source_endpoint` remains.

This enforces the strict source-of-truth rule that endpoint data for final projection must come from latest connection metadata only, even when it is null/empty.

## Fix (reviewer findings #3)

Addressed stale candidate selection re-flagging by narrowing source marking to the same eligibility rules used by projection:

- In `go/vehicle-gateway/internal/stats/source_mileage.go`, `markSelectedSourceSQL` now:
  - No longer joins `vehicle_daily_mileage` to discover the selected source.
  - Selects the same single winning candidate directly from `vehicle_daily_mileage_source`, constrained by:
    - VIN/date/protocol
    - `quality_status = QualityOK`
    - mileage bounds (`0..maxSelectedDailyMileageKM`)
    - enabled source metadata
    - same trust/sample/time ordering
  - Marks only that candidate as `is_selected = 1`.
- In `go/vehicle-gateway/internal/stats/source_mileage_test.go`, `TestProjectDailyMileageSelectsCandidateAndMarksSource` now verifies:
  - the mark query includes candidate filters and ordering, including `s2.quality_status`, `s2.daily_mileage_km`, and `COALESCE(ds.enabled, 1) = 1`.
  - it no longer references `vehicle_daily_mileage` as a join source.
  - it passes the selection window arg through to marking (`maxSelectedDailyMileageKM`) and uses seven bind args.

Validation commands:

```bash
cd go/vehicle-gateway && go test ./internal/stats -run TestProjectDailyMileage -count=1
# PASS: lingniu-vehicle-ingest/go/vehicle-gateway/internal/stats

cd go/vehicle-gateway && go test ./internal/stats -count=1
# PASS: lingniu-vehicle-ingest/go/vehicle-gateway/internal/stats
```
