# STYLE.md - how user-facing text is written (UX-08) This applies to everything a home owner or installer reads: notifications, phone pushes, the add-on page, refusals, add-on log lines at WARNING and above, and the names and descriptions of options. It is enforced by `goodwe_controller/test_messages.py`. Kinds that have not been rewritten yet are on its allowlist, and that allowlist only shrinks. ## 1. Shape - **Title**: at most 5 everyday words. It says what is wrong ("Meter reading may be stuck"). No "GoodWe:" prefix, no full stop. - **Body**: **one sentence** of at most 25 words, saying what happened and what to do. A **red alarm** may use up to **3 sentences** (70 words, each sentence at most 30 words), so that no action a person must take is lost. - **Details**: the last line links to the add-on documentation and names the section with the rest: `Details: add-on documentation, section "" under Notifications.` Background, figures, reason codes and history go there or into the log, never into the body. - **Status row**: at most 15 words. **Banner**: at most 12 words. **Refusal**: at most 30 words, naming the setting by its label. **Option name**: at most 6 words, not counting the group prefix. **Option description**: at most 30 words. Where a value comes from belongs in DOCS.md. - **Log line** (WARNING/ERROR): one line, at most 25 words. The reasoning goes on a DEBUG line. Log lines stay in English and are not translated. - **Sentences**: one idea each, active voice, present tense, with nothing nested in brackets. These translate well into Dutch and French. ## 2. Numbers Use a number only if it helps the reader act, for example the peak limit, or what was asked and what was sent in a fault report. Write it the way `app/messages.py` does: `5 000 W`, `20 %`, `10 minutes`, `14:05`. ## 3. Severity Severity is shown by the title and the colour, never by CAPITALS or by words like "BUG SIGNAL". | Level | Colour | When | |---|---|---| | alarm | red | Control stopped, money or energy lost now, a fault, or a person must act now. Up to 3 sentences. | | warning | orange | Control is still running, but something needs a look. 1 sentence. | | info | grey | No action needed. 1 sentence. | | resolved | green | An earlier alarm or warning has cleared. 1 sentence. | A rewrite never changes an alarm's severity, `notification_id` or cadence. ## 4. Words - the same word for the same thing everywhere | Say | Not | |---|---| | battery | pack, BMS pack | | inverter, or its name | unit, device, actuator | | controller | loop, planner | | meter | P1 feed, telegram | | peak limit / this month's peak | ceiling, capaciteitstarief, billed quarter | | 15-minute period | quarter | | battery level | SoC, state of charge | | cut-out level | BMS floor, `bms_soc_floor` | | peak reserve | `peak_soc_floor`, EMS floor | | inverter rating | `max_w`, rail | | control is stopped / every inverter is set to 0 W | failsafe, trip, latch, parked | | software fault | BUG SIGNAL | | control board | master, ESP32 | | shadow mode | a mode that makes every decision but commands 0 W. The name is kept. | **Banned in titles and bodies** (the test fails on them): SAFETY-/TARIFF-/TEL-/CFG-/FW-/HW-nn and other card ids, integrator, anti-windup, windup, clamp, clamped, saturated, BUG SIGNAL, latch, latched, arbiter, allocator, register, `0x…`, layer 1/2/3, heartbeat, watchdog, telegram, ACK, CRC, OTA, Modbus, planner, `§n`, file names, IP addresses, option keys in snake_case, **HA entity ids**, and runs of 2 or more CAPITALISED words. HA entity ids are allowed only in refusals and validator messages, where the installer has to find that entity. They are never allowed in alarms or status rows.