MAINT-20 part 2 r2: app/main.py comments, lines 3001-3500 (shadow .. cycle)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
6f94944e44
commit
391c4b4411
@@ -3023,25 +3023,15 @@ class Controller:
|
|||||||
|
|
||||||
def write_refusal(self, value: float, inv=None) -> str | None:
|
def write_refusal(self, value: float, inv=None) -> str | None:
|
||||||
"""Why `value` may NOT be written to `inv` right now, or None if it
|
"""Why `value` may NOT be written to `inv` right now, or None if it
|
||||||
may.
|
may. SAFETY-28: a number reaches the wire only if THE SINGLE ALLOCATOR
|
||||||
|
placed it, on this tick, for THIS unit (`Allocation.authorises()`); a
|
||||||
SAFETY-28: a number reaches the wire only if THE SINGLE ALLOCATOR
|
second writer must file a Claim. 0 W is ALWAYS authorised and tested
|
||||||
placed it, on this tick, for THIS unit (`Allocation.authorises()`).
|
first, reading nothing: the failsafe writes run while the allocator has
|
||||||
specs 1.5 makes two writers on one actuator a non-goal;
|
REFUSED, so a gate asking permission to command zero would deadlock the
|
||||||
`len(validate.ACTUATOR_WRITE_KEYS) == 1` is a statement about the
|
failsafe. It tests `value == 0.0`, not a flag the caller sets. DEV-02:
|
||||||
options schema, not the writes. A second writer must file a Claim and
|
the unit is an ARGUMENT (the record holds one share per unit); the
|
||||||
go through `resolve()`.
|
default is for N=1 callers and REFUSES at N>=2.
|
||||||
0 W is ALWAYS authorised and the test for zero is first and reads
|
DECISIONS/MAIN-orchestration.md."""
|
||||||
nothing: the failsafe writes run while the allocator has REFUSED, so a
|
|
||||||
gate asking its permission to command zero would deadlock the failsafe
|
|
||||||
behind the component whose failure it answers; and at S = 0 broadcast
|
|
||||||
and allocation coincide (no over-command). It tests `value == 0.0`, not
|
|
||||||
a `failsafe=True` flag (a flag is an assertion by the caller, which is
|
|
||||||
what a second writer would pass).
|
|
||||||
DEV-02: the unit is an ARGUMENT: the record holds one share per unit,
|
|
||||||
and the first inverter's name at a roster of two would authorise A's
|
|
||||||
share on B's wire. The default is for N=1 callers and REFUSES at N>=2
|
|
||||||
(`_only()`). DECISIONS/MAIN-orchestration.md."""
|
|
||||||
if value == 0.0:
|
if value == 0.0:
|
||||||
return None
|
return None
|
||||||
inv = self._only() if inv is None else inv
|
inv = self._only() if inv is None else inv
|
||||||
@@ -3311,8 +3301,10 @@ class Controller:
|
|||||||
if n]
|
if n]
|
||||||
|
|
||||||
def _provider_gate(self, now: datetime) -> None:
|
def _provider_gate(self, now: datetime) -> None:
|
||||||
"""PRICE-01: `cheap`, the gate and the gap from the standing plan.
|
"""PRICE-01: `cheap`, the gate and the gap from the standing plan. No
|
||||||
(DECISIONS/MAIN-orchestration-archive.md)"""
|
price for now is a closed gate, so the charge waits rather than run
|
||||||
|
unpriced; the gap flag stays False until the first refresh has
|
||||||
|
finished. (DECISIONS/MAIN-orchestration-archive.md)"""
|
||||||
plan = self.fresh_tariff_plan(now)
|
plan = self.fresh_tariff_plan(now)
|
||||||
published = None if plan is None else plan.published
|
published = None if plan is None else plan.published
|
||||||
if published is not None:
|
if published is not None:
|
||||||
@@ -3349,14 +3341,17 @@ class Controller:
|
|||||||
|
|
||||||
def _charge_gate_open(self, inv) -> bool:
|
def _charge_gate_open(self, inv) -> bool:
|
||||||
"""MAINT-13: may this pack charge now, for the maintenance timeout?
|
"""MAINT-13: may this pack charge now, for the maintenance timeout?
|
||||||
(DECISIONS/MAIN-orchestration-archive.md)"""
|
Closed only when a price gate exists, it is shut, and the pack is not
|
||||||
|
really taking charge. (DECISIONS/MAIN-orchestration-archive.md)"""
|
||||||
if not self._price_gated or self.cheap:
|
if not self._price_gated or self.cheap:
|
||||||
return True
|
return True
|
||||||
batt = inv.batt
|
batt = inv.batt
|
||||||
return batt is not None and float(batt) <= -MAINT_CHARGING_W
|
return batt is not None and float(batt) <= -MAINT_CHARGING_W
|
||||||
|
|
||||||
async def cycle(self) -> None:
|
async def cycle(self) -> None:
|
||||||
"""Gather claims, resolve precedence, write the winner.
|
"""Gather claims, resolve precedence, write the winner. Nothing here
|
||||||
|
decides who wins (arbiter.py does, by one rule); this method only
|
||||||
|
states what each strategy wants.
|
||||||
(DECISIONS/MAIN-orchestration-archive.md)"""
|
(DECISIONS/MAIN-orchestration-archive.md)"""
|
||||||
now = datetime.now(timezone.utc)
|
now = datetime.now(timezone.utc)
|
||||||
# BEFORE the first `return` of this method on purpose (TARIFF-11): it
|
# BEFORE the first `return` of this method on purpose (TARIFF-11): it
|
||||||
|
|||||||
Reference in New Issue
Block a user