SAFETY-86: peak guard outranks the maintenance hold
During a HOLD the holding battery gives what keeps the quarter at the peak aim. N=1: the peak floor is refiled at P_MAINTENANCE, as for a drain (SAFETY-83). N>=2: the hold's pin is raised to the floor minus what the other live batteries may place, so they give first. A site stop still decides alone. The hold ends on its clock even if the level dipped. Below the aim nothing changes (rows identical). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
513183aba3
commit
ba31e7c8b1
@@ -30,6 +30,5 @@ everything. Where the floor is at or below the drain rate nothing changes.
|
||||
**Not changed.**
|
||||
- Between the drain rate and the peak aim, the house still imports what the
|
||||
drain leaves (N=1 behaviour kept by the identity). At N=2 the loop covers it.
|
||||
- A maintenance HOLD (0 W, 120 min, battery full) still outranks the peak
|
||||
guard at N=1. Discharging there spends the charge the BMS balances on; it is
|
||||
an owner question, not this fix.
|
||||
- A maintenance HOLD (0 W, 120 min, battery full) still outranked the peak
|
||||
guard at N=1. Fixed by [[SAFETY-86]].
|
||||
|
||||
@@ -41,6 +41,6 @@ was fine.
|
||||
and the battery gives until the quarter is safe. The same sizing would fit
|
||||
there; that is an owner question, not this fix.
|
||||
- Outside a cheap window (`hi = 0`, solar only) nothing is filed, at any N.
|
||||
- A HOLD (SAFETY-86) and the "Battery is not keeping up" alarm (SAFETY-85)
|
||||
are untouched. In the identity runs that alarm's log line comes as often at
|
||||
N=2 as at N=1 (2 in 480 cycles).
|
||||
- A HOLD (later fixed by [[SAFETY-86]]) and the "Battery is not keeping up"
|
||||
alarm (SAFETY-85) are untouched. In the identity runs that alarm's log line
|
||||
comes as often at N=2 as at N=1 (2 in 480 cycles).
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# SAFETY-86 - the peak guard outranks the maintenance HOLD
|
||||
|
||||
**Status: DECIDED 2026-09-30 (owner).** Follows SAFETY-83's "Not changed"
|
||||
list. Tests: `test_safety86.py`.
|
||||
|
||||
**The defect.** The HOLD (battery resting full after the maintenance charge)
|
||||
is a SET of 0 W at `P_MAINTENANCE` (60), above the peak floor (`P_PEAK`, 50),
|
||||
so the floor did not bind. At N=1 a 6500 W house banked 6500 W quarters and
|
||||
'Load too high' fired (SAFETY-83 rig test, check 4). At N=2 only the other
|
||||
battery gave: 4500 W against a 3950 W aim (SAFETY-84 rig test, check 6).
|
||||
|
||||
**The fix** (`main.py`, `_peak_over_hold()`).
|
||||
- N=1: during a HOLD a peak floor above 0 W is refiled at `P_MAINTENANCE`, as
|
||||
for a drain (SAFETY-83). The battery gives the floor; the Why reads "raised
|
||||
for the peak limit".
|
||||
- N>=2: the holding battery's pin is raised to the floor minus what the other
|
||||
live batteries may place (their hard `hi`, or their pin). The others give
|
||||
first, the holding one only the shortfall. Why this split and not the
|
||||
allocator's shares: the hold is maintenance and outranks the others' use
|
||||
(owner order), and the owner rule for an Off battery is the same, "give way
|
||||
only for the shortfall". A battery Off by its mode (P_MODE, below
|
||||
maintenance) therefore still gives before the holding one.
|
||||
- Below the aim nothing changes: the floor is 0 W, the hold is 0 W, the rows
|
||||
are identical to before (test_safety86.py part 2).
|
||||
- A site stop (a SET above `P_PEAK`) decides alone: nothing is raised at N>=2,
|
||||
and the refiled floor at N=1 stays under `P_SAFETY`. If another battery is
|
||||
pinned to charge (a SAFETY-73 probe) the pin is not raised, so the site is
|
||||
never split both ways.
|
||||
- The hold resumes by itself: the rule is evaluated each cycle, so when the
|
||||
guard lets go the command is 0 W again.
|
||||
|
||||
**The level dips below the target: the hold finishes anyway.** The HOLD does
|
||||
not read the level; it ends on its clock (`maintenance_hold_min`). Topping up
|
||||
would mean going back to CHARGE, which waits for sun or a cheap window (up to
|
||||
36 h, `CHARGE_TIMEOUT_MIN`) while the pack keeps the site's one maintenance
|
||||
slot, so the other battery's cycle waits, and then a new full hold that the
|
||||
guard can interrupt again. The guard only gives while the quarter is at risk,
|
||||
and the next monthly cycle balances again. If the owner wants a top-up
|
||||
instead, it is a change to `maintenance.py`'s HOLD branch, not to this rule.
|
||||
|
||||
**Not changed.**
|
||||
- The peak guard still grades the emptiest battery (SAFETY-32): at N=2 with
|
||||
B under `peak_soc_floor` the floor is limited and A holds even when it is
|
||||
full (SAFETY-87).
|
||||
- "Battery is not keeping up" during maintenance (SAFETY-85), the N=2 charge
|
||||
flapping (SAFETY-88) and the N=1 charge headroom sizing are untouched.
|
||||
Reference in New Issue
Block a user