DOC-1. Operator docs told installers to do the wrong thing.
1. Wrong safety entity. The P1 age entity the ESP32 watchdog subscribes to is sensor.goodwe_p1_sample_age, not sensor.p1_sample_age_s. HA builds it from the device name GoodWe (app/mqtt.pyDEVICE) plus the entity name P1 sample age, and it matches the id recorded from the live install in tools/rehearsal/announced-reference.txt. Fixed in DOCS.md (heading and 4 mentions) and config.yaml:227. DOCS.md now says not to rename the device or the entity, rather than "the entity id".
2. Roster example wouldn't start. The DOCS.md inverters: example and table now include the required bms_soc_floor (and the table has capacity_kwh). The "three keys required" wording is corrected in DOCS.md and in the config.yaml schema comment.
3. Field guide.build_guide.py now says v0.1.0 is outdated (DOCS.md wins), and its slew_w row says 0 = follow the rail, with faster values refused (SAFETY-39). field-guide.html was regenerated, and the HTML build reproduces byte for byte at base. The PDF was not rebuilt: there is no Chrome on this host and CHROME is a Windows path. FIELD-GUIDE.md and README flag it as outdated. DOCS.md:7 now points to the PDF, and README's non-existent "FIELD-GUIDE.md §10" is now "field guide Step 7b".
New check test_docs.py:
The DOCS.md roster example, pasted over config.yaml's shipped options, is accepted by validate_startup_config(). It also has to carry every non-? per-entry schema key and no unknown keys.
A precondition confirms it is the roster being graded: without the roster, the example is refused.
The documented watchdog entity heading equals the id built from mqtt.DEVICE + the p1_age row, which is also checked against the recorded live id.
p1_sample_age_s appears in no shipped doc (DOCS.md, config.yaml, README.md, FIELD-GUIDE.md, build_guide.py, field-guide.html).
Mutations (each red, on a purged copy): drop bms_soc_floor from the example → 1b + 1d red; drop one capacity_kwh → 1d red; DOCS.md from a45ed06 → 1b/1d/2c/2d red; rename the device in mqtt.py → 2b/2c red; wrong id added to README → 2d red; config.yaml from a45ed06 → 2d red.
Suite: 32/32 PASS in goodwe-addon-checks:1 with checks.yml's exact command, on a purged tree mounted :ro.
Not touched: CHANGELOG.md and DECISIONS/TEL-07 still say p1_sample_age_s (history, out of scope).
DOC-1. Operator docs told installers to do the wrong thing.
**1. Wrong safety entity.** The P1 age entity the ESP32 watchdog subscribes to is `sensor.goodwe_p1_sample_age`, not `sensor.p1_sample_age_s`. HA builds it from the device name `GoodWe` (`app/mqtt.py` `DEVICE`) plus the entity name `P1 sample age`, and it matches the id recorded from the live install in `tools/rehearsal/announced-reference.txt`. Fixed in DOCS.md (heading and 4 mentions) and config.yaml:227. DOCS.md now says not to rename the device or the entity, rather than "the entity id".
**2. Roster example wouldn't start.** The DOCS.md `inverters:` example and table now include the required `bms_soc_floor` (and the table has `capacity_kwh`). The "three keys required" wording is corrected in DOCS.md and in the config.yaml schema comment.
**3. Field guide.** `build_guide.py` now says v0.1.0 is **outdated** (DOCS.md wins), and its `slew_w` row says 0 = follow the rail, with faster values refused (SAFETY-39). `field-guide.html` was regenerated, and the HTML build reproduces byte for byte at base. **The PDF was not rebuilt:** there is no Chrome on this host and `CHROME` is a Windows path. FIELD-GUIDE.md and README flag it as outdated. DOCS.md:7 now points to the PDF, and README's non-existent "FIELD-GUIDE.md §10" is now "field guide Step 7b".
**New check `test_docs.py`:**
- The DOCS.md roster example, pasted over config.yaml's shipped options, is **accepted by `validate_startup_config()`**. It also has to carry every non-`?` per-entry schema key and no unknown keys.
- A precondition confirms it is the roster being graded: without the roster, the example is refused.
- The documented watchdog entity heading equals the id built from `mqtt.DEVICE` + the `p1_age` row, which is also checked against the recorded live id.
- `p1_sample_age_s` appears in no shipped doc (DOCS.md, config.yaml, README.md, FIELD-GUIDE.md, build_guide.py, field-guide.html).
**Mutations (each red, on a purged copy):** drop `bms_soc_floor` from the example → 1b + 1d red; drop one `capacity_kwh` → 1d red; DOCS.md from a45ed06 → 1b/1d/2c/2d red; rename the device in mqtt.py → 2b/2c red; wrong id added to README → 2d red; config.yaml from a45ed06 → 2d red.
**Suite:** 32/32 PASS in `goodwe-addon-checks:1` with checks.yml's exact command, on a purged tree mounted `:ro`.
Not touched: CHANGELOG.md and DECISIONS/TEL-07 still say `p1_sample_age_s` (history, out of scope).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
- DOCS.md / config.yaml: the watchdog's P1 age entity is
sensor.goodwe_p1_sample_age (device "GoodWe" + "P1 sample age", as
app/mqtt.py announces and the live install recorded), not
sensor.p1_sample_age_s.
- DOCS.md: the inverters: example and per-entry table carry the required
bms_soc_floor (and capacity_kwh); config.yaml's schema comment says four
required keys, not three.
- Field guide: marked v0.1.0/outdated; slew_w row no longer recommends the
1000 W that SAFETY-39 now refuses. HTML regenerated; the PDF is NOT
rebuilt (no Chrome here). README/DOCS pointers fixed.
- test_docs.py: the documented roster must pass app/validate.py and the
schema's per-entry keys; the documented entity id must equal the id
composed from app/mqtt.py; the wrong id may appear in no shipped doc.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
Review of DOC-1 (head 29ca9b5): approved and merging.
CI is this PR's own run. Run 832, job 1957 shows PRNUM 119 and BASEREF release/1.0. It merged base a45ed06 with head 29ca9b5, and all 32 test files ran and passed, including test_docs.py.
The entity id is right.DEVICE["name"] is "GoodWe" (mqtt.py:29) and the row name is "P1 sample age". HA slugifies them together to sensor.goodwe_p1_sample_age, and object_id (p1_sample_age_s) does not decide the id. I checked this against three other sources: tools/rehearsal/live-entities-recorded.txt:38, announced-reference.txt (id and unique_id goodwe_ctl_p1_age), and the stage-4 failsafe firmware, which subscribes with entity_id: sensor.goodwe_p1_sample_age.
The roster example validates and the checks catch errors. I ran test_docs.py in the goodwe-addon-checks:1 image and it passed. I then applied 5 mutations of my own, and each one turned it red:
Removing bms_soc_floor from inverter-b fails 1b and 1d.
Putting back the old heading fails 2c and 2d.
Renaming the device to "GoodWe RS485 Controller" fails 2b and 2c.
Setting bms_soc_floor: 150 fails 1d.
Adding the wrong id to README fails 2d.
The change is docs only. Nothing changes under app/, and CHANGELOG and the version are untouched. The config.yaml diff is comments only. The anchors I checked in DOCS.md (#tariff-all-optional, the OPT-09 one, and the two-inverters one) all resolve. The README's "Step 7b" reference exists in the guide.
Non-blocking notes:
The test's 2b label says "the id recorded from the live install (announced-reference.txt)". That file's own header says it is not a live-registry dump: it records what the build announces. The live anchor is live-entities-recorded.txt. The check itself is still sound. Only the label overstates where the id came from.
The FIELD-GUIDE.md note about the CHROME Windows path is fine and useful. The verbosity is acceptable.
Known leftovers, not addressed here: the PDF is still v0.1.0 with slew_w: 1000. The wrong id is still in CHANGELOG.md and DECISIONS/TEL-07, kept as history. The comment at app/mqtt.py:68 still gives the device as "GoodWe RS485 Controller" where it should be "GoodWe".
**Review of DOC-1 (head 29ca9b5): approved and merging.**
- **CI is this PR's own run.** Run 832, job 1957 shows PRNUM 119 and BASEREF release/1.0. It merged base a45ed06 with head 29ca9b5, and all 32 test files ran and passed, including `test_docs.py`.
- **The entity id is right.** `DEVICE["name"]` is `"GoodWe"` (mqtt.py:29) and the row name is `"P1 sample age"`. HA slugifies them together to `sensor.goodwe_p1_sample_age`, and `object_id` (`p1_sample_age_s`) does not decide the id. I checked this against three other sources: `tools/rehearsal/live-entities-recorded.txt:38`, `announced-reference.txt` (id and unique_id `goodwe_ctl_p1_age`), and the stage-4 failsafe firmware, which subscribes with `entity_id: sensor.goodwe_p1_sample_age`.
- **The roster example validates and the checks catch errors.** I ran `test_docs.py` in the `goodwe-addon-checks:1` image and it passed. I then applied 5 mutations of my own, and each one turned it red:
1. Removing `bms_soc_floor` from inverter-b fails 1b and 1d.
2. Putting back the old heading fails 2c and 2d.
3. Renaming the device to "GoodWe RS485 Controller" fails 2b and 2c.
4. Setting `bms_soc_floor: 150` fails 1d.
5. Adding the wrong id to README fails 2d.
- **The change is docs only.** Nothing changes under `app/`, and CHANGELOG and the version are untouched. The config.yaml diff is comments only. The anchors I checked in DOCS.md (`#tariff-all-optional`, the OPT-09 one, and the two-inverters one) all resolve. The README's "Step 7b" reference exists in the guide.
Non-blocking notes:
- The test's 2b label says "the id recorded from the live install (announced-reference.txt)". That file's own header says it is **not** a live-registry dump: it records what the build announces. The live anchor is `live-entities-recorded.txt`. The check itself is still sound. Only the label overstates where the id came from.
- The FIELD-GUIDE.md note about the `CHROME` Windows path is fine and useful. The verbosity is acceptable.
Known leftovers, not addressed here: the PDF is still v0.1.0 with `slew_w: 1000`. The wrong id is still in CHANGELOG.md and DECISIONS/TEL-07, kept as history. The comment at `app/mqtt.py:68` still gives the device as "GoodWe RS485 Controller" where it should be "GoodWe".
admin
merged commit fa3d237ce1 into release/1.02026-09-24 23:42:14 +02: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.
DOC-1. Operator docs told installers to do the wrong thing.
1. Wrong safety entity. The P1 age entity the ESP32 watchdog subscribes to is
sensor.goodwe_p1_sample_age, notsensor.p1_sample_age_s. HA builds it from the device nameGoodWe(app/mqtt.pyDEVICE) plus the entity nameP1 sample age, and it matches the id recorded from the live install intools/rehearsal/announced-reference.txt. Fixed in DOCS.md (heading and 4 mentions) and config.yaml:227. DOCS.md now says not to rename the device or the entity, rather than "the entity id".2. Roster example wouldn't start. The DOCS.md
inverters:example and table now include the requiredbms_soc_floor(and the table hascapacity_kwh). The "three keys required" wording is corrected in DOCS.md and in the config.yaml schema comment.3. Field guide.
build_guide.pynow says v0.1.0 is outdated (DOCS.md wins), and itsslew_wrow says 0 = follow the rail, with faster values refused (SAFETY-39).field-guide.htmlwas regenerated, and the HTML build reproduces byte for byte at base. The PDF was not rebuilt: there is no Chrome on this host andCHROMEis a Windows path. FIELD-GUIDE.md and README flag it as outdated. DOCS.md:7 now points to the PDF, and README's non-existent "FIELD-GUIDE.md §10" is now "field guide Step 7b".New check
test_docs.py:validate_startup_config(). It also has to carry every non-?per-entry schema key and no unknown keys.mqtt.DEVICE+ thep1_agerow, which is also checked against the recorded live id.p1_sample_age_sappears in no shipped doc (DOCS.md, config.yaml, README.md, FIELD-GUIDE.md, build_guide.py, field-guide.html).Mutations (each red, on a purged copy): drop
bms_soc_floorfrom the example → 1b + 1d red; drop onecapacity_kwh→ 1d red; DOCS.md froma45ed06→ 1b/1d/2c/2d red; rename the device in mqtt.py → 2b/2c red; wrong id added to README → 2d red; config.yaml froma45ed06→ 2d red.Suite: 32/32 PASS in
goodwe-addon-checks:1with checks.yml's exact command, on a purged tree mounted:ro.Not touched: CHANGELOG.md and DECISIONS/TEL-07 still say
p1_sample_age_s(history, out of scope).🤖 Generated with Claude Code
https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
Review of DOC-1 (head
29ca9b5): approved and merging.a45ed06with head29ca9b5, and all 32 test files ran and passed, includingtest_docs.py.DEVICE["name"]is"GoodWe"(mqtt.py:29) and the row name is"P1 sample age". HA slugifies them together tosensor.goodwe_p1_sample_age, andobject_id(p1_sample_age_s) does not decide the id. I checked this against three other sources:tools/rehearsal/live-entities-recorded.txt:38,announced-reference.txt(id and unique_idgoodwe_ctl_p1_age), and the stage-4 failsafe firmware, which subscribes withentity_id: sensor.goodwe_p1_sample_age.test_docs.pyin thegoodwe-addon-checks:1image and it passed. I then applied 5 mutations of my own, and each one turned it red:bms_soc_floorfrom inverter-b fails 1b and 1d.bms_soc_floor: 150fails 1d.app/, and CHANGELOG and the version are untouched. The config.yaml diff is comments only. The anchors I checked in DOCS.md (#tariff-all-optional, the OPT-09 one, and the two-inverters one) all resolve. The README's "Step 7b" reference exists in the guide.Non-blocking notes:
live-entities-recorded.txt. The check itself is still sound. Only the label overstates where the id came from.CHROMEWindows path is fine and useful. The verbosity is acceptable.Known leftovers, not addressed here: the PDF is still v0.1.0 with
slew_w: 1000. The wrong id is still in CHANGELOG.md and DECISIONS/TEL-07, kept as history. The comment atapp/mqtt.py:68still gives the device as "GoodWe RS485 Controller" where it should be "GoodWe".