# 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í | ✅ **v2 AKTIVNÍ v produkci od 2026-06-12** (v1 = stín); + robustnostní trojice (changelog 2026-06-12) |
| 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.
