# UX-08 ratchet (test_messages.py part 3). Each line is a user-facing string that # does not follow STYLE.md yet: " # where :: start". # These are waiting for phase 2b (row, banner), 2c (refusal, option-name, # option-desc) and 2d (log). Delete the line when you rewrite the string, because # a stale line fails the test. Never add a line for a new string: write the new # string to STYLE.md instead. banner c185022e391f # main.py banned: SAFETY-25; option key: peak_soc_floor; capitals: THE PEAK GUARD ONLY :: '{…} - and peak_soc_floor bounds THE PEAK GUARD ONLY (SAFETY-25, see be' banner 4a246fc26def # main.py over 12 words (14); capitals: CIRCULATING POWER :: 'CIRCULATING POWER — the inverters were pushing against each other. Sit' banner 750ccd4f2126 # main.py over 12 words (14) :: "FAILSAFE — the site's total command opposed the meter. Every inverter " banner 637f334f130a # main.py over 12 words (26) :: 'FAILSAFE — the command opposed the meter. Inverter held at 0 W. / FAIL' banner 0a3d2d9c4232 # main.py capitals: NOT READY :: "NOT READY — {bad[0].get('banner') or bad[0]['text']}" banner dbcc227a9589 # main.py over 12 words (26); capitals: NOT DELIVERING :: 'NOT DELIVERING — {_nd} is standing at a share it is not producing. The' log a5e99679fd80 # main.py banned: SAFETY-02, latch :: 'SAFETY-02: the per-inverter store migration did not verify (%s). The l' log 128b18b32d86 # main.py over 25 words (41); banned: LATCHED, SAFETY-44, latched :: 'SAFETY-44: this store carries a LATCHED sign-disagreement failsafe und' log f60446541ae5 # main.py over 25 words (83); banned: LATCH, LATCHED, SAFETY-02, latch; capitals: LATCH GUARD :: 'SAFETY-02 LATCH GUARD: this store carries a LATCHED sign-disagreement ' log 04d06bf223c8 # main.py over 25 words (73); banned: REGISTER, SAFETY-37, SAFETY-57, register; capitals: WHICH IS NOT BY ITSELF :: 'SAFETY-37: %s battery-power reading did not move under a command that ' log aec01642bd07 # main.py banned: SAFETY-57 :: 'SAFETY-57: %s' log aebbca17acb3 # main.py over 25 words (52); banned: allocator :: 'write_setpoint() was asked to put %+.0f W on every one of %d inverters' log b74c3018461e # main.py over 25 words (30); banned: SAFETY-28, allocator :: 'SAFETY-28 REFUSED a write of %+.0f W to %s: %s. Commanding 0 W instead' log cefffafa8b27 # main.py over 25 words (31) :: 'the write of %+.0f W to %s (%s) did not complete in %.0f s and was aba' log 1001c6250b85 # main.py over 25 words (29); banned: SAFETY-02 :: 'SAFETY-02 TRIPPED on %s - %s. Commanding 0 W on that inverter and hold' log 8252ef5eefad # main.py over 25 words (48); banned: SAFETY-30 :: 'SAFETY-30 TRIPPED at the SITE - %s. That is the SUM of every standing ' log 8a65cf945e00 # main.py over 25 words (32); banned: SAFETY-31 :: 'SAFETY-31 TRIPPED - %s. Commanding 0 W on every inverter and holding i' log 5d2beed2f1a2 # main.py over 25 words (65); banned: HW-01, SAFETY-42; capitals: NOTHING IS COMMANDED DIFFERENTLY :: 'SAFETY-42 TRIPPED on %s - %s. NOTHING IS COMMANDED DIFFERENTLY: this g' log d50b775b9cd4 # main.py banned: ARBITER; capitals: ARBITER SCOPE :: 'ARBITER SCOPE: %s' log 749c2c6fe81d # main.py over 25 words (26); banned: SAFETY-10, heartbeat; capitals: SHADOW MODE IS ON :: 'SAFETY-10 SHADOW MODE IS ON. The full decision path runs and NOTHING i' log 4d271dfc6f1c # main.py banned: SAFETY-10 :: 'SAFETY-10 shadow mode is OFF. This controller is commanding the batter' log 730387e0da2b # main.py banned: SAFETY-03 :: 'SAFETY-03 - %s Engagements so far: %d.' log 3bf899e99297 # main.py over 25 words (56); banned: SAFETY-03, clamp, clamped, integrator; capitals: STILL RUNNING :: 'SAFETY-03 - %s Silently clipping this is how a winding integrator reac' log 78cb6bd09633 # main.py over 25 words (48); banned: SAFETY-07; capitals: STILL RUNNING :: 'SAFETY-07 - %s. The guard is asking for everything the inverter has an' log cc735997adc7 # main.py over 25 words (44); banned: SAFETY-24; capitals: STILL RUNNING :: 'SAFETY-24 - %s. The controller is STILL RUNNING and charging is still ' log ebcb428a70d0 # main.py over 25 words (70); banned: SAFETY-18, arbiter, watchdog; capitals: CHECK THE METER :: 'SAFETY-18 - %s. The grid-following loop is regulating against a number' log 38018b887495 # main.py over 25 words (43) :: 'tariff refresh degraded (%s); KEEPING the plan resolved at %s, %.0f s ' log 0eab1ec96fe8 # main.py capitals: CONTROL LOOP DIED :: 'CONTROL LOOP DIED (%s) - commanding 0 W and exiting with status %d' log db529f2c419d # main.py over 25 words (40); banned: SAFETY-02 :: 'SAFETY-02 was TRIPPED on %s before this restart and stays tripped: %s.' log c5aadd5c8bf9 # main.py over 25 words (45); banned: SAFETY-42; capitals: NOTHING IS BEING COMMANDED DIFFERENTLY :: 'SAFETY-42 was TRIPPED on %s before this restart and stays tripped: %s.' log d72bbdb7e595 # main.py over 25 words (39); banned: SAFETY-30 :: 'SAFETY-30 (site) was TRIPPED before this restart and stays tripped: %s' log 8b880e65a7c3 # main.py over 25 words (38); banned: SAFETY-31 :: 'SAFETY-31 was TRIPPED before this restart and stays tripped: %s. Every' log 23f58b7f305c # p1.py:1264 over 25 words (30) :: 'meter_poll_s %.1f leaves no room under meter_max_age_s %.1f: one misse' log 88a7251e842b # p1.py:470 banned: telegram :: 'P1 telegram rejected: %s' log 0dd83d6dfaf4 # price.py over 25 words (30) :: 'the feed published no price for %d of %d instants (index %s); those in' log bcfd7062e28e # price.py over 25 words (79); banned: §8 :: 'price_feed_url is set, so %s is requesting %s exactly as given and is ' log b57bc6de4a6b # price.py over 25 words (47); banned: validate.py :: 'price_taxes_profile cannot be used (%s: %s), so this fetch has NO tax ' log d5595aaaacc4 # price_history.py banned: §8 :: 'price history at %s is %s - starting from empty. §8.3 carry-forward ha' log dbed0b8e35ea # static_tariff.py banned: validate.py :: 'static_profile is unusable (%s); no cheap window. This should have bee' log 8fbe9f5407ea # static_tariff.py over 25 words (28); banned: §1, §6 :: '§11.4: %s, and no static_profile is configured to fall back to. The pl' log 4ce29e043d89 # static_tariff.py banned: §1 :: '§11.4: %s - falling back to the static profile, plan marked PROVISIONA' log a3c7c9719ed2 # store.py capitals: LOST STATE :: 'per-inverter store migration LOST STATE and has not been marked done: ' log 5b537a77052b # validate.py over 25 words (41); banned: arbiter, saturation :: 'integrator_max_w %.0f W is above max_w %.0f W. Not refused - the arbit' log 12ae40f9d289 # validate.py over 25 words (73); banned: arbiter, clamp, clamps :: 'maintenance_discharge_w %.0f W is above max_w%s %.0f W. Not refused - ' log c6dc799502cf # validate.py over 25 words (32) :: '%s carries negative levies %s EUR/kWh. That is accepted, but a tax com' log 1688a7478ceb # validate.py over 25 words (36) :: 'price_formula is filled in but price_provider is %r, so the coefficien' log f37f9fce4433 # validate.py over 25 words (96) :: '%s has no "card" block, so its coefficients are UNGRADED: nothing reco' log 396fbdd009c2 # validate.py over 25 words (52); banned: §1 :: "price_provider is %r but static_profile is empty. §11.4's degradation " log 37bba6ed37e3 # validate.py capitals: REFUSING TO START :: 'REFUSING TO START: the add-on configuration is not usable.' option-desc b927826d01f0 # en.yaml over 30 words (112); capitals: LEAVING IT OFF DOES NOT TURN THE PRICE FEED OFF :: 'Charge in the cheapest published hour and discharge in the dearest, bu' option-desc b98c42e34df7 # en.yaml over 30 words (34) :: 'The reserve price trading may not spend. Deliberately not the same key' option-desc 84e054da385b # en.yaml over 30 words (39) :: 'Off by default. Leave it off until the site has been commissioned: wit' option-desc 0f55d3b37afa # en.yaml over 30 words (38); banned: 0x0518, register, watchdog :: "The sensor that reports this inverter's own battery power, positive wh" option-desc 307afdd74f84 # en.yaml over 30 words (98); banned: 0x0560, Register; capitals: GW5000S-BP :: "MEASURED, not chosen: the percent at which the pack's OWN battery mana" option-desc 4da37ff6250d # en.yaml over 30 words (66); banned: SAFETY-31; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY. DERIVED (SAFETY-31): 75 s is fifteen contr' option-desc db464169ed66 # en.yaml over 30 words (144); banned: SAFETY-31; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY; with one inverter the quantity is identica' option-desc df9735452fa1 # en.yaml over 30 words (88); banned: OPT-08; capitals: THIS ONE IS NOT DERIVED FROM :: 'What one full round trip costs per kWh: wear on the pack plus conversi' option-desc 8147a82a437e # en.yaml over 30 words (51) :: 'A deadline on the gap between cycles, reset by every cycle. On a healt' option-desc cb66f230ef63 # en.yaml over 30 words (45); banned: register :: 'Errors smaller than this are ignored. ⚠️ The deadband is a one-way rat' option-desc 4167af90cfc2 # en.yaml over 30 words (288); banned: SAFETY-42, delivery_window.py, saturation; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY; with one inverter this check cannot fire a' option-desc 3c0898cc1149 # en.yaml over 30 words (63) :: 'What you are paid for feeding a kWh back into the grid, all in. One nu' option-desc 05560996cb2e # en.yaml capitals: MEASURED ON REAL HARDWARE :: 'How much of the remaining error the loop corrects each cycle. MEASURED' option-desc f225d7a8f3a5 # en.yaml over 30 words (32); banned: watchdog :: 'How often the setpoint is rewritten even when it has not changed. It m' option-desc ef70d16a93bd # en.yaml over 30 words (98); banned: clamp, saturation :: 'Caps how much stale error can be waiting to unwind when the sign flips' option-desc bde7357af38d # en.yaml over 30 words (107); capitals: EMPTY DOES NOT MEAN :: 'Leave this empty unless the site really has more than one inverter. EM' option-desc 217c5ae9599c # en.yaml over 30 words (66); banned: 0x0560, register :: "The percent at which THIS pack's own battery management system cuts ou" option-desc 746a0f9ae506 # en.yaml over 30 words (143) :: "THIS pack's usable capacity in kilowatt-hours, from its datasheet or i" option-desc cb6ad204f59d # en.yaml over 30 words (52) :: 'The supervised ceiling on what may be written to THIS inverter; the si' option-desc 46142bcc1ab1 # en.yaml over 30 words (36); banned: heartbeat, latch :: 'A short identifier for this inverter, for example inverter-a. It gives' option-desc d787e9f2454d # en.yaml over 30 words (63); banned: arbiter; capitals: MUST STAY AT OR BELOW :: '⚠️ MUST STAY AT OR BELOW the inverter rating, and the add-on refuses t' option-desc a90fced63631 # en.yaml over 30 words (52); banned: CLAMPED :: 'How fast the cycle drains the pack; the surplus is exported. Above the' option-desc ab58c8fae4fb # en.yaml over 30 words (57); capitals: THIS IS NOT THE PEAK GUARD :: 'The depth the monthly recalibration deliberately goes to, once a month' option-desc 73f51bdd3d6e # en.yaml over 30 words (83); capitals: THIS IS YOUR NUMBER :: 'THIS IS YOUR NUMBER, not a derived one: the hard ceiling on what may e' option-desc dd9023e6c812 # en.yaml over 30 words (45); capitals: POSITIVE MUST MEAN DRAWING FROM THE GRID :: "The net grid power sensor, used when the meter source is 'off'. POSITI" option-desc aa5b929f3c22 # en.yaml over 30 words (114); banned: SAFETY-18, latch; capitals: NOT CHOSEN :: 'MEASURED, NOT CHOSEN (SAFETY-18). How long the meter may keep answerin' option-desc 1b3038c5c9e5 # en.yaml over 30 words (46) :: 'Beyond this the grid figure counts as missing. On its own it does not ' option-desc bbf26329f056 # en.yaml over 30 words (48); banned: telegram, telegrams :: 'Must match your connection. A telegram whose phase count disagrees is ' option-desc 92da72e54e77 # en.yaml over 30 words (52) :: "For meter source homewizard_local only. 5 s is the meter's own update " option-desc 24f329136309 # en.yaml over 30 words (84) :: "'off' keeps the single Home Assistant entity below, which is what an e" option-desc 47e5fa0dba52 # en.yaml banned: register :: 'The UNSIGNED injection register, the counterpart of the import registe' option-desc 9b8f5ea6c656 # en.yaml banned: 192.168.2.250 :: "For meter source homewizard_local only: the meter's own address on you" option-desc d5d3e30ac4d2 # en.yaml over 30 words (37); banned: register :: 'The UNSIGNED consumption register. Do not point this at a signed templ' option-desc 0b05d89400ba # en.yaml over 30 words (39) :: 'For meter source ha_signed only. ONE signed sensor: positive is drawn ' option-desc e74a5db257e1 # en.yaml over 30 words (46) :: 'For meter source ha_signed only. Optional, in L1..L3 order, each signe' option-desc 3f07a88a61fd # en.yaml over 30 words (34); capitals: THIS IS YOUR NUMBER :: 'THIS IS YOUR NUMBER: the quarter-hour average demand the peak guard tr' option-desc 6ec195081ef9 # en.yaml over 30 words (112); banned: SAFETY-24; capitals: IT BOUNDS THE PEAK GUARD ONLY :: 'DERIVED, not picked (SAFETY-24): the reference pack holds 13.8 kWh usa' option-desc 228fdc168458 # en.yaml over 30 words (270); capitals: INJECTION IS EXEMPT FROM VAT :: 'Optional, and only if your supplier pays you a price that moves with t' option-desc 98987808a7f0 # en.yaml over 30 words (98); capitals: WHAT YOU TYPE IS SENT EXACTLY AS WRITTEN :: "Leave empty to use the chosen source's own feed. Only a host that sour" option-desc 26f17751b2f7 # en.yaml over 30 words (234); capitals: IN THE UNITS THE CARD PRINTS :: "For price source custom_formula only: your own contract's two coeffici" option-desc 011841a82d7d # en.yaml over 30 words (34) :: "Your supplier's margin. The add-on adds it ONLY when the chosen price " option-desc d34ef16ba99a # en.yaml over 30 words (63) :: 'The older way of getting a price, kept because retiring it would take ' option-desc c70929091e71 # en.yaml over 30 words (252); capitals: SWITCHING THIS ON IS WHAT STARTS THE PRICE FETCH :: "Where day-ahead or real-time prices come from. 'off' is what ships, an" option-desc a62e17ccf445 # en.yaml over 30 words (230); banned: TARIFF-18; capitals: THIS NUMBER IS NOT :: 'Everything on your bill that is not the energy itself - distribution, ' option-desc 56d56f58c43e # en.yaml over 30 words (206); capitals: THE NUMBERS HERE ARE THE LEVIES ALONE :: 'Leave this empty unless your network tariff really does charge a diffe' option-desc 313bdd035b0b # en.yaml over 30 words (193); capitals: MEASUREMENT ONLY :: 'Optional, and MEASUREMENT ONLY - it changes no control behaviour whats' option-desc 4172d9920d65 # en.yaml over 30 words (128); capitals: MEASUREMENT ONLY :: 'Optional, and MEASUREMENT ONLY - it changes no control behaviour whats' option-desc 09ceba2c6afb # en.yaml over 30 words (70); banned: clamp; capitals: MEASUREMENT ONLY :: 'Optional, MEASUREMENT ONLY. Some sensors - typically a kWh meter or a ' option-desc 42a7eaac6ff1 # en.yaml banned: saturated :: 'How many consecutive saturated cycles before the loop stops winding up' option-desc 12b0dffec9dd # en.yaml over 30 words (42) :: 'The gap between what was commanded and what the inverter delivers that' option-desc 91fd58c08a59 # en.yaml over 30 words (54) :: 'The ESPHome number entity this add-on writes the power setpoint to, no' option-desc 01e1af709cd5 # en.yaml over 30 words (201); banned: arbiter, clamps, heartbeat, latch :: 'Runs the whole decision path — strategies, arbiter, clamps and guards ' option-desc 96b077d4e2e9 # en.yaml over 30 words (72); banned: SAFETY-02; capitals: NOT CHOSEN :: 'MEASURED, NOT CHOSEN (SAFETY-02). How long the setpoint and the meter ' option-desc addf5c495ae8 # en.yaml over 30 words (90); banned: SAFETY-02, watchdog; capitals: NOT CHOSEN :: 'MEASURED, NOT CHOSEN (SAFETY-02). Both the setpoint being emitted and ' option-desc 0a66ac772b27 # en.yaml over 30 words (117); banned: SAFETY-30; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY. DERIVED FROM 1890 CLOSED-LOOP TEST RUNS (S' option-desc c0deabb69ab6 # en.yaml over 30 words (60); banned: SAFETY-30; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY. The same 300 W as the single-inverter thre' option-desc 7d7272743277 # en.yaml over 30 words (123); banned: SAFETY-39; capitals: MEANS FOLLOW THE INVERTER RATING :: 'How far the setpoint may move in one control cycle. ⚠️ 0 MEANS FOLLOW ' option-desc 436efca21a7d # en.yaml over 30 words (31) :: "The sensor that reports the pack's state of charge in percent. Use the" option-desc 9ac8a3b21a1e # en.yaml over 30 words (43) :: 'How long the inputs may be missing before the add-on commands 0 W. Wit' option-desc 86cbfd6a5693 # en.yaml over 30 words (130); capitals: RECOMMENDED EVEN ON :: 'Your fixed or day/night contract, written as a single line of JSON. RE' option-desc 996dffbf563d # en.yaml over 30 words (74); banned: register :: 'What the meter should sit at when nothing is happening; negative means' option-desc faf346256008 # en.yaml over 30 words (52); banned: SAFETY-30; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY. DERIVED FROM 1890 CLOSED-LOOP TEST RUNS (S' option-desc 5323134f3131 # en.yaml over 30 words (95); banned: SAFETY-30, saturation; capitals: TWO OR MORE INVERTERS ONLY :: 'TWO OR MORE INVERTERS ONLY; with one inverter this setting does nothin' option-name ca3a62bb8260 # en.yaml over 6 words (7) :: 'Circulating-power hold (s) — derived, do not change' option-name edee163fdc2b # en.yaml over 6 words (7) :: 'Circulating-power threshold (W) — measured, do not change' option-name 99b3beeab621 # en.yaml over 6 words (7) :: 'Cost of one full charge/discharge cycle (EUR/kWh)' option-name cccd8a42f51a # en.yaml over 6 words (8) :: 'Not-delivering report after (s) — derived, do not change' option-name 989891e2ce23 # en.yaml over 6 words (10); banned: Integrator :: 'Integrator bound (W, 0 means the same as the rating)' option-name 42c6b595320c # en.yaml over 6 words (9) :: 'Inverter list (leave empty if you have one inverter)' option-name 230e6dc9d872 # en.yaml over 6 words (7) :: 'Hour of day a due cycle starts' option-name 18e1de907c54 # en.yaml over 6 words (8) :: 'Frozen-meter alarm after (s) — measured, do not change' option-name 9071c4cfa460 # en.yaml over 6 words (7) :: 'A reading counts as stale after (s)' option-name e3d06ed93e2e # en.yaml banned: register :: 'Export register entity (W)' option-name a0f59ea5de36 # en.yaml banned: register :: 'Import register entity (W)' option-name ed757924f40f # en.yaml over 6 words (7) :: 'Per-phase signed net entities (L1, L2, L3)' option-name 52d03808da01 # en.yaml over 6 words (8) :: 'Your own INJECTION formula (one line of JSON)' option-name bf22f2121af4 # en.yaml over 6 words (8) :: 'Your own tariff formula (one line of JSON)' option-name 5593992fcf5b # en.yaml over 6 words (7) :: 'How far ahead to fetch prices (hours)' option-name d9fee5514a4b # en.yaml over 6 words (11) :: 'Levies and VAT by time of day (one line of JSON)' option-name 7d8d691905e0 # en.yaml over 6 words (7) :: 'PV production entities, one per inverter (W)' option-name eac7ee084aaa # en.yaml banned: Saturated :: 'Saturated cycles before freezing (count)' option-name 5c6bbc5cab40 # en.yaml banned: Saturation :: 'Saturation threshold (W)' option-name 99a1ec154d36 # en.yaml over 6 words (7) :: 'Shadow mode — run every decision, command nothing' option-name 82fcd0faa687 # en.yaml over 6 words (8); banned: watchdog :: 'Sign watchdog hold (s) — measured, do not change' option-name 8fc34172dc01 # en.yaml over 6 words (8); banned: watchdog :: 'Sign watchdog threshold (W) — measured, do not change' option-name 8516934704f5 # en.yaml over 6 words (8) :: 'Site-wide sign hold (s) — derived, do not change' option-name 2b8278ab2b16 # en.yaml over 6 words (8) :: 'Site-wide sign threshold (W) — measured, do not change' option-name bd52e795ea97 # en.yaml over 6 words (8) :: 'Command 0 W after inputs missing for (s)' option-name 9e33febf4481 # en.yaml over 6 words (8) :: 'Fixed or day/night tariff (one line of JSON)' option-name 40e1e3ba3841 # en.yaml over 6 words (8) :: 'Per-inverter sign hold (s) — derived, do not change' option-name 4ba7087578dc # en.yaml over 6 words (8) :: 'Per-inverter sign threshold (W) — derived, do not change' refusal 87620efa0704 # p1.py:1176 banned: telegram :: 'p1_phase_net_entities has {len(phase_net)} entities but meter_phases i' refusal 5d1b8147792b # p1.py:1186 banned: 192.168.2.250 :: "meter_source {SOURCE_HOMEWIZARD} needs p1_host (the meter's own addres" refusal 701db346696d # validate.py over 30 words (85); banned: SAFETY-30, watchdog :: 'unit_sign_disagree_w is {unit_sign_w} W but max_w{unit_where} is {weak' refusal 710b4d89a9d7 # validate.py over 30 words (88); banned: ARBITER, arbiter; capitals: THE CEILING WINS :: 'maintenance_charge_w is {charge_w} W but max_w{maint_where} is {maint_' refusal 16d40434116b # validate.py over 30 words (193); banned: NOTES.md, §5; capitals: THE PLANT WINS :: 'slew_w is {slew_w} W against a site rail of {rail} W, so the loop cros' refusal 613375fb6b5f # validate.py over 30 words (107); banned: SAFETY-07; capitals: THE BMS WINS :: "peak_soc_floor is {soc_floor} % but the pack's own cut-out (bms_soc_fl" refusal ba21c5ba8c0d # validate.py over 30 words (224); banned: TARIFF-07, §1; capitals: IT HAS NEVER FETCHED :: 'price_provider is {pid}, which WAS a shipped plugin and has been WITHD' refusal de8df32186b6 # validate.py over 30 words (46); banned: §1 :: 'price_provider is {pid}, which is not a shipped plugin. The ids that e' refusal 0ee7c15eafef # validate.py over 30 words (103); banned: arbitrage.py, main.py, static_tariff.py; capitals: THE HOME ASSISTANT ENTITIES WIN :: "price_provider is {pid} AND {' and '.join(ha_price)} {'is' if len(ha_p" refusal c4149a762c39 # validate.py over 30 words (62); banned: main.py; capitals: THE HOME ASSISTANT ENTITIES WIN :: "static_profile is set AND {' and '.join(ha_price)} {'is' if len(ha_pri" refusal 6af34466bbc2 # validate.py over 30 words (83); capitals: THE TABLE WINS :: '{TAXES_PROFILE_OPTION} is set AND price_taxes_eur_kwh is {scalar} rath' refusal 8f69bdbbf3fc # validate.py over 30 words (55) :: '{TAXES_PROFILE_OPTION} carries {steep} EUR/kWh. Belgian levies and dis' refusal 96a090d2ad97 # validate.py over 30 words (72); banned: DOCS.md, §1 :: "price_provider is 'custom_formula' but price_formula is empty, so the " refusal db9d0d53c4f1 # validate.py over 30 words (45); banned: §1 :: "cycle_cost_threshold_eur is {opts.get('cycle_cost_threshold_eur')} and" refusal 58ccb3bbd560 # validate.py over 30 words (63); banned: §1; capitals: NO PRICES AT ALL :: "arbitrage_enabled is on but price_provider is 'off' and static_profile" refusal 780592c897fb # validate.py over 30 words (85); banned: arbitrage.py, telegram, §9 :: "arbitrage_enabled is on but meter_source is 'off', so there is no P1 t" refusal 4f80c091ca95 # validate.py over 30 words (69) :: 'arbitrage_soc_floor is {floor} % and arbitrage_soc_ceiling is {ceiling' refusal 0c089bb2f200 # validate.py over 30 words (57); banned: §1 :: "price_provider is 'manual_csv' but price_csv_path is empty, so the off" refusal 152dfec79224 # validate.py over 30 words (48); banned: SAFETY-02, heartbeat, latch :: '{where} has no name. Every inverter needs one: the Store namespaces th' refusal eb14af760f5c # validate.py over 30 words (51); banned: SAFETY-02, heartbeat, latch :: '{where} and {seen[name]} are both called {name}. The Store keys every ' refusal 36f53c989b4a # validate.py over 30 words (55) :: '{who} has no setpoint_entity, so this add-on cannot command it. It wou' refusal c98c6ab66e9f # validate.py over 30 words (56) :: "{who} has no usable max_w (got {entry.get('max_w')}). It is the superv" refusal 5ca16a4d0a1e # validate.py over 30 words (71) :: '{who} has capacity_kwh {raw}, which is not a usable number of kilowatt' refusal 63a864d2e0a3 # validate.py over 30 words (73) :: "capacity_kwh is stated on {', '.join(stated)} and left empty on {', '." refusal 8d82500ecb1d # validate.py over 30 words (64) :: 'setpoint_entity is set to {flat_sp} AND an inverters list of {len(entr' refusal 3d778e0ab5e1 # validate.py over 30 words (36); capitals: THE DEVICE WINS :: '{name}: max_w is {cap} W but {entity} accepts at most {float(dev_max)}' refusal ecd0883f5649 # validate.py over 30 words (36); capitals: THE DEVICE WINS :: '{name}: max_w is {cap} W, so this controller may command {-cap} W, but' refusal eff7efac51f8 # validate.py over 30 words (56); banned: heartbeat :: 'setpoint_entity is not set, so this add-on has no actuator: every writ' refusal b126f1a88b77 # validate.py over 30 words (76); banned: §1 :: '{len(who)} configured writers can reach the one actuator {actuator}: {' refusal 07a88756c864 # validate.py over 30 words (48); banned: arbiter :: 'max_w is {max_w} W and must be positive - it is a magnitude, not a sig' refusal c4a1d0371e31 # validate.py over 30 words (42); capitals: THE DEVICE WINS :: "max_w is {max_w} W but {opts.get('setpoint_entity') or 'the setpoint d" refusal a15624d1aa10 # validate.py over 30 words (33); capitals: THE DEVICE WINS :: 'max_w is {max_w} W, so this controller may command {-max_w} W, but {op' refusal 26d0602c32d7 # validate.py over 30 words (79); capitals: THE FIRMWARE WINS :: 'meter_max_age_s is {max_age_s} s but the ESP32 firmware vetoes any P1 ' refusal 2ade09aaa579 # validate.py over 30 words (73); banned: SAFETY-02, arbiter, watchdog :: 'sign_disagree_w is {sign_w} W but max_w{where} is {weakest} W, so the ' row c24ab8bd9cb3 # main.py over 15 words (18); banned: heartbeat, layer 1; capitals: NO PASS FOR :: 'control loop: NO PASS FOR {_pass_age} s (layer 1 zeroes the inverter a' row c771d4bc1e0a # main.py over 15 words (17); banned: telegrams :: "P1 meter ({o.get('meter_source')}): {self.p1.net_w} W, {age} s old, {s" row f6195fee8575 # main.py over 15 words (33); capitals: METER MAY BE FROZEN :: 'METER MAY BE FROZEN - {…}. The loop is STILL FOLLOWING it and is still' row db05be7cd99c # main.py over 15 words (16); option key: meter_source; capitals: NOT COVERED :: "freeze detector: NOT COVERED on meter_source {o.get('meter_source')} -" row 9a21960bbbe8 # main.py capitals: NOT COVERED :: 'freeze detector: NOT COVERED - {…}' row c38b746a6585 # main.py banned: SATURATED; capitals: PEAK GUARD SATURATED :: 'PEAK GUARD SATURATED - {…}' row dd0629834473 # main.py over 15 words (36); banned: SAFETY-25; option key: peak_soc_floor; capitals: THE PEAK GUARD ONLY :: '{…}. NOTE: peak_soc_floor bounds THE PEAK GUARD ONLY - it is not a pac' row 4132e246e675 # main.py over 15 words (26); banned: telegrams; option key: meter_source; capitals: NOT COVERED :: "peak guard: NOT COVERED on meter_source {o.get('meter_source')} - the " row 7b34b16d8bb2 # main.py over 15 words (61) :: '{label}: no usable value this cycle from {entity} - and this row canno' row 04e0381f16c2 # main.py banned: CLAMP; capitals: OUTPUT CLAMP ENGAGED :: 'OUTPUT CLAMP ENGAGED - {…} Engagements: {self.clamp_wd.engagements}.' row 9f8b8adcbc6c # main.py banned: INTEGRATOR; capitals: LOOP AT INTEGRATOR BOUND :: 'LOOP AT INTEGRATOR BOUND - {…} Engagements: {self.clamp_wd.engagements' row f00cc9688eca # main.py over 15 words (20); banned: clamp :: 'output clamp: not engaged now, but it has engaged {self.clamp_wd.engag' row a44333431331 # main.py over 15 words (31); capitals: SIGN-DISAGREEMENT FAILSAFEX :: 'SIGN-DISAGREEMENT FAILSAFE{tag} - {…}. The inverter is held at 0 W. Fi' row 3ef4e60f2328 # main.py over 15 words (17) :: 'sign watchdog{tag}: armed{vs} (trips after {inv.sign_wd.cfg.hold_s} s ' row 9f879b339282 # main.py over 15 words (50); banned: integrator; capitals: SITE SIGN-DISAGREEMENT FAILSAFE :: 'SITE SIGN-DISAGREEMENT FAILSAFE - {…}. EVERY inverter is held at 0 W. ' row 96e93e34bdbf # main.py over 15 words (24); banned: watchdog :: 'site sign watchdog: armed against the sum of the commands (trips after' row 9ee8d293fea5 # main.py over 15 words (38); capitals: CIRCULATING POWER :: 'CIRCULATING POWER - {…}. EVERY inverter is held at 0 W. The meter cann' row 55eb950acd5f # main.py over 15 words (17); banned: watchdog :: 'circulation watchdog: armed (trips after {self.circ_wd.cfg.hold_s} s o' row 1817192a7f1c # main.py over 15 words (42); capitals: NOT DELIVERINGX :: 'NOT DELIVERING{tag} - {…}. Nothing has been commanded differently and ' row 685c1416364b # main.py over 15 words (26) :: 'delivery watchdog{tag}: armed (reports after {inv.delivery_wd.cfg.hold' row d3cd52827dd0 # main.py over 15 words (29); banned: watchdog :: 'delivery watchdog: n/a at one inverter - a unit short of its share is ' row d6981c8d7b56 # main.py banned: latched :: 'no e-stop fitted: if this host dies the battery stays latched at its l' row 685c8f02c97a # main.py capitals: NO SITE TOTAL :: 'PV production: NO SITE TOTAL - {…}. Reporting: {…}' row abef339bf192 # main.py over 15 words (25); option key: pv_entities :: 'PV production: `pv_entities` is set, so `pv_entity` is IGNORED - the {' row 514511bd0a93 # main.py over 15 words (32); option key: pv_invert_entities :: 'PV production: {ent} reads {watt} W - far below zero, so its sign is p' row 328abd6171ce # main.py over 15 words (22); option key: pv_invert_entities :: 'PV production: `pv_invert_entities` names {ent}, which is not a PV ent'