Compare commits

...
3 Commits
Author SHA1 Message Date
glenn schrooyenandClaude Opus 5 8e3734f5ea PKG-12: the live options WERE checked, and the changelog said they were not
checks / unit (pull_request) Successful in 6m17s
Review approved the bump and, in doing so, dated one of its own paragraphs.
When this section was written the pre-deploy check had not been run and the
changelog said so, correctly. The owner then exported the reference install's
options and the check cleared, which makes the shipped sentence false in the
release notes an operator reads at the hardware.

Replaced with what was measured, twice:

  stored blob as-is                          exit 0, CLEARED
  effective post-upgrade config              exit 0, CLEARED
    (the 70 stored keys merged OVER 0.9.0's
     71 config.yaml defaults)

  max_w 5000, slew_w 400, rule-10 ceiling 555.6 W.

⚠️ AND THE SECOND CHECK IS NOT CEREMONY. The stored blob has 70 keys, not 71:
`delivery_hold_s` arrived with SAFETY-42 in 0.8.0, so a box running 0.7.0 has
never stored it, and it is REQUIRED in the schema with no trailing `?` - the
exact shape that becomes exit 78. It resolves to its `options:` default of 185
because the Supervisor sets `App.options = deepmerge(defaults, stored)`, which
`tools/supervisor_selfapi_probe.py` §D pins against a real Supervisor image.
Review re-derived that independently rather than taking the reasoning on trust.

"Your saved settings are valid" and "what the box will actually run is valid"
are different questions, and only the second one is the one being asked before
a deploy.

Suite: 26 files, all pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
2026-09-07 00:47:11 +02:00
glenn schrooyenandClaude Opus 5 86bdf49332 PKG-12: bump 0.8.0 -> 0.9.0, so the five merges behind it can actually ship
checks / unit (pull_request) Successful in 6m14s
⚠️ MINOR FOR NEW FUNCTIONALITY, NOT FOR A BREAK, AND THAT DISTINCTION IS
CHECKED RATHER THAN ASSERTED. PKG-07 was minor because a config that started on
0.7.0 could be REFUSED on 0.8.0. Nothing of that kind is true here:

  - `options:` and `schema:` hold 71 top-level keys on both 06661c5 and HEAD.
    The one schema addition is a PER-ENTRY key, `capacity_kwh: float(0.1,200)?`,
    and the trailing `?` makes it OPTIONAL.
  - An unmodified 0.8.0-era config validates clean on 0.9.0. Measured through
    the shipped validator on both the flat single-inverter shape the reference
    install runs and an N=2 roster with no `capacity_kwh` on any entry: 0
    problems each.
  - OPT-09's two new refusals fire only on configs that USE the new key - an
    unparseable value, or the key stated on one entry and left empty on another.
    Neither can reach a config written before the key existed.

PKG-07's first draft justified its bump with an invented compatibility break and
review caught it. This one states what was measured, and the measurement says
existing installs upgrade untouched.

Contents since 0.8.0 (`06661c5`): UX-02 (`3d29993`), OPT-09 (`fdb3b69`),
PKG-09 (`fcaa724`).

⚠️ THE VERSION WENT UNBUMPED FOR THE THIRD TIME IN THREE DAYS - PKG-06 six
merges, PKG-07 six, this one five - and this time PKG-09's own tool caught it
during PKG-09's review rather than a person. The changelog carries OPT-09's
disclosed N=2 detection regression and points at the pre-deploy check.

⚠️ STILL NOT DONE, AND STILL NOT DOABLE FROM HERE: the live options have not
been checked against this version's validator. The gate reports exit 2 - NOT
CLEARED - rather than clearing, which is correct. Export the options from the
Supervisor and re-run before `ha apps update`.

