---
name: ems-delta-triage
description: Triáž neekonomického chování plánovače po nasazení — vysvětlit PROČ plán udělal co udělal, porovnat v1 vs v2 (shadow), vyčíslit ztrátu proti oracle. Použít když uživatel hlásí "divné/neekonomické chování", "proč to v X hodin nabíjelo/exportovalo", nebo chce vyhodnotit shadow data v1 vs v2.
---

# EMS delta-triáž (v1 vs v2 vs realita vs oracle)

Cíl: z konkrétního dne/situace vyrobit vysvětlení s čísly, ne dojmy. Vždy
pracuj v pořadí: (1) co se REÁLNĚ stalo, (2) co chtěl plán, (3) co chtěl peer
(shadow), (4) co bylo optimum, (5) proč se liší.

## 0. Vstupy od uživatele
site code (home-01/BA81/KV1/…), den či časové okno (Prague), co je „divné".

## 1. Realita (audit) — MCP `query` na `user-postgres-ems`
```sql
select interval_start, actual_grid_power_w, actual_battery_power_w,
       actual_battery_soc_pct, actual_pv_power_w, actual_load_power_w,
       actual_cost_czk, deviation_cost_czk, planning_run_id
from ems.audit_interval
where site_id = :id and interval_start >= :od and interval_start < :do
order by interval_start;
```
+ efektivní ceny: `ems.vw_site_effective_price` (stejné okno). Hledej sloty,
kde tok jde PROTI ceně (import za draho při nabité baterii, export při sell<0…).

## 2. Plán a jeho zdůvodnění
- Aktivní run pro slot: `audit_interval.planning_run_id` → `ems.planning_run`
  (`solver_params`: `version`, `relax_chain`, `neg_sell_*`, `evening_push_ts`…)
  a `ems.planning_interval` (setpointy, expected_cost).
- `ems.fn_plan_explain_bundle` + skill `.cursor/skills/ems-plan-explain`.
- v1 vs v2 shadow diff: `planning_run.solver_params->'comparison'`
  (`diff.total_expected_cost_czk`, `slot_diffs` — kde se verze rozcházejí).

## 3. Replay lokálně (přesná rekonstrukce)
```bash
python3 scripts/harness/extract_fixtures.py --site-code <code> --day <YYYY-MM-DD> --tag triage_<duvod>
cd backend && python3 ../scripts/harness/solver_v2_eval.py   # v1 (golden) vs v2 na fixture
```
Pozor: context = AKTUÁLNÍ konfigurace; pro historickou věrnost srovnej
`planning_run.solver_params.inputs` (battery parametry tehdy).

## 4. Optimum (kolik se nechalo na stole)
```bash
EMS_DB_DSN=… python3 scripts/harness/economics_report.py --site-code <code> --from <den> --to <den>
```
GAP = forecast error + neefektivita dispatche. Pro oddělení: porovnej plán
(forecast vstupy) vs oracle (skutečné PV/load) — velký rozdíl plán/oracle při
malém rozdílu plán/realita ⇒ chyba forecastu, ne dispatche.

## 5. Verdikt — vždy jedna z kategorií + číslo v Kč
- **forecast error** (PV/load se netrefil; plán byl na svá data racionální),
- **heuristika v1** (penalty/maska vynutila neekonomický tok — ukaž kterou:
  vypni ji přes `penalty_audit.py --only NAZEV` na fixture dne),
- **tvrdé pravidlo** (block_export, arb floor, breaker, režim — správné chování),
- **chyba modelu v2** (jen pokud aktivní v2; ověř `solver_v2_eval.py` + unit testy),
- **exekuce** (plán dobrý, zařízení neposlechlo — `ems.modbus_command` journal,
  skill ems-planner-bug-triage).

## Zásady
- Žádné závěry bez čísel ze SQL/harnessu; vždy uveď sloty a Kč.
- Nikdy neměnit plánovač bez golden gate (viz docs/refactor-clean-planner.md).
- Nálezy zapsat do docs/planning-changelog.md (formát: datum · problém · příčina · ověření).
