fix: reports 500, NaN scores, hypothesis dedup blocking

Reports 500 (Internal Server Error):
- app.py: Replace NaN/Infinity->null before json.loads() in both
  /reports and /api/runs routes. Old summary.json files with invalid
  NaN are now handled transparently.
- reports/writer.py: Added _safe_val() helper using math.isfinite().
  All summary.json values now use safe rounding (NaN->0, Inf->0).

No new hypotheses (optimizer stops after 1 iter):
- optimizer_loop.py: Changed dedup from DB-wide history to
  session-scoped (self.session_tested_deltas). Previous runs from
  old sessions no longer block new hypothesis proposals.
- Each tested hypothesis is tracked within the session only.

Result: optimizer now runs multiple iterations, scores are valid
numbers, reports page loads without 500.
This commit is contained in:
LEGSTECH Optimizer
2026-04-13 03:29:33 +00:00
parent 26e5f9d0c4
commit cf8613eb49
4 changed files with 26 additions and 7 deletions
+4 -3
View File
@@ -66,6 +66,7 @@ class OptimizerLoop:
self.current_run_id: Optional[str] = None
self.score_history: list[dict] = []
self.run_start_ts: Optional[float] = None
self.session_tested_deltas: list[dict] = [] # dedup within this session only
with open(config_path) as f:
self.cfg = yaml.safe_load(f)
@@ -177,12 +178,11 @@ class OptimizerLoop:
self._emit("log", {"level": "warn", "msg": "No actionable findings. Stopping."})
break
# Mutation proposals
recent_deltas = store.get_recent_param_deltas(cfg["mutation"]["dedup_lookback_runs"])
# Mutation proposals — only dedup within this session
hypotheses = mutator.propose(
findings=findings,
current_params=current_params,
recent_deltas=recent_deltas,
recent_deltas=self.session_tested_deltas,
max_proposals=cfg["mutation"]["max_hypotheses_per_cycle"],
)
@@ -249,6 +249,7 @@ class OptimizerLoop:
hypothesis=hyp, baseline_score=current_metrics.composite_score)
store.update_hypothesis_status(hyp.hypothesis_id, "tested", run_id)
self.session_tested_deltas.append(hyp.param_delta) # track for session dedup
if iteration_best is None or test_metrics.composite_score > iteration_best.composite_score:
iteration_best = test_metrics