SMA-2: each inverter is reached through a driver. A pure refactor: GoodWe behaviour, commands, log lines and sentences are unchanged.
app/drivers.py: a Driver per roster entry (configured, actuator_id, limits, read, write, release, probe, link_stale_s, batt_bound, settle_s, brand, words). GoodWeEsphomeDriver makes the calls the old code made, in the same order; its release() is write(0).
Inverter.driver; has_writer(), is_live() and link_note() read it. Moved to the driver: the SoC/power read, the write, the device range (run_control, amain, the settings panel), rule 2 per unit, the status rows' source test, and the SAFETY-28 census (counts actuator_id()s).
Schema: setpoint_entity optional per entry, plus driver (only goodwe_esphome), host, port, unit_id, maintenance (checked, not read). Supervisor shape probe re-run (section K, all cases pass).
Not here: the user-definable name, the two idle states, any SMA or FoxESS driver. Nothing calls release() yet.
Checked against 23ff9d0: replay digests and a log of every Home Assistant call byte-identical at N=1 and N=2; TEL-07 announce diff 0/0/0 at N=1 and N=2; 386 distinct option blobs from the existing tests validate identically; full suite 99 files green locally. New test_sma2_driver.py: a fake driver beside a GoodWe unit; twelve seam mutants all caught. Report: reports/SMA-2-dev-report.md.
Existing tests touched, each because the thing it pins moved with the seam: test_inverter.py (schema: setpoint_entity optional, five new keys), test_freshness.py (BOUNDS["batt"] is subscripted by drivers.py), test_uilayout.py (driver keys are per-entry keys the page does not draw), test_translations.py (13 per-entry keys).
New text, for the new keys only: en/nl field names in translations, five refusal labels, and the rule 9 sentences for a bad driver, host, port, unit number or maintenance value. No existing sentence changed.
SMA-2: each inverter is reached through a driver. A pure refactor: GoodWe behaviour, commands, log lines and sentences are unchanged.
- `app/drivers.py`: a `Driver` per roster entry (`configured`, `actuator_id`, `limits`, `read`, `write`, `release`, `probe`, `link_stale_s`, `batt_bound`, `settle_s`, `brand`, `words`). `GoodWeEsphomeDriver` makes the calls the old code made, in the same order; its `release()` is `write(0)`.
- `Inverter.driver`; `has_writer()`, `is_live()` and `link_note()` read it. Moved to the driver: the SoC/power read, the write, the device range (run_control, amain, the settings panel), rule 2 per unit, the status rows' source test, and the SAFETY-28 census (counts `actuator_id()`s).
- Schema: `setpoint_entity` optional per entry, plus `driver` (only `goodwe_esphome`), `host`, `port`, `unit_id`, `maintenance` (checked, not read). Supervisor shape probe re-run (section K, all cases pass).
- Not here: the user-definable name, the two idle states, any SMA or FoxESS driver. Nothing calls `release()` yet.
Checked against 23ff9d0: replay digests and a log of every Home Assistant call byte-identical at N=1 and N=2; TEL-07 announce diff 0/0/0 at N=1 and N=2; 386 distinct option blobs from the existing tests validate identically; full suite 99 files green locally. New `test_sma2_driver.py`: a fake driver beside a GoodWe unit; twelve seam mutants all caught. Report: reports/SMA-2-dev-report.md.
Existing tests touched, each because the thing it pins moved with the seam: `test_inverter.py` (schema: `setpoint_entity` optional, five new keys), `test_freshness.py` (`BOUNDS["batt"]` is subscripted by drivers.py), `test_uilayout.py` (driver keys are per-entry keys the page does not draw), `test_translations.py` (13 per-entry keys).
New text, for the new keys only: en/nl field names in translations, five refusal labels, and the rule 9 sentences for a bad driver, host, port, unit number or maintenance value. No existing sentence changed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
app/drivers.py holds one Driver per roster entry (configured, actuator_id,
limits, read, write, release, probe, link_stale_s, batt_bound, settle_s, brand,
words). GoodWeEsphomeDriver makes the calls the code it replaced made, in the
same order. Inverter gets driver; has_writer, is_live and link_note read it. The
SoC/power read, the write, the device range (run_control, amain, the settings
panel), rule 2 per unit and the SAFETY-28 census go through it.
setpoint_entity is optional per entry beside driver, host, port, unit_id and
maintenance; only goodwe_esphome is selectable, the rest are checked and unused.
Co-Authored-By: Claude <noreply@anthropic.com>
Owner decision 2026-11-07: clients see nothing new until SMA-4. config.yaml,
translations, labels and the page layout are back to 23ff9d0's. The validation
of the keys stays for callers that skip the schema.
Co-Authored-By: Claude <noreply@anthropic.com>
Pure refactor: wire log of every HA call in the 7 replay identity tools (N=1 and N=2, ~113k calls) and their digests byte-identical base 23ff9d0 vs head. 386 option blobs give identical results. TEL-07 announce diff 0/0/0 at N=1 (11 topics) and N=2 (19). Every moved call site read: same calls, same order, same timeout/exception handling.
Safety: census identical to base on 344 + 144 shapes (incl. driver keys, odd types, nested). Rule 9(d) refuses a GoodWe entry without setpoint_entity, same sentence. Heartbeat, stop, shutdown and zero paths unchanged; nothing calls release().
Hidden keys: config.yaml, translations, messages, uilayout/uimodel/uipage byte-identical to base. Supervisor probe F identical (383 lines); probe exit 0, 71 PASS. Rule 9(h): no exception on 115 odd values (NaN, inf, bool, list, dict).
Tests: full suite locally 99 files, 0 failed, 1427 s. test_sma2_driver 66 checks pass. Two of my own mutants (write bypass, is_live window) both caught. CI 1557/1558 green on c015230.
Cycle time: head within noise of base (N=1 worst 2.78-2.93 vs 2.82-2.91 ms; N=2 4.00-4.02 vs 3.95-4.13 ms).
Non-blocking notes for SMA-4/SMA-10 are in reports/SMA-2-review-report.md.
Review (Opus) of c015230: **approved, merging.**
- Pure refactor: wire log of every HA call in the 7 replay identity tools (N=1 and N=2, ~113k calls) and their digests byte-identical base 23ff9d0 vs head. 386 option blobs give identical results. TEL-07 announce diff 0/0/0 at N=1 (11 topics) and N=2 (19). Every moved call site read: same calls, same order, same timeout/exception handling.
- Safety: census identical to base on 344 + 144 shapes (incl. `driver` keys, odd types, nested). Rule 9(d) refuses a GoodWe entry without `setpoint_entity`, same sentence. Heartbeat, stop, shutdown and zero paths unchanged; nothing calls `release()`.
- Hidden keys: config.yaml, translations, messages, uilayout/uimodel/uipage byte-identical to base. Supervisor probe F identical (383 lines); probe exit 0, 71 PASS. Rule 9(h): no exception on 115 odd values (NaN, inf, bool, list, dict).
- Tests: full suite locally 99 files, 0 failed, 1427 s. test_sma2_driver 66 checks pass. Two of my own mutants (write bypass, is_live window) both caught. CI 1557/1558 green on c015230.
- Cycle time: head within noise of base (N=1 worst 2.78-2.93 vs 2.82-2.91 ms; N=2 4.00-4.02 vs 3.95-4.13 ms).
Non-blocking notes for SMA-4/SMA-10 are in reports/SMA-2-review-report.md.
admin
merged commit 57c8d1b912 into release/1.02026-11-07 14:46:59 +01:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
SMA-2: each inverter is reached through a driver. A pure refactor: GoodWe behaviour, commands, log lines and sentences are unchanged.
app/drivers.py: aDriverper roster entry (configured,actuator_id,limits,read,write,release,probe,link_stale_s,batt_bound,settle_s,brand,words).GoodWeEsphomeDrivermakes the calls the old code made, in the same order; itsrelease()iswrite(0).Inverter.driver;has_writer(),is_live()andlink_note()read it. Moved to the driver: the SoC/power read, the write, the device range (run_control, amain, the settings panel), rule 2 per unit, the status rows' source test, and the SAFETY-28 census (countsactuator_id()s).setpoint_entityoptional per entry, plusdriver(onlygoodwe_esphome),host,port,unit_id,maintenance(checked, not read). Supervisor shape probe re-run (section K, all cases pass).release()yet.Checked against
23ff9d0: replay digests and a log of every Home Assistant call byte-identical at N=1 and N=2; TEL-07 announce diff 0/0/0 at N=1 and N=2; 386 distinct option blobs from the existing tests validate identically; full suite 99 files green locally. Newtest_sma2_driver.py: a fake driver beside a GoodWe unit; twelve seam mutants all caught. Report: reports/SMA-2-dev-report.md.Existing tests touched, each because the thing it pins moved with the seam:
test_inverter.py(schema:setpoint_entityoptional, five new keys),test_freshness.py(BOUNDS["batt"]is subscripted by drivers.py),test_uilayout.py(driver keys are per-entry keys the page does not draw),test_translations.py(13 per-entry keys).New text, for the new keys only: en/nl field names in translations, five refusal labels, and the rule 9 sentences for a bad driver, host, port, unit number or maintenance value. No existing sentence changed.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
Review (Opus) of
c015230: approved, merging.23ff9d0vs head. 386 option blobs give identical results. TEL-07 announce diff 0/0/0 at N=1 (11 topics) and N=2 (19). Every moved call site read: same calls, same order, same timeout/exception handling.driverkeys, odd types, nested). Rule 9(d) refuses a GoodWe entry withoutsetpoint_entity, same sentence. Heartbeat, stop, shutdown and zero paths unchanged; nothing callsrelease().c015230.Non-blocking notes for SMA-4/SMA-10 are in reports/SMA-2-review-report.md.