MAINT-20 part 1 review: restore three lost lines, rewrap ragged comments
checks / unit (pull_request) Successful in 19m51s
infra-pin / fresh (pull_request) Successful in 2s

Comment, docstring and DECISIONS only (same-code script OK; python -OO
bytecode now identical for all six files).
- peakguard.charge_room_w: one-line docstring + SAFETY-125 pointer (cut whole).
- peakguard.shaping_suspended: keep 'the one place this conjunction is
  written; do not inline it'.
- price_forecast module note: an hour with no price and no yesterday is left
  out, never filled (test_price.py 14d cites the module note for it).
- Refill comment blocks the cut left ragged; DECISIONS pointers on one line.
- FCST-04 note: _yesterday_of(), not _previous_day(); FCST-03 note: the 49
  stronger cases are why the rule is a real change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
This commit is contained in:
glenn schrooyen
2026-11-01 03:02:51 +01:00
co-authored by Claude Opus 5.5
parent 6e2fde63ff
commit 63dda4b0d3
7 changed files with 61 additions and 78 deletions
+10 -7
View File
@@ -29,8 +29,7 @@ FLOOR_AT_SOC_FLOOR = "the battery level is at or below the peak reserve"
SOURCE = "peak"
# Mirror of config.yaml's peak options, pinned to the file by
# test_peakguard.py.
# Not a read: `decide()` takes them as arguments.
# test_peakguard.py. Not a read: `decide()` takes them as arguments.
PEAK_OPTION_DEFAULTS = {
# Percent a forced discharge may not go below. 20 is derived from the
# reference pack, 300 Ah at 51.2 V with DoD 90 - 13.8 kWh usable (a test
@@ -42,8 +41,7 @@ PEAK_OPTION_DEFAULTS = {
# SAFETY-79. Watts the guard aims under `peak_cap_w`.
"peak_margin_w": 50,
}
# SAFETY-79. Range of `peak_margin_w` in config.yaml, pinned by
# test_peakguard.py.
# SAFETY-79. Range of `peak_margin_w` in config.yaml; test_peakguard.py pins it.
PEAK_MARGIN_RANGE_W = (0, 500)
@@ -75,8 +73,8 @@ class PeakDecision:
held: tuple = ()
able_w: float | None = None
# SAFETY-126: power is wanted but the quarter still ends within
# ALARM_MISS_W
# of the aim with the batteries at 0 W (`misses_aim()`). Set by main.py.
# ALARM_MISS_W of the aim with the batteries at 0 W (`misses_aim()`). Set
# by main.py.
within_aim: bool = False
def explain(self) -> str:
@@ -422,6 +420,9 @@ def charge_headroom_w(decision) -> float | None:
def charge_room_w(decision, projection) -> float | None:
"""SAFETY-125: `charge_headroom_w()` less the unread seconds counted at the
last reading, so a late reading is not room for a grid charge.
DECISIONS/SAFETY-125-grid-charge-under-the-month-peak.md."""
room = charge_headroom_w(decision)
if not room or projection is None or projection.block_start is None:
return room
@@ -437,7 +438,9 @@ def shaping_suspended(decision, peak_forecast_w, cap_w) -> bool:
Crossing limits resolve to 0 W, so the rule is suppression, not priority.
Both terms are needed: the forecast entity is empty on a default install,
where the measured guard fires. Dropping either parks the battery in the
billed quarter (test_peakguard.py part 7). DECISIONS/SAFETY-07-peak-guard.md."""
billed quarter (test_peakguard.py part 7). The one place this conjunction is
written, public so the test grades the shipped expression: do not inline it.
DECISIONS/SAFETY-07-peak-guard.md."""
if peak_at_risk(peak_forecast_w, float(cap_w)):
return True
return decision is not None and decision.engaged