# Refaktor „Čistý plánovač“ — plán a stav Cíl: odstranit příčinu neekonomického provozu — heuristickou vrstvu okolo MILP solveru (pre-solver fáze/okna/kotvy + ~26 ručně laděných penalt v objective), která se vzájemně pere a převažuje reálné peníze. Strategie: **ne big-bang přepis projektu** (predikce, Modbus, telemetrie, audit, DB jsou odladěné), ale řízená náhrada jádra plánovače za regresním harnessem. ## Diagnóza (měřeno 2026-06-11) - `planning_engine.py` (před refaktorem 6 345 ř., 112 funkcí): ~35 % ekonomické logiky v heuristikách PŘED solverem, ~60 % jako měkké penalty v objective s ~20 konstantami natvrdo. Solver = „vykonavatel heuristického plánu“. - Na neg-sell dni Σ penalt 2 119 Kč při cashflow −163 Kč (13×). - GAP actual vs perfect-hindsight oracle, home-01 29 dní: **2 185 Kč ≈ 27 %** (stabilní dny 1–5 %, volatilní/neg-sell 50–160 %). - Den 2026-05-01 (buy −13,26): v1 Infeasible po všech 8 relax krocích. - Penalty audit: **16/26 penalt mrtvých** na 6 reprezentativních fixtures. ## Fáze a stav | Fáze | Obsah | Stav | |------|-------|------| | 0 | Ekonomický harness: golden replay gate, fixtures z reálné DB, economics report (actual vs oracle), penalty audit | ✅ hotovo | | 1 | Dekompozice `planning_engine.py` → `services/planning/` (constants/types/forecast/db_io/heuristics), fasáda, identita chování | ✅ hotovo | | 2 | Penalty audit, stale testy → xfail, rozšíření fixtures (extrémní dny) | ✅ hotovo | | 3 | `solver_v2` (čisté jádro) + router verzí + shadow porovnání | ✅ hotovo (kód); **čeká na shadow data z produkce** | | 4 | Slupka: FE výkon + responsivita | ✅ první vlna (viz `docs/audits/`) | ## Jak se pracuje (závazná pravidla) 1. **Golden gate** (`backend/tests/test_golden_replay.py`) musí projít po každé změně plánovače. Snapshoty se regenerují (`GOLDEN_UPDATE=1`) jen při vědomé změně chování, s odůvodněním v commitu a s nezhoršeným GAPem (`scripts/harness/economics_report.py`). 2. Ekonomické parametry patří do DB (CLAUDE.md pravidlo 16), ne do Pythonu. 3. v2 nikdy neměnit bez `solver_v2_eval.py` (v2 vs v1 na fixtures). ## Nasazení v2 (návod) 1. **Shadow**: do prod env `PLANNING_ENGINE_COMPARE_ENABLED=true` → v1 řídí, v2 se počítá paralelně, diff v `planning_run.solver_params.comparison`. 2. Po ~týdnu vyhodnotit: `select solver_params->'comparison' from ems.planning_run …` + `economics_report.py` (trend GAPu). 3. **Přepnutí**: `PLANNING_ENGINE_VERSION=v2`; golden snapshoty vědomě zregenerovat; heuristics.py + mrtvé penalty postupně mazat. ## Klíčové výsledky v2 (fixtures, SoC-fér) v2 lepší na všech 5 řešitelných fixtures, **+231,5 Kč ≈ +22 %**; den 2026-05-01 v1=INFEASIBLE → v2 řeší (−674,5 Kč). Detail: `scripts/harness/solver_v2_eval.py`, changelog 2026-06-11. ## Otevřené body - v2 výkon na extrémních dnech (10 s time limit) — omezit binárky `y_imp`/`z_exp` jen na sloty, kde dávají smysl. - `fn_plan_current_bundle` 3,8 s (90 % v `fn_forecast_pv_slots_range_canonical_ab`) — viz `docs/audits/frontend-performance-2026-06-11.md`. - Virtualizace Planning tabulky; Recharts Cell mapování. - Po přepnutí na v2: smazat mrtvé heuristiky/penalty, přepsat 4 xfail testy na ekonomické asserty.