SAFETY-83: peak guard outranks the maintenance drain at N=1
At N=1 the drain is the site SET at P_MAINTENANCE (60), so the peak floor
(P_PEAK, 50) was not applied and the house imported what the drain left.
Where the floor asks for more than the drain rate, main.py now refiles the
peak claim at P_MAINTENANCE, so it wins; safety SETs still park everything.
Nothing else changes: safety78_identity --diff against 35cdffe changes only
cycles where the guard wanted more than the drain; N=2 is byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ DECISIONS/SAFETY-78-drain-at-two.md has the record.
|
||||
3. Battery modes on, a Cheap hours battery in a cheap run during the drain:
|
||||
no grid charge, and its card says why.
|
||||
4. The peak guard binds during a drain, and the arbiter's order holds.
|
||||
5. N=1 is byte-identical to release/1.0 5a4cdc2, and the harness bites.
|
||||
5. The N=1 and N=2 digests hold, and the harness bites.
|
||||
6. A seeded sweep of the floor against the loop, trades, the peak floor, a
|
||||
safety stop, refusals and an Off battery.
|
||||
|
||||
@@ -326,26 +326,32 @@ check("⭐ the order holds: a safety stop parks everything; the peak floor "
|
||||
and _got["a grid charge (trade)"][1] == {A: 2000, B: 0})
|
||||
|
||||
# ============================================================================ #
|
||||
print("\n5. N=1: byte-identical to release/1.0 5a4cdc2")
|
||||
# Printed by `python3 tools/safety78_identity.py` on release/1.0 5a4cdc2 (the
|
||||
# same file copied in, nothing else changed), goodwe-addon-checks:1,
|
||||
print("\n5. the N=1 and N=2 digests")
|
||||
# Printed by `python3 tools/safety78_identity.py`, goodwe-addon-checks:1,
|
||||
# 2026-09-29. 480 cycles each, draining throughout, every claim and the
|
||||
# newest action-log line hashed.
|
||||
AT_5A4CDC2 = {
|
||||
# newest action-log line hashed. N=2: the same on release/1.0 35cdffe. N=1:
|
||||
# re-pinned by SAFETY-83, whose `--diff` against 35cdffe changes only cycles
|
||||
# where the peak guard asked for more than the drain (test_safety83.py).
|
||||
PINNED = {
|
||||
"n1_drain":
|
||||
"55fcfc4a0b9251746f315cfdea607a33640d3a81faf6604c4718a04bbc7dd776",
|
||||
"b0f9ef44149163bc0acece537fe047871c00f0d9ea213e7a7fc8efc4ad3aa500",
|
||||
"n1_drain_modes":
|
||||
"93867eb4ee4132b47c030668bd7f07587a353bced2461524e09421125c3c4edf",
|
||||
"95ab82426e23bce308db3edebe18b1ab37d956952e9f521adce37150ce87ee8a",
|
||||
"n1_drain_owner":
|
||||
"10f7f42a6a952e899d739eb10c674874215c440f41ead7a9f2408bc9b4cb9ea4",
|
||||
"n2_drain":
|
||||
"055d83de0552d3a014dc73d87fdd697dde8b5933b8032f9b3a464ff0d08795fb",
|
||||
"n2_drain_owner":
|
||||
"05750347f1829c249f99154613f068f442a59ef59f409093907f6d0add78dd4c",
|
||||
}
|
||||
_now = s78.digests()
|
||||
for k in AT_5A4CDC2:
|
||||
print(f" {k} {'same' if _now[k] == AT_5A4CDC2[k] else 'DIFFERS'} "
|
||||
for k in PINNED:
|
||||
print(f" {k} {'same' if _now[k] == PINNED[k] else 'DIFFERS'} "
|
||||
f"{_now[k][:16]}")
|
||||
check("⭐ at one inverter a drain under a house below, at and above its "
|
||||
"rate, a surplus and a load over the peak limit, with battery modes "
|
||||
"off and on, is byte-identical to 5a4cdc2: commands, reasons, roles, "
|
||||
"trades and every claim",
|
||||
_now == AT_5A4CDC2)
|
||||
check("⭐ a drain under a house below, at and above its rate, a surplus and a "
|
||||
"load over the peak limit, at N=1 (modes off and on) and N=2, matches "
|
||||
"the pinned digests: commands, reasons, roles, trades and every claim",
|
||||
_now == PINNED)
|
||||
Controller._drain_floor = lambda self, claims, results: (
|
||||
2000.0 if any(r.phase == DRAIN for r in results) else None)
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user