Fáze 0: ekonomický regresní harness plánovače

- scripts/harness/extract_fixtures.py: extrakce vstupů solveru
  (fn_planning_site_context + fn_load_planning_slots_full) do JSON fixtures
- backend/tests/test_golden_replay.py: golden gate — replay fixtures přes
  solve_dispatch_two_pass, bit-perfektní diff proti snapshotům (GOLDEN_UPDATE=1
  pro vědomou regeneraci); 4 scénáře: home-01 neg-sell extrém / normal, BA81, KV1
- scripts/harness/economics_report.py: actual (audit_interval) vs oracle MILP
  (perfect hindsight, čistá ekonomika bez heuristických penalt), SoC-adjusted

Baseline home-01 2026-05-12..06-09: GAP 2185 Kč / 29 dní (~27 %).
Známý stav: 4/124 testů test_planning_dispatch_milp.py failuje už na main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dusan Vojacek
2026-06-11 10:48:13 +02:00
parent edc8ae9774
commit 484f1f85fc
12 changed files with 35461 additions and 0 deletions

78
scripts/harness/README.md Normal file
View File

@@ -0,0 +1,78 @@
# Ekonomický regresní harness (Fáze 0 — „Čistý plánovač“)
Nástroje pro objektivní měření ekonomiky plánovače a regresní bránu pro jeho
dekompozici. Kontext a fáze: viz strategie refaktoru (Fáze 04) v paměti
projektu / plánu „Čistý plánovač“.
## Komponenty
| Soubor | Účel |
|--------|------|
| `extract_fixtures.py` | Stáhne z EMS DB kompletní vstupy plánovače (context + sloty `fn_load_planning_slots_full`) pro zadanou site a pražský den → JSON fixture do `backend/tests/golden/fixtures/`. |
| `economics_report.py` | Pro rozsah dní spočítá skutečný cashflow (audit_interval) vs. **oracle LP** (perfect hindsight, čistý model bez heuristických penalt) → tabulka GAP per den. |
| `../../backend/tests/test_golden_replay.py` | Pytest gate: replay fixtures přes `solve_dispatch_two_pass`, porovnání s golden snapshoty v `backend/tests/golden/snapshots/`. |
## Připojení k DB
Všechny skripty čtou DSN v pořadí `--dsn` > `EMS_DB_DSN` > `DB_HOST`/`DB_PORT`/
`DB_USER`/`DB_PASSWORD`/`DB_NAME` (default lokální docker `127.0.0.1:5432/ems`).
Čtou pouze (SELECT) — bezpečné proti produkci.
```bash
export EMS_DB_DSN="postgresql://ems_user:***@10.200.200.1:5432/ems"
```
## Golden replay gate (regresní brána dekompozice)
```bash
cd backend
python3 -m pytest tests/test_golden_replay.py -q # ověření (identity refactor → musí projít)
GOLDEN_UPDATE=1 python3 -m pytest tests/test_golden_replay.py -q # vědomá změna chování → regenerace
```
Pravidla:
- **Fáze 1 (dekompozice)**: snapshoty se NIKDY neregenerují — výstup musí být bitově shodný
(floaty zaokrouhleny na 4 d.m.).
- **Fáze 2/3 (změny ekonomiky)**: regenerace snapshotů je povolená pouze s odůvodněním
v commit message a se zlepšeným/nezhoršeným GAPem v `economics_report.py`.
- Fixtures jsou zmrazené vstupy z reálné DB (konfigurace k datu extrakce, EV sessions
vynulovány, `operating_mode=AUTO`) — deterministické, bez DB při běhu testu.
### Přidání fixture
```bash
python3 scripts/harness/extract_fixtures.py --site-code home-01 --day 2026-06-07 --tag neg_sell_deep
cd backend && GOLDEN_UPDATE=1 python3 -m pytest tests/test_golden_replay.py -q
```
Pokryté scénáře (v4 fixtures): home-01 hluboký neg-sell (sell 1.57, buy 0.89),
home-01 běžný spot den, BA81 běžný den, KV1 fixní nákup. Při změnách heuristik
přidávej scénář, který změnu pokrývá.
## Ekonomický report (metrika „kolik necháváme na stole“)
```bash
python3 scripts/harness/economics_report.py --site-code home-01 --from 2026-05-12 --to 2026-06-09
```
- **actual** = skutečný cashflow dne z auditu (import × eff. buy export × eff. sell),
- **oracle** = dolní mez: čistý MILP se skutečnou PV/spotřebou/cenami (perfect foresight),
- obojí **SoC-adjusted**: koncový SoC oceněn průměrnou denní nákupní cenou, aby den
„nevyhrával“ vybitím baterie,
- **gap = actual oracle** = chyba forecastu + neefektivita dispatche. Oracle je
nedosažitelná dolní mez; sleduj TREND gapu (před/po změně plánovače), ne absolutní nulu.
Vyloučeno z obou stran: zelený bonus PV B (nezávislý na dispatch rozhodnutích),
přesouvání EV/TČ zátěže (spotřeba je brána jako fixní).
## Známý stav k 2026-06-11 (baseline)
- `tests/test_planning_dispatch_milp.py`: **4 ze 124 testů failují už na main**
(`test_future_neg_buy_evening_export_at_high_soc_relaxed_prep`,
`test_grid_charge_respects_import_and_battery_caps`,
`test_morning_exports_pv_when_cushion_ok`,
`test_evening_reserve_soc_near_reserve_after_discharge`) — všechny z neg-sell/prep
heuristik. Nezakrývat regenerací; vyřešit ve Fázi 1/2.
- Golden snapshot home-01 neg-sell dne: `penalty_czk = 2119 Kč` při cashflow 163 Kč —
heuristické penalty v objective 13× převažují reálné peníze. To je kvantifikace
problému, který Fáze 2/3 odstraňují.