UX-10: the last plain-language leftovers: log lines, two table rows, 'Why: Other', red at 0 s
- test_messages.py part 6: every dynamic part of a WARNING+ line is classified as data or as a built text, and every built text is produced by the real code and checked. This is the gap the 2d scan had: it counted `%s` as one word, so reasons built by loop_clamp_note() and friends were never seen. - Quoted reasons rewritten to STYLE.md (red-alarm shape, codes kept): OUTPUT_CLAMP, METER_FROZEN, CIRCULATING_POWER, STALE_READING, the peak guard (codes now PEAK_GUARD*), the migration report, price feed, price history and gate reasons. Plurals via messages.times()/count(). - Top table: Price history "96 prices over 24 hours for 26 Sep", Tariff "one every 15 minutes or every hour", "not final yet" dropped. - Levels and noise: per-cycle shadow line DEBUG, shadow on/off INFO, aiohttp access log only at log level debug, settings warnings once per start, one plain line per Home Assistant outage (hass.Outage). - INFO jargon and error texts: no "§8.3", ISO times, "banked", "keys ARE", "NOT_OBSERVED", "did NOT land", "AND". - Display bugs: WHY_WINNER covers every winner and safety reason (main.why_key(), part 7 finds them in the code); the meter row is amber "waiting for the first reading" inside its limit after a start; the missing-reading age is counted when the page asks. - STYLE.md and DECISIONS/UX-08-short-notifications.md (UX-10 section). No change to safety behaviour, alarm levels, notification ids, triggers, cadence or the banner cascade. One row colour changes (meter at start), justified in DECISIONS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
125b0702a2
commit
23a3a3f5b5
@@ -1240,13 +1240,13 @@ check("an engagement that is not saturated raises NO notification - §10.3's "
|
||||
"goodwe_peak_saturated" not in hass.notifications)
|
||||
check("...but it does reach the action log, which is where a control action "
|
||||
"that moves energy belongs",
|
||||
any("PEAK GUARD" in e for e in c.events))
|
||||
n_events = sum(1 for e in c.events if "PEAK GUARD" in e)
|
||||
any("PEAK_GUARD" in e for e in c.events))
|
||||
n_events = sum(1 for e in c.events if "PEAK_GUARD" in e)
|
||||
asyncio.get_event_loop_policy().new_event_loop().run_until_complete(c.cycle())
|
||||
check("...and it is edge-logged, not level-logged: a second engaged cycle adds "
|
||||
"no second line, so a quarter of engagement cannot push the cause of the "
|
||||
"event off a 40-line log",
|
||||
sum(1 for e in c.events if "PEAK GUARD" in e) == n_events)
|
||||
sum(1 for e in c.events if "PEAK_GUARD" in e) == n_events)
|
||||
|
||||
# The saturated case, through the same real cycle.
|
||||
# A floor of 1.5x what the inverter can give: it saturates wherever in the
|
||||
@@ -1661,8 +1661,8 @@ check("...and it still says what it WOULD have taken, so the under-shave is a "
|
||||
near(d_lim.wanted_w, WANTED, 1e-6) and d_lim.wanted_w > d_lim.floor_w)
|
||||
check("...and its one-line explanation tells the operator the consequence in "
|
||||
"the words that matter - the quarter is going over the ceiling",
|
||||
"FLOOR-LIMITED" in d_lim.explain()
|
||||
and "WILL GO OVER THE CEILING" in d_lim.explain()
|
||||
"FLOOR_LIMITED" in d_lim.explain()
|
||||
and "will go over the limit" in d_lim.explain()
|
||||
and f"{CEIL:.0f} W" in d_lim.explain())
|
||||
check("an unreadable SoC lands in the same branch, with the OTHER reason - so "
|
||||
"an operator reading one line can tell a flat battery from a dead sensor",
|
||||
@@ -1944,7 +1944,7 @@ check("the status page carries exactly one peak-guard row and it is NOT ok - "
|
||||
"the money is going to be spent and a human is the only actuator left",
|
||||
len(rows24) == 1 and not rows24[0]["ok"] and not rows24[0]["warn"]
|
||||
and "peak limit will be passed" in rows24[0]["text"])
|
||||
check("...and it reaches the action log too", any("FLOOR-LIMITED" in e
|
||||
check("...and it reaches the action log too", any("FLOOR_LIMITED" in e
|
||||
for e in c24.events))
|
||||
# A missing SoC sensor, through the same real cycle. `inputs_ok` stops the loop
|
||||
# at 0 W in that state, so the guard's own answer is what is graded here.
|
||||
|
||||
Reference in New Issue
Block a user