TEL-14 N1: trim DECISIONS (drop probe transcript, §1 to the reason), move the mutation ledger there with M2/M5
checks / unit (pull_request) Successful in 8m44s
checks / unit (pull_request) Successful in 8m44s
test_pv.py part 11 now prints a one-line pointer instead of the 12-row table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
This commit is contained in:
@@ -7,49 +7,24 @@ Owner report on 0.12.0: `sensor.espressif_vermogen` (ESPHome clamp) and
|
||||
|
||||
## 1. This reverses TEL-11 §2, and why
|
||||
|
||||
TEL-11 §2 refused a `pv_invert` because (1) PV is read by nothing in the control
|
||||
path, and (2) a reversed sensor "announces itself as −4 kW at noon" and should be
|
||||
"fixed where it is produced". (1) still holds: the flip is applied inside
|
||||
`pv.total()`, which only feeds the MQTT `pv` row and the status page;
|
||||
`test_pv.py` part 12 re-runs part 6's 40-cycle identity with a flip set, and
|
||||
`tools/tel11_pv_trace.py` on release/1.0 vs this tree gives identical `control`
|
||||
documents for `unset`, `one` and `multi`; the only telemetry change is the new
|
||||
caution in the `negative` (−4200 W) cells. Its `--compare` verdict itself now
|
||||
REFUSES on any honest run, because both trees know `pv_entities` — TEL-12 §3's
|
||||
discriminator has aged out, as TEL-11's did; not fixed here. (2) did
|
||||
not survive contact with a real site: these sensors are not *wrong*, they
|
||||
follow a different convention; at night they read a plausible small positive
|
||||
number, so nothing announces anything; and "fix it where it is produced" means a
|
||||
template sensor, which TEL-12 §2 already names as the place an `unavailable`
|
||||
source goes quietly wrong.
|
||||
TEL-11 §2 refused a `pv_invert` on two grounds. "PV is read by nothing in the
|
||||
control path" still holds: the flip lives in `pv.total()`, and `test_pv.py`
|
||||
part 12 re-runs part 6's 40-cycle identity with a flip set. "A reversed sensor
|
||||
announces itself" did not survive a real site: these sensors follow a different
|
||||
convention, read a plausible small positive number at night, and the only other
|
||||
fix is a template sensor, the place TEL-12 §2 says goes quietly wrong.
|
||||
|
||||
## 2. The shape: a parallel list, `pv_invert_entities` — measured
|
||||
## 2. The shape: a parallel list, `pv_invert_entities`
|
||||
|
||||
`tools/supervisor_shape_probe.py` §H, Supervisor 2026.08.0, against a 0.12.0
|
||||
blob (`pv_entities` set, no new key):
|
||||
|
||||
```
|
||||
== H. TEL-14: the SHAPE of a per-entity PV sign option ==
|
||||
PASS (a) PREFIX: `-sensor.pv_meter` validates under the shipped `- str` - Supervisor does not look inside the string, ...
|
||||
PASS (b) ⭐ PARALLEL LIST, SHIPPED: the 0.12.0 blob (no `pv_invert_entities` key) validates unchanged and the new key defaults to []
|
||||
PASS ...and one entity marked inverted validates
|
||||
PASS ⭐ ...and the shipped `options:` block with ONLY `pv_invert_entities` removed is REFUSED BY NAME ...
|
||||
Missing option 'pv_invert_entities' in root in GoodWe RS485 Controller (local_goodwe_controller)
|
||||
PASS ...and the Configuration tab renders it as a REPEATABLE string field with its own top-level (translated) label
|
||||
[{"name": "pv_invert_entities", "multiple": true, "required": true, "type": "string"}]
|
||||
PASS (c) LIST OF DICTS ON `pv_entities`: the STRINGS a 0.12.0 install stored are REFUSED ...
|
||||
Invalid dict for option 'pv_entities' in GoodWe RS485 Controller (local_goodwe_controller)
|
||||
PASS (c2) ...as a THIRD key it validates, but renders as a type-schema repeatable section whose per-entry keys reach the screen RAW ...
|
||||
PASS (d) GLOBAL `pv_invert: bool` validates too - it loses on SEMANTICS (one sign for a mixed roster), not on the schema
|
||||
== all cases passed ==
|
||||
```
|
||||
Measured by `tools/supervisor_shape_probe.py` §H (Supervisor 2026.08.0, against
|
||||
a 0.12.0 blob); re-run it for the transcript.
|
||||
|
||||
| shape | schema | why it lost / won |
|
||||
|---|---|---|
|
||||
| (a) `-sensor.x` prefix | accepted | invisible: the sign is a syntax only the description explains, in a field an installer fills with the entity picker's text |
|
||||
| (b) parallel list | accepted, 0.12.0 blob unchanged | **ships**: its own labelled, translated field ("PV entities whose sign is reversed"); an installer lists the odd ones out |
|
||||
| (c) dicts on `pv_entities` | **refuses 0.12.0's stored strings** | bricks the upgrade — TEL-12's trap again |
|
||||
| (c2) dicts as a third key | accepted | per-entry labels render raw (`entity`, `invert`) — §F; and a third PV surface |
|
||||
| (c2) dicts as a third key | accepted | per-entry labels render raw (`entity`, `invert`) — probe §F; and a third PV surface |
|
||||
| (d) global bool | accepted | one sign cannot describe inverter + meter in one roster |
|
||||
|
||||
(b)'s known cost is a typo in the second list: `pv.stray_inverts()` turns it into
|
||||
@@ -67,12 +42,35 @@ three correct meters at −20 W sum to −60 W and must stay quiet, while a reve
|
||||
a wrong threshold costs a spurious or missed caution, never data. The text says
|
||||
ADD (unflipped) or REMOVE (already flipped).
|
||||
|
||||
## 4. History
|
||||
## 4. Mutations
|
||||
|
||||
Fresh `cp -a` each, `__pycache__` purged, CI image, `:ro`, `--network none`;
|
||||
`test_pv.py` only unless stated. T1-T12 at 7559d21; M2/M5 are review #1628's,
|
||||
red since B1 (merged into release/1.0 @ 43b2740).
|
||||
|
||||
| # | mutation | bytes | reds |
|
||||
|---|---|---|---|
|
||||
| T1 | flip ignored in `total()` | −45 | 9 |
|
||||
| T2 | flip applied to every member | −7 | 6 |
|
||||
| T3 | `0.0 - w` → `-w` | −5 | 1 |
|
||||
| T4 | flip written as `abs()` | −1 | 2 |
|
||||
| T5 | `_read_pv()` stops passing the flip | −26 | 7 |
|
||||
| T6 | caution threshold −50 → 0 W | −17 | 3 |
|
||||
| T7 | `[sign inverted]` marker dropped | −39 | 3 |
|
||||
| T8 | negative caution made `bad` | +1 | 1 |
|
||||
| T9 | `stray_inverts()` always empty | −50 | 1 |
|
||||
| T10 | `inverted()` stops stripping | −8 | 1 |
|
||||
| T11 | ADD/REMOVE advice swapped | +4 | 2 |
|
||||
| T12 | `pv_invert_entities: []` deleted from `options:` | −25 | 2 test_translations + 17 probe |
|
||||
| M2 | `stray_inverts()` roster ignores `pv_entity` | +15 | 2 (REPORTED CASE, PADDING) |
|
||||
| M5 | `_read_pv()` flip set not stripped | +25 | 1 (PADDING) |
|
||||
|
||||
## 5. History
|
||||
|
||||
OPT-10's `sensor.goodwe_pv_power` recorded since 2026-09-24 on an install with
|
||||
such sensors carries the old sign; nothing rewrites it.
|
||||
|
||||
## 5. CHANGELOG entry for the next PKG cut
|
||||
## 6. CHANGELOG entry for the next PKG cut
|
||||
|
||||
Not written into `CHANGELOG.md`: `test_version_gate.py` 11b/11d refuse an
|
||||
`## Unreleased` heading (measured on this branch: 4 reds). For PKG to paste:
|
||||
|
||||
@@ -1343,27 +1343,9 @@ print(" time - see DECISIONS/TEL-11-pv-production.md §5 for the transcript."
|
||||
print(" ⚠️ A RED COUNT IS A PROPERTY OF THE SUITE AS MUCH AS OF THE MUTATION:")
|
||||
print(" these name THIS tree. Re-measure rather than inherit.")
|
||||
|
||||
# --- TEL-14's battery: fresh copy each, no __pycache__, CI image, :ro, --------
|
||||
# --network none. Every red is a NAMED check in part 12; no traceback.
|
||||
print()
|
||||
print(" TEL-14 mutation bytes reds")
|
||||
print(" ------------------------------------------------ ----- --------")
|
||||
for row in [
|
||||
("T1 the flip ignored in total()", "-45 B", "9 here"),
|
||||
("T2 the flip applied to EVERY member", "-7 B", "6 here"),
|
||||
("T3 `0.0 - w` -> `-w` (a -0.0 leaks)", "-5 B", "1 here"),
|
||||
("T4 the flip written as abs()", "-1 B", "2 here"),
|
||||
("T5 _read_pv() stops passing the flip", "-26 B", "7 here"),
|
||||
("T6 caution threshold -50 W -> 0 W", "-17 B", "3 here"),
|
||||
("T7 the [sign inverted] marker dropped", "-39 B", "3 here"),
|
||||
("T8 the negative caution made `bad`", "+1 B", "1 here"),
|
||||
("T9 stray_inverts() always empty", "-50 B", "1 here"),
|
||||
("T10 inverted() stops stripping", "-8 B", "1 here"),
|
||||
("T11 ADD/REMOVE advice swapped", "+4 B", "2 here"),
|
||||
("T12 `pv_invert_entities: []` deleted from options:", "-25 B",
|
||||
"2 test_translations + 17 probe"),
|
||||
]:
|
||||
print(f" {row[0]:<48} {row[1]:>5} {row[2]}")
|
||||
print(" TEL-14: 14 mutations, all red, no survivors - bytes and named reds in")
|
||||
print(" DECISIONS/TEL-14-pv-sign.md §4.")
|
||||
|
||||
print()
|
||||
if fails:
|
||||
|
||||
Reference in New Issue
Block a user