waytoRSIRecursive self-improvement, examined
Back to latest

OpenEvolve v0.4.0: an edit boundary can disappear before evaluation

A trace of the frozen source shows why an explicitly enabled setting fails to reach the worker—and how a function rename can survive the restoration step.

OpenEvolve tries to improve a program by repeatedly proposing changes and evaluating the resulting versions. A developer supplies an initial program, an evaluator—the checker that returns measurements—and an iteration count. The model receives context from earlier programs and their metrics; available execution feedback can also enter the prompt for a later attempt. This is a search through candidate versions of the supplied program. Documented workflow, generation and evaluation source

Such a search can also come with a requirement to preserve the interface used by other code. A function's name and arguments tell callers how to invoke it. Changing its implementation can be allowed while changing that interface is forbidden. OpenEvolve's optimization guidance explicitly distinguishes internal changes from preserving function signatures and external APIs. Interface constraints

The v0.4.0 release describes an option for enforcing such a text boundary. Comment markers identify the regions allowed to change; before evaluation, edits outside those regions are restored to the parent program, the version being modified. The feature is opt-in through enforce_evolve_blocks. Release description

One rename shows what restoration should preserve

Consider a synthetic example in which callers require solve(values). Its definition sits outside the EVOLVE-BLOCK-START and EVOLVE-BLOCK-END comment markers. The line between the markers, return sorted(values), is the editable region.

The proposed version makes two changes. Inside the markers, it substitutes return list(sorted(values)). Outside them, it renames the function to solve_fast. The first change is permitted by the example's boundary; the second changes the name the caller requires. Neither the expression nor the name solve_fast is evidence of a speed improvement. This invented proposal is used only to follow the two edits.

Editorial teaching diagram: the parent solve function and a proposed solve_fast rename, the omitted configuration switch, and the two conditional candidate outcomes.

Editorial teaching illustration. The solid route depicts the omitted-switch path derived from source; the dashed route shows the alternative if the worker's switch is True.

The intended result appears at the diagram's lower right: keep the name solve, but use the proposal's new return expression. With restoration enabled and one intact marker pair in each version, the helper builds precisely that combination. It takes outside text, including the markers, from the parent and block contents from the proposal. Evaluation can then judge the reconstructed candidate. Restoring the specified text says nothing by itself about whether the new implementation is useful. Reconstruction helper, subsequent evaluation

The transfer dictionary leaves out the switch

The missing setting becomes visible when following configuration to the process that uses it. In OpenEvolve.run, the main configuration is given to the parallel controller, which starts separate worker processes. The controller's _serialize_config method prepares a dictionary of named settings for transfer. Its complete returned dictionary does not include enforce_evolve_blocks. Main entry, configuration transfer

The process pool sends that dictionary to _worker_init. The initializer constructs a fresh Config from the received entries. The missing setting is therefore supplied by the class default, False. The worker checks its own value before calling the restoration helper. Worker initialization and restoration condition, Configuration default

For the unmodified path at captured v0.4.0 commit f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c, this yields a source-derived conclusion: an explicit main-process True is not transmitted, and the worker skips restoration. This is an inference from the handoff, not a reported full worker run. The middle of the diagram shows why: main True → omitted dictionary entry → fresh worker False. Complete handoff, Default value

Default False matches the documented opt-in design. The defect in this path is the loss of an explicitly requested True during transfer. Opt-in behavior, Omitted field

The rename can survive all the way to evaluation

Return to the same proposed solve_fast function. If earlier candidate construction succeeds and the later code-length check passes, the skipped restoration step leaves both edits in the text sent to the evaluator. The proposed return expression survives, and so does the outside rename. That is the diagram's lower-left outcome. Restoration, length check and evaluation input

An evaluator written to require solve could reject that candidate. Such a rejection would not demonstrate that the edit boundary had worked: the rename could have reached the evaluator precisely because restoration was skipped. The actual evaluator outcome is not established here. The boundary's job in this example is to restore specified text; evaluation separately judges the candidate it receives.