Suite: 26 files, all pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
2026-09-07 00:18:36 +02:00
admin fcaa72418d Merge pull request 'PKG-09: refuse a deploy that would be a no-op, or that the add-on would reject' (#63) from PKG-09 into release/1.0
PKG-09: refuse a deploy that would be a no-op, or that the add-on would reject
2026-09-07 00:04:32 +02:00
2 changed files with 82 additions and 1 deletions
+81
View File
@@ -1,5 +1,86 @@
# Changelog
## 0.9.0
⚠️ **MINOR FOR NEW FUNCTIONALITY, NOT FOR A BREAK - AND THAT DISTINCTION IS THE
POINT.** 0.8.0 was minor because a config that started on 0.7.0 could be
REFUSED on it (rule 10 against 0.7.0's own default `slew_w: 1000`). Nothing of
that kind is true here, and it was checked rather than assumed:
- `options:` and `schema:` both hold **71 top-level keys**, the same 71 as
0.8.0. The one schema addition is a per-entry key, `capacity_kwh:
float(0.1,200)?` - **note the trailing `?`, it is OPTIONAL**.
- An unmodified 0.8.0-era config validates clean on 0.9.0. Measured on both the
flat single-inverter shape the reference install runs and an N=2 roster with
no `capacity_kwh` on any entry: **0 problems each**.
- The two refusals [[OPT-09]] adds fire only on configs that USE the new key -
an unparseable value, or the key stated on one roster entry and left empty on
another. Neither can reach a config written before the key existed.
So: existing installs upgrade untouched, and the bump is minor because the
option surface and the behaviour grew.
Contents, in merge order since 0.8.0 (`06661c5`):
| | |
|---|---|
| `3d29993` | UX-02 - the validator's refusals, next to the field, before the save |
| `fdb3b69` | OPT-09 - the weights parameter nothing ever passed, and what it cannot do |
| `fcaa724` | PKG-09 - refuse a deploy that would be a no-op, or that the add-on would reject |
**UX-02** builds the real configuration surface in the ingress panel, beside the
Supervisor Configuration tab that cannot be removed. The prize is not styling:
`validate.py` writes long cross-field refusals the Supervisor UI *structurally
cannot show*, and until now an operator met them as **exit 78 in a log**, after
saving and restarting. ⚠️ Two config surfaces now exist and the DECISIONS record
names the **stored options blob** as authoritative, neither UI.
**OPT-09** makes the architecture's one free parameter real. `main.py` called
`resolve()` without weights, so the split was a fixed 50/50 regardless of what
either pack could deliver; it now passes SoC- and capacity-aware weights.
⚠️ **OPT-09 SHIPS A DISCLOSED DETECTION REGRESSION AT N=2.** `delivery.
delinquent()` reads an ABSOLUTE 500 W gap, so weighting a low-headroom unit down
to a small share puts a unit delivering **none of what it was asked** under the
threshold. Measured: a wedged inverter goes from named on 199 of 200 cycles to
**0 of 200** at a load its sibling can carry alone. The alarm returns once the
healthy pack saturates - swept, that is a 5000 W load on the fixture, **below**
the proportional-regime formula's 6500 W and not above it. ⚠️ **N=1 IS
UNAFFECTED**: `allocator.plan()` returns before weights are read at all. The
closure is card SAFETY-43.
**PKG-09** adds `tools/predeploy_check.py`. ⚠️ **RUN IT BEFORE DEPLOYING THIS
RELEASE** - it is what caught the fact that 0.8.0 had five runtime commits
behind it, which is why this section exists:
docker run --rm -v <repo>:/w:ro goodwe-addon-checks:1 \
python3 /w/goodwe_controller/tools/predeploy_check.py \
--deployed-version 0.8.0 --options /w/live-options.json
Exit `0` cleared, `1` REFUSED, `2` NOT CLEARED. ⚠️ **2 is not a pass.**
✅ **RUN AGAINST THIS RELEASE, 2026-09-07: CLEARED, exit 0.** The reference
install's options were exported from the Supervisor (70 keys) and checked twice
- the stored blob as-is, and the **effective post-upgrade config**, being those
70 keys merged over 0.9.0's 71 defaults. Both pass. `max_w` 5000, `slew_w` 400
against a rule-10 ceiling of 555.6 W.
⚠️ **THE STORED BLOB HAS 70 KEYS, NOT 71, AND THAT IS THE INTERESTING PART.**
`delivery_hold_s` arrived with SAFETY-42 in 0.8.0, so an install running 0.7.0
has never stored it - and it is REQUIRED in the schema, no trailing `?`, which
is the shape that becomes exit 78. It resolves to its `options:` default of
**185**, because the Supervisor sets `App.options = deepmerge(config.yaml
defaults, stored options)`; `tools/supervisor_selfapi_probe.py` §D pins that
against a real Supervisor image rather than assuming it. The second check above
exists because "your saved settings are valid" and "what the box will actually
run is valid" are different questions, and only the second one matters.
⚠️ **THE VERSION WENT UNBUMPED FOR THE THIRD TIME IN THREE DAYS** - PKG-06 six
merges, PKG-07 six, this one five - and this time it was caught by PKG-09's own
tool during PKG-09's review rather than by a person. `ha apps update` against an
unchanged version installs nothing and reports success. PKG-10 carries the
post-merge alarm so that noticing stops being a human's job.
## Unreleased
⚠️ **THIS HAS NO VERSION AND CANNOT REACH AN INSTALL UNTIL IT GETS ONE.**
+1 -1
View File
@@ -1,5 +1,5 @@
name: GoodWe RS485 Controller
version: "0.8.0"
version: "0.9.0"
slug: goodwe_controller
description: >-
Drives a GoodWe ES/BP battery inverter over RS485 by emulating its smart