fix: probe plan survives a reboot - #37
Merged
Merged
Conversation
…t from the event log The amp controller kept its state in /tmp/derate_amp_control.state.json. The 2026-09-24 04:00 kernel-update reboot cleared it, the daemon read the plan as never started, and that evening's session probed 32A cold again - three days after the last one, against a weekly cadence, while three conditions still had no replicates at all. Two layers. The installer now runs the daemon with StateDirectory= and --state-file /var/lib/derate-amp-control/state.json, carrying an existing /tmp file over. And a daemon that finds its probe history empty rebuilds it once from wallmonitor's amp events: a probe counts as completed when the controller's next amp event (or now) comes a full hold after its start, since a probe finishing on a sustainable current no higher than its own logs nothing at completion, and the cadence is anchored at the session's plug-in. If wallmonitor cannot answer, that tick runs with the probe disabled rather than treat the plan as overdue; thermal capping is unaffected. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Problem
The amp controller's state (active cap, debounce streaks, probe-plan progress) lived in
/tmp/derate_amp_control.state.json, the daemon's default--state-file, which the installer never overrode. The mini-PC's 2026-09-24 04:00 kernel-update reboot cleared it. The daemon then treated the plan as never started, and at that evening's session start it capped to 32A for a cold probe. The last 32A cold probe had run on 09-21, only three days earlier, the plan interval is 7 days, and 40A cold, 32A warm and 40A warm still had zero replicates. The 09-21 run was also lost from the daemon's count. The installer creates no other state, so every reboot has the same effect (the box rebooted on 09-05, 09-11 and 09-24).Code touched
deploy/install-derate-amp-control.sh: the unit getsStateDirectory=derate-amp-control, and--state-filenow defaults to/var/lib/derate-amp-control/state.json. An existing/tmpstate file is copied there once, so the move does not drop a cap that is active mid-session. An explicit--state-filestill wins.contrib/derate_amp_control.py:probe_history_from_events()(pure) rebuildsprobes_doneandlast_probe_tsfromamp_cappedevents that carrydetail.probe, and from legacy events whose reason says "calibration probe" (counted asany). A probe counts as complete when the controller's next amp event, or now if there is none, comes at least a full hold after its start (60 s tolerance). That is needed because a probe that finishes on a sustainable current no higher than its own logs nothing at completion. Abandoned probes always log something sooner: a lower thermal cap, or the session-end restore. The cadence anchor is the plug-in time of the probe's session from/api/sessions, which is a few minutes before the daemon's own charging start. That can only make the next probe due sooner, never push a cold slot too late.main()runs the rebuild at most once per state file (probe_history_checked), only when the plan is enabled, no hold is in progress and the history is empty. If wallmonitor cannot answer, that tick runs with the probe disabled rather than treat the plan as overdue.--state-filehelp now says the default is cleared on reboot.last_charging_tsis not rebuilt, so the first session after a state loss still cannot count as cold (existing, tested behavior). The daemon's own/tmpdefault is kept for ad-hoc runs.Risk
/api/events,/api/sessions) the first time a state file is empty, then none.Verification
uv run pytest: 167 passed. The 4 new tests cover: tonight's incident replayed (3 days later: no probe; 7 days later: 32A warm at minute 30, not cold again); abandoned, silent-completion, legacy and in-progress probes; the rebuild running exactly once; and the plan holding when the rebuild fails.probe history rebuilt from the event log: 3 completed(one pre-plan 32Aany, both 32A cold),last_probe_ts= 2026-09-24 17:50:43 (tonight's plug-in).Deploy: re-run
install-derate-amp-control.shwith the current flags. On this box, delete/tmp/derate_amp_control.state.jsonfirst (between sessions). Otherwise the installer migrates its one-entry history, the rebuild never triggers, and the count stays one short.🤖 Generated with Claude Code