Skip to content

Architecture Decisions

Records of decisions that shaped the project, written when the decision was made and kept afterwards. They explain why something is the way it is, which the code itself cannot.

They are numbered sequentially and append-only. A decision that no longer holds is not edited or deleted, it is superseded by a later one that says so.

# Decision Status In short
0001 Wiring to the pvlearn forecast core Accepted The forecast regression test compares error metrics within a tolerance instead of exact predictions, and pvlearn errors are translated at the service boundary.
0002 Speaking pvlearn's canonical weather schema Partly superseded by 0007 The OpenWeatherMap condition id is mapped onto WMO 4677, deliberately losing detail.
0003 The weather provider is stamped onto every row Partly superseded by 0007 The provider became a first-class field rather than an assumption.
0004 Build with uv, drop arm/v7 Accepted The Docker build uses uv sync --frozen for reproducible pins, and 32-bit ARM images are no longer published. Includes a self-build recipe.
0005 Install the wheel in Docker Accepted The final image installs a built wheel instead of copying source, which fixes the missing generated version file.
0006 A local SQLite file replaces InfluxDB Accepted The history moved into an embedded database in the configuration directory, removing a mandatory external service.
0007 The storage holds the canonical schema Accepted Training data is stored under the forecast model's own field names, translated once on write instead of on every read.
0008 The weather service hands out canonical snapshots Accepted The weather event and the published topic carry provider-independent field names.
0009 The migration consolidates the module series Accepted The InfluxDB import merges duplicate module series, caused by a changed optimizer identifier, keyed by serial number.
0010 The forecast model is rebuilt on a slower cadence Accepted Training data is still written hourly, while the model, the hyperparameter search and their state on disk each follow their own interval.
0011 Stored energy and session energy get their own Home Assistant classes Accepted Battery capacities became energy_storage measurements, the EV charger session became a total_increasing energy counter, which costs a one-time statistics repair.

Writing a new one

Take the next free number, keep the file name in the NNNN-kebab-case-title.md shape, and add a row to the table above. State the context, the decision, and the consequence you accepted. A decision that only records what was done, without the alternatives that were rejected, is not worth keeping.