Summary
When summarising or analysing `readings` (the BME280 / PMS5003 / gas
sensor data), pair every indoor anomaly with the corresponding rows
from `epa_air_quality`, `outdoor`, and `nws_weather`. The latter
three are already collected by `airnow_wx`, `ambient_wx`, and
`nws_wx` services — they're just not used during interpretation.
This is principle-level, not a new service. The fix is discipline:
no enviro+ analysis without outdoor cross-reference.
Driver
Real failure mode caught 2026-04-26: an indoor PM2.5 cluster and a
separate indoor 100% RH reading were initially attributed to "Sunday
morning cooking and shower steam." Cross-referencing the four tables
produced the correct story:
| Indoor anomaly |
What it actually was |
| PM2.5 elevated overnight (avg 12.3, peak 29 µg/m³ at 07:46 ET) |
EPA AirNow regional AQI was "Good" all day → not infiltration. Outdoor humidity 96-97% with calm wind → AC working hard against humid stagnant air → AC dust release from coils/ducts |
| Indoor 100% RH + 57.6°F at 15:20 ET |
Outdoor humidity was dropping (77→64%) and outdoor temp was rising (78→85°F) → not weather front, not infiltration. Indoor temp dropped 24°F in 40 minutes → impossible for a room → sensor got cold-blasted (direct AC vent? freezer proximity?) and the BME280 face condensed |
Without outdoor cross-reference, both events looked human-caused.
Three-way classification
When an indoor anomaly fires, the cross-reference produces one of:
| Indoor flag |
Outdoor matches |
Outdoor doesn't |
Physically impossible |
| Means |
Infiltration |
Local source |
Sensor artifact |
| Action |
Inform |
Investigate |
Discard + flag sensor health |
Acceptance — all of these surfaces should join indoor with outdoor:
Lighter implementation than a full classifier
Initially I had specced a sidecar anomaly-classifier service. Bryan
pushed back: just make this a discipline rather than building new
infrastructure. The four tables are already in one DB. The fix is in
the queries that produce reports / alerts, not in adding code that
classifies for them.
When this issue's covered, all enviroplus user-facing surfaces will
join indoor + outdoor by default and surface the three-way
classification when relevant.
Summary
When summarising or analysing `readings` (the BME280 / PMS5003 / gas
sensor data), pair every indoor anomaly with the corresponding rows
from `epa_air_quality`, `outdoor`, and `nws_weather`. The latter
three are already collected by `airnow_wx`, `ambient_wx`, and
`nws_wx` services — they're just not used during interpretation.
This is principle-level, not a new service. The fix is discipline:
no enviro+ analysis without outdoor cross-reference.
Driver
Real failure mode caught 2026-04-26: an indoor PM2.5 cluster and a
separate indoor 100% RH reading were initially attributed to "Sunday
morning cooking and shower steam." Cross-referencing the four tables
produced the correct story:
Without outdoor cross-reference, both events looked human-caused.
Three-way classification
When an indoor anomaly fires, the cross-reference produces one of:
Acceptance — all of these surfaces should join indoor with outdoor:
time series side-by-side
Lighter implementation than a full classifier
Initially I had specced a sidecar anomaly-classifier service. Bryan
pushed back: just make this a discipline rather than building new
infrastructure. The four tables are already in one DB. The fix is in
the queries that produce reports / alerts, not in adding code that
classifies for them.
When this issue's covered, all enviroplus user-facing surfaces will
join indoor + outdoor by default and surface the three-way
classification when relevant.