diff --git a/scripts/harness/README.md b/scripts/harness/README.md index b41322c..86de647 100644 --- a/scripts/harness/README.md +++ b/scripts/harness/README.md @@ -45,6 +45,11 @@ python3 scripts/harness/extract_fixtures.py --site-code home-01 --day 2026-06-07 cd backend && GOLDEN_UPDATE=1 python3 -m pytest tests/test_golden_replay.py -q ``` +`--keep-ev` zmrazí do fixture i otevřené EV sessions z doby extrakce (default je +vynulovat — historické okno bez session). Hodí se pro EV scénáře (deadline, +měkký cíl / oportunistické nabíjení, min. výkon wallboxu); `meta.keep_ev` +ve fixture říká, jak byla pořízena. + 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á. diff --git a/scripts/harness/extract_fixtures.py b/scripts/harness/extract_fixtures.py index 1035309..62975d5 100644 --- a/scripts/harness/extract_fixtures.py +++ b/scripts/harness/extract_fixtures.py @@ -154,10 +154,12 @@ async def extract(args: argparse.Namespace) -> Path: # Determinismus replay: # - SoC/TUV fixujeme do contextu (přepis aktuálních hodnot historickými / extrakčními), - # - otevřené EV sessions z doby extrakce nepatří k historickému oknu → vynulovat, + # - otevřené EV sessions z doby extrakce nepatří k historickému oknu → default + # vynulovat; --keep-ev je zmrazí do fixture (EV scénáře: deadline, měkký cíl), # - operating_mode fixně AUTO (plný solver, srovnatelnost napříč fixtures). ctx["soc_wh"] = soc_wh - ctx["ev_sessions"] = [] + if not args.keep_ev: + ctx["ev_sessions"] = [] ctx["operating_mode"] = "AUTO" fixture = { @@ -172,12 +174,18 @@ async def extract(args: argparse.Namespace) -> Path: "soc_wh": round(soc_wh, 1), "soc_source": soc_source, "tag": args.tag, + "keep_ev": bool(args.keep_ev), "extracted_at": datetime.now(tz=PRAGUE).isoformat(), "dsn_host": dsn.split("@")[-1].split("/")[0] if "@" in dsn else "?", "note": ( "Vstupy plánovače zmrazené k okamžiku extrakce (context = aktuální konfigurace, " "sloty = fn_load_planning_slots_full nad historickými cenami/forecasty). " - "EV sessions vynulovány, operating_mode=AUTO." + + ( + "EV sessions zmrazeny (--keep-ev)" + if args.keep_ev + else "EV sessions vynulovány" + ) + + ", operating_mode=AUTO." ), }, "context_json": ctx, @@ -209,6 +217,11 @@ def main() -> None: p.add_argument("--day", required=True, help="Pražský den YYYY-MM-DD (začátek okna 00:00)") p.add_argument("--hours", type=int, default=36, help="Délka okna v hodinách (default 36)") p.add_argument("--tag", required=True, help="Krátký popis scénáře (neg_sell_deep, normal, …)") + p.add_argument( + "--keep-ev", + action="store_true", + help="Zachovat otevřené EV sessions v contextu (default: vynulovat — historické okno)", + ) p.add_argument("--dsn", default=None, help="postgresql:// DSN (jinak EMS_DB_DSN / DB_* env)") p.add_argument("--out-dir", default=str(DEFAULT_OUT_DIR), help="Cílový adresář fixtures") args = p.parse_args()