- app/ui_text/nl.json and app/uitext.py: every page word in Dutch, English
fallback per key; the page picks by browser language. Home's sentences
move into ui_text `home_words`, so /status?lang=nl builds them in Dutch.
- test_ui_text.py: EN/NL key and placeholder parity, STYLE limits, jargon
lists for both languages, no inline details, untranslated Dutch caught.
Shared rules moved unchanged to tools/style_rules.py.
- tools/ux13_screenshots.sh/.py: DOCS screenshots from the demo fixtures in
headless Chromium; docs/img/ux13/. Battery modes (P3): no screenshot.
- "Other time windows": a list editor (ui.periods) that builds
static_profile and names bad times, empty prices, overlaps and gaps.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1. Discard reloads /config/model: after a stale save the page kept the
new fingerprint with the old values, so Discard + Save overwrote the
other surface's change without a 409.
2. Removing cards back to one restores the stored inverter shape, so a
flat site stays flat after add + remove.
3. A choice the page can only keep ("Other time windows") stays offered
while it is the stored value.
4. A load locks every locked value again.
5. at_zero() needs an accepted 0 W write; before the first one Home says
"Going to 0 W" (the heartbeat writes every heartbeat_s, so it clears).
6. A field with a unit drops the translation's "(W)" from its label: the
peak limit read "Peak limit (W)" beside a kW value.
7. A mirrored choice lists the mirrored field's keys, so a search for
static_profile finds the contract on a fixed-price site.
8. test_settings: a save refused by ui_to_options writes nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Settings tab: the Installer view (app/static/settings.js), drawn from
app/uilayout.py through the new app/uipage.py: search, six collapsible
groups with "n to fix / n to check / n changed" badges and an "applies
after a restart" chip, radio cards, segmented choices, sliders with units
(the peak limit in kW), entity pickers with search and the live reading,
inverter cards, solar rows, locked measured values behind "Change", and
the add-on's refusals, warnings and info beside the field they name.
- Save path: the page posts its model to the existing config/validate and
config/save; uimodel turns it into options before the shipped validator,
so nothing it refuses is saved. No route added. A value equal to the
stored one is written as stored, so a save that changed nothing writes an
identical blob. Save bar, then the restart dialog that names 0 W.
- The region choice shows its preset year; Wallonia and Brussels are listed
as having no preset yet (TARIFF-22). "Classic settings" keeps /config.
- P1 test findings: (a) "Going to 0 W" until the last accepted power request
is 0 W; (b) the trade blocks and the price line name the feed's own points
("Lowest published price"), the hour bars say "hour average"; (c) the entity
list's WARNING gives a reason on a timeout.
- test_settings.py; test_home, test_haentities, test_uilayout extended.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyR88rXETvwhTgx6yHE39p
- Trade blocks: none on a battery with no room, no sale at a negative price
or while the emptiest battery is at arbitrage's floor, nothing when a
level is unknown. A give after a charge may use what the charge put in.
- The refusal line names the real reason: prices not published vs gap.
- The plan's peak line uses the guard's ceiling (this month's peak once
above the cap), as the peak card does.
- House below zero: 0 W inside the idle band, no figure beyond it.
- Price bars are "Low price" / "High price": the add-on trades in one hour.
- Control toggle: one request in flight at a time.
- test_home: the new cases; the house-sign mutation now goes red.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- app/static/{index.html,app.css,app.js}: tabs (Home, Batteries, Settings,
Setup), hash routes, phone bottom tabs, light/dark. Served inlined at "/";
the route list is unchanged, and every URL is relative.
- app/homeview.py: /status gains state, now, batteries, plan, attention,
month_peak and control beside the old fields. The plan is what the add-on
does today: the arbitrage verdict (the same plan.arbitrage() call as the
cycle), the monthly cycle, the peak limit, "follows the house".
- The Home plan chart has hover, tap and keyboard-focus tooltips: price bar =
hour and price; block = what, when, why, kWh and EUR.
- Region preset and year: in config/model (for P2) and on the Home price line.
- test_home.py; test_messages part 8 scans every Home sentence; STYLE plan line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyR88rXETvwhTgx6yHE39p