fix(planner): EV session viditelna i bez deadline / nad targetem (BUG2)
Zivy incident home-01: aktivni plan mel ev_sessions:0, ac session bezela (target 70 %). Planovac neviděl ~6 kW zatez auta a spatne rozvrhl baterii (zbytecny vecerni import). Root cause (dve pasti): - fn_planning_site_context vracela session jako null, kdyz needed_wh=0 (auto nad targetem) i kdyz target_deadline is null. - _ev_session_from_json (Python) zahazovala session bez deadline. Fix: - R__038 fn_ev_session_planning_json: session se vyradi (null) JEN bez tvrdych dat (kapacita vozidla / soc_at_connect). target_deadline smi byt NULL -- solver hard deadline constraint aplikuje jen pri needed>0; oportunisticka vrstva bezi i bez deadline. Auto nad targetem zustava v planu jako znama zatez i s headroomem k levnemu doplneni. R__039 vola helper (deduplikace dvou inline poddotazu, SQL-first). - _ev_session_from_json si NULL deadline ponecha (energy_needed_wh default 0). - testy test_ev_session_parse.py; docs ev-charging + planning-changelog; CLAUDE.md funkce. Navrh agresivnejsiho oportunistickeho algoritmu (P50 levnych oken z market_price_stats misto konstanty 1 Kc/kWh) -- NEnasazeno, k rozhodnuti, sepsano v docs/04-modules/planning.md (EV oportunismus); riziko regrese golden ekonomiky, nutny EV fixture + eval. Overeni: pytest -q 362 passed; golden replay gate 7 passed; solver_v2_eval beze zmeny (fixtures bez EV session). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,12 +31,15 @@ def _ev_session_from_json(obj: object) -> Optional[SimpleNamespace]:
|
||||
obj = json.loads(obj)
|
||||
if not isinstance(obj, dict):
|
||||
return None
|
||||
# target_deadline SMÍ být None: oportunistická session (auto nad targetem,
|
||||
# nebo bez nastaveného cíle) zůstává v plánu kvůli headroomu i jako známá
|
||||
# zátěž. Tvrdý deadline constraint se aplikuje jen při energy_needed_wh > 0
|
||||
# (a needed > 0 nastane jen s deadlinem). Dřív se taková session zahazovala
|
||||
# (None) a plánovač pak neviděl zátěž auta — bug 2026-06-13.
|
||||
td = _parse_json_dt(obj.get("target_deadline"))
|
||||
if td is None:
|
||||
return None
|
||||
return SimpleNamespace(
|
||||
target_deadline=td,
|
||||
energy_needed_wh=float(obj["energy_needed_wh"]),
|
||||
energy_needed_wh=float(obj.get("energy_needed_wh") or 0.0),
|
||||
headroom_wh=float(obj.get("headroom_wh") or 0.0),
|
||||
opportunistic_value_czk_kwh=float(obj.get("opportunistic_value_czk_kwh") or 0.0),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user