173 lines
6.6 KiB
Markdown
173 lines
6.6 KiB
Markdown
# Utah Vehicle Health
|
|
|
|
Kevin Bell's summer 2026 development prototype for the first-attempt outcome of
|
|
a returning vehicle's next emissions-inspection episode.
|
|
|
|
## Prototype status
|
|
|
|
The repository implements one research question:
|
|
|
|
> Using only information available before an inspection episode begins, how
|
|
> well can a calibrated logistic regression estimate whether a returning
|
|
> vehicle's next episode will have a first-attempt non-pass outcome?
|
|
|
|
The final model is regularized logistic regression with Platt calibration.
|
|
Histogram gradient boosting is a benchmark only. The final feature set uses
|
|
inspection history; DMV enrichment, multiclass modeling, cold-start prediction,
|
|
station analysis, and vehicle-level prediction service are outside scope.
|
|
|
|
All analytical results and dashboard values come from the private, page-sampled
|
|
10,000-vehicle development cohort. They are **sample results, not population
|
|
estimates**. They must not be used for statewide/county prevalence, county
|
|
rankings, causal claims, individual decisions, diagnoses, or guarantees.
|
|
|
|
Start with the [final report](docs/final_report.md). Supporting deliverables:
|
|
|
|
- [Project charter](docs/project_charter.md)
|
|
- [Leakage-safe modeling protocol](docs/modeling_protocol.md)
|
|
- [Detailed development results](docs/development_results.md)
|
|
- [Model card](docs/model_card.md)
|
|
- [Static dashboard specification](docs/dashboard_spec.md)
|
|
- [Private-to-public architecture](docs/architecture.mmd)
|
|
- [10-minute presentation outline](docs/presentation_outline.md)
|
|
- [Dashboard demo script](docs/demo_script.md)
|
|
|
|
The [data inventory](docs/data_inventory.md) and archived
|
|
[project options](docs/project_options.md) provide source-discovery history;
|
|
they do not expand the finished prototype scope.
|
|
|
|
## Privacy boundary
|
|
|
|
Never publish or display VINs, plates, ZIPs, stations, technician identifiers,
|
|
private vehicle tokens, raw JSON, credentials, operational records, or row-level
|
|
predictions. Private extracts, marts, databases, keys, and model artifacts stay
|
|
in Git-ignored local paths. The browser never connects to `countydata`.
|
|
|
|
```text
|
|
countydata (read-only)
|
|
-> private local extraction, feature, and model pipeline
|
|
-> suppression-reviewed aggregate JSON
|
|
-> dashboard-only static site
|
|
```
|
|
|
|
## Local setup
|
|
|
|
Create the local environment once:
|
|
|
|
```bash
|
|
python3 -m venv .venv
|
|
.venv/bin/pip install -r requirements.txt
|
|
.venv/bin/python scripts/create_vin_hash_key.py
|
|
```
|
|
|
|
The local `.env` contains PostgreSQL connection values and the project-specific
|
|
`VIN_HASH_KEY`; it is excluded from Git. Never put those values in source code,
|
|
screenshots, browser JavaScript, or presentation materials.
|
|
|
|
## Safe database access in VS Code
|
|
|
|
1. Install the workspace-recommended Microsoft PostgreSQL extension
|
|
(`ms-ossdata.vscode-pgsql`).
|
|
2. Run **Tasks: Run Task > Countydata: test read-only connection**. The task
|
|
requires TLS and forces the PostgreSQL session into read-only mode.
|
|
3. If using the PostgreSQL sidebar, store the profile at User scope and the
|
|
password in macOS Keychain, not workspace settings.
|
|
4. Run [sql/00_read_only_connection_check.sql](sql/00_read_only_connection_check.sql)
|
|
after connecting. Safe aggregate examples are in
|
|
[sql/01_safe_data_overview.sql](sql/01_safe_data_overview.sql).
|
|
5. Run **Countydata: inventory metadata safely** to inspect relation/field
|
|
metadata without printing row values. The task uses
|
|
[scripts/inventory_metadata.py](scripts/inventory_metadata.py).
|
|
|
|
The current database login has broader privileges than this project needs.
|
|
Continue to enforce read-only transactions and use a dedicated read-only role
|
|
before any separately approved operational integration.
|
|
|
|
## Reproducible private workflow
|
|
|
|
The VS Code tasks preserve the intended order:
|
|
|
|
1. Test the read-only TLS connection.
|
|
2. Run label-mapping and aggregate feasibility audits.
|
|
3. Export the private 10,000-vehicle development histories.
|
|
4. Build the private DuckDB warehouse and Parquet feature mart.
|
|
5. Run the test suite.
|
|
6. Train the baselines and logistic model with the 2025 gate closed.
|
|
7. Train the boosted-tree benchmark with the same gate closed.
|
|
8. Export the sanitized dashboard preview from approved pre-2025 partitions.
|
|
|
|
The extraction is deliberately not population-representative. It page-samples
|
|
inspection records and then retrieves complete histories for the selected
|
|
vehicles, which over-represents vehicles with more inspection records.
|
|
|
|
The explicit 2025 gate was opened once after specifications were frozen. No
|
|
model was changed in response. The values in the final report are one-time
|
|
development-sample holdout diagnostics—not pristine future-test or population
|
|
performance. Normal training leaves the gate closed.
|
|
|
|
## Tests
|
|
|
|
Run the complete repository test suite:
|
|
|
|
```bash
|
|
.venv/bin/python -m unittest discover -s tests -v
|
|
```
|
|
|
|
Run the dashboard contract checks directly:
|
|
|
|
```bash
|
|
npm --prefix dashboard test
|
|
```
|
|
|
|
## Static dashboard
|
|
|
|
Preview the site from the repository root:
|
|
|
|
```bash
|
|
node dashboard/server.mjs
|
|
```
|
|
|
|
Open `http://127.0.0.1:4173`. Do not open `index.html` with a `file:` URL and do
|
|
not serve the repository root.
|
|
|
|
The four routes are Overview, Sample cohorts, Model & benchmark, and Data &
|
|
methods. The site identifies calibrated logistic regression as final, the tree
|
|
as benchmark-only, and displayed model cards as 2024 calibration-fit checks.
|
|
The opened 2025 comparison stays in the report and presentation, not the public
|
|
JSON. There is no vehicle-level prediction service.
|
|
|
|
The browser validates schemas, publication flags, cross-file consistency, and
|
|
checksums. It shows no estimates if the approved aggregate bundle fails its
|
|
contract. Every checked-in asset is marked as a development preview and not a
|
|
population estimate.
|
|
|
|
### Live demo from another computer
|
|
|
|
When both computers are on the same network, start the LAN demo from the
|
|
repository root. Stop any older dashboard process with `Ctrl-C` first:
|
|
|
|
```bash
|
|
node dashboard/server.mjs --lan
|
|
```
|
|
|
|
The server prints a **This computer** URL and one or more interface-labeled
|
|
**Other devices** URLs. Open the URL for the shared Wi-Fi or Ethernet interface
|
|
on the second computer; do not use `0.0.0.0` as the browser address. Confirm the
|
|
header reads **Validated sample aggregates**. Stop the server with `Ctrl-C`
|
|
after the demo.
|
|
|
|
The LAN page still checks every approved JSON asset against its SHA-256 digest.
|
|
Browsers do not expose the SubtleCrypto digest API to a non-loopback plain-HTTP
|
|
page, so the dashboard includes a dependency-free checksum implementation for
|
|
that case. These checks validate bundle consistency; plain HTTP does not
|
|
authenticate the network transport, so use a trusted demo network.
|
|
|
|
|
|
## Author
|
|
|
|
Kevin Bell
|
|
|
|
<kevinBell@Linux.com>
|
|
|
|
<https://kevinbell.dev/>
|