Execute one evolution action. Returns new SkillRecord or None. The global semaphore is NOT acquired here — it is managed at the trigger-method level so the concurrency limit covers the whole batch.
(self, ctx: EvolutionContext)
| 232 | self._background_tasks.clear() |
| 233 | |
| 234 | async def evolve(self, ctx: EvolutionContext) -> Optional[SkillRecord]: |
| 235 | """Execute one evolution action. Returns new SkillRecord or None. |
| 236 | |
| 237 | The global semaphore is NOT acquired here — it is managed at the |
| 238 | trigger-method level so the concurrency limit covers the whole batch. |
| 239 | """ |
| 240 | try: |
| 241 | from gdpval_bench.token_tracker import set_call_source, reset_call_source |
| 242 | _src_tok = set_call_source("evolver") |
| 243 | except ImportError: |
| 244 | _src_tok = None |
| 245 | |
| 246 | evo_type = ctx.suggestion.evolution_type |
| 247 | try: |
| 248 | if evo_type == EvolutionType.FIX: |
| 249 | return await self._evolve_fix(ctx) |
| 250 | elif evo_type == EvolutionType.DERIVED: |
| 251 | return await self._evolve_derived(ctx) |
| 252 | elif evo_type == EvolutionType.CAPTURED: |
| 253 | return await self._evolve_captured(ctx) |
| 254 | else: |
| 255 | logger.warning(f"Unknown evolution type: {evo_type}") |
| 256 | return None |
| 257 | except Exception as e: |
| 258 | targets = "+".join(ctx.suggestion.target_skill_ids) or "(new)" |
| 259 | logger.error(f"Evolution failed [{evo_type.value}] target={targets}: {e}") |
| 260 | return None |
| 261 | finally: |
| 262 | if _src_tok is not None: |
| 263 | reset_call_source(_src_tok) |
| 264 | |
| 265 | # Trigger 1: post-analysis |
| 266 | async def process_analysis( |
no test coverage detected