- TariffPlan.arbitrage(now=...) is required (keyword-only, no default); so are
homeview.trade_verdict/refusal_key's now. Existing test calls pass one.
- test_arbitrage.py: no module-level decide wrapper. Fixtures that probed a
one-day plan after its extremes now hold two days (as a site does); the
flap day gets a unique cheapest and dearest hour; the replay breaks its
ties without direction. The flap bound is <= 4 and the replay check is
len(_trades) < 365 again. 228 checks pass on the old and the new code.
- test_price02.py part 6: ties (equal quarters, a real 15-minute day,
alternating hourly prices) and the required now.
- Identity pins: the masked digest is only for the older-tree comparison;
this tree's own digests are pinned with nothing hidden.
- DECISIONS: the tie analysis with numbers.
Co-Authored-By: Claude <noreply@anthropic.com>
TariffPlan.arbitrage(now=...) drops the points whose period has ended
(end <= now), so the cheapest and dearest point can still be traded.
decide() (modes off), the modes-on allowed() gate and the Home verdict
all pass their own now. Hourly feeds and the static tariff are unchanged.
The off-peak sentence and the charge/discharge sentences say "price
period". Tests: test_price02.py; test_arbitrage.py rolls its whole-day
plans to start at now; test_modes_p3.py part 1 digests leave the trade
sentence out (commands unchanged on 7a00f12, 90bc901 and this tree).
Co-Authored-By: Claude <noreply@anthropic.com>