565 Commits
Author SHA1 Message Date
glenn schrooyenandClaude Opus 5.5 ba31e7c8b1 SAFETY-86: peak guard outranks the maintenance hold
checks / unit (pull_request) Successful in 24m17s
infra-pin / fresh (pull_request) Successful in 1s
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>
2026-10-01 00:56:34 +02:00
glenn schrooyenandClaude Opus 5.5 513183aba3 test_peak_margin: read the month peak on the runs' clock, not today's
Part 3 read the simulated September's peak with the wall clock, so from
2026-10-01 it read no peak and crashed on every tree (4ad8298 too).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:56:34 +02:00
admin 4ad8298ead Merge pull request 'SAFETY-84: maintenance charge at N=2 no longer stalls' (#160) from safety-84-n2-maint-charge into release/1.0
infra-pin / fresh (push) Successful in 1s
2026-09-30 21:00:56 +02:00
adminandClaude Opus 5.5 5c9f64d87a SAFETY-84 review: check the charging pack gives under the guard, and no-P1 at N=2
checks / unit (pull_request) Successful in 23m51s
infra-pin / fresh (pull_request) Successful in 1s
A 6500 W house needs more than B alone: A must give (the N>=2 suspension),
with a non-vacuous run without it (banks over the cap, 'Load too high').
Without P1 the charge is not sized, as at N=1: A charges at 2000 W.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:36:46 +02:00
glenn schrooyenandClaude Opus 5.5 43a52e7f60 SAFETY-84: maintenance charge at N=2 no longer stalls
checks / unit (pull_request) Successful in 23m57s
infra-pin / fresh (pull_request) Successful in 2s
At N>=2 a cheap-window maintenance charge files a site `hi` (`charge`,
P_MAINT_SHAPE) equal to what the charging pack's own `hi` places, so the
other pack never has to give against it. The charge is sized to the
quarter's headroom under the peak aim so it yields to the peak guard, and
to 0 W under a site safety stop. N=1 byte-identical (safety84_identity).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:47:15 +02:00
admin 9d5b7d129a Merge pull request 'SAFETY-83: peak guard outranks the maintenance drain at N=1' (#158) from safety-83-peak-over-drain into release/1.0
infra-pin / fresh (push) Successful in 2s
2026-09-30 14:58:41 +02:00
glenn schrooyenandClaude Opus 5.5 bc6d744c6c SAFETY-83 review: banked month peak and no false alarm during a drain
checks / unit (pull_request) Successful in 23m23s
infra-pin / fresh (pull_request) Successful in 1s
test_safety83 part 1: under a month peak banked above the limit the drain
is lifted to peak - margin, and a drain the guard raises (steady or with
5 s spikes that saturate it) gives no 'Load too high' alarm; the part 3
overload still does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:41:47 +02:00
glenn schrooyenandClaude Opus 5.5 79b94024cb Merge release/1.0 (OPT-11 P4, #156) into safety-83-peak-over-drain
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:35:28 +02:00
goodwe-agent 2f5ab1f378 MAINT-10: DECISIONS says where the release note lives
checks / unit (pull_request) Successful in 23m8s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:09:06 +02:00
goodwe-agent fbdd552555 MAINT-10: CHANGELOG draft line moves to the PR (version gate refuses an Unreleased block)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:08:46 +02:00
admin 1145a931ac Merge pull request 'OPT-11 P4: solar forecast and day plan' (#156) from opt11-p4-solar-forecast into release/1.0
infra-pin / fresh (push) Successful in 2s
2026-09-29 23:01:48 +02:00
adminandClaude Opus 5.5 56cafefa79 SAFETY-83: a refiled peak floor stays under a safety SET, graded directly
checks / unit (pull_request) Successful in 23m32s
infra-pin / fresh (pull_request) Successful in 1s
Kills M5 (refiled at P_SAFETY) on its own sentence, not only through the
per-cycle claim check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:52:52 +02:00
goodwe-agent 02c0a3dd7b MAINT-10: maintenance start hour in local time, default 19:00
The start hour was compared with the UTC hour, so the shipped 10 started at
12:00 in a Belgian summer. It is now read in Home Assistant's time zone
(fallback: the container's TZ, then UTC, one log line says which), and the
default moves to 19. DST: a missing hour starts at the first hour after the
jump; a repeated hour starts only in its first pass. Stored options are not
rewritten: a saved 10 now means 10:00 local (DOCS, CHANGELOG).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:52:05 +02:00
adminandClaude Opus 5.5 3f69c174af SAFETY-83: grade the refile at its boundary, and N=2 on its own
checks / unit (pull_request) Successful in 23m37s
infra-pin / fresh (pull_request) Successful in 1s
A floor exactly at the drain rate stays at P_PEAK (kills `lo >= rate`), and
part 4's N=2 check no longer shares its failure list with N=1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:50:46 +02:00
adminandClaude Opus 5.5 d77f1b1fdf SAFETY-83: peak guard outranks the maintenance drain at N=1
checks / unit (pull_request) Successful in 16m54s
infra-pin / fresh (pull_request) Successful in 1s
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>
2026-09-29 22:40:14 +02:00
glenn schrooyenandClaude Opus 5.5 b171ada894 Merge release/1.0 (SAFETY-78, #154) into opt11-p4-solar-forecast
checks / unit (pull_request) Successful in 23m54s
infra-pin / fresh (pull_request) Successful in 1s
Conflicts: modetrade.decide() takes both the day plan (targets) and
SAFETY-78's draining flag; the Why line keeps SAFETY-78's other_cycle
ahead of the plan's word (test added).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:37:09 +02:00
Claude review c38dd1e969 OPT-15 review: bound unmeasured charge stops, test the hold's rules and M15
checks / unit (pull_request) Failing after 3s
infra-pin / fresh (pull_request) Successful in 1s
- A second unmeasured-headroom stop in a quarter latches the charge: a
  headroom missing every other cycle flipped it 1799 times in 30 min.
- Unit test of the run-edge hold's end conditions and of a small step.
- Outside its probe a refuser does not make the others rest (M15 red).
- DECISIONS: one review line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:31:52 +02:00
glenn schrooyenandClaude Opus 5.5 0b96e3191c OPT-11 P4 review: records and text
checks / unit (pull_request) Failing after 4s
infra-pin / fresh (pull_request) Successful in 1s
- DECISIONS: the Cheap hours change and why; the no-sun replay (the gain is
  Leftover solar buying the evening's shortfall; the forecast added 0.14
  EUR); the reconstruction bias stated plainly.
- DOCS: Cheap hours ignores the forecast; a reading from before midnight
  is stale.
- The forecast line: "Solar still to come today: ..." (it is what is
  left, and it stays within the 12-word limit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:29:00 +02:00
admin 35cdffe766 Merge pull request 'SAFETY-78: maintenance drain at N=2 no longer stalls' (#154) from safety-78-drain-at-two into release/1.0
infra-pin / fresh (push) Successful in 1s
2026-09-29 22:20:29 +02:00
glenn schrooyenandClaude Opus 5.5 a692560960 Merge release/1.0 (SAFETY-81, #155) into opt11-p4-solar-forecast
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:08:52 +02:00
glenn schrooyenandClaude Opus 5.5 fbd884797d OPT-11 P4 review: Cheap hours ignores the plan; midnight-stale forecast; stricter ids
- Cheap hours only fills to the ceiling with or without a forecast, as the
  design (section 1) says. Skipping the sun's share cost 0.31 EUR on real
  2026 prices (29.72 against P3's 29.41) and saved nothing on the P3 set.
- A forecast reading from before local midnight is stale: until the
  integration refreshes, "left today" is still yesterday's 0 and
  "tomorrow" is really today.
- Forecast entity ids must be sensor.[a-z0-9_]+ (they go into the
  /api/states/<id> path).
- House profile: a stored day that is not a date, or is after today, is
  dropped instead of kept forever.
- Text: the forecast line says "for the rest of today"; the learning line
  no longer promises "tomorrow" (a plan needs one full day).
- Tests for four surviving review mutants (hour sample floor, the dear run
  after the cheap run, share by room, daytime use) and the fixes above.
- Replay tool: `--fc zero` (a forecast of no sun).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:08:47 +02:00
goodwe-review 516bc8b4ec Merge release/1.0 into safety-78-drain-at-two
checks / unit (pull_request) Successful in 18m49s
infra-pin / fresh (pull_request) Successful in 2s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:53:47 +02:00
admin 4f25b24aa6 Merge pull request 'SAFETY-81: no false Load too high alarms' (#155) from safety-81-load-too-high into release/1.0
infra-pin / fresh (push) Successful in 2s
2026-09-29 21:45:19 +02:00
goodwe-review 044fc0d5bd SAFETY-78 review: card truth while the drain waits, more checks
checks / unit (pull_request) Successful in 16m15s
infra-pin / fresh (pull_request) Successful in 1s
- homeview: no "This one does not charge" while the draining battery waits
  (no floor then, so the other battery may charge from solar).
- test_safety78: one wait line across a probe, a second episode logs again,
  the card while waiting, and a seeded sweep of the floor against every
  other claim (part 6).
- DECISIONS: the wait case, and the measured N=1 peak and N=2 charge
  follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:13:31 +02:00
adminandClaude Opus 5.5 f967073cfe SAFETY-81 review: 10 s hold, ERROR line per episode, more scenarios
checks / unit (pull_request) Successful in 20m31s
infra-pin / fresh (pull_request) Successful in 2s
- The alarm must hold for peakguard.ALARM_HOLD_S (10 s) on the projection's
  clock. A load that tops cap + battery for ~5 s every 30 s alarmed at every
  quarter start while the quarter landed under the aim (sine4500_fast).
- A cycle with no battery reading leaves the hold alone.
- Notified once per quarter, but the ERROR line is written per episode.
- New sim scenarios (sine4500_fast, twice7000, step6500_gap) with 5a4cdc2
  digests; control still byte-identical. Unit checks for export and the
  hold across a missing reading. test_peakguard's saturated fixture moves
  the hold start back instead of waiting it out.
- DECISIONS and DOCS updated: costs of the hold, tolerance reasoning, the
  double count in control left to a follow-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:58:37 +02:00
adminandClaude Opus 5.5 fae6681e19 OPT-15: price-run fixes (quarter edge, charge-end overshoot, refusal probe)
checks / unit (pull_request) Successful in 18m49s
infra-pin / fresh (pull_request) Successful in 1s
F1: with battery modes on, the peak guard projects the quarter `now` is in
even before its first P1 sample (PeakTracker.project(roll=True)), and only
a measured stop latches the period. The edge tick no longer reads "no
seconds left", so a charge is not stopped and latched at a quarter edge.

F2: after a run edge the loop is held at E until the meter shows the step
(EDGE_HOLD_S, longer while the battery still moves). The replay gained a
lag model (dead time, reading age, P1 debounce, 1 s cycles) that shows
TEST-23's overshoot without the hold.

F3: a charge refuser's SAFETY-73 probe inside a cheap run is a charger
pinned at PROBE_W, the others rest, so the probe actually runs.

Modes off stays byte-identical to 5a4cdc2 (new late-P1 identity scenarios).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:22:32 +02:00
Claude aabc2a27fd OPT-11 P4: tests for eight surviving mutants; guarded reads
checks / unit (pull_request) Successful in 23m10s
infra-pin / fresh (pull_request) Successful in 2s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:22:16 +02:00
Claude af39c10893 SAFETY-78: test_safety78 points at MUTATION.md (test_bytecode)
checks / unit (pull_request) Successful in 15m23s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:14:33 +02:00
goodwe-agent 6eb67c0f9c SAFETY-81: no false 'Load too high' alarms
checks / unit (pull_request) Successful in 16m11s
infra-pin / fresh (pull_request) Successful in 1s
The alarm now also needs peakguard.load_too_high(): with the battery at
full power, the quarter still ends more than 10 W over the real limit.
The battery reading is the lower of this cycle's and the last, so a meter
sample from before the battery's last increase is not counted twice.
At most one alarm per quarter. Control outputs unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:55:38 +02:00
Claude 5d27f8496f SAFETY-78: maintenance drain at N=2 no longer stalls
checks / unit (pull_request) Failing after 17m13s
infra-pin / fresh (pull_request) Successful in 2s
At two inverters the drain pins its pack and the site target is split
around the pin. Below the pin the other pack had to charge, the allocator
refused the opposite directions, and the site sat at 0 W with an ARBITER
line every cycle (house below or above the drain rate, or a grid charge).

main.py now files a site limit `drain` (lo = what the pin places, at
P_MAINTENANCE) at N>=2 while a pack drains, so the other pack only adds
power in the same direction. A drain that cannot give power waits with
one log line. With battery modes on, no grid charge while a pack drains,
and the other battery's card says why. N=1 is byte-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:52:51 +02:00
Claude eb10537aee OPT-11 P4: solar forecast and day plan
A Home Assistant solar forecast (Forecast.Solar, Solcast or Open-Meteo
shapes) and the add-on's own hourly house use decide, before each cheap
run, whether the sun will fill each battery before the expensive hours.
Leftover solar then buys from the grid only the shortfall; Cheap hours only
skips the part the sun covers; Solar first never grid-charges. No, stale or
failed forecast: P3 option A exactly (12 digests pinned from 5a4cdc2).

Replay (16 recorded days, forecast errors from Elia's day-ahead BE solar):
year-earlier prices P4 19.15 vs P2 19.33 / option A 19.44 / old trade 18.14;
real 2026 prices P4 29.19 vs 32.26 / 32.01 / 31.40 EUR net.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:29:32 +02:00
admin 5a4cdc273e Merge pull request 'OPT-11 P3: price runs per battery' (#153) from opt11-p3-price-runs into release/1.0
infra-pin / fresh (push) Successful in 2s
OPT-11 P3: price runs per battery (owner option A: selling off, Leftover solar solar-only until P4) (#153)
2026-09-29 11:37:46 +02:00
glenn schrooyenandClaude Opus 5.5 7104515229 OPT-11 P3 option A review: wizard no longer says modes come later
checks / unit (pull_request) Successful in 15m14s
infra-pin / fresh (pull_request) Successful in 1s
Step 5 said "Choosing a mode for each battery comes in a later update",
stale since P1. It now points to battery modes on the Batteries screen
(EN/NL); test_setup checks the new line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:21:32 +02:00
Claude dev agent 6dab4ec16b OPT-11 P3, owner option A: selling off, Leftover solar takes solar only
checks / unit (pull_request) Successful in 15m12s
infra-pin / fresh (pull_request) Successful in 1s
Owner decision 2026-09-29. Selling is off until it can be judged on the price
the grid pays: packmode.SELLING_ENABLED = False makes read() answer
sell=False whatever the store holds, pack_sell is refused ("Selling is off
for now."), and the page has no selling switch; the sell code stays. Until
the P4 forecast, only Cheap hours only charges from the grid
(packmode.GRID_CHARGE_MODES); Leftover solar holds and gives in the
expensive runs. Help, Today and plan lines, DOCS and DECISIONS follow.
Replay, 16 days: Solar first + Leftover solar 19.44 EUR net (P2 19.33).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:42:58 +02:00
glenn schrooyenandClaude Opus 5.5 b014fd2e16 OPT-11 P3 review: sale shows no money, honest sell text, tests for four surviving mutants
checks / unit (pull_request) Successful in 14m5s
infra-pin / fresh (pull_request) Successful in 1s
- A sale block on the plan no longer says "Worth up to" at the import
  price: a sale earns the lower injection price.
- The selling switch help (EN/NL) and DOCS say the grid pays less than
  power costs; DECISIONS records why P3 loses on the replay.
- test_modes_p3 part 11: modes on ignore the site trade switch (R13), a
  battery in maintenance takes no part (R10), a headroom stop latches for
  the period (R8). All three mutants survived before and are red now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 03:51:15 +02:00
Claude dev agent 902524ae5e OPT-11 P3: price runs per battery
checks / unit (pull_request) Successful in 13m45s
infra-pin / fresh (pull_request) Successful in 1s
Cheap and expensive hours as runs of consecutive firm price slots
(priceruns.py); each battery's role per tick from its mode (modetrade.py):
grid charging for Leftover solar / Cheap hours only, never Solar first;
holding for the expensive runs; selling per battery (pack_sell) above the
spread and the floor. The site trade is sized inside the modes (loop bound)
and the peak guard's headroom; a run edge reseeds the loop. Cheap hours only
and selling are enabled on the Batteries screen and in the HA select
(appended). The site Why row no longer says "held back" when the peak limit
pushes power up (F2). Modes off: byte-identical to 7a00f12 on the trade path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 02:37:44 +02:00
adminandClaude Opus 5.5 7a00f12c76 SAFETY-79: peak guard keeps a margin below the limit (#151)
infra-pin / fresh (push) Successful in 1s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:01:35 +02:00
Review AgentandClaude Opus 5.5 ce0aea30b6 SAFETY-79 review: margin under a banked month peak too; identity harness reaches headroom and maintenance
checks / unit (pull_request) Successful in 11m50s
infra-pin / fresh (pull_request) Successful in 1s
- quarter_target_w() is now the margin under quarter_ceiling_w(): a peak
  banked between cap - margin and the cap was aimed at exactly, so one
  overshoot crossed the cap; above the cap the same overshoot raised the bill.
- safety79_identity.py hashes charge_headroom_w() and the shaping suspension,
  and adds n1_maint/n2_maint (cheap window, forecast across cap - 50 .. cap).
  Digests re-printed on ed739d4 and pinned; margin 0 still identical.
- test_margin_under_banked_peak; DECISIONS and DOCS updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:49:16 +02:00
Review AgentandClaude Opus 5.5 e6096d3e17 Merge release/1.0 (7337b79, OPT-11 P2) into safety-79-peak-margin
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:23:14 +02:00
admin 7337b791e5 OPT-11 P2: HA entities for battery modes (#152)
infra-pin / fresh (push) Successful in 2s
2026-09-29 00:13:49 +02:00
glenn schrooyenandClaude Opus 5.5 308adc9277 Merge release/1.0 (7995e4d, UX-13 P3) into opt11-p2-ha-entities
checks / unit (pull_request) Successful in 11m29s
infra-pin / fresh (pull_request) Successful in 2s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:58:39 +02:00
adminandClaude Opus 5.5 c664e38ef4 OPT-11 P2 review: refusals stay counted, removals survive a start with no broker
- A refusal past the log-once set or the 32 cap is counted in the log at
  1, 10, 100 and so on, so a repeated attack stays visible.
- The logged topic is printable only (no forged log lines).
- mode_announcement(): the start-up store logic, now tested with a real
  Store. A removed config topic stays stored, so a start with no broker
  cannot forget it (rename case tested).
- A test ties each HA mode option to the page's English name.
- packmode.enabled() is tested for "true", 1 and "false".
- Retained-command text, DOCS and DECISIONS updated to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:58:34 +02:00
glenn schrooyen 0951cb227f Merge release/1.0 into safety-79-peak-margin
infra-pin / fresh (pull_request) Successful in 1s
checks / unit (pull_request) Successful in 11m36s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	goodwe_controller/app/uilayout.py
2026-09-28 23:56:33 +02:00
admin 7995e4df0f UX-13 P3: Simple view and Batteries screen (#150)
infra-pin / fresh (push) Successful in 2s
2026-09-28 23:44:26 +02:00
glenn schrooyenandClaude Opus 5.5 e5a0ba23d7 SAFETY-79: CI fixes - MUTATION.md pointer, no key-taking helper, fixture sized on the aim
checks / unit (pull_request) Successful in 11m36s
infra-pin / fresh (pull_request) Successful in 2s
test_peakguard's over-limit fixture now sizes its load against
cap - margin, so the floor it asks for is exact wherever in the quarter
the suite runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBtqPrG1mDLXzTEBnhEkkV
2026-09-28 23:37:55 +02:00
goodwe-review-agent a9f7d78527 UX-13 P3 review: truthful peak lines, a clock-proof test, Simple stays default
checks / unit (pull_request) Successful in 11m10s
infra-pin / fresh (pull_request) Successful in 2s
- The peak limit's Why and plan block need a real power request (floor above
  0 W), not a blind or floor-limited guard. An Off battery gets the peak
  block only while it gives power. Why no longer says every battery gives.
- test_batteries_screen pins the fixture clock: unpinned it failed every
  morning. New checks cover the trade and cycle filters, the blind guard and
  an Off battery that A covers alone.
- Settings keeps only a picked view; a link to Installer is not remembered.
- Browser check: badges, unsaved change across views, locked value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:20:33 +02:00
adminandClaude Opus 5.5 b310282729 OPT-11 P2: HA entities for battery modes
checks / unit (pull_request) Successful in 11m12s
infra-pin / fresh (pull_request) Successful in 2s
Each battery gets an MQTT-discovered Mode select and Use switch, only while
battery_modes_enabled is true. Commands go through handle_action(), the
/action path; refusals are logged once. Retained commands are never applied.
Turning modes off removes exactly the configs announced (kept in the store).
With modes off the announcement is byte-identical to ed739d4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:12:04 +02:00
glenn schrooyenandClaude Opus 5.5 7c4c8f5c66 SAFETY-79: peak guard keeps a margin below the limit
checks / unit (pull_request) Failing after 11m34s
infra-pin / fresh (pull_request) Successful in 1s
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
2026-09-28 23:09:39 +02:00
Claude 2d2b6afb07 UX-13 P3: Simple view and Batteries screen
checks / unit (pull_request) Successful in 11m9s
infra-pin / fresh (pull_request) Successful in 2s
- Batteries: one card per battery with On/Off, the mode list (cheap hours
  and selling greyed out until OPT-11 P3), level, and Now / Today / Why
  lines built in homeview.py. Replaces the OPT-11 P1 minimal cards and uses
  the existing pack_use / pack_mode actions and store keys.
- An Off battery the peak limit still needs says so with its figure; no line
  shows 0 W beside moving power (OPT-11 P1 test F2). Today says "Not planned
  yet" until OPT-11 P3/P4.
- Home's plan leaves Off batteries out, except for the peak limit.
- Settings opens on Simple: the layout's simple fields with an applies chip
  and a note, plus the battery switches and modes. Installer is one tap.
- English and Dutch words in app/ui_text; test_batteries_screen.py; browser
  check tools/ux13_browser_check.py (CHECK=1 ux13_screenshots.sh); new and
  changed screenshots only.

No control, allocator, arbiter or command module changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBtqPrG1mDLXzTEBnhEkkV
2026-09-28 22:39:43 +02:00
adminandClaude Opus 5.5 ed739d4cdb OPT-11 P1: per-battery mode limits, on/off, solar order (#149)
infra-pin / fresh (push) Successful in 2s
Reviewed: a mode gives way to the peak floor only as far as it needs; SAFETY-03 kept at the rail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:53:22 +02:00