Repository navigation
feat(log): log the inputs each plan uses as "Replay input:" lines, so a log can be replayed exactly - #5427
Open
chalfontchubby wants to merge 2 commits into
Open
feat(log): log the inputs each plan uses as "Replay input:" lines, so a log can be replayed exactly#5427chalfontchubby wants to merge 2 commits into
chalfontchubby wants to merge 2 commits into
Conversation
… a log can be replayed exactly A debug yaml captures one moment; a forward replay of the log after it (draft PR #5363) needs the values each later plan started from, which the human-readable lines round or omit. Each line is prefixed "Replay input:", reads back exactly (repr floats, or dicts that ast.literal_eval reads), and is logged on change where the value rarely changes. None of it changes what Predbat does: every logger catches its own errors, and a value that cannot be logged warns once per change. Tariff comparison runs (save=False / publish=False) log none of it, as their inputs are not the live plan's. - PV forecast, on change: p50/p10/p90 per minute from now to the end of the forecast, as runs of [kWh, minutes]. - Load forecast, every cycle: the two values per 5-minute step the plan reads (step start and the minute after). Rounded to 0.1 Wh, so logged compactly as Wh per step from a cumulative base, about half the size of the full cumulative kWh line it falls back to for a forecast that is not in whole tenths of a Wh. - Load ML predictions, on change, exactly as read from the sensor. - Rates, on change: import/export and their base rates from now, as change points. - Plan starting state every cycle: SoC, SoC max, in-day adjustment, cost so far, the day counters, the charge and discharge rates in force and the battery temperature. - Car state and the inverter's programmed state (windows, charging/exporting and targets, reserve, rate limits), each on change; and the load divergence exactly as the plan uses it (None when divergence is off). The on-change lines share one helper (log_replay_changed). On a live system the replay lines are about 5% of the log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Empty forecasts, dynamic-load baselines, and current iBoost usage are not captured, preventing exact replay in supported runtime scenarios.
3 open findings
What changed in this PR
Adds exact Replay input: logging to support deterministic forward plan replay.
Changes:
- Logs forecasts, rates, runtime state, cars, inverter state, and load divergence.
- Suppresses replay logging during tariff comparisons.
- Adds comprehensive logger tests and test registration.
| File | Description |
|---|---|
apps/predbat/fetch.py |
Implements replay-input serialization and logging hooks. |
apps/predbat/plan.py |
Logs exact load divergence. |
apps/predbat/predbat.py |
Logs plan-start and inverter state. |
apps/predbat/tests/test_log_replay_inputs.py |
Tests serialization, change detection, and error handling. |
apps/predbat/unit_test.py |
Registers the new test suite. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…st_only and the dynamic load baseline (#5427 review) Four inputs the plan reads that the replay lines did not carry: - an empty load forecast, logged when the forecast becomes empty (not every cycle, as many setups have none), so a replay drops the forecast it still holds and plans on history as live did; - iboost_today, which the iBoost plan and the prediction's remaining iBoost allowance read, and load_forecast_only, which decides whether the load history is used at all, both now in the state line; - the dynamic load baseline that dynamic_load() sets for a high-load cycle and every load scenario adds, logged on change from the live plan (usually {}). The replay does not read these yet; they are logged now so that logs carry them when it does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
A debug yaml captures one moment. Replaying the log that follows it (#5363) needs the values each later plan started from, which the human-readable log lines round or leave out. This adds
Replay input:log lines carrying them exactly. None of it changes what Predbat plans or does.Each line reads back exactly (
reprfloats, or dicts thatast.literal_evalreads), and inputs that rarely change are logged only when they change. Tariff comparison runs (save=False/publish=False) log none of it, as their inputs are not the live plan's.PV forecast changed[kWh, minutes]load from HH:MM base X Wh, Wh/5min [...]ML load forecast changedrates changedstateload_forecast_onlycars changed,inverter changedload forecast emptyload divergenceNonewhen off)dynamic load baselinedynamic_load()sets for a high-load cycle (usually{})Safety
log_replay_changed.Measured on a live system (Sigenergy, IOG, 5-6 Oct 2026)
Changes
apps/predbat/fetch.py: the loggers and the shared on-change helper; PV and ML logging gated onsave.apps/predbat/plan.py: the load divergence and dynamic load baseline lines, gated onpublish.apps/predbat/predbat.py: logs the plan's starting state and the inverter state each cycle.apps/predbat/tests/test_log_replay_inputs.py(new), registered inunit_test.py.Test plan
./run_all(full suite) and pre-commit pass.🤖 Generated with Claude Code