- Details link: /config/app/<slug>/documentation on HA 2026.2+ (the old /hassio/addon path is a 404 from 2026.5), /hassio/addon on 2026.1 and older. Slug from GET /addons/self/info, version from GET /info, hostname as fallback. - Shadow mode: the over-rating alarm and row say what would have been sent, the peak alarm no longer says the battery is giving all it can. - "controller" -> "the add-on" / "control". Settings named by their labels; four labels changed to match (Peak reserve, Battery level entity, Solar production ..., Reversed-sign solar entities). - Shadow banner and inverter link notes moved to messages.py and checked. - DOCS Notifications and Status page rewritten for home owners, with a "For installers" part each. Allowlist 168 -> 167. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LyR88rXETvwhTgx6yHE39p
9.0 KiB
UX-08 phase 2a: short notifications, and what moved out of them
The owner decided on 2026-09-27: a title of at most about 5 everyday words and a one-sentence body. A red safety alarm may use up to 3 sentences, so no action-relevant information is lost. Titles are neutral, with no "GoodWe:" prefix. HA entity ids appear only in refusals. The rule is STYLE.md at the repository root, the texts are in app/messages.py, and test_messages.py enforces both. The detail each notification used to carry is in DOCS.md under "Notifications", and the body links to it.
Unchanged: every notification_id, every trigger and cadence (edges, SAFETY-34 re-announce, per-unit ids), every log line and every status row. The status banner and rows are phase 2b, refusals and option texts 2c, logs 2d; ux08_allowlist.txt lists them until then.
Where a choice was made
- Severity of "not delivering" (SAFETY-42). The notification is an alarm, so it may use 3 sentences. Its log line is ERROR and the alarm is latched. The page banner stays amber, as SAFETY-42 decided, because control keeps running; the two answer different questions (is control running / must a person act) and HA shows no colour on a notification. The three checks stay in their original order. Clearing it takes stop then start, and the body says so.
- Figures left the bodies of the frozen-meter card (the rail and the command), the circulating-power card (the watts and the time window) and the peak cards (the projection). None of them is needed to act, and all of them are still in the reason text that the log line and the status row carry.
test_freeze.pyandtest_watchdog.pynow pin that. The frozen-meter card can therefore no longer quote a wrong rail (SAFETY-20), because it quotes none. - The over-rating alarm keeps its numbers (asked, sent, and which limit cut it), because they are what a fault report needs.
ClampWatchdog.factscarries them under the same keep-the-bug rule asreason, so the words and the numbers always describe the same tick, with asked before sent (SAFETY-40,test_clamp.pypart 6). - SAFETY-25 stays in the peak-reserve alarm as its last sentence ("the reserve only limits peak shaving … down to its cut-out level"). The alarm now gives each branch its own action: at the reserve, lower it; battery level unread, check the sensor; floor unknown, set the cut-out level. That last branch is
soc_floor is None, which happens when an inverter's cut-out level is missing, not the peak reserve (that option always has a value). Before, every branch said "lower peak_soc_floor". The title, "Battery stopped limiting the peak", is true on all three branches. - SAFETY-32 at a roster of one. The body no longer ends in a separate "WHICH PACK" paragraph. The pack's name is part of the first sentence ("The battery of inverter-b …"), and at a roster of one that is the only difference.
- Dropped as background, now in DOCS: "charging stays blocked" (peak reserve), "why no other guard fired" (circulating power, not delivering), and the saturation-freeze distinction (over-rating). "The meter cannot see this" stays in the circulating-power card, as the owner asked.
- The Details link opens the add-on's documentation page (
/hassio/addon/<slug>/documentation, with the slug taken from the container hostname) and names the section. A#headinganchor was not used because nobody has checked that Home Assistant's documentation tab renders heading ids; if it does, adding one is a one-line change. Outside an add-on container it names the section without a link.
Phase 2b: status rows and page banners
Every row of the Commissioning list and every banner is now in app/messages.py (row_*, banner_*), and test_messages.py checks a rendering of each. The row and banner kinds are gone from ux08_allowlist.txt (200 → 168 entries). DOCS.md "Status page" explains the rows. Unchanged: every row's colour (ok / warn / bad), which rows show when, and the banner cascade order.
Where a choice was made
- A red row may use 3 sentences (30 words). STYLE.md gave rows 15 words; the owner allows red safety states 3 sentences. A red row needs room for what happened, the state (0 W) and how it clears. STYLE.md now says so, and the test applies it by colour.
- Figures left the rows, not the product. The reason texts (freeze, sign, circulating, delivery, peak guard) carry reason codes and limits; they stay on the ERROR/WARNING log line and the event list, as before. Rows keep the numbers a reader acts on: the stall age and the 0 W deadline, the meter age and limit, asked and sent for an over-rating, the peak limit, and "opposite for 12 of 60 seconds" while a check counts. So 2a item 2 ("also on the status row") no longer holds, and DOCS.md says "in the add-on log".
- No entity id on any row, even the green ones that used to print
sensor.x = 54. The sensor rows name the setting (Battery power for inverter-b). Solar sources are numbered in the order of the settings list (source 2 of 3, entry 1 of the reversed-sign list). This retires TEL-12's rule that a one-entity site reads 0.11.0's sentence byte for byte. Atools/tel11_pv_trace.py --compareagainst a pre-UX-08 tree therefore shows the PV rows as changed telemetry, and the control documents stay equal. The per-source watts and units left the multi-source row. The total, the count and which source is missing remain. - UX-07 item 1.
ClampWatchdognow also countsover_ratingandboundseparately. After an episode, each count shows under its own alarm's title ("Power request too high: 2 times since start, not now", "Battery is not keeping up: …"). A site with both gets two amber rows where it had one. - The "Not ready" banner is the first red row's own
banner, or else its first sentence. The peak-reserve and over-rating rows setbannerto their notification title. The three trips keep their own banner branches, reworded (e.g. "Inverters worked against each other. Every inverter is set to 0 W."). - How a latch clears stays on the row, shortened: "Only starting control clears this", "A restart does not clear this", "only stopping and starting control clears this" (not delivering). SAFETY-25's sentence stays on the peak-reserve row.
- Rows got an
id(meter_frozen,direction,pv, …), so tests find a row by what it is, not by its words. The page ignores it. - Left for later: texts that rows embed from other modules and that were not flagged as rows (the month-peak line,
peakguard.explain(), the liveness and stale notes,shadow.banner()). The month-peak row only lost its semicolons.
UX-09: fixes after the phase 2a test
- The Details link follows the Home Assistant version. HA 2026.2 added the built-in
apppanel (core #157554, frontend #28245), whose add-on pages are/config/app/<slug>/documentation. 2026.5 stopped registering thehassiopanel, so/hassio/addon/<slug>/documentationis a 404 there (TEST-23, HA 2026.9.1). 2026.1 and older have only the old path. The one path valid on both,/_my_redirect/supervisor_addon?addon=<slug>, opens the Info tab, not Documentation. So the add-on reads its slug (GET /addons/self/info) and the HA version (GET /info) at start, and picks the path. An unknown version gets the current path. The hostname stays as a fallback for the slug. Phase 2a item 7 is replaced by this. - Shadow mode says "would". The over-rating alarm and row said "sent X W" while 0 W was on the wire, and the peak alarm said "the battery is giving all it can". Both now take
shadow=, and in shadow mode say what would have been sent and that the inverters stay at 0 W. Severity, id and cadence do not change with the mode. - "Controller" is gone from texts. "The add-on" names who decides, and "control" names what it does, as in the existing "start control". The add-on is what the reader sees in Home Assistant, and "controller" was easy to confuse with the control board.
- One term per setting, matching its label. Four labels changed instead of the texts, because the texts' words were plainer: “Peak reserve (%)” (was "Peak guard will not discharge below"), “Battery level entity (%)” (was "Battery charge level"), and “Solar production entity / entities, per inverter / Reversed-sign solar entities” (was "PV …"). The Dutch labels already said "Zonneproductie". Option descriptions are phase 2c and were not changed, so some still say "PV".
- The shadow banner and the inverter notes are now
messages.banner_shadow()androw_no_setpoint/row_not_controllable/row_commands_refused, sotest_messages.pychecks them. The red shadow banner no longer lists the latches, because 12 words cannot carry them. It says a safety stop stays on, and each latch keeps its own red row, which names it and says how it clears. The colour of a liveness row now comes fromis_live(), not from matching "NOT COMMANDABLE" in the text. - DOCS "Notifications" and "Status page" are written for a home owner, and the card ids, keys and log detail moved to a "For installers" part of each.