Fáze 2.1: 4 zastaralé testy → expectedFailure; +2 fixtures vč. Infeasible reproduceru

Analýza (agent + ručně): všechny 4 failující testy vynucují heuristické chování
před retry-chain v5; současné chování je ekonomicky správné nebo jde o korektní
fallback. Scénáře zachovány s @unittest.expectedFailure + zdůvodněním —
přepsat na ekonomické asserty ve Fázi 3. Suite: 120 passed, 4 xfailed.

Nové golden fixtures home-01: 2026-05-01 extreme_neg_buy (buy −13.26;
ZACHYCENO: solver Infeasible po celém relax řetězci — zmrazeno jako golden
failure snapshot), 2026-05-25 evening_push. Golden replay i penalty audit
umí solver_error výsledky (penalta měnící feasibility se zviditelní).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dusan Vojacek
2026-06-11 13:56:12 +02:00
parent 0dc2e1df96
commit 9a2229641d
7 changed files with 14598 additions and 20 deletions

View File

@@ -122,19 +122,28 @@ def _replay_fixture(fixture: dict) -> dict:
db,
soc_wh=soc_wh,
)
results, _ms, _snap = pe.solve_dispatch_two_pass(
slots,
battery,
heat_pump,
grid,
ev_sessions,
vehicles,
soc_wh,
tuv_temp,
tuv_delta_stats=tuv_stats,
operating_mode=operating_mode or "AUTO",
planner_version=pe._planner_engine_version(),
)
try:
results, _ms, _snap = pe.solve_dispatch_two_pass(
slots,
battery,
heat_pump,
grid,
ev_sessions,
vehicles,
soc_wh,
tuv_temp,
tuv_delta_stats=tuv_stats,
operating_mode=operating_mode or "AUTO",
planner_version=pe._planner_engine_version(),
)
except pe.PlannerSolverError as exc:
# Selhání solveru je taky chování k zafixování (např. home-01 2026-05-01:
# Infeasible po celém relax řetězci). Až ho Fáze 2/3 opraví, golden diff
# to zviditelní a snapshot se vědomě zregeneruje.
return {
"solver_error": exc.solver_status,
"relax_chain": list(exc.relax_chain),
}
return _normalize_results(results)
return asyncio.run(_run())
@@ -170,6 +179,9 @@ def _make_test(path: Path):
f"Chybí snapshot {snap_path.name} vygeneruj přes GOLDEN_UPDATE=1",
)
expected = json.loads(snap_path.read_text(encoding="utf-8"))
if "solver_error" in expected or "solver_error" in actual:
self.assertEqual(expected, actual, f"{path.name}: změna výsledku/selhání solveru")
return
self.assertEqual(
expected["totals"],
actual["totals"],