Skip to content

merge_batch_size: 1 causes an infinite loop in _hierarchical_merge #194

Description

@sonnietran190586

Summary

Setting merge_batch_size: 1 makes _hierarchical_merge spin forever. The
tournament loop never reduces the patch list, so training hangs indefinitely
after the reflect stage produces two or more patches.

Affected code

skillopt/gradient/aggregate.py, _hierarchical_merge (lines 92–136):

while len(current) > 1:                            # line 92
    level += 1
    for i in range(0, len(current), batch_size):   # line 95
        batch = current[i : i + batch_size]
    ...
    if len(batch) == 1:                            # line 110
        next_level[idx] = batch[0]                 # line 111
With batch_size = 1, line 95 splits N patches into N single-item batches.
Line 110 then treats every batch as "already merged" and copies the patch
through unchanged, so current never shrinks and len(current) > 1 stays
true forever. level increments without boundin our run it passed
7,200,000 before we killed the process.

Reproduction
Use any config with merge_batch_size: 1. configs/searchqa/claude_code_smoke.yaml
(line 34) ships with this value; every other benchmark config defaults to 8.
Run training until the reflect stage yields at least two patches.
The run hangs at the aggregate step, emitting
[aggregate success] level=N 2 patches2 batches (parallel, batch_size=1)
with N climbing without limit.
Note that a step where reflect produces zero patches will short-circuit with
action: skip_no_patches and appear to succeedthe hang only surfaces once
patches actually reach the merge stage, which makes this easy to miss.

Why it went unnoticed
trainer.py:793 reads merge_batch_size and validates batch_size and
accumulation at lines 806809, but never validates merge_batch_size.
The affected lines are unchanged since the initial release commit 244e346.

Suggested fix
Two small changes:

Clamp the stride in aggregate.py:95 so a round always makes progress:
range(0, len(current), max(2, batch_size))
Reject the degenerate value earlyraise ValueError in trainer.py
(near the existing validation at 806809) when merge_batch_size < 2.
Additionally, configs/searchqa/claude_code_smoke.yaml should be updated,
since as shipped it will hang on any step that produces patches.

Environment
SkillOpt 0.2.0 (editable install from source)
Python 3.12.10, Windows 11
Backend: claude_chat (optimizer) / claude_code_exec (target)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions