7.3 KiB
7.3 KiB
name, description
| name | description |
|---|---|
| ems-plan-explain | Explains EMS dispatch plans from live Postgres (MCP): why battery/grid/PV/curtailment for a site and time window. If the user does not explicitly name a site (id, code, or unambiguous name), query ems.site (with active plan hint), show a numbered list, and ask which site to use — do not run plan analysis for multiple sites in one turn. Use when the user asks why the plan looks a certain way, planning_interval rows, negative prices, export zero, rolling replan, or says „vysvětli plán“, „proč nabíjí“, „proč škrtí FVE“. |
EMS — vysvětlení plánu (živá DB + kontext kódu)
Kdy skill použít
- Otázky typu proč plán dělá X (nabíjení, export, curtailment, režim, ceny).
- Uživatel zmíní kód lokality (
BA81, …) nebo „aktuální plán“. - Porovnání model vs realita (záporná cena, nulový export, pole A/B).
Tvrdá pravidla
- Nejdřív data z DB přes MCP (
user-postgres-ems, nástrojquery, pouzeSELECT). Nevysvětlovat konkrétní sloty „z hlavy“ bez dotazu. - Pokud MCP selže: uvést přesnou chybu a praktické kroky (VPN, MCP zapnutý, dostupnost DB).
site_idjen po explicitní volbě uživatele (kód, id, potvrzení jedné řádky), nebo když uživatel lokalitu v dotazu sám pojmenoval. Neuvedená lokalita → nejprve jen dotaz na výběr (viz Krok 1); zakázáno analyzovat plán pro vícesitev jedné odpovědi „preventivně“.- V odpovědi rozlišit: co říká plán v DB vs co předpokládá LP model vs co omeží hardware (např. taper nabíjení u vysokého SoC dnes v LP není).
Postup (zkopíruj checklist)
- [ ] Zjistit site_id: uživatel ji v dotazu pojmenoval? → případně MCP lookup. Jinak MCP seznam + **zeptat se** (viz Krok 1); až po odpovědi → jedna `site_id`
- [ ] MCP: fn_plan_explain_bundle(site_id, hours) — default hours=6
- [ ] Z JSONu: operating_mode, grid limity, battery limity, intervals_next_window
- [ ] Potřebuji konkrétní čas? → doplnit SELECT na planning_interval (viz reference.md)
- [ ] Vysvětlit bilanci slotu + relevantní LP pravidla (solve_dispatch)
Krok 1 — site_id
Co znamená „lokalita explicitně zmíněná“: v textu uživatele je číselné site_id, kód lokality (BA81, home-01, …), nebo jednoznačný název/fragment, ze kterého MCP vrátí právě jednu řádku ems.site.
- Pokud uživatel dal
site_idjako číslo: ověřit MCP, že řádek vems.siteexistuje → použít. - Pokud dal kód nebo část názvu (
BA81, …): MCPselect id, code, name from ems.site where code ilike … or name ilike ….- 0 řádků → nabídnout seznam z reference.md §0 (všechny lokality) + zeptat se, kterou myslí.
- 1 řádek → použít jeho
id. - Více řádků → číslovaný výpis + zeptat se na jednu (můžeš hintnout kdo má aktivní plán, ale nepouštěj analýzu dřív než výběr).
- Pokud lokalita vůbec zmíněná není („vysvětli plán“, „proč nabíjí“ bez kódu apod.):
- MCP: SQL z reference.md §0 (seřazený seznam
site+active_planning_run_id). - V odpovědi uvést číslovaný seznam
id | code | name | má aktivní plán?. - Výslovně se zeptat uživatele, kterou lokalitu myslí (číslo z výpisu,
code, neboid). fn_plan_explain_bundleani rozšířený SELECT naplanning_intervalpro tuto otázku nespouštěj, dokud uživatel nevybere jednu lokalitu (kód / číslo řádku / id / jednoznačné „tu s BA81“). Nepředvybírej „beru první řádek“ ani nespouštěj paralelně bundle pro všechnysite_id— je to zbytečná zátěž a matoucí výstup.- Je v DB jen jeden záznam
ems.site: stejně nejdřív napiš která lokalita to je a zeptej se na krátké potvrzení (např. „Mám plán vysvětlit pro CODE?“ / stačí „ano“) — bezfn_plan_explain_bundlepřed odpovědí. Výjimku tvoří jen situace, kdy uživatel v téže zprávě současně explicitně odkáže na tuto jedinou lokalitu (pak není „neuvedená“).
- MCP: SQL z reference.md §0 (seřazený seznam
Krok 2 — balík pro vysvětlení
select ems.fn_plan_explain_bundle(<site_id>, <hours>);
<hours>: default 6. Jiná hodnota jen když uživatel explicitně chce delší/kratší okno.- Výstup je jeden JSONB (
bundle): viz.cursor/rules/plan-explain-bundle.mdc— které klíče číst.
Krok 3 — interpretace (struktura odpovědi)
Krátce a v pořadí:
- Kontext:
operating_mode.mode_code,active_planning_run(run_type,triggered_by,soc_at_replan_wh,forecast_correction_factor). - Slot(y): z
intervals_next_windownebo z dodatečného SQL — pro každý relevantní interval:- Výkon:
battery_setpoint_w(+ nabíjení / − vybíjení),grid_setpoint_w(+ import / − export),load_baseline_w. - FVE:
pv_a_forecast_solver_w,pv_b_forecast_solver_w,pv_a_curtailed_w(useknuté W na pole A). - Ceny:
effective_buy_price,effective_sell_price,is_predicted_price. - Exekuce Deye (pokud je ve sloupcích):
deye_physical_mode,deye_gen_cutoff_enabled.
- Výkon:
- Proč (odkaz na logiku, ne dlouhá citace):
- Záporná prodejní cena → export do sítě v LP neekonomický / u části instalací tvrdě 0; přebytek → nabíjení / curtailment A / GEN cutoff (viz
solve_dispatchvbackend/services/planning_engine.py). - Pole B je v modelu nekontrolovatelné — nelze ho
pv_a_curtailedomezit. - Zelený bonus není v účelové funkci LP; počítá se v auditu (
fn_green_bonus_revenue) — vizdocs/04-modules/planning.md. - ~60 % SoC ve slunci (BA81/KV1) nebo ranní export před sell<0 (home-01): často v58 (
bc_pv=0přisell > min+0,20) nebo v33 pre-neg cushion — plánovaná náhrada:docs/04-modules/planning-charge-slot-budget.md(zatím ne v produkci).
- Záporná prodejní cena → export do sítě v LP neekonomický / u části instalací tvrdě 0; přebytek → nabíjení / curtailment A / GEN cutoff (viz
- Mezery modelu (upozornit jednou větu, když je to relevantní):
- LP používá horní strop
max_charge_power_wbez závislosti na SoC → u vysokého SoC může reálný proud být nižší než plán.
- LP používá horní strop
Kdy se zeptat uživatele
- Lokalita neuvedená nebo nejednoznačná — vždy nejdřív výběr / potvrzení (viz Krok 1); nikdy hned neanalyzovat všechny lokality najednou.
- Čas bez časové zóny („v 11:15“) — potvrdit Europe/Prague nebo explicitní offset.
- Širší horizont než pár hodin — domluvit
hoursnebo přesnéfrom/toUTC pro doplnkový SELECT.
Další SQL a šablony
Anti-patterns
- Hromadná analýza (
fn_plan_explain_bundle,planning_intervalpro vícesite_id) jen proto, že uživatel neřekl kterou lokalitu — vždy se nejprve zeptat. - Nevyhledávat plán přes desítky ad-hoc dotazů, když stačí
fn_plan_explain_bundlea případně jeden doplnkovýSELECTna časové okno. - Nezaměňovat
pv_a_curtailed_w(plán) s tím, co je vždy zapsané na Modbus — exekuce curtailmentu na Deye může být instalacně závislá; při pochybnostech říct „ověřit vdocs/05-todo.md/ modbus docs“.