1. CRITICAL FIX - Reports 500 Internal Server Error:
Root cause: {{}} in onclick was Jinja2 template expression
Fix: Changed to single {} in reports_index.html onclick
2. Score history chart always empty:
Root cause: score_update only emitted inside wfv.passed block
Fix: Emit score_update after every hypothesis run with {promoted:false}
Fix: Baseline run also pushes to chart via run_complete handler
3. IS gate too strict - optimizer produces 0 candidates forever:
Root cause: min_calmar=0.35 but best EA has calmar=0.165
Fix: Two-tier IS check - passes if composite_score improves vs baseline
(absolute thresholds still apply as alternative pass condition)
4. Findings emitted twice (double UI display):
Root cause: baseline analyzed once after run, then re-analyzed in iter 1
Fix: Cache baseline findings, reuse in iteration 1 without re-emitting
5. Chart labels improved:
'Baseline' for first point, 'It1·h1' for hypothesis runs
Calmar normalized -0.5..2.0 -> 0..1 for chart display
6. Best score header only updates on actual promotion (not per-hypothesis)
- NaN composite score: dropna().mean() on empty series returns NaN,
nan is truthy so (nan or 0)=nan. Fixed: use None when no MFE data
so scorer uses 0.5 fallback instead of propagating NaN.
- Analysis stopping: gate WFV was importing from main.execute_run
(old CLI code that uses broken runner). Fixed: gate.run_walk_forward
now accepts an executor callable from optimizer_loop.
- Back to Dashboard opened blank tab: Reports button used
window.open(_blank). Fixed: same-tab navigation + history.back().
- NaN in reports card: downstream of composite_score NaN above.