UX-08 2d: plain log lines, the rest of the status page, and DOCS
checks / unit (pull_request) Successful in 8m55s
infra-pin / fresh (pull_request) Successful in 1s

Every WARNING and ERROR line is one plain line of at most 25 words, with
no card ids, capitals or semicolons; the reasoning of the ten longest is
on a DEBUG line. The ux08 allowlist is empty and its cap is 0 (43 -> 0).

The status page: the month-peak and peak-guard rows, the stale-reading
row, the top table (Why, Tariff, Arbitrage, Shadow mode, labels), the
Stopped banner and the line under the buttons, which now shows the plain
hint of each event instead of the raw action log. The Supervisor question
at start logs one line with a real reason.

Refusals are counted as shown (labels expanded, long cases driven), seven
were shortened, the card and parse errors lost their internals, a blank
value reads "empty", and the panel no longer files inverters.max_w under
the flat max_w. Option names lose "(JSON)", the NL texts are checked too.

DOCS gets a glossary (control board, isolator, Developer Tools) and card
ids move from headings to a "For installers" line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyR88rXETvwhTgx6yHE39p
This commit is contained in:
2026-09-27 08:01:16 +02:00
co-authored by Claude Opus 5.5
parent a02cd4b713
commit 6a95447248
38 changed files with 1294 additions and 742 deletions
+9 -9
View File
@@ -516,7 +516,7 @@ check("⚠️ AN UNSET OPTION ADDS NO STATUS ROW AND NO PAGE ROW - not a caution
"input; this is instrumentation and a permanent caution on every install "
"that never asked for it is the warning spam the card forbids",
not pv_rows(c_off)
and not [r for r in page_rows(c_off) if r[0] == "PV"])
and not [r for r in page_rows(c_off) if r[0] == "Solar production"])
check("...and the whole row list is otherwise the same length, so nothing else "
"moved either", len(_on_rows) == len(_off_rows) + 1)
_pv_row = [r["text"] for r in pv_rows(c_on)]
@@ -527,7 +527,7 @@ check("a good read says the watts, as a green row, and names no entity id",
_pv_row == [f"Solar production: {messages.signed_watts(3210)}"]
and "sensor." not in _pv_row[0]
and pv_rows(c_on)[0]["ok"] is True
and ("PV", "3 210 W") in page_rows(c_on))
and ("Solar production", "3 210 W") in page_rows(c_on))
c_bad, _, _ = run(cycles=1, states=[state("1234", "%")], **PV_ON)
_bad_row = pv_rows(c_bad)
@@ -552,7 +552,7 @@ check("⭐ ...and it is a CAUTION, never a `bad` row: `status_payload()` builds
and c_bad.status_payload()["banner"]
== c_off.status_payload()["banner"])
check("...and the page row renders an absence as an em dash, not as 0 W",
("PV", "—") in page_rows(c_bad))
("Solar production", "—") in page_rows(c_bad))
# ==============================================================================
@@ -936,7 +936,7 @@ print(f" {_many_row}")
check("a healthy roster says the SITE total and how many sources it came from",
_many_row == [f"Solar production: {messages.signed_watts(3750)} from 3 "
f"sources"]
and ("PV", "3 750 W") in page_rows(_c_many))
and ("Solar production", "3 750 W") in page_rows(_c_many))
_c_gap, _, _ = run(cycles=1, by_entity=HOLES[E2][0], **PV_MANY)
_gap_row = pv_rows(_c_gap)
@@ -960,8 +960,8 @@ check("⭐ ...and it is a CAUTION, never a `bad` row, at a roster exactly as at
== c_off.status_payload()["banner"])
check("...and the page row is an em dash, not a smaller number: the one row an "
"operator glances at cannot show a partial total either",
("PV", "—") in page_rows(_c_gap)
and ("PV", "3 300 W") not in page_rows(_c_gap))
("Solar production", "—") in page_rows(_c_gap)
and ("Solar production", "3 300 W") not in page_rows(_c_gap))
# ⚠️ THE ACCEPTANCE CRITERION THE REST OF THIS FILE CANNOT STATE: at a roster of
# ONE the surfaces are 0.11.0's, character for character. `c_on` above is the
@@ -978,7 +978,7 @@ check("⭐ ONE ENTITY IS ONE PATH, however it was declared: the status "
== [r["text"] for r in pv_rows(c_on)]
== [f"Solar production: {messages.signed_watts(3210)}"]
and page_rows(_c_one_new)[[r[0] for r in page_rows(_c_one_new)]
.index("PV")] == ("PV", "3 210 W"))
.index("Solar production")] == ("Solar production", "3 210 W"))
check("...and a refused read at a roster of one is the one-sensor refusal "
"too, not the roster one - `no reading, <reason>`",
[r["text"] for r in pv_rows(run(cycles=1, pv_entities=[E1],
@@ -1007,7 +1007,7 @@ check("...and that caution appears ONLY when both are set - not on the 0.11.0 "
check("...and an install with NO PV roster still adds no row of any kind - the "
"whole of TEL-12 is invisible at the shipped default",
not pv_rows(c_off)
and not [r for r in page_rows(c_off) if r[0] == "PV"]
and not [r for r in page_rows(c_off) if r[0] == "Solar production"]
and len(rows_of(_c_many)) == len(rows_of(c_off)) + 1
and run(cycles=1)[1].state_calls == []
and run(cycles=1, pv_entities=[])[1].state_calls == []
@@ -1106,7 +1106,7 @@ check("the status row prints the total AFTER the sign",
_mix_row == [f"Solar production: {messages.signed_watts(MIX_TOTAL)} "
f"from 3 sources"])
check("...and the page's PV row is the corrected total",
("PV", "3 270 W") in page_rows(_c_mix))
("Solar production", "3 270 W") in page_rows(_c_mix))
_c_hole_f, _, _ = run(cycles=1, by_entity=dict(MIX, **{E1: [None]}), **PV_FLIP)
check("a holed roster with a flipped member names the missing source, not "
"the flipped one",