Check both the function name and the edited line

For someone depending on this boundary, a useful diagnostic is to inspect the effective worker setting together with the exact candidate immediately before evaluation. In this example, the expected combination is unambiguous: the function is still named solve, and its marked line contains return list(sorted(values)). Point of evaluation, Expected reconstruction

Checking the name alone would also admit the unchanged parent, which already defines solve. Checking the retained inner edit as well distinguishes the intended reconstruction from simply discarding the proposal. A main-process True and an evaluator score or error leave this question unresolved: which of those texts actually entered evaluation?

For this v0.4.0 handoff, depending on the boundary therefore requires following it through to the candidate at the evaluator's entrance. That is where the difference between a requested setting and its effect becomes concrete: the permitted inner edit remains, while the outside name has either been restored or allowed through.

The object of this search is the supplied program. This configuration trace does not establish that OpenEvolve improves its own improvement machinery, or demonstrate general recursive self-improvement.

Source scope: frozen v0.4.0 commit f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c, identified by the captured tag reference. The figures are editorial teaching illustrations. This revision adds no experiment and reports no full process-pool, worker, model or evaluator execution, or independently measured optimization gain.

Go to the source

The primary materials used in this analysis. Source versions stay explicit.

  1. OpenEvolve v0.4.0 — evolution configuration
    Citation & version

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/config.py | L425–L450

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/config.py

  2. OpenEvolve v0.4.0 — code parsing and edit boundaries
    Citation & version

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/utils/code_utils.py | L14–L29; L64–L135; L193–L227; L378–L433

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/utils/code_utils.py

  3. OpenEvolve v0.4.0 — candidate worker
    Citation & version

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/process_parallel.py | L188–L366; L1015–L1044

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/process_parallel.py

  4. OpenEvolve v0.4.0 — controller entry
    Citation & version

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/controller.py | L316–L360; L496–L506

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/openevolve/controller.py

  5. OpenEvolve v0.4.0 — GitHub release metadata
    Citation & version

    https://api.github.com/repos/algorithmicsuperintelligence/openevolve/releases/tags/v0.4.0 | L1

    https://api.github.com/repos/algorithmicsuperintelligence/openevolve/releases/tags/v0.4.0

  6. OpenEvolve v0.4.0 — GitHub tag reference
    Citation & version

    https://api.github.com/repos/algorithmicsuperintelligence/openevolve/git/ref/tags/v0.4.0 | L1

    https://api.github.com/repos/algorithmicsuperintelligence/openevolve/git/ref/tags/v0.4.0

  7. OpenEvolve v0.4.0 — release notes
    Citation & version

    https://github.com/algorithmicsuperintelligence/openevolve/releases/tag/v0.4.0 | L170–L174; L190–L193

    https://github.com/algorithmicsuperintelligence/openevolve/releases/tag/v0.4.0

  8. OpenEvolve v0.4.0 — evolutionary coding pipeline and optimization boundaries
    Citation & version

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/README.md | L74–L127; L220–L232; L640–L651; L714–L772; L801–L829; L930–L939

    https://raw.githubusercontent.com/algorithmicsuperintelligence/openevolve/f7b633986c0b3dbd0a171f6eb0cb0f0ba4fdfb0c/README.md

Back to the top
Updated Oct 14, 2026
Technical version
Article
openevolve-edit-boundaries
Release
bc45816db366147c7c0d4aa43f6a13e6b7db1a20a82345d51f4fa8f5aba4fa7b
Content digest
bc45816db366147c7c0d4aa43f6a13e6b7db1a20a82345d51f4fa8f5aba4fa7b

Keep reading

Programs & agents

Topics in this article

Recursive self-improvement OpenEvolve

Figure detail

Scroll to explore the full figure. Press Esc or Close to return to your place.