MAINT-20 part 2 review: comment-only fixes in main.py and the MAIN notes
- check_peak_floor_limited: restore the SAFETY-25 line (the reserve sentence is
in messages.peak_reserve() on every branch, unreadable SoC included).
- Three status-page comments that no longer said anything (SAFETY-20 row,
AC 5 delivery row, banner-vs-text) now say their rule in one line.
- tariff_refresh_wanted docstring: no orphan "TARIFF-24)" line.
- MAIN-orchestration.md: blank line before the first heading.
- MAIN-orchestration-archive.md: refilled intro; says how to find a section
from a main.py pointer.
No code change: maint20_same_code.py 16029d7 -> SAME CODE, -OO same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f8df7cd860
commit
bbbc89b235
@@ -2,9 +2,12 @@
|
||||
|
||||
Written by MAINT-20 part 2. Each section is one comment block or docstring as it
|
||||
stood in `app/main.py` at release/1.0 `d4c01da`, keyed by its first line number
|
||||
there; the last heading holds the ones that came in by `16029d7` (keyed there). It is a record, not a design: the live rule is the one-line comment now in
|
||||
the code, and the curated reasoning is in [[MAIN-orchestration]]. Comment blocks
|
||||
have their `#` removed; docstrings their quotes.
|
||||
there; the last heading holds the ones that came in by `16029d7` (keyed
|
||||
there). It is a record, not a design: the live rule is the one-line comment now
|
||||
in the code, and the curated reasoning is in [[MAIN-orchestration]]. Comment
|
||||
blocks have their `#` removed; docstrings their quotes. A pointer in `main.py`
|
||||
names this file only: find its section by searching here for a phrase of the
|
||||
comment it ends.
|
||||
|
||||
### L1080 Set by amain() once the transport is built, so the status page can sho
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ comments that were shortened but not rewritten here are kept word for word in
|
||||
[[SAFETY-30-per-unit-sign]], [[SAFETY-73-refusal-per-inverter]],
|
||||
[[SAFETY-121-bound-every-quarter]], [[TARIFF-10-fetching-is-not-trading]],
|
||||
[[TARIFF-24-modes-need-the-tariff-task]], [[OPT-34-the-night-charge-keeps-its-level]].
|
||||
|
||||
## Controller construction
|
||||
|
||||
- **Per-write budget (DEV-02).** Each write is dispatched concurrently and bounded, so one hung `hass.call()` cannot eat a sibling's layer-1 budget (the ESP32 zeroes after about 30 s, and a fault on A could zero a healthy B). The number is derived: `heartbeat_s` max 25 s, layer-1 veto `validate.FIRMWARE_INGEST_VETO_S` 30 s, so 25 + 4 < 30. test_inverter.py grades the inequality, so raising the heartbeat ceiling goes red instead of taking an inverter to zero. Below hass.py's 10 s HTTP timeout on purpose: abandon the write and re-issue it next tick, since `last_write` moves only on an accepted write.
|
||||
|
||||
@@ -162,9 +162,8 @@ TARIFF_MAX_AGE_S = 3 * TARIFF_REFRESH_S
|
||||
|
||||
def tariff_refresh_wanted(opts: dict) -> bool:
|
||||
"""Does this install need the background tariff refresh? (TARIFF-10,
|
||||
TARIFF-24)
|
||||
Yes with a price feed, trading armed, or battery modes on. It decides
|
||||
whether prices are looked up, never whether energy moves.
|
||||
TARIFF-24) Yes with a price feed, trading armed, or battery modes on. It
|
||||
decides whether prices are looked up, never whether energy moves.
|
||||
DECISIONS/TARIFF-10-fetching-is-not-trading.md and
|
||||
DECISIONS/TARIFF-24-modes-need-the-tariff-task.md."""
|
||||
return (provider_configured(opts) or arbitrage.enabled(opts)
|
||||
@@ -4666,7 +4665,9 @@ class Controller:
|
||||
"lower: %s.", messages.reason_code(g.reason))
|
||||
_LOG.debug("Evidence: %s.", g.reason)
|
||||
# A fixed notification_id, and a DIFFERENT one from every other alarm
|
||||
# here - check_meter_frozen() gives the reasoning.
|
||||
# here - check_meter_frozen() gives the reasoning. ⚠️ SAFETY-25's
|
||||
# sentence (the reserve binds the peak guard only) is in
|
||||
# messages.peak_reserve() on every branch, unreadable SoC included.
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
await self.hass.call("persistent_notification", "create",
|
||||
messages.peak_reserve(
|
||||
@@ -5183,8 +5184,9 @@ class Controller:
|
||||
elif rail_unreachable(self.site_max_w,
|
||||
dev_min=self.site_dev_bound("dev_min"),
|
||||
dev_max=self.site_dev_bound("dev_max")):
|
||||
# SAFETY-20, and THE SECOND REASON TO USE THIS ROW RATHER THAN
|
||||
# A NEW MECHANISM. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# SAFETY-20: the same row as the transport case above (the
|
||||
# check cannot be evaluated here); only the missing term
|
||||
# differs. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
_no_rating = (not self.site_max_w
|
||||
or not is_commandable(self.site_max_w))
|
||||
out.append({"ok": False, "warn": True, "id": "freeze_check",
|
||||
@@ -5476,8 +5478,9 @@ class Controller:
|
||||
inv.name, _dheld,
|
||||
inv.delivery_wd.cfg.hold_s)})
|
||||
else:
|
||||
# AC 5, and the same honesty `circulating power: n/a` uses one
|
||||
# block up. (DECISIONS/MAIN-orchestration-archive.md)
|
||||
# AC 5: at one inverter this check has nothing to find, so it is
|
||||
# not called "armed" (as `circulating power: n/a` above).
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
out.append({"ok": True, "warn": False, "id": "delivery",
|
||||
"text": messages.row_one_inverter("Delivery check")})
|
||||
|
||||
@@ -5598,7 +5601,8 @@ class Controller:
|
||||
level, banner = "bad", messages.banner_direction(
|
||||
len(self.inverters) > 1)
|
||||
elif bad:
|
||||
# ⚠️ `banner` IF THE ROW OFFERS ONE, `text` OTHERWISE.
|
||||
# ⚠️ `banner` IF THE ROW OFFERS ONE, `text` OTHERWISE: a row may
|
||||
# say more than fits the headline (SAFETY-25's floor row).
|
||||
# (DECISIONS/MAIN-orchestration-archive.md)
|
||||
level, banner = "bad", messages.banner_not_ready(bad[0])
|
||||
# SAFETY-112: nothing to do but wait, so Home says that instead
|
||||
|
||||
Reference in New Issue
Block a user