New option peak_margin_w (default 50 W, 0-500 W). The peak guard, the
forecast checks and the maintenance charge sizing aim at
peak_cap_w - peak_margin_w; the month peak, the bill, headroom, warnings
and every notice keep the real cap. Owner decision 2026-09-28.
peak_margin_w 0 is byte-identical to ed739d4 (tools/safety79_identity.py,
test_peak_margin.py part 1). validate.py rule 12 refuses a value outside
0-500, not whole, or not below the peak limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBtqPrG1mDLXzTEBnhEkkV
40 lines
1.6 KiB
Markdown
40 lines
1.6 KiB
Markdown
# SAFETY-79 — the peak guard keeps a margin below the peak limit
|
|
|
|
**Status: DECIDED 2026-09-28 (owner decision).**
|
|
|
|
## Decision
|
|
|
|
The peak guard aims at `peak_cap_w - peak_margin_w`, not at `peak_cap_w`.
|
|
`peak_margin_w` is a setting: default 50 W, range 0-500 W, whole watts. An
|
|
install without the key gets 50.
|
|
|
|
**Why (owner):** the guard aimed exactly at the cap, and in the OPT-11 P1 test
|
|
a quarter banked 3501.9 W against a 3500 W limit (OPT-11-P1-test-report.md,
|
|
check 4). A peak even 1 W over still sets the billed peak. It is a setting and
|
|
not a constant because the add-on is sold to several sites.
|
|
|
|
## What uses which number
|
|
|
|
- **cap - margin (the aim):** `peakguard.decide()` (the claim's floor, and so
|
|
arbitrage's `charge_headroom_w()` and OPT-11's give-way, which read it),
|
|
`shaping_suspended()` and `maintenance_charge_floor()` (the forecast checks,
|
|
via `Controller.peak_aim_w()`).
|
|
- **the real cap (reporting and billing):** `PeakTracker` (month peak,
|
|
headroom, 80 % warning), the decision's `ceiling_w` and every notice and
|
|
status row built from it, Home's limit, and `validate.config_notes()`.
|
|
|
|
A month peak already banked above cap - margin is aimed at as it stands
|
|
(`quarter_target_w()` is `quarter_ceiling_w()` on the lowered cap), so the
|
|
margin never holds a quarter below a peak that is already paid for.
|
|
|
|
## Checks
|
|
|
|
`peak_margin_w: 0` is byte-identical to ed739d4 (test_peak_margin.py part 1,
|
|
digests from tools/safety79_identity.py). validate.py rule 12 refuses a value
|
|
outside 0-500, not whole, or not below `peak_cap_w`.
|
|
|
|
## Open
|
|
|
|
Whether the margin should also apply below a banked month peak above the cap
|
|
is not decided here; today it does not.
|