Bug fixes
Booleans in metrics are flags, not scores. bool is a subclass of int, so a naive isinstance(value, (int, float)) check silently treated True/False as 1.0/0.0. OpenEvolve's own evaluator emits timeout: True as a metric, so this was not a hypothetical input.
- Fitness math (
utils/metrics_utils.py) — the significant one. When an evaluation timed out,evaluator.pyreturns{"error": 0.0, "timeout": True}, whichsafe_numeric_averagescored as 0.5 — handing a program that failed outright a mid-range fitness and letting it compete for survival in the MAP-Elites database. Bothsafe_numeric_average()andget_fitness_score()now exclude booleans, so it correctly scores 0.0.combined_scoreprecedence and feature-dimension exclusion are unaffected. - Formatting (
utils/format_utils.py) — boolean metrics render astimeout=Truerather than a meaninglesstimeout=1.0000, and are skipped when computing improvements (a flag flippingFalse → Trueis not a+1.0000improvement).
Cleanup
- Removed the module-level
_format_metrics/_format_improvementhelpers fromcontroller.py. They were dead code — never called, since the controller imports the sharedformat_utilsversions — and confusingly already contained the bool fix the live path lacked.
Docs
- README: switched the PyPI downloads badge to the pepy.tech monthly badge, and dropped the GitHub stars badge (GitHub already displays the star count).
Full changelog: v0.3.1...v0.3.2